diff options
Diffstat (limited to 'sys/dev/ata/ata-queue.c')
-rw-r--r-- | sys/dev/ata/ata-queue.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/sys/dev/ata/ata-queue.c b/sys/dev/ata/ata-queue.c index 036b008..5de54ff 100644 --- a/sys/dev/ata/ata-queue.c +++ b/sys/dev/ata/ata-queue.c @@ -95,12 +95,14 @@ ata_queue_request(struct ata_request *request) /* if this is not a callback wait until request is completed */ if (!request->callback) { ATA_DEBUG_RQ(request, "wait for completition"); - while (!dumping && - sema_timedwait(&request->done, request->timeout * hz * 4)) { + if (!dumping && + sema_timedwait(&request->done, request->timeout * hz * 4)) { device_printf(request->dev, - "req=%p %s semaphore timeout !! DANGER Will Robinson !!\n", - request, ata_cmd2str(request)); - ata_start(ch->dev); + "WARNING - %s taskqueue timeout " + "- completing request directly\n", + ata_cmd2str(request)); + request->flags |= ATA_R_DANGER1; + ata_completed(request, 0); } sema_destroy(&request->done); } @@ -252,6 +254,17 @@ ata_completed(void *context, int dummy) struct ata_device *atadev = device_get_softc(request->dev); struct ata_composite *composite; + if (request->flags & ATA_R_DANGER2) { + device_printf(request->dev, + "WARNING - %s freeing taskqueue zombie request\n", + ata_cmd2str(request)); + request->flags &= ~(ATA_R_DANGER1 | ATA_R_DANGER2); + ata_free_request(request); + return; + } + if (request->flags & ATA_R_DANGER1) + request->flags |= ATA_R_DANGER2 + ATA_DEBUG_RQ(request, "completed entered"); /* if we had a timeout, reinit channel and deal with the falldown */ |