svn commit: r314733 - stable/10/sys/dev/isp
Alexander Motin
mav at FreeBSD.org
Mon Mar 6 06:22:39 UTC 2017
Author: mav
Date: Mon Mar 6 06:22:37 2017
New Revision: 314733
URL: https://svnweb.freebsd.org/changeset/base/314733
Log:
MFC r314086: 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.
Modified:
stable/10/sys/dev/isp/isp_freebsd.c
stable/10/sys/dev/isp/isp_freebsd.h
stable/10/sys/dev/isp/isp_target.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/dev/isp/isp_freebsd.c
==============================================================================
--- stable/10/sys/dev/isp/isp_freebsd.c Mon Mar 6 06:22:07 2017 (r314732)
+++ stable/10/sys/dev/isp/isp_freebsd.c Mon Mar 6 06:22:37 2017 (r314733)
@@ -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 %d or wildcard", __func__, aep->at_rxid, 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 %d datalen %u", aep->at_rxid, atp->cdb0, 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 ***
More information about the svn-src-stable-10
mailing list