From 849eac52f2e0be6b77cf5756053a9984996edf81 Mon Sep 17 00:00:00 2001 From: mjacob Date: Tue, 18 Sep 2001 20:20:26 +0000 Subject: [PATCH] Rather than run a periph's queue from scsipi_periph_timed_thaw which is called via a callout, kick the completion thread to run it for us (uses a new flag, SCSIPI_CHAN_KICK). If we've received BUSY status and we haven't started the completion thread yet, don't freeze do a callout to scsipi_periph_timed_thaw which then will try and kick the completion thread- instead treat the command as if it were a polled command and just call delay for 1 second. If DIAGNOSTIC is defined, and the periph qfreeze count is less than zero, panic because some HBA has corrupted the periph structure's accounting. --- sys/dev/scsipi/scsipi_base.c | 42 +++++++++++++++++++++++++++--------- sys/dev/scsipi/scsipiconf.h | 4 +++- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/sys/dev/scsipi/scsipi_base.c b/sys/dev/scsipi/scsipi_base.c index 43b19baae754..44375e80ab10 100644 --- a/sys/dev/scsipi/scsipi_base.c +++ b/sys/dev/scsipi/scsipi_base.c @@ -1,4 +1,4 @@ -/* $NetBSD: scsipi_base.c,v 1.55 2001/09/01 00:54:38 mjacob Exp $ */ +/* $NetBSD: scsipi_base.c,v 1.56 2001/09/18 20:20:26 mjacob Exp $ */ /*- * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. @@ -621,6 +621,14 @@ scsipi_periph_thaw(periph, count) s = splbio(); periph->periph_qfreeze -= count; +#ifdef DIAGNOSTIC + if (periph->periph_qfreeze < 0) { + static const char pc[] = "periph freeze count < 0"; + scsipi_printaddr(periph); + printf("%s\n", pc); + panic(pc); + } +#endif if (periph->periph_qfreeze == 0 && (periph->periph_flags & PERIPH_WAITING) != 0) wakeup(periph); @@ -636,17 +644,20 @@ void scsipi_periph_timed_thaw(arg) void *arg; { + int s; struct scsipi_periph *periph = arg; callout_stop(&periph->periph_callout); + + s = splbio(); scsipi_periph_thaw(periph, 1); /* - * Kick the channel's queue here. Note, we're running in - * interrupt context (softclock), so the adapter driver - * had better not sleep. + * Tell the completion thread to kick the channel's queue here. */ - scsipi_run_queue(periph->periph_channel); + periph->periph_channel->chan_flags |= SCSIPI_CHAN_KICK; + wakeup(&periph->periph_channel->chan_complete); + splx(s); } /* @@ -919,7 +930,6 @@ scsipi_interpret_sense(xs) printf("\n"); } #else - scsipi_printaddr(periph); printf("Sense Error Code 0x%x", sense->error_code & SSD_ERRCODE); @@ -1413,9 +1423,10 @@ scsipi_complete(xs) /* * Wait one second, and try again. */ - if (xs->xs_control & XS_CTL_POLL) + if ((xs->xs_control & XS_CTL_POLL) || + (chan->chan_flags & SCSIPI_CHAN_TACTIVE) == 0) { delay(1000000); - else { + } else { scsipi_periph_freeze(periph, 1); callout_reset(&periph->periph_callout, hz, scsipi_periph_timed_thaw, periph); @@ -1505,7 +1516,7 @@ scsipi_complete(xs) } else { bp->b_error = 0; bp->b_resid = xs->resid; - } + } biodone(bp); } @@ -1942,12 +1953,16 @@ scsipi_completion_thread(arg) struct scsipi_xfer *xs; int s; + s = splbio(); + chan->chan_flags |= SCSIPI_CHAN_TACTIVE; + splx(s); for (;;) { s = splbio(); xs = TAILQ_FIRST(&chan->chan_complete); if (xs == NULL && (chan->chan_flags & - (SCSIPI_CHAN_SHUTDOWN | SCSIPI_CHAN_CALLBACK)) == 0) { + (SCSIPI_CHAN_SHUTDOWN | SCSIPI_CHAN_CALLBACK | + SCSIPI_CHAN_KICK)) == 0) { (void) tsleep(&chan->chan_complete, PRIBIO, "sccomp", 0); splx(s); @@ -1960,6 +1975,13 @@ scsipi_completion_thread(arg) splx(s); continue; } + if (chan->chan_flags & SCSIPI_CHAN_KICK) { + /* explicitly run the queues for this channel */ + chan->chan_flags &= ~SCSIPI_CHAN_KICK; + scsipi_run_queue(chan); + splx(s); + continue; + } if (chan->chan_flags & SCSIPI_CHAN_SHUTDOWN) { splx(s); break; diff --git a/sys/dev/scsipi/scsipiconf.h b/sys/dev/scsipi/scsipiconf.h index 1f04f0e7f195..428300b95086 100644 --- a/sys/dev/scsipi/scsipiconf.h +++ b/sys/dev/scsipi/scsipiconf.h @@ -1,4 +1,4 @@ -/* $NetBSD: scsipiconf.h,v 1.57 2001/09/02 13:11:53 tsutsui Exp $ */ +/* $NetBSD: scsipiconf.h,v 1.58 2001/09/18 20:20:26 mjacob Exp $ */ /*- * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. @@ -305,6 +305,8 @@ struct scsipi_channel { #define SCSIPI_CHAN_CANGROW 0x04 /* channel can grow resources */ #define SCSIPI_CHAN_NOSETTLE 0x08 /* don't wait for devices to settle */ #define SCSIPI_CHAN_CALLBACK 0x10 /* has to call chan_callback() */ +#define SCSIPI_CHAN_KICK 0x20 /* need to run queues */ +#define SCSIPI_CHAN_TACTIVE 0x40 /* completion thread is active */ #define SCSIPI_CHAN_MAX_PERIPH(chan) \ (((chan)->chan_flags & SCSIPI_CHAN_OPENINGS) ? \