Make the aac driver be INTR_MPSAFE. Once the interrupt handler determines

that a command completion happened, all further processing is deferred to
a taskqueue.  The taskqueue itself runs implicetely under Giant, but we
already used a taskqueue for the biodone() processing, so this at least
saves the contesting of Giant in the interrupt handler.
This commit is contained in:
Scott Long 2003-02-19 21:58:34 +00:00
parent 1fd65abf88
commit 9c3a7fce37
2 changed files with 21 additions and 44 deletions

View File

@ -83,7 +83,6 @@ static int aac_bio_command(struct aac_softc *sc, struct aac_command **cmp);
static void aac_bio_complete(struct aac_command *cm);
static int aac_wait_command(struct aac_command *cm, int timeout);
static void aac_command_thread(struct aac_softc *sc);
static void aac_host_response(struct aac_softc *sc);
/* Command Buffer Management */
static void aac_map_command_helper(void *arg, bus_dma_segment_t *segs,
@ -661,7 +660,8 @@ aac_intr(void *arg)
/* It's not ok to return here because of races with the previous step */
if (reason & AAC_DB_RESPONSE_READY)
aac_host_response(sc);
/* handle completion processing */
taskqueue_enqueue(taskqueue_swi, &sc->aac_task_complete);
/* controller wants to talk to the log */
if (reason & AAC_DB_PRINTF) {
@ -844,43 +844,6 @@ aac_command_thread(struct aac_softc *sc)
kthread_exit(0);
}
/*
* Handle notification of one or more FIBs completed by the controller
*/
static void
aac_host_response(struct aac_softc *sc)
{
struct aac_command *cm;
struct aac_fib *fib;
u_int32_t fib_size;
debug_called(2);
for (;;) {
/* look for completed FIBs on our queue */
if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size,
&fib))
break; /* nothing to do */
/* get the command, unmap and queue for later processing */
cm = (struct aac_command *)fib->Header.SenderData;
if (cm == NULL) {
AAC_PRINT_FIB(sc, fib);
} else {
aac_remove_busy(cm);
aac_unmap_command(cm); /* XXX defer? */
aac_enqueue_complete(cm);
}
}
/* handle completion processing */
#if __FreeBSD_version >= 500005
taskqueue_enqueue(taskqueue_swi, &sc->aac_task_complete);
#else
aac_complete(sc, 0);
#endif
}
/*
* Process completed commands.
*/
@ -889,16 +852,29 @@ aac_complete(void *context, int pending)
{
struct aac_softc *sc;
struct aac_command *cm;
struct aac_fib *fib;
u_int32_t fib_size;
debug_called(2);
sc = (struct aac_softc *)context;
/* pull completed commands off the queue */
for (;;) {
cm = aac_dequeue_complete(sc);
if (cm == NULL)
/* look for completed FIBs on our queue */
if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size,
&fib))
break; /* nothing to do */
/* get the command, unmap and queue for later processing */
cm = (struct aac_command *)fib->Header.SenderData;
if (cm == NULL) {
AAC_PRINT_FIB(sc, fib);
break;
}
aac_remove_busy(cm);
aac_unmap_command(cm); /* XXX defer? */
cm->cm_flags |= AAC_CMD_COMPLETED;
/* is there a completion handler? */

View File

@ -223,8 +223,9 @@ aac_pci_attach(device_t dev)
#ifndef INTR_ENTROPY
#define INTR_ENTROPY 0
#endif
if (bus_setup_intr(sc->aac_dev, sc->aac_irq, INTR_TYPE_BIO|INTR_ENTROPY,
aac_intr, sc, &sc->aac_intr)) {
if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
INTR_MPSAFE|INTR_TYPE_BIO|INTR_ENTROPY, aac_intr,
sc, &sc->aac_intr)) {
device_printf(sc->aac_dev, "can't set up interrupt\n");
goto out;
}