From owner-svn-src-all@freebsd.org Wed Feb 22 06:43:50 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id E3B5BCE932D; Wed, 22 Feb 2017 06:43:50 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 7B0461622; Wed, 22 Feb 2017 06:43:50 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v1M6hnXq012557; Wed, 22 Feb 2017 06:43:49 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v1M6hn6T012555; Wed, 22 Feb 2017 06:43:49 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201702220643.v1M6hn6T012555@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Wed, 22 Feb 2017 06:43:49 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r314086 - head/sys/dev/isp X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Feb 2017 06:43:51 -0000 Author: mav Date: Wed Feb 22 06:43:49 2017 New Revision: 314086 URL: https://svnweb.freebsd.org/changeset/base/314086 Log: Fix multiple problems around LUN disable under load. - Move private data about ATIOs/INOTs from per-LUN to per-channel data. This allows active commands to continue operation after LUN destruction. This also simplifies lookup of the data by tag in some situations. - Unify three restart_queue processing implementations. - Complete all ATIOs from restart_queue on LUN disable. - Delete ATIO private data when command completed or aborted, not depending on the ATIO being requeued, that was ugly hack and could never happen. CAM should always call ether XPT_CONT_TARGET_IO with status or XPT_ABORT. - Implement XPT_ABORT for queued ATIOs/INOTs to allow CAM do graceful shutdown, not depending on LUN disable, as it is done in ahd(4)/targ(4). - Unify isp_endcmd() arguments to make it more usable in generic code. - Remove never really used LUN state reference counter. MFC after: 2 weeks Modified: head/sys/dev/isp/isp_freebsd.c head/sys/dev/isp/isp_freebsd.h head/sys/dev/isp/isp_target.c Modified: head/sys/dev/isp/isp_freebsd.c ============================================================================== --- head/sys/dev/isp/isp_freebsd.c Wed Feb 22 06:26:50 2017 (r314085) +++ head/sys/dev/isp/isp_freebsd.c Wed Feb 22 06:43:49 2017 (r314086) @@ -109,6 +109,9 @@ isp_attach_chan(ispsoftc_t *isp, struct struct ccb_setasync csa; struct cam_sim *sim; struct cam_path *path; +#ifdef ISP_TARGET_MODE + int i; +#endif /* * Construct our SIM entry. @@ -149,6 +152,14 @@ isp_attach_chan(ispsoftc_t *isp, struct spi->path = path; #ifdef ISP_TARGET_MODE TAILQ_INIT(&spi->waitq); + STAILQ_INIT(&spi->ntfree); + for (i = 0; i < ATPDPSIZE; i++) + STAILQ_INSERT_TAIL(&spi->ntfree, &spi->ntpool[i], next); + LIST_INIT(&spi->atfree); + for (i = ATPDPSIZE-1; i >= 0; i--) + LIST_INSERT_HEAD(&spi->atfree, &spi->atpool[i], next); + for (i = 0; i < ATPDPHASHSIZE; i++) + LIST_INIT(&spi->atused[i]); #endif } else { fcparam *fcp = FCPARAM(isp, chan); @@ -167,6 +178,14 @@ isp_attach_chan(ispsoftc_t *isp, struct TASK_INIT(&fc->gtask, 1, isp_gdt_task, fc); #ifdef ISP_TARGET_MODE TAILQ_INIT(&fc->waitq); + STAILQ_INIT(&fc->ntfree); + for (i = 0; i < ATPDPSIZE; i++) + STAILQ_INSERT_TAIL(&fc->ntfree, &fc->ntpool[i], next); + LIST_INIT(&fc->atfree); + for (i = ATPDPSIZE-1; i >= 0; i--) + LIST_INSERT_HEAD(&fc->atfree, &fc->atpool[i], next); + for (i = 0; i < ATPDPHASHSIZE; i++) + LIST_INIT(&fc->atused[i]); #endif isp_loop_changed(isp, chan); ISP_UNLOCK(isp); @@ -831,19 +850,15 @@ isp_free_pcmd(ispsoftc_t *isp, union ccb * Put the target mode functions here, because some are inlines */ #ifdef ISP_TARGET_MODE -static ISP_INLINE int is_lun_enabled(ispsoftc_t *, int, lun_id_t); static ISP_INLINE tstate_t *get_lun_statep(ispsoftc_t *, int, lun_id_t); -static ISP_INLINE tstate_t *get_lun_statep_from_tag(ispsoftc_t *, int, uint32_t); -static ISP_INLINE void rls_lun_statep(ispsoftc_t *, tstate_t *); -static ISP_INLINE inot_private_data_t *get_ntp_from_tagdata(ispsoftc_t *, uint32_t, uint32_t, tstate_t **); -static ISP_INLINE atio_private_data_t *isp_get_atpd(ispsoftc_t *, tstate_t *, uint32_t); -static ISP_INLINE atio_private_data_t *isp_find_atpd(ispsoftc_t *, tstate_t *, uint32_t); -static ISP_INLINE void isp_put_atpd(ispsoftc_t *, tstate_t *, atio_private_data_t *); -static ISP_INLINE inot_private_data_t *isp_get_ntpd(ispsoftc_t *, tstate_t *); -static ISP_INLINE inot_private_data_t *isp_find_ntpd(ispsoftc_t *, tstate_t *, uint32_t, uint32_t); -static ISP_INLINE void isp_put_ntpd(ispsoftc_t *, tstate_t *, inot_private_data_t *); +static atio_private_data_t *isp_get_atpd(ispsoftc_t *, int, uint32_t); +static atio_private_data_t *isp_find_atpd(ispsoftc_t *, int, uint32_t); +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); +static void isp_put_ntpd(ispsoftc_t *, int, inot_private_data_t *); static cam_status create_lun_state(ispsoftc_t *, int, struct cam_path *, tstate_t **); -static void destroy_lun_state(ispsoftc_t *, tstate_t *); +static void destroy_lun_state(ispsoftc_t *, int, tstate_t *); static void isp_enable_lun(ispsoftc_t *, union ccb *); static void isp_disable_lun(ispsoftc_t *, union ccb *); static timeout_t isp_refire_putback_atio; @@ -859,43 +874,7 @@ static void isp_handle_platform_notify_f static void isp_handle_platform_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *); static int isp_handle_platform_target_notify_ack(ispsoftc_t *, isp_notify_t *, uint32_t rsp); static void isp_handle_platform_target_tmf(ispsoftc_t *, isp_notify_t *); -static void isp_target_mark_aborted(ispsoftc_t *, union ccb *); -static void isp_target_mark_aborted_early(ispsoftc_t *, tstate_t *, uint32_t); - -static ISP_INLINE int -is_lun_enabled(ispsoftc_t *isp, int bus, lun_id_t lun) -{ - tstate_t *tptr; - struct tslist *lhp; - - ISP_GET_PC_ADDR(isp, bus, lun_hash[LUN_HASH_FUNC(lun)], lhp); - SLIST_FOREACH(tptr, lhp, next) { - if (tptr->ts_lun == lun) { - return (1); - } - } - return (0); -} - -static void -dump_tstates(ispsoftc_t *isp, int bus) -{ - int i, j; - struct tslist *lhp; - tstate_t *tptr = NULL; - - if (bus >= isp->isp_nchan) { - return; - } - for (i = 0; i < LUN_HASH_SIZE; i++) { - ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp); - j = 0; - SLIST_FOREACH(tptr, lhp, next) { - xpt_print(tptr->owner, "[%d, %d] atio_cnt=%d inot_cnt=%d\n", i, j, tptr->atio_count, tptr->inot_count); - j++; - } - } -} +static void isp_target_mark_aborted_early(ispsoftc_t *, int chan, tstate_t *, uint32_t); static ISP_INLINE tstate_t * get_lun_statep(ispsoftc_t *isp, int bus, lun_id_t lun) @@ -906,74 +885,50 @@ get_lun_statep(ispsoftc_t *isp, int bus, if (bus < isp->isp_nchan) { ISP_GET_PC_ADDR(isp, bus, lun_hash[LUN_HASH_FUNC(lun)], lhp); SLIST_FOREACH(tptr, lhp, next) { - if (tptr->ts_lun == lun) { - tptr->hold++; + if (tptr->ts_lun == lun) return (tptr); - } } } return (NULL); } -static ISP_INLINE tstate_t * -get_lun_statep_from_tag(ispsoftc_t *isp, int bus, uint32_t tagval) -{ - tstate_t *tptr = NULL; - atio_private_data_t *atp; - struct tslist *lhp; - int i; - - if (bus < isp->isp_nchan && tagval != 0) { - for (i = 0; i < LUN_HASH_SIZE; i++) { - ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp); - SLIST_FOREACH(tptr, lhp, next) { - atp = isp_find_atpd(isp, tptr, tagval); - if (atp) { - tptr->hold++; - return (tptr); - } - } - } - } - return (NULL); -} - -static ISP_INLINE inot_private_data_t * -get_ntp_from_tagdata(ispsoftc_t *isp, uint32_t tag_id, uint32_t seq_id, tstate_t **rslt) +static int +isp_atio_restart(ispsoftc_t *isp, int bus, tstate_t *tptr) { inot_private_data_t *ntp; - tstate_t *tptr; - struct tslist *lhp; - int bus, i; + struct ntpdlist rq; - for (bus = 0; bus < isp->isp_nchan; bus++) { - for (i = 0; i < LUN_HASH_SIZE; i++) { - ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp); - SLIST_FOREACH(tptr, lhp, next) { - ntp = isp_find_ntpd(isp, tptr, tag_id, seq_id); - if (ntp) { - *rslt = tptr; - tptr->hold++; - return (ntp); - } - } + if (STAILQ_EMPTY(&tptr->restart_queue)) + return (0); + STAILQ_INIT(&rq); + STAILQ_CONCAT(&rq, &tptr->restart_queue); + while ((ntp = STAILQ_FIRST(&rq)) != NULL) { + STAILQ_REMOVE_HEAD(&rq, next); + if (IS_24XX(isp)) { + isp_prt(isp, ISP_LOGTDEBUG0, + "%s: restarting resrc deprived %x", __func__, + ((at7_entry_t *)ntp->data)->at_rxid); + isp_handle_platform_atio7(isp, (at7_entry_t *) ntp->data); + } else { + isp_prt(isp, ISP_LOGTDEBUG0, + "%s: restarting resrc deprived %x", __func__, + ((at2_entry_t *)ntp->data)->at_rxid); + isp_handle_platform_atio2(isp, (at2_entry_t *) ntp->data); } + isp_put_ntpd(isp, bus, ntp); + if (!STAILQ_EMPTY(&tptr->restart_queue)) + break; } - return (NULL); -} - -static ISP_INLINE void -rls_lun_statep(ispsoftc_t *isp, tstate_t *tptr) -{ - KASSERT((tptr->hold), ("tptr not held")); - tptr->hold--; + if (!STAILQ_EMPTY(&rq)) { + STAILQ_CONCAT(&rq, &tptr->restart_queue); + STAILQ_CONCAT(&tptr->restart_queue, &rq); + } + return (!STAILQ_EMPTY(&tptr->restart_queue)); } 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; @@ -983,31 +938,8 @@ isp_tmcmd_restart(ispsoftc_t *isp) for (bus = 0; bus < isp->isp_nchan; bus++) { for (i = 0; i < LUN_HASH_SIZE; i++) { ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp); - SLIST_FOREACH(tptr, lhp, next) { - if ((restart_queue = tptr->restart_queue) != NULL) - tptr->restart_queue = NULL; - while (restart_queue) { - ntp = restart_queue; - restart_queue = ntp->rd.nt.nt_hba; - if (IS_24XX(isp)) { - isp_prt(isp, ISP_LOGTDEBUG0, "%s: restarting resrc deprived %x", __func__, ((at7_entry_t *)ntp->rd.data)->at_rxid); - isp_handle_platform_atio7(isp, (at7_entry_t *) ntp->rd.data); - } else { - isp_prt(isp, ISP_LOGTDEBUG0, "%s: restarting resrc deprived %x", __func__, ((at2_entry_t *)ntp->rd.data)->at_rxid); - isp_handle_platform_atio2(isp, (at2_entry_t *) ntp->rd.data); - } - isp_put_ntpd(isp, tptr, ntp); - if (tptr->restart_queue && restart_queue != NULL) { - ntp = tptr->restart_queue; - tptr->restart_queue = restart_queue; - while (restart_queue->rd.nt.nt_hba) { - restart_queue = restart_queue->rd.nt.nt_hba; - } - restart_queue->rd.nt.nt_hba = ntp; - break; - } - } - } + SLIST_FOREACH(tptr, lhp, next) + isp_atio_restart(isp, bus, tptr); } /* @@ -1022,95 +954,108 @@ isp_tmcmd_restart(ispsoftc_t *isp) } } -static ISP_INLINE atio_private_data_t * -isp_get_atpd(ispsoftc_t *isp, tstate_t *tptr, uint32_t tag) +static atio_private_data_t * +isp_get_atpd(ispsoftc_t *isp, int chan, uint32_t tag) { + struct atpdlist *atfree; + struct atpdlist *atused; atio_private_data_t *atp; - atp = LIST_FIRST(&tptr->atfree); + ISP_GET_PC_ADDR(isp, chan, atfree, atfree); + atp = LIST_FIRST(atfree); if (atp) { LIST_REMOVE(atp, next); atp->tag = tag; - LIST_INSERT_HEAD(&tptr->atused[ATPDPHASH(tag)], atp, next); + ISP_GET_PC(isp, chan, atused, atused); + LIST_INSERT_HEAD(&atused[ATPDPHASH(tag)], atp, next); } return (atp); } -static ISP_INLINE atio_private_data_t * -isp_find_atpd(ispsoftc_t *isp, tstate_t *tptr, uint32_t tag) +static atio_private_data_t * +isp_find_atpd(ispsoftc_t *isp, int chan, uint32_t tag) { + struct atpdlist *atused; atio_private_data_t *atp; - LIST_FOREACH(atp, &tptr->atused[ATPDPHASH(tag)], next) { + ISP_GET_PC(isp, chan, atused, atused); + LIST_FOREACH(atp, &atused[ATPDPHASH(tag)], next) { if (atp->tag == tag) return (atp); } return (NULL); } -static ISP_INLINE void -isp_put_atpd(ispsoftc_t *isp, tstate_t *tptr, atio_private_data_t *atp) +static void +isp_put_atpd(ispsoftc_t *isp, int chan, atio_private_data_t *atp) { + struct atpdlist *atfree; + if (atp->ests) { isp_put_ecmd(isp, atp->ests); } LIST_REMOVE(atp, next); memset(atp, 0, sizeof (*atp)); - LIST_INSERT_HEAD(&tptr->atfree, atp, next); + ISP_GET_PC_ADDR(isp, chan, atfree, atfree); + LIST_INSERT_HEAD(atfree, atp, next); } static void -isp_dump_atpd(ispsoftc_t *isp, tstate_t *tptr) +isp_dump_atpd(ispsoftc_t *isp, int chan) { - atio_private_data_t *atp; + atio_private_data_t *atp, *atpool; const char *states[8] = { "Free", "ATIO", "CAM", "CTIO", "LAST_CTIO", "PDON", "?6", "7" }; - for (atp = tptr->atpool; atp < &tptr->atpool[ATPDPSIZE]; atp++) { - xpt_print(tptr->owner, "ATP: [0x%x] origdlen %u bytes_xfrd %u lun %x 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]); + ISP_GET_PC(isp, chan, atpool, atpool); + for (atp = atpool; atp < &atpool[ATPDPSIZE]; atp++) { + isp_prt(isp, ISP_LOGALL, "Chan %d ATP [0x%x] origdlen %u bytes_xfrd %u lun %jx nphdl 0x%04x s_id 0x%06x d_id 0x%06x oxid 0x%04x state %s\n", + chan, atp->tag, atp->orig_datalen, atp->bytes_xfered, (uintmax_t)atp->lun, atp->nphdl, atp->sid, atp->portid, atp->oxid, states[atp->state & 0x7]); } } - -static ISP_INLINE inot_private_data_t * -isp_get_ntpd(ispsoftc_t *isp, tstate_t *tptr) +static inot_private_data_t * +isp_get_ntpd(ispsoftc_t *isp, int chan) { + struct ntpdlist *ntfree; inot_private_data_t *ntp; - ntp = tptr->ntfree; - if (ntp) { - tptr->ntfree = ntp->next; - } + + ISP_GET_PC_ADDR(isp, chan, ntfree, ntfree); + ntp = STAILQ_FIRST(ntfree); + if (ntp) + STAILQ_REMOVE_HEAD(ntfree, next); return (ntp); } -static ISP_INLINE inot_private_data_t * -isp_find_ntpd(ispsoftc_t *isp, tstate_t *tptr, uint32_t tag_id, uint32_t seq_id) +static inot_private_data_t * +isp_find_ntpd(ispsoftc_t *isp, int chan, uint32_t tag_id, uint32_t seq_id) { - inot_private_data_t *ntp; - for (ntp = tptr->ntpool; ntp < &tptr->ntpool[ATPDPSIZE]; ntp++) { - if (ntp->rd.tag_id == tag_id && ntp->rd.seq_id == seq_id) { + inot_private_data_t *ntp, *ntp2; + + ISP_GET_PC(isp, chan, ntpool, ntp); + ISP_GET_PC_ADDR(isp, chan, ntpool[ATPDPSIZE], ntp2); + for (; ntp < ntp2; ntp++) { + if (ntp->tag_id == tag_id && ntp->seq_id == seq_id) return (ntp); - } } return (NULL); } -static ISP_INLINE void -isp_put_ntpd(ispsoftc_t *isp, tstate_t *tptr, inot_private_data_t *ntp) +static void +isp_put_ntpd(ispsoftc_t *isp, int chan, inot_private_data_t *ntp) { - ntp->rd.tag_id = ntp->rd.seq_id = 0; - ntp->next = tptr->ntfree; - tptr->ntfree = ntp; + struct ntpdlist *ntfree; + + ntp->tag_id = ntp->seq_id = 0; + ISP_GET_PC_ADDR(isp, chan, ntfree, ntfree); + STAILQ_INSERT_HEAD(ntfree, ntp, next); } static cam_status create_lun_state(ispsoftc_t *isp, int bus, struct cam_path *path, tstate_t **rslt) { - cam_status status; lun_id_t lun; struct tslist *lhp; tstate_t *tptr; - int i; lun = xpt_path_lun_id(path); if (lun != CAM_LUN_WILDCARD) { @@ -1118,30 +1063,13 @@ create_lun_state(ispsoftc_t *isp, int bu return (CAM_LUN_INVALID); } } - if (is_lun_enabled(isp, bus, lun)) { - return (CAM_LUN_ALRDY_ENA); - } tptr = malloc(sizeof (tstate_t), M_DEVBUF, M_NOWAIT|M_ZERO); if (tptr == NULL) { return (CAM_RESRC_UNAVAIL); } tptr->ts_lun = lun; - status = xpt_create_path(&tptr->owner, NULL, xpt_path_path_id(path), xpt_path_target_id(path), lun); - if (status != CAM_REQ_CMP) { - free(tptr, M_DEVBUF); - return (status); - } SLIST_INIT(&tptr->atios); SLIST_INIT(&tptr->inots); - LIST_INIT(&tptr->atfree); - for (i = ATPDPSIZE-1; i >= 0; i--) - LIST_INSERT_HEAD(&tptr->atfree, &tptr->atpool[i], next); - for (i = 0; i < ATPDPHASHSIZE; i++) - LIST_INIT(&tptr->atused[i]); - for (i = 0; i < ATPDPSIZE-1; i++) - tptr->ntpool[i].next = &tptr->ntpool[i+1]; - tptr->ntfree = tptr->ntpool; - tptr->hold = 1; ISP_GET_PC_ADDR(isp, bus, lun_hash[LUN_HASH_FUNC(lun)], lhp); SLIST_INSERT_HEAD(lhp, tptr, next); *rslt = tptr; @@ -1149,34 +1077,30 @@ create_lun_state(ispsoftc_t *isp, int bu return (CAM_REQ_CMP); } -static ISP_INLINE void -destroy_lun_state(ispsoftc_t *isp, tstate_t *tptr) +static void +destroy_lun_state(ispsoftc_t *isp, int bus, tstate_t *tptr) { union ccb *ccb; struct tslist *lhp; + inot_private_data_t *ntp; - KASSERT((tptr->hold != 0), ("tptr is not held")); - KASSERT((tptr->hold == 1), ("tptr still held (%d)", tptr->hold)); - do { - ccb = (union ccb *)SLIST_FIRST(&tptr->atios); - if (ccb) { - SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle); - ccb->ccb_h.status = CAM_REQ_ABORTED; - xpt_done(ccb); - } - } while (ccb); - do { - ccb = (union ccb *)SLIST_FIRST(&tptr->inots); - if (ccb) { - SLIST_REMOVE_HEAD(&tptr->inots, sim_links.sle); - ccb->ccb_h.status = CAM_REQ_ABORTED; - xpt_done(ccb); - } - } while (ccb); - ISP_GET_PC_ADDR(isp, cam_sim_bus(xpt_path_sim(tptr->owner)), lun_hash[LUN_HASH_FUNC(tptr->ts_lun)], lhp); + while ((ccb = (union ccb *)SLIST_FIRST(&tptr->atios)) != NULL) { + SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle); + ccb->ccb_h.status = CAM_REQ_ABORTED; + xpt_done(ccb); + }; + while ((ccb = (union ccb *)SLIST_FIRST(&tptr->inots)) != NULL) { + SLIST_REMOVE_HEAD(&tptr->inots, sim_links.sle); + ccb->ccb_h.status = CAM_REQ_ABORTED; + xpt_done(ccb); + } + while ((ntp = STAILQ_FIRST(&tptr->restart_queue)) != NULL) { + isp_endcmd(isp, ntp->data, NIL_HANDLE, bus, SCSI_STATUS_BUSY, 0); + STAILQ_REMOVE_HEAD(&tptr->restart_queue, next); + isp_put_ntpd(isp, bus, ntp); + } + ISP_GET_PC_ADDR(isp, bus, lun_hash[LUN_HASH_FUNC(tptr->ts_lun)], lhp); SLIST_REMOVE(lhp, tptr, tstate, next); - ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, tptr->owner, "destroyed tstate\n"); - xpt_free_path(tptr->owner); free(tptr, M_DEVBUF); } @@ -1223,7 +1147,6 @@ isp_enable_lun(ispsoftc_t *isp, union cc return; } - rls_lun_statep(isp, tptr); ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); } @@ -1254,7 +1177,7 @@ isp_disable_lun(ispsoftc_t *isp, union c return; } - destroy_lun_state(isp, tptr); + destroy_lun_state(isp, bus, tptr); ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); } @@ -1263,7 +1186,6 @@ static void isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb, enum Start_Ctio_How how) { int fctape, sendstatus, resid; - tstate_t *tptr; fcparam *fcp; atio_private_data_t *atp; struct ccb_scsiio *cso; @@ -1271,16 +1193,6 @@ isp_target_start_ctio(ispsoftc_t *isp, u uint32_t dmaresult, handle, xfrlen, sense_length, tmp; uint8_t local[QENTRY_LEN]; - 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_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)); @@ -1313,10 +1225,10 @@ isp_target_start_ctio(ispsoftc_t *isp, u } } - atp = isp_find_atpd(isp, tptr, cso->tag_id); + atp = isp_find_atpd(isp, XS_CHANNEL(ccb), 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); + isp_dump_atpd(isp, XS_CHANNEL(ccb)); ccb->ccb_h.status = CAM_REQ_CMP_ERR; xpt_done(ccb); continue; @@ -1763,7 +1675,6 @@ isp_target_start_ctio(ispsoftc_t *isp, u atp->ctcnt++; atp->seqno++; } - rls_lun_statep(isp, tptr); } static void @@ -1860,7 +1771,7 @@ isp_handle_platform_atio2(ispsoftc_t *is */ if ((aep->at_status & ~QLTM_SVALID) != AT_CDB) { isp_prt(isp, ISP_LOGWARN, "bogus atio (0x%x) leaked to platform", aep->at_status); - isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0); + isp_endcmd(isp, aep, NIL_HANDLE, 0, SCSI_STATUS_BUSY, 0); return; } @@ -1884,9 +1795,9 @@ isp_handle_platform_atio2(ispsoftc_t *is if (tptr == NULL) { isp_prt(isp, ISP_LOGWARN, "%s: [0x%x] no state pointer for lun %jx or wildcard", __func__, aep->at_rxid, (uintmax_t)lun); if (lun == 0) { - isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0); + isp_endcmd(isp, aep, nphdl, 0, SCSI_STATUS_BUSY, 0); } else { - isp_endcmd(isp, aep, SCSI_STATUS_CHECK_COND | ECMD_SVALID | (0x5 << 12) | (0x25 << 16), 0); + isp_endcmd(isp, aep, nphdl, 0, SCSI_STATUS_CHECK_COND | ECMD_SVALID | (0x5 << 12) | (0x25 << 16), 0); } return; } @@ -1895,38 +1806,15 @@ isp_handle_platform_atio2(ispsoftc_t *is /* * Start any commands pending resources first. */ - if (tptr->restart_queue) { - inot_private_data_t *restart_queue = tptr->restart_queue; - tptr->restart_queue = NULL; - while (restart_queue) { - ntp = restart_queue; - restart_queue = ntp->rd.nt.nt_hba; - isp_prt(isp, ISP_LOGTDEBUG0, "%s: restarting resrc deprived %x", __func__, ((at2_entry_t *)ntp->rd.data)->at_rxid); - isp_handle_platform_atio2(isp, (at2_entry_t *) ntp->rd.data); - isp_put_ntpd(isp, tptr, ntp); - /* - * If a recursion caused the restart queue to start to fill again, - * stop and splice the new list on top of the old list and restore - * it and go to noresrc. - */ - if (tptr->restart_queue) { - ntp = tptr->restart_queue; - tptr->restart_queue = restart_queue; - while (restart_queue->rd.nt.nt_hba) { - restart_queue = restart_queue->rd.nt.nt_hba; - } - restart_queue->rd.nt.nt_hba = ntp; - goto noresrc; - } - } - } + if (isp_atio_restart(isp, 0, tptr)) + goto noresrc; atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios); if (atiop == NULL) { goto noresrc; } - atp = isp_get_atpd(isp, tptr, aep->at_rxid); + atp = isp_get_atpd(isp, 0, aep->at_rxid); if (atp == NULL) { goto noresrc; } @@ -2001,19 +1889,15 @@ isp_handle_platform_atio2(ispsoftc_t *is atp->state = ATPD_STATE_CAM; xpt_done((union ccb *)atiop); isp_prt(isp, ISP_LOGTDEBUG0, "ATIO2[0x%x] CDB=0x%x lun %jx datalen %u", aep->at_rxid, atp->cdb0, (uintmax_t)lun, atp->orig_datalen); - rls_lun_statep(isp, tptr); return; noresrc: - ntp = isp_get_ntpd(isp, tptr); + ntp = isp_get_ntpd(isp, 0); if (ntp == NULL) { - rls_lun_statep(isp, tptr); - isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0); + isp_endcmd(isp, aep, nphdl, 0, SCSI_STATUS_BUSY, 0); return; } - memcpy(ntp->rd.data, aep, QENTRY_LEN); - ntp->rd.nt.nt_hba = tptr->restart_queue; - tptr->restart_queue = ntp; - rls_lun_statep(isp, tptr); + memcpy(ntp->data, aep, QENTRY_LEN); + STAILQ_INSERT_TAIL(&tptr->restart_queue, ntp, next); } static void @@ -2118,40 +2002,13 @@ isp_handle_platform_atio7(ispsoftc_t *is /* * Start any commands pending resources first. */ - if (tptr->restart_queue) { - inot_private_data_t *restart_queue = tptr->restart_queue; - tptr->restart_queue = NULL; - while (restart_queue) { - ntp = restart_queue; - restart_queue = ntp->rd.nt.nt_hba; - isp_prt(isp, ISP_LOGTDEBUG0, "%s: restarting resrc deprived %x", __func__, ((at7_entry_t *)ntp->rd.data)->at_rxid); - isp_handle_platform_atio7(isp, (at7_entry_t *) ntp->rd.data); - isp_put_ntpd(isp, tptr, ntp); - /* - * If a recursion caused the restart queue to start to fill again, - * stop and splice the new list on top of the old list and restore - * it and go to noresrc. - */ - if (tptr->restart_queue) { - isp_prt(isp, ISP_LOGTDEBUG0, "%s: restart queue refilling", __func__); - if (restart_queue) { - ntp = tptr->restart_queue; - tptr->restart_queue = restart_queue; - while (restart_queue->rd.nt.nt_hba) { - restart_queue = restart_queue->rd.nt.nt_hba; - } - restart_queue->rd.nt.nt_hba = ntp; - } - goto noresrc; - } - } - } + if (isp_atio_restart(isp, chan, tptr)) + goto noresrc; /* * If the f/w is out of resources, just send a BUSY status back. */ if (aep->at_rxid == AT7_NORESRC_RXID) { - rls_lun_statep(isp, tptr); isp_endcmd(isp, aep, nphdl, chan, SCSI_BUSY, 0); return; } @@ -2165,7 +2022,7 @@ isp_handle_platform_atio7(ispsoftc_t *is goto noresrc; } - oatp = isp_find_atpd(isp, tptr, aep->at_rxid); + oatp = isp_find_atpd(isp, chan, aep->at_rxid); if (oatp) { isp_prt(isp, ISP_LOGTDEBUG0, "[0x%x] tag wraparound in isp_handle_platforms_atio7 (N-Port Handle 0x%04x S_ID 0x%04x OX_ID 0x%04x) oatp state %d", aep->at_rxid, nphdl, sid, aep->at_hdr.ox_id, oatp->state); @@ -2174,7 +2031,7 @@ isp_handle_platform_atio7(ispsoftc_t *is */ goto noresrc; } - atp = isp_get_atpd(isp, tptr, aep->at_rxid); + atp = isp_get_atpd(isp, chan, aep->at_rxid); if (atp == NULL) { isp_prt(isp, ISP_LOGTDEBUG0, "[0x%x] out of atps", aep->at_rxid); goto noresrc; @@ -2230,22 +2087,17 @@ isp_handle_platform_atio7(ispsoftc_t *is isp_prt(isp, ISP_LOGTDEBUG0, "ATIO7[0x%x] CDB=0x%x lun %jx datalen %u", aep->at_rxid, atp->cdb0, (uintmax_t)lun, atp->orig_datalen); xpt_done((union ccb *)atiop); - rls_lun_statep(isp, tptr); return; noresrc: - if (atp) { - isp_put_atpd(isp, tptr, atp); - } - ntp = isp_get_ntpd(isp, tptr); + if (atp) + isp_put_atpd(isp, chan, atp); + ntp = isp_get_ntpd(isp, chan); if (ntp == NULL) { - rls_lun_statep(isp, tptr); isp_endcmd(isp, aep, nphdl, chan, SCSI_STATUS_BUSY, 0); return; } - memcpy(ntp->rd.data, aep, QENTRY_LEN); - ntp->rd.nt.nt_hba = tptr->restart_queue; - tptr->restart_queue = ntp; - rls_lun_statep(isp, tptr); + memcpy(ntp->data, aep, QENTRY_LEN); + STAILQ_INSERT_TAIL(&tptr->restart_queue, ntp, next); } @@ -2256,7 +2108,7 @@ noresrc: * transaction. */ static void -isp_handle_srr_start(ispsoftc_t *isp, tstate_t *tptr, atio_private_data_t *atp) +isp_handle_srr_start(ispsoftc_t *isp, atio_private_data_t *atp) { in_fcentry_24xx_t *inot; uint32_t srr_off, ccb_off, ccb_len, ccb_end; @@ -2356,7 +2208,6 @@ mdp: static void isp_handle_srr_notify(ispsoftc_t *isp, void *inot_raw) { - tstate_t *tptr; in_fcentry_24xx_t *inot = inot_raw; atio_private_data_t *atp; uint32_t tag = inot->in_rxid; @@ -2367,15 +2218,8 @@ isp_handle_srr_notify(ispsoftc_t *isp, v return; } - tptr = get_lun_statep_from_tag(isp, bus, tag); - if (tptr == NULL) { - isp_prt(isp, ISP_LOGERR, "%s: cannot find tptr for tag %x in SRR Notify", __func__, tag); - isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot); - return; - } - atp = isp_find_atpd(isp, tptr, tag); + atp = isp_find_atpd(isp, bus, tag); if (atp == NULL) { - rls_lun_statep(isp, tptr); isp_prt(isp, ISP_LOGERR, "%s: cannot find adjunct for %x in SRR Notify", __func__, tag); isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot); return; @@ -2385,8 +2229,7 @@ isp_handle_srr_notify(ispsoftc_t *isp, v 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); - rls_lun_statep(isp, tptr); + isp_handle_srr_start(isp, atp); } static void @@ -2394,7 +2237,6 @@ isp_handle_platform_ctio(ispsoftc_t *isp { union ccb *ccb; 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, moved_data = 0, data_requested; @@ -2413,19 +2255,10 @@ isp_handle_platform_ctio(ispsoftc_t *isp } bus = XS_CHANNEL(ccb); - tptr = get_lun_statep(isp, bus, XS_LUN(ccb)); - if (tptr == NULL) { - tptr = get_lun_statep(isp, bus, CAM_LUN_WILDCARD); - } - if (tptr == NULL) { - isp_prt(isp, ISP_LOGERR, "%s: cannot find tptr for tag %x after I/O", __func__, ccb->csio.tag_id); - return; - } - if (IS_24XX(isp)) { - atp = isp_find_atpd(isp, tptr, ((ct7_entry_t *)arg)->ct_rxid); + atp = isp_find_atpd(isp, bus, ((ct7_entry_t *)arg)->ct_rxid); } else { - atp = isp_find_atpd(isp, tptr, ((ct2_entry_t *)arg)->ct_rxid); + atp = isp_find_atpd(isp, bus, ((ct2_entry_t *)arg)->ct_rxid); } if (atp == NULL) { /* @@ -2433,10 +2266,9 @@ isp_handle_platform_ctio(ispsoftc_t *isp * ct_rxid value, filling only ct_syshandle. Workaround * that using tag_id from the CCB, pointed by ct_syshandle. */ - atp = isp_find_atpd(isp, tptr, ccb->csio.tag_id); + atp = isp_find_atpd(isp, bus, ccb->csio.tag_id); } if (atp == NULL) { - rls_lun_statep(isp, tptr); isp_prt(isp, ISP_LOGERR, "%s: cannot find adjunct for %x after I/O", __func__, ccb->csio.tag_id); return; } @@ -2451,8 +2283,7 @@ isp_handle_platform_ctio(ispsoftc_t *isp if (ct->ct_nphdl == CT7_SRR) { atp->srr_ccb = ccb; if (atp->srr_notify_rcvd) - isp_handle_srr_start(isp, tptr, atp); - rls_lun_statep(isp, tptr); + isp_handle_srr_start(isp, atp); return; } if (ct->ct_nphdl == CT_HBA_RESET) { @@ -2473,8 +2304,7 @@ isp_handle_platform_ctio(ispsoftc_t *isp if (ct->ct_status == CT_SRR) { atp->srr_ccb = ccb; if (atp->srr_notify_rcvd) - isp_handle_srr_start(isp, tptr, atp); - rls_lun_statep(isp, tptr); + isp_handle_srr_start(isp, atp); isp_target_putback_atio(ccb); return; } @@ -2509,7 +2339,6 @@ isp_handle_platform_ctio(ispsoftc_t *isp ccb->ccb_h.status |= CAM_REQ_CMP_ERR; } atp->state = ATPD_STATE_PDON; - rls_lun_statep(isp, tptr); /* * We never *not* notify CAM when there has been any error (ok == 0), @@ -2525,6 +2354,12 @@ isp_handle_platform_ctio(ispsoftc_t *isp } /* + * If we sent status or error happened, we are done with this ATIO. + */ + if (sentstatus || !ok) + isp_put_atpd(isp, bus, atp); + + /* * We're telling CAM we're done with this CTIO transaction. * * 24XX cards never need an ATIO put back. @@ -2904,11 +2739,11 @@ isp_handle_platform_target_tmf(ispsoftc_ switch (notify->nt_ncode) { case NT_ABORT_TASK: - isp_target_mark_aborted_early(isp, tptr, inot->tag_id); + isp_target_mark_aborted_early(isp, notify->nt_channel, tptr, inot->tag_id); inot->arg = MSG_ABORT_TASK; break; case NT_ABORT_TASK_SET: - isp_target_mark_aborted_early(isp, tptr, TAG_ANY); + isp_target_mark_aborted_early(isp, notify->nt_channel, tptr, TAG_ANY); inot->arg = MSG_ABORT_TASK_SET; break; case NT_CLEAR_ACA: @@ -2934,30 +2769,26 @@ isp_handle_platform_target_tmf(ispsoftc_ goto bad; } - ntp = isp_get_ntpd(isp, tptr); + ntp = isp_get_ntpd(isp, notify->nt_channel); if (ntp == NULL) { isp_prt(isp, ISP_LOGWARN, "%s: out of inotify private structures", __func__); goto bad; } - ISP_MEMCPY(&ntp->rd.nt, notify, sizeof (isp_notify_t)); + ISP_MEMCPY(&ntp->nt, notify, sizeof (isp_notify_t)); if (notify->nt_lreserved) { - ISP_MEMCPY(&ntp->rd.data, notify->nt_lreserved, QENTRY_LEN); - ntp->rd.nt.nt_lreserved = &ntp->rd.data; + ISP_MEMCPY(&ntp->data, notify->nt_lreserved, QENTRY_LEN); + ntp->nt.nt_lreserved = &ntp->data; } - ntp->rd.seq_id = notify->nt_tagval; - ntp->rd.tag_id = notify->nt_tagval >> 32; + ntp->seq_id = notify->nt_tagval; + ntp->tag_id = notify->nt_tagval >> 32; tptr->inot_count--; SLIST_REMOVE_HEAD(&tptr->inots, sim_links.sle); - rls_lun_statep(isp, tptr); ISP_PATH_PRT(isp, ISP_LOGTDEBUG2, inot->ccb_h.path, "%s: Take FREE INOT count now %d\n", __func__, tptr->inot_count); inot->ccb_h.status = CAM_MESSAGE_RECV; xpt_done((union ccb *)inot); return; bad: - if (tptr) { - rls_lun_statep(isp, tptr); - } if (notify->nt_need_ack && notify->nt_lreserved) { if (((isphdr_t *)notify->nt_lreserved)->rqs_entry_type == RQSTYPE_ABTS_RCVD) { if (isp_acknak_abts(isp, notify->nt_lreserved, ENOMEM)) { @@ -2969,72 +2800,39 @@ bad: } } -/* - * Find the associated private data and mark it as dead so - * we don't try to work on it any further. - */ -static void -isp_target_mark_aborted(ispsoftc_t *isp, union ccb *ccb) -{ - tstate_t *tptr; - atio_private_data_t *atp; - union ccb *accb = ccb->cab.abort_ccb; - - tptr = get_lun_statep(isp, XS_CHANNEL(accb), XS_LUN(accb)); - if (tptr == NULL) { - tptr = get_lun_statep(isp, XS_CHANNEL(accb), CAM_LUN_WILDCARD); - if (tptr == NULL) { - ccb->ccb_h.status = CAM_REQ_INVALID; - return; - } - } - - atp = isp_find_atpd(isp, tptr, accb->atio.tag_id); - if (atp == NULL) { - ccb->ccb_h.status = CAM_REQ_INVALID; - } else { - atp->dead = 1; - ccb->ccb_h.status = CAM_REQ_CMP; - } - rls_lun_statep(isp, tptr); -} - static void -isp_target_mark_aborted_early(ispsoftc_t *isp, tstate_t *tptr, uint32_t tag_id) +isp_target_mark_aborted_early(ispsoftc_t *isp, int chan, tstate_t *tptr, uint32_t tag_id) { - atio_private_data_t *atp; - inot_private_data_t *restart_queue = tptr->restart_queue; + atio_private_data_t *atp, *atpool; + inot_private_data_t *ntp, *tmp; + uint32_t this_tag_id; /* * First, clean any commands pending restart */ - tptr->restart_queue = NULL; - while (restart_queue) { - uint32_t this_tag_id; - inot_private_data_t *ntp = restart_queue; - - restart_queue = ntp->rd.nt.nt_hba; - - if (IS_24XX(isp)) { - this_tag_id = ((at7_entry_t *)ntp->rd.data)->at_rxid; - } else { - this_tag_id = ((at2_entry_t *)ntp->rd.data)->at_rxid; - } + STAILQ_FOREACH_SAFE(ntp, &tptr->restart_queue, next, tmp) { + if (IS_24XX(isp)) + this_tag_id = ((at7_entry_t *)ntp->data)->at_rxid; + else + this_tag_id = ((at2_entry_t *)ntp->data)->at_rxid; if ((uint64_t)tag_id == TAG_ANY || tag_id == this_tag_id) { - isp_put_ntpd(isp, tptr, ntp); - } else { - ntp->rd.nt.nt_hba = tptr->restart_queue; - tptr->restart_queue = ntp; + isp_endcmd(isp, ntp->data, NIL_HANDLE, chan, + ECMD_TERMINATE, 0); + isp_put_ntpd(isp, chan, ntp); + STAILQ_REMOVE(&tptr->restart_queue, ntp, + inot_private_data, next); } } /* * Now mark other ones dead as well. */ - for (atp = tptr->atpool; atp < &tptr->atpool[ATPDPSIZE]; atp++) { - if ((uint64_t)tag_id == TAG_ANY || atp->tag == tag_id) { + ISP_GET_PC(isp, chan, atpool, atpool); + for (atp = atpool; atp < &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 @@ -3433,6 +3231,77 @@ isp_kthread(void *arg) kthread_exit(); } +#ifdef ISP_TARGET_MODE +static void +isp_abort_atio(ispsoftc_t *isp, union ccb *ccb) +{ + atio_private_data_t *atp; + union ccb *accb = ccb->cab.abort_ccb; + struct ccb_hdr *sccb; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***