summaryrefslogtreecommitdiffstats
path: root/sys/dev/ata/ata-queue.c
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2004-08-05 21:13:41 +0000
committersos <sos@FreeBSD.org>2004-08-05 21:13:41 +0000
commit6016d1505d6da6a688dda60cc49a2d9c250cdd53 (patch)
treefef880fd3fbfb215f0710bc58da3a5427a75a2d1 /sys/dev/ata/ata-queue.c
parent54e73750902ac8a57e6d5447c0eae6969362a103 (diff)
downloadFreeBSD-src-6016d1505d6da6a688dda60cc49a2d9c250cdd53.zip
FreeBSD-src-6016d1505d6da6a688dda60cc49a2d9c250cdd53.tar.gz
Try to narrow down the race window on HW that does not have ways to
poll for which channel actually pulled the irq line.
Diffstat (limited to 'sys/dev/ata/ata-queue.c')
-rw-r--r--sys/dev/ata/ata-queue.c28
1 files changed, 14 insertions, 14 deletions
diff --git a/sys/dev/ata/ata-queue.c b/sys/dev/ata/ata-queue.c
index 8b2b318..34edd2d 100644
--- a/sys/dev/ata/ata-queue.c
+++ b/sys/dev/ata/ata-queue.c
@@ -160,15 +160,8 @@ ata_start(struct ata_channel *ch)
if (ch->flags & ATA_IMMEDIATE_MODE)
return;
- /* lock the ATA HW for this request */
- mtx_lock(&ch->queue_mtx);
- ch->locking(ch, ATA_LF_LOCK);
- if (!ATA_LOCK_CH(ch)) {
- mtx_unlock(&ch->queue_mtx);
- return;
- }
-
/* if we dont have any work, ask the subdriver(s) */
+ mtx_lock(&ch->queue_mtx);
if (TAILQ_EMPTY(&ch->ata_queue)) {
mtx_unlock(&ch->queue_mtx);
if (ch->device[MASTER].start)
@@ -177,7 +170,15 @@ ata_start(struct ata_channel *ch)
ch->device[SLAVE].start(&ch->device[SLAVE]);
mtx_lock(&ch->queue_mtx);
}
+
+ /* if we have work todo, try to lock the ATA HW and start transaction */
if ((request = TAILQ_FIRST(&ch->ata_queue))) {
+ ch->locking(ch, ATA_LF_LOCK);
+ if (!ATA_LOCK_CH(ch)) {
+ mtx_unlock(&ch->queue_mtx);
+ return;
+ }
+
TAILQ_REMOVE(&ch->ata_queue, request, chain);
mtx_unlock(&ch->queue_mtx);
@@ -192,15 +193,14 @@ ata_start(struct ata_channel *ch)
/* kick HW into action and wait for interrupt if it flies*/
if (ch->hw.transaction(request) == ATA_OP_CONTINUES)
return;
- }
- /* unlock ATA channel HW */
- ATA_UNLOCK_CH(ch);
- ch->locking(ch, ATA_LF_UNLOCK);
+ /* unlock ATA channel HW */
+ ATA_UNLOCK_CH(ch);
+ ch->locking(ch, ATA_LF_UNLOCK);
- /* if we have a request here it failed and should be completed */
- if (request)
+ /* finish up this (failed) request */
ata_finish(request);
+ }
else
mtx_unlock(&ch->queue_mtx);
}
OpenPOWER on IntegriCloud