summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>1997-04-07 18:32:47 +0000
committergibbs <gibbs@FreeBSD.org>1997-04-07 18:32:47 +0000
commit0c6c55f6885ca2889ed08f91d49fc6a5ea67ab3a (patch)
tree47d788761d1ec8bb27dcfb5c75322e752a28a5fd /sys
parent5b77d8f791df05a5162504555a1585bfe9afa200 (diff)
downloadFreeBSD-src-0c6c55f6885ca2889ed08f91d49fc6a5ea67ab3a.zip
FreeBSD-src-0c6c55f6885ca2889ed08f91d49fc6a5ea67ab3a.tar.gz
Fix an infinite loop caused by calling ahc_run_done queue while the
driver is waiting a bus settle delay. There should really be a facility for the controller driver to "freeze" its queue during recovery operations which would make all of this gymnastics unnecessary.
Diffstat (limited to 'sys')
-rw-r--r--sys/i386/scsi/aic7xxx.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/sys/i386/scsi/aic7xxx.c b/sys/i386/scsi/aic7xxx.c
index 08e82fb..7254683 100644
--- a/sys/i386/scsi/aic7xxx.c
+++ b/sys/i386/scsi/aic7xxx.c
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aic7xxx.c,v 1.112 1997/04/04 19:36:04 gibbs Exp $
+ * $Id: aic7xxx.c,v 1.113 1997/04/05 21:41:13 gibbs Exp $
*/
/*
* TODO:
@@ -301,6 +301,7 @@ static void ahc_add_curscb_to_free_list __P((struct ahc_softc *ahc));
static void ahc_clear_intstat __P((struct ahc_softc *ahc));
static void ahc_reset_current_bus __P((struct ahc_softc *ahc));
static void ahc_run_done_queue __P((struct ahc_softc *ahc));
+static void ahc_untimeout_done_queue __P((struct ahc_softc *ahc));
static void ahc_scsirate __P((struct ahc_softc* ahc, u_int8_t *scsirate,
u_int8_t *period, u_int8_t *offset,
char channel, int target));
@@ -3625,6 +3626,8 @@ ahc_reset_current_bus(ahc)
/* Wait a minimal bus settle delay */
DELAY(AHC_BUSSETTLE_DELAY);
+
+ ahc_run_done_queue(ahc);
}
}
@@ -3692,6 +3695,7 @@ ahc_busreset_settle_complete(arg)
printf("Clearing 'in-reset' flag\n");
ahc->in_reset &= (args->bus == 'A' ? ~CHANNEL_A_RESET
: ~CHANNEL_B_RESET);
+ ahc_run_done_queue(ahc);
splx(s);
}
@@ -3777,11 +3781,22 @@ ahc_reset_channel(ahc, channel, xs_error, initiate_reset)
ahc_clear_intstat(ahc);
restart_sequencer(ahc);
}
- ahc_run_done_queue(ahc);
+ /*
+ * Untimeout our scbs now in case we have to delay our done
+ * processing.
+ */
+ ahc_untimeout_done_queue(ahc);
+ if (initiate_reset == 0) {
+ /*
+ * If we initiated the reset, we'll run the queue
+ * once our bus-settle delay has expired.
+ */
+ ahc_run_done_queue(ahc);
+ }
return found;
}
-void
+static void
ahc_run_done_queue(ahc)
struct ahc_softc *ahc;
{
@@ -3795,6 +3810,20 @@ ahc_run_done_queue(ahc)
}
}
+static void
+ahc_untimeout_done_queue(ahc)
+ struct ahc_softc *ahc;
+{
+ int i;
+ struct scb *scbp;
+
+ for (i = 0; i < ahc->scb_data->numscbs; i++) {
+ scbp = ahc->scb_data->scbarray[i];
+ if (scbp->flags & SCB_QUEUED_FOR_DONE)
+ untimeout(ahc_timeout, (caddr_t)scbp);
+ }
+}
+
static int
ahc_match_scb (scb, target, channel, lun, tag)
struct scb *scb;
OpenPOWER on IntegriCloud