diff options
author | sos <sos@FreeBSD.org> | 2002-03-11 21:04:32 +0000 |
---|---|---|
committer | sos <sos@FreeBSD.org> | 2002-03-11 21:04:32 +0000 |
commit | 2bbd43c8f1465da1596d644343204c5855f5af99 (patch) | |
tree | b285f3cbc9ac091eb6723d13404e5674e00ccd41 /sys/dev/ata/ata-all.c | |
parent | fb6b9eab60b6bbddfa7ced0500e84f057fb0e8ec (diff) | |
download | FreeBSD-src-2bbd43c8f1465da1596d644343204c5855f5af99.zip FreeBSD-src-2bbd43c8f1465da1596d644343204c5855f5af99.tar.gz |
Add new support for locking an ATA channel and use that throughout
the ATA/ATAPI driver. This solves the concurrency problem with
the new GEOM code, and also cuts a good deal of the patch size
in the upcoming MFC.
Diffstat (limited to 'sys/dev/ata/ata-all.c')
-rw-r--r-- | sys/dev/ata/ata-all.c | 46 |
1 files changed, 22 insertions, 24 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 2c63f77..870c4ea 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -218,11 +218,9 @@ ata_detach(device_t dev) return ENXIO; /* make sure channel is not busy */ - s = splbio(); - while (!atomic_cmpset_int(&ch->active, ATA_IDLE, ATA_CONTROL)) - tsleep((caddr_t)&s, PRIBIO, "atarel", hz/4); - splx(s); + ATA_SLEEPLOCK_CH(ch, ATA_CONTROL); + s = splbio(); #ifdef DEV_ATADISK if (ch->devices & ATA_ATA_MASTER && ch->device[MASTER].driver) ad_detach(&ch->device[MASTER], 1); @@ -235,6 +233,7 @@ ata_detach(device_t dev) if (ch->devices & ATA_ATAPI_SLAVE && ch->device[SLAVE].driver) atapi_detach(&ch->device[SLAVE]); #endif + splx(s); if (ch->device[MASTER].param) { free(ch->device[MASTER].param, M_ATA); @@ -260,7 +259,7 @@ ata_detach(device_t dev) ch->r_altio = NULL; ch->r_bmio = NULL; ch->r_irq = NULL; - ch->active = ATA_IDLE; + ATA_UNLOCK_CH(ch); return 0; } @@ -276,7 +275,7 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td) struct ata_cmd *iocmd = (struct ata_cmd *)addr; struct ata_channel *ch; device_t device = devclass_get_device(ata_devclass, iocmd->channel); - int error, s; + int error; if (cmd != IOCATA) return ENOTTY; @@ -300,12 +299,8 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td) case ATAREINIT: if (!device || !(ch = device_get_softc(device))) return ENXIO; - - s = splbio(); - while (!atomic_cmpset_int(&ch->active, ATA_IDLE, ATA_ACTIVE)) - tsleep((caddr_t)&s, PRIBIO, "atarin", hz/4); + ATA_SLEEPLOCK_CH(ch, ATA_ACTIVE); error = ata_reinit(ch); - splx(s); return error; #ifdef DEV_ATADISK @@ -607,10 +602,12 @@ ata_start(struct ata_channel *ch) #if defined(DEV_ATAPICD) || defined(DEV_ATAPIFD) || defined(DEV_ATAPIST) struct atapi_request *atapi_request; #endif + int s; - if (!atomic_cmpset_int(&ch->active, ATA_IDLE, ATA_ACTIVE)) + if (!ATA_LOCK_CH(ch, ATA_ACTIVE)) return; + s = splbio(); #ifdef DEV_ATADISK /* find & call the responsible driver if anything on the ATA queue */ if (TAILQ_EMPTY(&ch->ata_queue)) { @@ -623,8 +620,10 @@ ata_start(struct ata_channel *ch) TAILQ_REMOVE(&ch->ata_queue, ad_request, chain); ch->active = ATA_ACTIVE_ATA; ch->running = ad_request; - if (ad_transfer(ad_request) == ATA_OP_CONTINUES) + if (ad_transfer(ad_request) == ATA_OP_CONTINUES) { + splx(s); return; + } } #endif @@ -640,10 +639,13 @@ ata_start(struct ata_channel *ch) TAILQ_REMOVE(&ch->atapi_queue, atapi_request, chain); ch->active = ATA_ACTIVE_ATAPI; ch->running = atapi_request; - if (atapi_transfer(atapi_request) == ATA_OP_CONTINUES) + if (atapi_transfer(atapi_request) == ATA_OP_CONTINUES) { + splx(s); return; + } } #endif + splx(s); ch->active = ATA_IDLE; } @@ -782,7 +784,7 @@ ata_reinit(struct ata_channel *ch) if (!ch->r_io || !ch->r_altio || !ch->r_irq) return ENXIO; - ch->active = ATA_CONTROL; + ATA_FORCELOCK_CH(ch, ATA_CONTROL); ch->running = NULL; devices = ch->devices; ata_printf(ch, -1, "resetting devices .. "); @@ -859,7 +861,7 @@ ata_reinit(struct ata_channel *ch) } #endif printf("done\n"); - ch->active = ATA_IDLE; + ATA_UNLOCK_CH(ch); ata_start(ch); return 0; } @@ -1037,7 +1039,7 @@ ata_command(struct ata_device *atadev, u_int8_t command, if (atadev->channel->flags & ATA_QUEUED) ATA_OUTB(atadev->channel->r_altio, ATA_ALTSTAT, ATA_A_4BIT); - if (tsleep((caddr_t)atadev->channel, PRIBIO, "atacmd", 10 * hz) != 0) { + if (tsleep((caddr_t)atadev->channel, PRIBIO, "atacmd", 10 * hz)) { ata_prtdev(atadev, "timeout waiting for interrupt\n"); atadev->channel->active &= ~ATA_WAIT_INTR; error = -1; @@ -1086,10 +1088,6 @@ static void ata_change_mode(struct ata_device *atadev, int mode) { int umode, wmode, pmode; - int s = splbio(); - - while (!atomic_cmpset_int(&atadev->channel->active, ATA_IDLE, ATA_ACTIVE)) - tsleep((caddr_t)&s, PRIBIO, "atachm", hz/4); umode = ata_umode(atadev->param); wmode = ata_wmode(atadev->param); @@ -1111,11 +1109,11 @@ ata_change_mode(struct ata_device *atadev, int mode) umode = -1; wmode = -1; } - ata_dmainit(atadev->channel, atadev->unit, pmode, wmode, umode); - atadev->channel->active = ATA_IDLE; + ATA_SLEEPLOCK_CH(atadev->channel, ATA_ACTIVE); + ata_dmainit(atadev->channel, atadev->unit, pmode, wmode, umode); + ATA_UNLOCK_CH(atadev->channel); ata_start(atadev->channel); - splx(s); } int |