From cedc7194d503380e120f3bc805f9426520497454 Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=B8ren=20Schmidt?= Date: Mon, 19 Jan 2004 15:20:00 +0000 Subject: [PATCH] Fix breakage on timeout/retries. The bug cause a sema to be leaked so that the calling process would newer wakeup. --- sys/dev/ata/ata-all.c | 3 ++- sys/dev/ata/ata-all.h | 2 +- sys/dev/ata/ata-queue.c | 44 +++++++++++++++++++++-------------------- sys/dev/ata/atapi-cd.c | 2 +- 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index a1946940896..d23c3d9e588 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -565,7 +565,7 @@ ata_getparam(struct ata_device *atadev, u_int8_t command) if (request) { request->device = atadev; request->u.ata.command = command; - request->flags = (ATA_R_READ | ATA_R_AT_HEAD | ATA_R_QUIET); + request->flags = (ATA_R_READ | ATA_R_IMMEDIATE | ATA_R_QUIET); request->data = (caddr_t)atadev->param; request->timeout = 2; request->retries = 3; @@ -576,6 +576,7 @@ ata_getparam(struct ata_device *atadev, u_int8_t command) if (!(error = request->result)) break; request->retries--; + request->flags |= ATA_R_REQUEUE; } ata_free_request(request); } diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index 70a26a915cc..495f5ec2f38 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -193,7 +193,7 @@ struct ata_request { #define ATA_R_TIMEOUT 0x0080 #define ATA_R_ORDERED 0x0100 -#define ATA_R_AT_HEAD 0x0200 +#define ATA_R_IMMEDIATE 0x0200 #define ATA_R_REQUEUE 0x0400 #define ATA_R_SKIPSTART 0x0800 diff --git a/sys/dev/ata/ata-queue.c b/sys/dev/ata/ata-queue.c index ca43afd29d8..24c9b50144d 100644 --- a/sys/dev/ata/ata-queue.c +++ b/sys/dev/ata/ata-queue.c @@ -53,12 +53,13 @@ ata_queue_request(struct ata_request *request) { /* mark request as virgin */ request->result = request->status = request->error = 0; - if (!request->callback) + if (!request->callback && !(request->flags & ATA_R_REQUEUE)) sema_init(&request->done, 0, "ATA request done"); - if (request->device->channel->flags & ATA_IMMEDIATE_MODE) { - - // request->flags |= ATA_R_DEBUG; + /* in IMMEDIATE_MODE we dont queue but call HW directly */ + /* used only during reinit for getparm and config */ + if ((request->device->channel->flags & ATA_IMMEDIATE_MODE) && + (request->flags & (ATA_R_CONTROL | ATA_R_IMMEDIATE))) { /* arm timeout */ if (!request->timeout_handle.callout && !dumping) { @@ -67,16 +68,16 @@ ata_queue_request(struct ata_request *request) } /* kick HW into action */ - if (request->device->channel->hw.transaction(request) == - ATA_OP_CONTINUES) { - ATA_DEBUG_RQ(request, "wait for completition"); - sema_wait(&request->done); + if (request->device->channel->hw.transaction(request)==ATA_OP_FINISHED){ + if (!request->callback) + sema_destroy(&request->done); + return; } } else { /* put request on the locked queue at the specified location */ mtx_lock(&request->device->channel->queue_mtx); - if (request->flags & ATA_R_AT_HEAD) + if (request->flags & ATA_R_IMMEDIATE) TAILQ_INSERT_HEAD(&request->device->channel->ata_queue, request, chain); else @@ -86,21 +87,21 @@ ata_queue_request(struct ata_request *request) ATA_DEBUG_RQ(request, "queued"); - /* should we skip start ? */ + /* should we skip start to avoid lock recursion ? */ if (!(request->flags & ATA_R_SKIPSTART)) ata_start(request->device->channel); - - /* if this is a requeued request callback/sleep is already setup */ - if (request->flags & ATA_R_REQUEUE) - return; - /* if this is not a callback wait until request is completed */ - if (!request->callback) { - ATA_DEBUG_RQ(request, "wait for completition"); - sema_wait(&request->done); - } } - if (!request->callback) + + /* if this is a requeued request callback/sleep has been setup */ + if (request->flags & ATA_R_REQUEUE) + return; + + /* if this is not a callback wait until request is completed */ + if (!request->callback) { + ATA_DEBUG_RQ(request, "wait for completition"); + sema_wait(&request->done); sema_destroy(&request->done); + } } int @@ -231,7 +232,7 @@ ata_completed(void *context, int pending) /* if retries still permit, reinject this request */ if (request->retries-- > 0) { request->flags &= ~(ATA_R_TIMEOUT | ATA_R_SKIPSTART); - request->flags |= (ATA_R_AT_HEAD | ATA_R_REQUEUE); + request->flags |= (ATA_R_IMMEDIATE | ATA_R_REQUEUE); ata_queue_request(request); return; } @@ -269,6 +270,7 @@ ata_completed(void *context, int pending) printf(" LBA=%llu", (unsigned long long)request->u.ata.lba); printf("\n"); request->flags &= ~ATA_R_SKIPSTART; + request->flags |= (ATA_R_IMMEDIATE | ATA_R_REQUEUE); ata_queue_request(request); return; } diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c index 9dea17dcd20..3896917eb8d 100644 --- a/sys/dev/ata/atapi-cd.c +++ b/sys/dev/ata/atapi-cd.c @@ -1345,7 +1345,7 @@ acd_select_slot(struct acd_softc *cdp) ATA_PROTO_ATAPI_12 ? 16 : 12); request->timeout = 30; request->callback = acd_unload_done; - request->flags |= (ATA_R_ATAPI | ATA_R_AT_HEAD); + request->flags |= (ATA_R_ATAPI | ATA_R_IMMEDIATE); ata_queue_request(request); } -- 2.45.2