aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/amr
diff options
context:
space:
mode:
authorMike Smith <msmith@FreeBSD.org>1999-10-26 23:18:57 +0000
committerMike Smith <msmith@FreeBSD.org>1999-10-26 23:18:57 +0000
commitba2ace5164f73213319a3a36a3fed30bb19d237c (patch)
tree2ccfac32c9a0db01822c9d5a99d04e547833ff39 /sys/dev/amr
parent6d193c9936ee9827ac8ddb215d1ba85f15750b36 (diff)
downloadsrc-ba2ace5164f73213319a3a36a3fed30bb19d237c.tar.gz
src-ba2ace5164f73213319a3a36a3fed30bb19d237c.zip
Change the queueing model used by the controller to drastically reduce
the time spent at splbio(). We now avoid it unless we are actually manipulating the command queues themselves. This doesn't improve performance noticeably, but should improve concurrency somewhat.
Notes
Notes: svn path=/head/; revision=52543
Diffstat (limited to 'sys/dev/amr')
-rw-r--r--sys/dev/amr/amr.c86
-rw-r--r--sys/dev/amr/amr_disk.c3
-rw-r--r--sys/dev/amr/amrvar.h4
3 files changed, 49 insertions, 44 deletions
diff --git a/sys/dev/amr/amr.c b/sys/dev/amr/amr.c
index ca83a1354c92..69c8d2b3aa9b 100644
--- a/sys/dev/amr/amr.c
+++ b/sys/dev/amr/amr.c
@@ -328,7 +328,7 @@ amr_attach(struct amr_softc *sc)
/*
* Initialise per-controller queues.
*/
- TAILQ_INIT(&sc->amr_donecmds);
+ TAILQ_INIT(&sc->amr_work);
TAILQ_INIT(&sc->amr_freecmds);
bufq_init(&sc->amr_bufq);
@@ -505,7 +505,6 @@ amr_shutdown(device_t dev)
s = splbio();
error = 0;
-
/* assume we're going to shut down */
sc->amr_state |= AMR_STATE_SHUTDOWN;
for (i = 0; i < AMR_MAXLD; i++) {
@@ -604,9 +603,13 @@ amr_intr(void *arg)
int
amr_submit_buf(struct amr_softc *sc, struct buf *bp)
{
+ int s;
+
debug("called");
+ s = splbio();
bufq_insert_tail(&sc->amr_bufq, bp);
+ splx(s);
sc->amr_waitbufs++;
amr_startio(sc);
return(0);
@@ -811,8 +814,7 @@ amr_flush(struct amr_softc *sc)
* Pull as much work off the softc's work queue as possible and give it to the
* controller. Leave a couple of slots free for emergencies.
*
- * Must be called at splbio or in an equivalent fashion that prevents
- * reentry or activity on the bufq.
+ * We avoid running at splbio() whenever possible.
*/
static void
amr_startio(struct amr_softc *sc)
@@ -823,8 +825,10 @@ amr_startio(struct amr_softc *sc)
int blkcount;
int driveno;
int cmd;
+ int s;
/* spin until something prevents us from doing any work */
+ s = splbio();
for (;;) {
/* see if there's work to be done */
@@ -841,6 +845,7 @@ amr_startio(struct amr_softc *sc)
/* get the buf containing our work */
bufq_remove(&sc->amr_bufq, bp);
sc->amr_waitbufs--;
+ splx(s);
/* connect the buf to the command */
ac->ac_complete = amr_completeio;
@@ -883,7 +888,9 @@ amr_startio(struct amr_softc *sc)
ac->ac_status = AMR_STATUS_WEDGED;
amr_completeio(ac);
}
+ s = splbio();
}
+ splx(s);
}
/********************************************************************************
@@ -974,8 +981,8 @@ amr_poll_command(struct amr_command *ac)
} while ((ac->ac_status == AMR_STATUS_BUSY) && (count++ < 100000));
s = splbio();
if (ac->ac_status != AMR_STATUS_BUSY) {
- TAILQ_REMOVE(&sc->amr_donecmds, ac, ac_link);
- sc->amr_donecmdcount--;
+ TAILQ_REMOVE(&sc->amr_work, ac, ac_link);
+ sc->amr_workcount--;
error = 0;
} else {
/* take the command out of the busy list, mark slot as bogus */
@@ -1128,6 +1135,8 @@ amr_start(struct amr_command *ac)
bcopy(&ac->ac_mailbox, sc->amr_mailbox, AMR_MBOX_CMDSIZE);
sc->amr_submit_command(sc);
done = 1;
+ sc->amr_workcount++;
+ TAILQ_INSERT_TAIL(&sc->amr_work, ac, ac_link);
/* not free, try to clean up while we wait */
} else {
@@ -1161,14 +1170,14 @@ amr_start(struct amr_command *ac)
/********************************************************************************
* Extract one or more completed commands from the controller (sc)
*
- * Returns nonzero if work was moved to the done queue.
+ * Returns nonzero if any commands on the work queue were marked as completed.
*/
static int
amr_done(struct amr_softc *sc)
{
struct amr_command *ac;
struct amr_mailbox mbox;
- int i, idx, s, result;
+ int i, idx, result;
debug("called");
@@ -1188,23 +1197,18 @@ amr_done(struct amr_softc *sc)
sc->amr_busycmd[idx] = NULL;
sc->amr_busycmdcount--;
+ /* unmap data buffer */
+ amr_unmapcmd(ac);
+
/* aborted command? */
if (ac == (struct amr_command *)sc) {
device_printf(sc->amr_dev, "aborted command completed (%d)\n", idx);
ac = NULL;
-
- /* normally completed command, move it to the done queue */
+
+ /* completed normally, save status */
} else {
- sc->amr_donecmdcount++;
- s = splbio();
- TAILQ_INSERT_TAIL(&sc->amr_donecmds, ac, ac_link);
- splx(s);
- /* save completion status */
ac->ac_status = mbox.mb_status;
debug("completed command with status %x", mbox.mb_status);
-
- /* unmap data buffer */
- amr_unmapcmd(ac);
}
result = 1;
}
@@ -1227,34 +1231,38 @@ amr_complete(struct amr_softc *sc)
count = 0;
s = splbio();
- ac = TAILQ_FIRST(&sc->amr_donecmds);
+ ac = TAILQ_FIRST(&sc->amr_work);
while (ac != NULL) {
nc = TAILQ_NEXT(ac, ac_link);
-
- /*
- * Is there a completion handler?
- */
- if (ac->ac_complete != NULL) {
- /* remove and give to completion handler */
- TAILQ_REMOVE(&sc->amr_donecmds, ac, ac_link);
- sc->amr_donecmdcount--;
- ac->ac_complete(ac);
+ /* Skip if command is still active */
+ if (ac->ac_status != AMR_STATUS_BUSY) {
/*
- * Is someone sleeping on this one?
+ * Is there a completion handler?
*/
- } else if (ac->ac_private != NULL) {
-
- /* remove and wake up */
- TAILQ_REMOVE(&sc->amr_donecmds, ac, ac_link);
- sc->amr_donecmdcount--;
- wakeup_one(ac->ac_private);
+ if (ac->ac_complete != NULL) {
- /*
- * Leave it for a polling caller.
- */
- } else {
+ /* remove and give to completion handler */
+ TAILQ_REMOVE(&sc->amr_work, ac, ac_link);
+ sc->amr_workcount--;
+ ac->ac_complete(ac);
+
+ /*
+ * Is someone sleeping on this one?
+ */
+ } else if (ac->ac_private != NULL) {
+
+ /* remove and wake up */
+ TAILQ_REMOVE(&sc->amr_work, ac, ac_link);
+ sc->amr_workcount--;
+ wakeup_one(ac->ac_private);
+
+ /*
+ * Leave it for a polling caller.
+ */
+ } else {
+ }
}
ac = nc;
}
diff --git a/sys/dev/amr/amr_disk.c b/sys/dev/amr/amr_disk.c
index e33b56ac5a25..7b66f4f8c930 100644
--- a/sys/dev/amr/amr_disk.c
+++ b/sys/dev/amr/amr_disk.c
@@ -184,7 +184,6 @@ static void
amrd_strategy(struct buf *bp)
{
struct amrd_softc *sc = amrd_getsoftc(bp->b_dev);
- int s;
debug("called");
@@ -208,10 +207,8 @@ amrd_strategy(struct buf *bp)
/* pass reference to us */
bp->b_driver1 = sc;
- s = splbio();
devstat_start_transaction(&sc->amrd_stats);
amr_submit_buf(sc->amrd_controller, bp);
- splx(s);
return;
bad:
diff --git a/sys/dev/amr/amrvar.h b/sys/dev/amr/amrvar.h
index c35d5db2e910..f3955a6e41f8 100644
--- a/sys/dev/amr/amrvar.h
+++ b/sys/dev/amr/amrvar.h
@@ -137,8 +137,8 @@ struct amr_softc
int amr_waitbufs;
struct amr_command *amr_busycmd[AMR_MAXCMD];
int amr_busycmdcount;
- TAILQ_HEAD(,amr_command) amr_donecmds;
- int amr_donecmdcount;
+ TAILQ_HEAD(,amr_command) amr_work;
+ int amr_workcount;
TAILQ_HEAD(,amr_command) amr_freecmds;
/* controller type-specific support */