Index: sys/dev/ata/ata-all.c =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/dev/ata/ata-all.c,v retrieving revision 1.233 diff -u -r1.233 ata-all.c --- sys/dev/ata/ata-all.c 19 Oct 2004 20:13:38 -0000 1.233 +++ sys/dev/ata/ata-all.c 16 Nov 2004 02:23:48 -0000 @@ -426,6 +426,7 @@ ch->state = ATA_ACTIVE; else ch->state = ATA_IDLE; + callout_stop(&request->callout); mtx_unlock(&ch->state_mtx); ch->locking(ch, ATA_LF_UNLOCK); ata_finish(request); Index: sys/dev/ata/ata-queue.c =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/dev/ata/ata-queue.c,v retrieving revision 1.39 diff -u -r1.39 ata-queue.c --- sys/dev/ata/ata-queue.c 20 Oct 2004 10:11:05 -0000 1.39 +++ sys/dev/ata/ata-queue.c 17 Nov 2004 02:19:35 -0000 @@ -56,7 +56,7 @@ /* mark request as virgin */ request->result = request->status = request->error = 0; - callout_init(&request->callout, 1); + callout_init_mtx(&request->callout, &ch->state_mtx, CALLOUT_RETURNUNLOCKED); if (!request->callback && !(request->flags & ATA_R_REQUEUE)) sema_init(&request->done, 0, "ATA request done"); @@ -67,6 +67,7 @@ (request->flags & (ATA_R_CONTROL | ATA_R_IMMEDIATE))) { /* arm timeout */ + mtx_lock(&ch->state_mtx); if (!dumping) callout_reset(&request->callout, request->timeout * hz, (timeout_t*)ata_timeout, request); @@ -75,11 +76,13 @@ ch->running = request; if (ch->hw.begin_transaction(request) == ATA_OP_FINISHED) { ch->running = NULL; - callout_drain(&request->callout); + callout_stop(&request->callout); if (!request->callback) sema_destroy(&request->done); + mtx_unlock(&ch->state_mtx); return; } + mtx_unlock(&ch->state_mtx); } else { /* put request on the locked queue at the specified location */ @@ -193,6 +196,7 @@ ch->running = NULL; ch->state = ATA_IDLE; mtx_unlock(&ch->queue_mtx); + callout_stop(&request->callout); mtx_unlock(&ch->state_mtx); ch->locking(ch, ATA_LF_UNLOCK); ata_finish(request); @@ -259,9 +263,6 @@ request->result = EIO; } else { - /* untimeout request now we have control back */ - callout_drain(&request->callout); - /* if this is a soft ECC error warn about it */ if ((request->status & (ATA_S_CORR | ATA_S_ERROR)) == ATA_S_CORR) { ata_prtdev(request->device, @@ -404,9 +405,8 @@ { struct ata_channel *ch = request->device->channel; - mtx_lock(&ch->state_mtx); - ATA_DEBUG_RQ(request, "timeout"); + mtx_assert(&ch->state_mtx, MA_OWNED); /* if interrupt has been seen, shout and just rearm timeout */ if (request->flags & ATA_R_INTR_SEEN) { @@ -422,6 +422,7 @@ callout_reset(&request->callout, request->timeout * hz, (timeout_t*)ata_timeout, request); mtx_unlock(&ch->state_mtx); + /* CALLOUT_RETURNUNLOCKED */ return; } @@ -450,6 +451,7 @@ mtx_unlock(&ch->state_mtx); ata_prtdev(request->device, "timeout state=%d unexpected\n", ch->state); } + /* CALLOUT_RETURNUNLOCKED */ } void @@ -460,10 +462,11 @@ mtx_lock(&ch->state_mtx); request = ch->running; ch->running = NULL; + if (request) + callout_stop(&request->callout); mtx_unlock(&ch->state_mtx); if (request) { - callout_drain(&request->callout); ata_prtdev(request->device, "WARNING - %s requeued due to channel reset", ata_cmd2str(request)); @@ -497,11 +500,12 @@ mtx_lock(&ch->state_mtx); request = ch->running; ch->running = NULL; + if (request) + callout_stop(&request->callout); mtx_unlock(&ch->state_mtx); /* if we have a request "in flight" fail it as well */ if (request && (!device || request->device == device)) { - callout_drain(&request->callout); request->result = ENXIO; if (request->callback) (request->callback)(request);