diff options
author | scottl <scottl@FreeBSD.org> | 2004-06-01 05:32:26 +0000 |
---|---|---|
committer | scottl <scottl@FreeBSD.org> | 2004-06-01 05:32:26 +0000 |
commit | bee5c9d805da9a42e655f2af28f7b22fac2385f5 (patch) | |
tree | 8bb95b330a92f5a1b617aa5c4baccd26dcbe866c /sys/dev/aac | |
parent | e2c87d8b848b6eca8eafbf70db9dd5ed330943ff (diff) | |
download | FreeBSD-src-bee5c9d805da9a42e655f2af28f7b22fac2385f5.zip FreeBSD-src-bee5c9d805da9a42e655f2af28f7b22fac2385f5.tar.gz |
Collapse aac_map_command() into aac_startio(). Check the AAC_QUEUE_FRZN in
every iteration of aac_startio(). This ensures that a command that is
deferred for lack of resources doesn't immediately get retried in the
aac_startio() loop. This avoids an almost certain livelock.
Diffstat (limited to 'sys/dev/aac')
-rw-r--r-- | sys/dev/aac/aac.c | 74 |
1 files changed, 31 insertions, 43 deletions
diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c index 33348cd..8181651 100644 --- a/sys/dev/aac/aac.c +++ b/sys/dev/aac/aac.c @@ -68,7 +68,6 @@ static void aac_get_bus_info(struct aac_softc *sc); /* Command Processing */ static void aac_timeout(struct aac_softc *sc); -static int aac_map_command(struct aac_command *cm); static void aac_complete(void *context, int pending); static int aac_bio_command(struct aac_softc *sc, struct aac_command **cmp); static void aac_bio_complete(struct aac_command *cm); @@ -654,14 +653,19 @@ void aac_startio(struct aac_softc *sc) { struct aac_command *cm; + int error; debug_called(2); - if (sc->flags & AAC_QUEUE_FRZN) - return; - for (;;) { /* + * This flag might be set if the card is out of resources. + * Checking it here prevents an infinite loop of deferrals. + */ + if (sc->flags & AAC_QUEUE_FRZN) + break; + + /* * Try to get a command that's been put off for lack of * resources */ @@ -678,47 +682,30 @@ aac_startio(struct aac_softc *sc) if (cm == NULL) break; + /* don't map more than once */ + if (cm->cm_flags & AAC_CMD_MAPPED) + panic("aac: command %p already mapped", cm); + /* - * Try to give the command to the controller. Any error is - * catastrophic since it means that bus_dmamap_load() failed. + * Set up the command to go to the controller. If there are no + * data buffers associated with the command then it can bypass + * busdma. */ - if (aac_map_command(cm) != 0) - panic("aac: error mapping command %p\n", cm); - } -} - -/* - * Deliver a command to the controller; allocate controller resources at the - * last moment when possible. - */ -static int -aac_map_command(struct aac_command *cm) -{ - struct aac_softc *sc; - int error; - - debug_called(2); - - sc = cm->cm_sc; - error = 0; - - /* don't map more than once */ - if (cm->cm_flags & AAC_CMD_MAPPED) - panic("aac: command %p already mapped", cm); - - if (cm->cm_datalen != 0) { - error = bus_dmamap_load(sc->aac_buffer_dmat, cm->cm_datamap, - cm->cm_data, cm->cm_datalen, - aac_map_command_sg, cm, 0); - if (error == EINPROGRESS) { - debug(1, "freezing queue\n"); - sc->flags |= AAC_QUEUE_FRZN; - error = 0; - } - } else { - aac_map_command_sg(cm, NULL, 0, 0); + if (cm->cm_datalen != 0) { + error = bus_dmamap_load(sc->aac_buffer_dmat, + cm->cm_datamap, cm->cm_data, + cm->cm_datalen, + aac_map_command_sg, cm, 0); + if (error == EINPROGRESS) { + debug(1, "freezing queue\n"); + sc->flags |= AAC_QUEUE_FRZN; + error = 0; + } else + panic("aac_startio: unexpected error %d from " + "busdma\n", error); + } else + aac_map_command_sg(cm, NULL, 0, 0); } - return (error); } /* @@ -1285,9 +1272,10 @@ aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error) BUS_DMASYNC_PREWRITE); cm->cm_flags |= AAC_CMD_MAPPED; - /* put the FIB on the outbound queue */ + /* Put the FIB on the outbound queue */ if (aac_enqueue_fib(sc, cm->cm_queue, cm) == EBUSY) { aac_unmap_command(cm); + sc->flags |= AAC_QUEUE_FRZN; aac_requeue_ready(cm); } |