From nobody Mon Dec 23 14:34:59 2024 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4YH0sv2Qtbz5h8WZ; Mon, 23 Dec 2024 14:34:59 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4YH0sv1PFdz4cWW; Mon, 23 Dec 2024 14:34:59 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1734964499; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=1WVvjyEx3o8fCjzudKmlRB3HPr9CtW+oSFNqVv/WQtY=; b=ZZG9AZFFfibkopW+OznsK/UW7XN3dMIJtJXa1Sn3RyMQn/XCoTjpC+V2lzi7Z5Z/TMYqPg 3UT/v504d4+FfOdmXNGYdQlZVXHinCun5hl0FTiBwAJA4p4O/8xsp9rbNWzZbHW2K59mQy IxgDAXaakgssoNUcHu7Ao6BfdQRzrWeZC/VXoUPyPGfPGt6tMPzZ/mI/zJznYn3giMH2JP /hHDxtdtEIsfK8N6mrY+xEIycErxkA7jLiSknspCzIjWcV1WsLXseFyEvCQSY9r1jZuADG 66RcZkW239rfRxcyn3wbuOrbBq7VR7FOj5PDPhJI6Av/b7F4wID6q6/k+CmECw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1734964499; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=1WVvjyEx3o8fCjzudKmlRB3HPr9CtW+oSFNqVv/WQtY=; b=UtV8XwBQUBS7Ep2mZaT8pBfoBPbOIMFHg0XKivv9ctHTMk0tcnxBvV+GHvY8ugsrRKMKOK dJ7/IgblSNjewzBPzov9C35bzO3g7yjDX6u9vx+WhcDlt/JDsbx5pRuW5ftqIstH4/4FZ2 NlMQCeFvHNL7+JI06KBi4lE+F5dp0lJbGPvQadmQ4Ewz0CjQz5qvL/+arDOutLS4slLXaj eMlqBAkCVro4QHpRBwmw9Az1A+CuBi+msGSVR4a8WgYX0jItl2XtYeG+F8SNksmKeOoZ0T /1gdghBFHgTpXL9QsnfZt9wnBHh+C1nCccRpfufdEqsFqDR6woo99ylodVnenQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1734964499; a=rsa-sha256; cv=none; b=Nz49hXJdfOiXdJs2OzRoD2qNxQY5zAjdcyEk9mmarKMnalHYNEoy4GhRqlvIH04qJZ0tBe rrz/7JPYrEL+FWcrEhWCHgW4OkXZZkATKsIK1M9aKRqCIQ5Y18ZDRNCfCkaSqwKd4VCdmw kfZDB8uK4fWCEUTzyjjgUGWi8hhTT/Y+7ac9eOQ7I9Dqle5O+HGBJd+FxMiZ3F1NYUwWnF SHKWcF5uR9GfW5KrOqJJHyWll/tGdSArplWnnlTCs1dht4OHBqfYBKSDdWzyff1GFJbIRT XD8JSOYFvPOGbP4lgrdstqFdoszKLktFLeqgCxAJtWWHh+9CeUDXnssCFy//MA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4YH0sv0snPzxjh; Mon, 23 Dec 2024 14:34:59 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 4BNEYxDJ078304; Mon, 23 Dec 2024 14:34:59 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 4BNEYxb4078301; Mon, 23 Dec 2024 14:34:59 GMT (envelope-from git) Date: Mon, 23 Dec 2024 14:34:59 GMT Message-Id: <202412231434.4BNEYxb4078301@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Alexander Motin Subject: git: d353c342a12c - stable/13 - isp: Improve task aborts handling List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mav X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: d353c342a12cd346c79c074660709657f7a741ef Auto-Submitted: auto-generated The branch stable/13 has been updated by mav: URL: https://cgit.FreeBSD.org/src/commit/?id=d353c342a12cd346c79c074660709657f7a741ef commit d353c342a12cd346c79c074660709657f7a741ef Author: Alexander Motin AuthorDate: 2024-12-09 16:52:26 +0000 Commit: Alexander Motin CommitDate: 2024-12-23 14:34:50 +0000 isp: Improve task aborts handling - When handling notify acknowledge from target code for task abort request, not only send abort to the firmware, but also delete the ATIO private data associated with the command. It is required for proper tag reuse, allowing new "conflicting" commands to be passed to the target. CTL was already fixed to handle that right, instead of delaying them in restart queue of the driver. - When target finally aborts the command (which it should have done before the notify ack) we should not send another abort to the firmware. Since we already sent the abort and deleted ATIO private data above, just return successful completion here, doing nothing. Since the tag can be reused by that time, we can not rely on its uniqueness, so when searching to the ATIO private data compare also the aborted CCB pointer in addition to the tag. - Fix BA_RJT sending in isp_acknak_abts(). While it should be rare, teach the code to send error responses for ABTS requests. MFC after: 2 weeks (cherry picked from commit ec3175fc3b2c1b07144a85e6a3e2fe534acc0c87) --- sys/dev/isp/isp_freebsd.c | 142 +++++++++++++++++++++------------------------- sys/dev/isp/isp_freebsd.h | 9 ++- sys/dev/isp/isp_target.c | 11 ++-- 3 files changed, 77 insertions(+), 85 deletions(-) diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index 51c1e3abb6de..d5aa7a54142e 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -626,8 +626,9 @@ isp_free_pcmd(ispsoftc_t *isp, union ccb *ccb) */ #ifdef ISP_TARGET_MODE static ISP_INLINE tstate_t *get_lun_statep(ispsoftc_t *, int, lun_id_t); -static atio_private_data_t *isp_get_atpd(ispsoftc_t *, int, uint32_t); +static atio_private_data_t *isp_get_atpd(ispsoftc_t *, int, uint32_t, void *); static atio_private_data_t *isp_find_atpd(ispsoftc_t *, int, uint32_t); +static atio_private_data_t *isp_find_atpd_ccb(ispsoftc_t *, int, uint32_t, void *); static void isp_put_atpd(ispsoftc_t *, int, atio_private_data_t *); static inot_private_data_t *isp_get_ntpd(ispsoftc_t *, int); static inot_private_data_t *isp_find_ntpd(ispsoftc_t *, int, uint32_t, uint32_t); @@ -715,7 +716,7 @@ isp_tmcmd_restart(ispsoftc_t *isp) } static atio_private_data_t * -isp_get_atpd(ispsoftc_t *isp, int chan, uint32_t tag) +isp_get_atpd(ispsoftc_t *isp, int chan, uint32_t tag, void *ccb) { struct isp_fc *fc = ISP_FC_PC(isp, chan); atio_private_data_t *atp; @@ -723,6 +724,7 @@ isp_get_atpd(ispsoftc_t *isp, int chan, uint32_t tag) atp = LIST_FIRST(&fc->atfree); if (atp) { LIST_REMOVE(atp, next); + atp->ccb = ccb; atp->tag = tag; LIST_INSERT_HEAD(&fc->atused[ATPDPHASH(tag)], atp, next); } @@ -742,6 +744,23 @@ isp_find_atpd(ispsoftc_t *isp, int chan, uint32_t tag) return (NULL); } +/* + * Similar to above, but in addition to tag searches for opaque CCB pointer, + * It can be used in situations when the tag alone may already be reused. + */ +static atio_private_data_t * +isp_find_atpd_ccb(ispsoftc_t *isp, int chan, uint32_t tag, void *ccb) +{ + struct isp_fc *fc = ISP_FC_PC(isp, chan); + atio_private_data_t *atp; + + LIST_FOREACH(atp, &fc->atused[ATPDPHASH(tag)], next) { + if (atp->tag == tag && atp->ccb == ccb) + return (atp); + } + return (NULL); +} + static void isp_put_atpd(ispsoftc_t *isp, int chan, atio_private_data_t *atp) { @@ -967,16 +986,6 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb, enum Start_Ctio_How how) 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; - } - /* * Check to make sure we're still in target mode. */ @@ -1378,7 +1387,7 @@ isp_handle_platform_atio7(ispsoftc_t *isp, at7_entry_t *aep) */ goto noresrc; } - atp = isp_get_atpd(isp, chan, aep->at_rxid); + atp = isp_get_atpd(isp, chan, aep->at_rxid, atiop); if (atp == NULL) { isp_prt(isp, ISP_LOGTDEBUG0, "[0x%x] out of atps", aep->at_rxid); isp_endcmd(isp, aep, nphdl, chan, SCSI_BUSY, 0); @@ -1733,32 +1742,8 @@ isp_handle_platform_target_notify_ack(ispsoftc_t *isp, isp_notify_t *mp, uint32_ /* * This case is for a responding to an ABTS frame */ - if (mp->nt_lreserved && ((isphdr_t *)mp->nt_lreserved)->rqs_entry_type == RQSTYPE_ABTS_RCVD) { - - /* - * Overload nt_need_ack here to mark whether we've terminated the associated command. - */ - if (mp->nt_need_ack) { - abts_t *abts = (abts_t *)mp->nt_lreserved; - - ISP_MEMZERO(cto, sizeof (ct7_entry_t)); - isp_prt(isp, ISP_LOGTDEBUG0, "%s: [%x] terminating after ABTS received", __func__, abts->abts_rxid_task); - cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7; - cto->ct_header.rqs_entry_count = 1; - cto->ct_nphdl = mp->nt_nphdl; - cto->ct_rxid = abts->abts_rxid_task; - cto->ct_iid_lo = mp->nt_sid; - cto->ct_iid_hi = mp->nt_sid >> 16; - cto->ct_oxid = abts->abts_ox_id; - cto->ct_vpidx = mp->nt_channel; - cto->ct_flags = CT7_NOACK|CT7_TERMINATE; - if (isp_send_entry(isp, cto)) { - return (ENOMEM); - } - mp->nt_need_ack = 0; - } - return (isp_acknak_abts(isp, mp->nt_lreserved, 0)); - } + if (mp->nt_lreserved && ((isphdr_t *)mp->nt_lreserved)->rqs_entry_type == RQSTYPE_ABTS_RCVD) + return (isp_acknak_abts(isp, mp->nt_lreserved, (rsp == 0) ? 0 : EINVAL)); /* * General purpose acknowledgement @@ -1890,17 +1875,15 @@ bad: } } +/* + * Clean aborted commands pending restart + */ static void isp_target_mark_aborted_early(ispsoftc_t *isp, int chan, tstate_t *tptr, uint32_t tag_id) { - struct isp_fc *fc = ISP_FC_PC(isp, chan); - atio_private_data_t *atp; inot_private_data_t *ntp, *tmp; uint32_t this_tag_id; - /* - * First, clean any commands pending restart - */ STAILQ_FOREACH_SAFE(ntp, &tptr->restart_queue, next, tmp) { this_tag_id = ((at7_entry_t *)ntp->data)->at_rxid; if ((uint64_t)tag_id == TAG_ANY || tag_id == this_tag_id) { @@ -1911,16 +1894,6 @@ isp_target_mark_aborted_early(ispsoftc_t *isp, int chan, tstate_t *tptr, uint32_ isp_put_ntpd(isp, chan, ntp); } } - - /* - * Now mark other ones dead as well. - */ - for (atp = fc->atpool; atp < &fc->atpool[ATPDPSIZE]; atp++) { - if (atp->lun != tptr->ts_lun) - continue; - if ((uint64_t)tag_id == TAG_ANY || atp->tag == tag_id) - atp->dead = 1; - } } #endif @@ -2283,6 +2256,25 @@ isp_kthread(void *arg) } #ifdef ISP_TARGET_MODE +static int +isp_abort_atpd(ispsoftc_t *isp, int chan, atio_private_data_t *atp) +{ + uint8_t storage[QENTRY_LEN]; + ct7_entry_t *cto = (ct7_entry_t *) storage; + + ISP_MEMZERO(cto, sizeof (ct7_entry_t)); + cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7; + cto->ct_header.rqs_entry_count = 1; + cto->ct_nphdl = atp->nphdl; + cto->ct_vpidx = chan; + cto->ct_iid_lo = atp->sid; + cto->ct_iid_hi = atp->sid >> 16; + cto->ct_rxid = atp->tag; + cto->ct_flags = CT7_NOACK|CT7_TERMINATE; + cto->ct_oxid = atp->oxid; + return (isp_send_entry(isp, cto)); +} + static void isp_abort_atio(ispsoftc_t *isp, union ccb *ccb) { @@ -2308,30 +2300,16 @@ isp_abort_atio(ispsoftc_t *isp, union ccb *ccb) } /* Search for the ATIO among running. */ - atp = isp_find_atpd(isp, XS_CHANNEL(accb), accb->atio.tag_id); + atp = isp_find_atpd_ccb(isp, XS_CHANNEL(accb), accb->atio.tag_id, accb); if (atp != NULL) { - /* Send TERMINATE to firmware. */ - if (!atp->dead) { - uint8_t storage[QENTRY_LEN]; - ct7_entry_t *cto = (ct7_entry_t *) storage; - - ISP_MEMZERO(cto, sizeof (ct7_entry_t)); - cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7; - cto->ct_header.rqs_entry_count = 1; - cto->ct_nphdl = atp->nphdl; - cto->ct_rxid = atp->tag; - cto->ct_iid_lo = atp->sid; - cto->ct_iid_hi = atp->sid >> 16; - cto->ct_oxid = atp->oxid; - cto->ct_vpidx = XS_CHANNEL(accb); - cto->ct_flags = CT7_NOACK|CT7_TERMINATE; - isp_send_entry(isp, cto); + if (isp_abort_atpd(isp, XS_CHANNEL(accb), atp)) { + ccb->ccb_h.status = CAM_UA_ABORT; + return; } isp_put_atpd(isp, XS_CHANNEL(accb), atp); - ccb->ccb_h.status = CAM_REQ_CMP; - } else { - ccb->ccb_h.status = CAM_UA_ABORT; } + + ccb->ccb_h.status = CAM_REQ_CMP; } static void @@ -2504,6 +2482,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb) } case XPT_NOTIFY_ACKNOWLEDGE: /* notify ack */ { + atio_private_data_t *atp; inot_private_data_t *ntp; /* @@ -2522,8 +2501,19 @@ isp_action(struct cam_sim *sim, union ccb *ccb) xpt_done(ccb); break; } - if (isp_handle_platform_target_notify_ack(isp, &ntp->nt, - (ccb->ccb_h.flags & CAM_SEND_STATUS) ? ccb->cna2.arg : 0)) { + + /* + * Target should abort all affected CCBs before ACK-ing INOT, + * but if/since it doesn't, add this hack to allow tag reuse. + */ + uint32_t rsp = (ccb->ccb_h.flags & CAM_SEND_STATUS) ? ccb->cna2.arg : 0; + if (ntp->nt.nt_ncode == NT_ABORT_TASK && (rsp & 0xff) == 0 && + (atp = isp_find_atpd(isp, XS_CHANNEL(ccb), ccb->cna2.seq_id)) != NULL) { + if (isp_abort_atpd(isp, XS_CHANNEL(ccb), atp) == 0) + isp_put_atpd(isp, XS_CHANNEL(ccb), atp); + } + + if (isp_handle_platform_target_notify_ack(isp, &ntp->nt, rsp)) { cam_freeze_devq(ccb->ccb_h.path); cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 10, 0); ccb->ccb_h.status &= ~CAM_STATUS_MASK; diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h index bd5bba92c0a9..5bb3dd43b6de 100644 --- a/sys/dev/isp/isp_freebsd.h +++ b/sys/dev/isp/isp_freebsd.h @@ -89,10 +89,11 @@ void isp_put_ecmd(struct ispsoftc *, isp_ecmd_t *); #include typedef struct atio_private_data { LIST_ENTRY(atio_private_data) next; + void * ccb; + uint32_t tag; /* typically f/w RX_ID */ uint32_t orig_datalen; uint32_t bytes_xfered; uint32_t bytes_in_transit; - uint32_t tag; /* typically f/w RX_ID */ lun_id_t lun; uint32_t nphdl; uint32_t sid; @@ -102,11 +103,9 @@ typedef struct atio_private_data { 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, + uint8_t cdb0; + uint8_t srr_notify_rcvd : 1, sendst : 1, - dead : 1, tattr : 3, state : 3; void * ests; diff --git a/sys/dev/isp/isp_target.c b/sys/dev/isp/isp_target.c index 081524aff53c..9d8f8e2a3766 100644 --- a/sys/dev/isp/isp_target.c +++ b/sys/dev/isp/isp_target.c @@ -481,10 +481,14 @@ isp_acknak_abts(ispsoftc_t *isp, void *arg, int errno) ISP_MEMCPY(rsp, abts, QENTRY_LEN); rsp->abts_rsp_header.rqs_entry_type = RQSTYPE_ABTS_RSP; + isp_prt(isp, ISP_LOGTINFO, "[0x%x] ABTS of 0x%x being %s'd", + rsp->abts_rsp_rxid_abts, rsp->abts_rsp_rxid_task, + (errno == 0) ? "BA_ACC" : "BA_RJT"); + rsp->abts_rsp_r_ctl = (errno == 0) ? BA_ACC : BA_RJT; + /* * Swap destination and source for response. */ - rsp->abts_rsp_r_ctl = BA_ACC; tmpw = rsp->abts_rsp_did_lo; tmpb = rsp->abts_rsp_did_hi; rsp->abts_rsp_did_lo = rsp->abts_rsp_sid_lo; @@ -505,15 +509,14 @@ isp_acknak_abts(ispsoftc_t *isp, void *arg, int errno) rx_id = rsp->abts_rsp_rx_id; ox_id = rsp->abts_rsp_ox_id; ISP_MEMZERO(&rsp->abts_rsp_payload.ba_acc, sizeof (rsp->abts_rsp_payload.ba_acc)); - isp_prt(isp, ISP_LOGTINFO, "[0x%x] ABTS of 0x%x being BA_ACC'd", rsp->abts_rsp_rxid_abts, rsp->abts_rsp_rxid_task); rsp->abts_rsp_payload.ba_acc.aborted_rx_id = rx_id; rsp->abts_rsp_payload.ba_acc.aborted_ox_id = ox_id; rsp->abts_rsp_payload.ba_acc.high_seq_cnt = 0xffff; } else { - ISP_MEMZERO(&rsp->abts_rsp_payload.ba_rjt, sizeof (rsp->abts_rsp_payload.ba_acc)); + ISP_MEMZERO(&rsp->abts_rsp_payload.ba_rjt, sizeof (rsp->abts_rsp_payload.ba_rjt)); switch (errno) { case ENOMEM: - rsp->abts_rsp_payload.ba_rjt.reason = 5; /* Logical Unit Busy */ + rsp->abts_rsp_payload.ba_rjt.reason = 5; /* Logical busy */ break; default: rsp->abts_rsp_payload.ba_rjt.reason = 9; /* Unable to perform command request */