From: Marcin Dalecki <dalecki@evision.ag>
To: Linus Torvalds <torvalds@transmeta.com>
Cc: Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: [PATCH] IDE 107
Date: Fri, 26 Jul 2002 15:34:31 +0200 [thread overview]
Message-ID: <3D414FE7.2070807@evision.ag> (raw)
In-Reply-To: Pine.LNX.4.33.0207241410040.3542-100000@penguin.transmeta.com
[-- Attachment #1: Type: text/plain, Size: 91 bytes --]
- Fix "temporal anomaly" in do_ide_request pointed out by Petr
Vandrovec. Thanks Petr!
[-- Attachment #2: ide-107.diff --]
[-- Type: text/plain, Size: 14571 bytes --]
diff -durNp -x '*.[ao]' -x '*~' -x '*.cmd' -x '*.orig' -x '*.rej' -x 'vmlinu*' -x bzImage -x bootsect -x conmakehash -x setup -x build -x asm -x config -x '.*' -x consolemap_deftbl.c -x defkeymap.c -x devlist.h -x classlist.h -x autoconf.h -x compile.h -x version.h -x System.map -x gen-devlist -x fixdep -x split-include linux-2.5.28/drivers/ide/ide.c linux/drivers/ide/ide.c
--- linux-2.5.28/drivers/ide/ide.c 2002-07-26 09:50:43.000000000 +0200
+++ linux/drivers/ide/ide.c 2002-07-26 14:30:05.000000000 +0200
@@ -517,258 +517,251 @@ void ide_stall_queue(struct ata_device *
* Issue a new request.
* Caller must have already done spin_lock_irqsave(channel->lock, ...)
*/
-static void do_request(struct ata_channel *channel)
+void do_ide_request(request_queue_t *q)
{
- struct ata_channel *ch;
- struct ata_device *drive = NULL;
- unsigned int unit;
- ide_startstop_t ret;
+ struct ata_channel *channel = q->queuedata;
- local_irq_disable(); /* necessary paranoia */
+ while (!test_and_set_bit(IDE_BUSY, channel->active)) {
+ struct ata_channel *ch;
+ struct ata_device *drive = NULL;
+ unsigned int unit;
+ ide_startstop_t ret;
- /*
- * Select the next device which will be serviced. This selects
- * only between devices on the same channel, since everything
- * else will be scheduled on the queue level.
- */
+ /*
+ * Select the next device which will be serviced. This selects
+ * only between devices on the same channel, since everything
+ * else will be scheduled on the queue level.
+ */
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- struct ata_device *tmp = &channel->drives[unit];
+ for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ struct ata_device *tmp = &channel->drives[unit];
- if (!tmp->present)
- continue;
+ if (!tmp->present)
+ continue;
- /* There are no requests pending for this device.
- */
- if (blk_queue_empty(&tmp->queue))
- continue;
+ /* There are no requests pending for this device.
+ */
+ if (blk_queue_empty(&tmp->queue))
+ continue;
- /* This device still wants to remain idle.
- */
- if (tmp->sleep && time_after(tmp->sleep, jiffies))
- continue;
+ /* This device still wants to remain idle.
+ */
+ if (tmp->sleep && time_after(tmp->sleep, jiffies))
+ continue;
- /* Take this device, if there is no device choosen thus
- * far or which is more urgent.
- */
- if (!drive || (tmp->sleep && (!drive->sleep || time_after(drive->sleep, tmp->sleep)))) {
- if (!blk_queue_plugged(&tmp->queue))
- drive = tmp;
+ /* Take this device, if there is no device choosen thus
+ * far or which is more urgent.
+ */
+ if (!drive || (tmp->sleep && (!drive->sleep || time_after(drive->sleep, tmp->sleep)))) {
+ if (!blk_queue_plugged(&tmp->queue))
+ drive = tmp;
+ }
}
- }
- if (!drive) {
- unsigned long sleep = 0;
+ if (!drive) {
+ unsigned long sleep = 0;
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- struct ata_device *tmp = &channel->drives[unit];
+ for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ struct ata_device *tmp = &channel->drives[unit];
- if (!tmp->present)
- continue;
+ if (!tmp->present)
+ continue;
- /* This device is sleeping and waiting to be serviced
- * earlier than any other device we checked thus far.
- */
- if (tmp->sleep && (!sleep || time_after(sleep, tmp->sleep)))
- sleep = tmp->sleep;
- }
+ /* This device is sleeping and waiting to be serviced
+ * earlier than any other device we checked thus far.
+ */
+ if (tmp->sleep && (!sleep || time_after(sleep, tmp->sleep)))
+ sleep = tmp->sleep;
+ }
- if (sleep) {
- /*
- * Take a short snooze, and then wake up again. Just
- * in case there are big differences in relative
- * throughputs.. don't want to hog the cpu too much.
- */
+ if (sleep) {
+ /*
+ * Take a short snooze, and then wake up again. Just
+ * in case there are big differences in relative
+ * throughputs.. don't want to hog the cpu too much.
+ */
- if (time_after(jiffies, sleep - WAIT_MIN_SLEEP))
- sleep = jiffies + WAIT_MIN_SLEEP;
+ if (time_after(jiffies, sleep - WAIT_MIN_SLEEP))
+ sleep = jiffies + WAIT_MIN_SLEEP;
#if 1
- if (timer_pending(&channel->timer))
- printk(KERN_ERR "%s: timer already active\n", __FUNCTION__);
+ if (timer_pending(&channel->timer))
+ printk(KERN_ERR "%s: timer already active\n", __FUNCTION__);
#endif
- set_bit(IDE_SLEEP, channel->active);
- mod_timer(&channel->timer, sleep);
-
- /*
- * We purposely leave us busy while sleeping becouse we
- * are prepared to handle the IRQ from it.
- *
- * FIXME: Make sure sleeping can't interferre with
- * operations of other devices on the same channel.
- */
- } else {
- /* FIXME: use queue plugging instead of active to block
- * upper layers from stomping on us */
- /* Ugly, but how can we sleep for the lock otherwise?
- * */
+ set_bit(IDE_SLEEP, channel->active);
+ mod_timer(&channel->timer, sleep);
- ide_release_lock(&ide_irq_lock);/* for atari only */
- clear_bit(IDE_BUSY, channel->active);
+ /*
+ * We purposely leave us busy while sleeping becouse we
+ * are prepared to handle the IRQ from it.
+ *
+ * FIXME: Make sure sleeping can't interferre with
+ * operations of other devices on the same channel.
+ */
+ } else {
+ /* FIXME: use queue plugging instead of active to block
+ * upper layers from stomping on us */
+ /* Ugly, but how can we sleep for the lock otherwise?
+ * */
- /* All requests are done.
- *
- * Disable IRQs from the last drive on this channel, to
- * make sure that it wan't throw stones at us when we
- * are not prepared to take them.
- */
+ ide_release_lock(&ide_irq_lock);/* for atari only */
+ clear_bit(IDE_BUSY, channel->active);
- if (channel->drive && !channel->drive->using_tcq)
- ata_irq_enable(channel->drive, 0);
- }
+ /* All requests are done.
+ *
+ * Disable IRQs from the last drive on this channel, to
+ * make sure that it wan't throw stones at us when we
+ * are not prepared to take them.
+ */
- return;
- }
+ if (channel->drive && !channel->drive->using_tcq)
+ ata_irq_enable(channel->drive, 0);
+ }
- /* Remember the last drive we where acting on.
- */
- ch = drive->channel;
- ch->drive = drive;
+ return;
+ }
- /* Feed commands to a drive until it barfs.
- */
- do {
- struct request *rq = NULL;
- sector_t block;
+ /* Remember the last drive we where acting on.
+ */
+ ch = drive->channel;
+ ch->drive = drive;
- /* Abort early if we can't queue another command. for non tcq,
- * ata_can_queue is always 1 since we never get here unless the
- * drive is idle.
+ /* Feed commands to a drive until it barfs.
*/
+ do {
+ struct request *rq = NULL;
+ sector_t block;
- if (!ata_can_queue(drive)) {
- if (!ata_pending_commands(drive)) {
- clear_bit(IDE_BUSY, ch->active);
- if (drive->using_tcq)
- ata_irq_enable(drive, 0);
- }
- break;
- }
+ /* Abort early if we can't queue another command. for non tcq,
+ * ata_can_queue is always 1 since we never get here unless the
+ * drive is idle.
+ */
- drive->sleep = 0;
+ if (!ata_can_queue(drive)) {
+ if (!ata_pending_commands(drive)) {
+ clear_bit(IDE_BUSY, ch->active);
+ if (drive->using_tcq)
+ ata_irq_enable(drive, 0);
+ }
+ break;
+ }
- if (test_bit(IDE_DMA, ch->active)) {
- printk(KERN_ERR "%s: error: DMA in progress...\n", drive->name);
- break;
- }
+ drive->sleep = 0;
- /* There's a small window between where the queue could be
- * replugged while we are in here when using tcq (in which case
- * the queue is probably empty anyways...), so check and leave
- * if appropriate. When not using tcq, this is still a severe
- * BUG!
- */
+ if (test_bit(IDE_DMA, ch->active)) {
+ printk(KERN_ERR "%s: error: DMA in progress...\n", drive->name);
+ break;
+ }
- if (blk_queue_plugged(&drive->queue)) {
- BUG_ON(!drive->using_tcq);
- break;
- }
+ /* There's a small window between where the queue could be
+ * replugged while we are in here when using tcq (in which case
+ * the queue is probably empty anyways...), so check and leave
+ * if appropriate. When not using tcq, this is still a severe
+ * BUG!
+ */
- if (!(rq = elv_next_request(&drive->queue))) {
- if (!ata_pending_commands(drive)) {
- clear_bit(IDE_BUSY, ch->active);
- if (drive->using_tcq)
- ata_irq_enable(drive, 0);
+ if (blk_queue_plugged(&drive->queue)) {
+ BUG_ON(!drive->using_tcq);
+ break;
}
- drive->rq = NULL;
- break;
- }
+ if (!(rq = elv_next_request(&drive->queue))) {
+ if (!ata_pending_commands(drive)) {
+ clear_bit(IDE_BUSY, ch->active);
+ if (drive->using_tcq)
+ ata_irq_enable(drive, 0);
+ }
+ drive->rq = NULL;
- /* If there are queued commands, we can't start a
- * non-fs request (really, a non-queuable command)
- * until the queue is empty.
- */
- if (!(rq->flags & REQ_CMD) && ata_pending_commands(drive))
- break;
+ break;
+ }
- drive->rq = rq;
+ /* If there are queued commands, we can't start a
+ * non-fs request (really, a non-queuable command)
+ * until the queue is empty.
+ */
+ if (!(rq->flags & REQ_CMD) && ata_pending_commands(drive))
+ break;
- spin_unlock(ch->lock);
- /* allow other IRQs while we start this request */
- local_irq_enable();
+ drive->rq = rq;
- /*
- * This initiates handling of a new I/O request.
- */
+ spin_unlock(ch->lock);
+ /* allow other IRQs while we start this request */
+ local_irq_enable();
- BUG_ON(!(rq->flags & REQ_STARTED));
+ /*
+ * This initiates handling of a new I/O request.
+ */
+
+ BUG_ON(!(rq->flags & REQ_STARTED));
#ifdef DEBUG
- printk("%s: %s: current=0x%08lx\n", ch->name, __FUNCTION__, (unsigned long) rq);
+ printk("%s: %s: current=0x%08lx\n", ch->name, __FUNCTION__, (unsigned long) rq);
#endif
- /* bail early if we've exceeded max_failures */
- if (drive->max_failures && (drive->failures > drive->max_failures))
- goto kill_rq;
+ /* bail early if we've exceeded max_failures */
+ if (drive->max_failures && (drive->failures > drive->max_failures))
+ goto kill_rq;
- block = rq->sector;
+ block = rq->sector;
- /* Strange disk manager remap.
- */
- if (rq->flags & REQ_CMD)
- if (drive->type == ATA_DISK || drive->type == ATA_FLOPPY)
- block += drive->sect0;
+ /* Strange disk manager remap.
+ */
+ if (rq->flags & REQ_CMD)
+ if (drive->type == ATA_DISK || drive->type == ATA_FLOPPY)
+ block += drive->sect0;
- /* Yecch - this will shift the entire interval, possibly killing some
- * innocent following sector.
- */
- if (block == 0 && drive->remap_0_to_1 == 1)
- block = 1; /* redirect MBR access to EZ-Drive partn table */
+ /* Yecch - this will shift the entire interval, possibly killing some
+ * innocent following sector.
+ */
+ if (block == 0 && drive->remap_0_to_1 == 1)
+ block = 1; /* redirect MBR access to EZ-Drive partn table */
- ata_select(drive, 0);
- ret = ata_status_poll(drive, drive->ready_stat, BUSY_STAT | DRQ_STAT,
- WAIT_READY, rq);
+ ata_select(drive, 0);
+ ret = ata_status_poll(drive, drive->ready_stat, BUSY_STAT | DRQ_STAT,
+ WAIT_READY, rq);
- if (ret != ATA_OP_READY) {
- printk(KERN_ERR "%s: drive not ready for command\n", drive->name);
+ if (ret != ATA_OP_READY) {
+ printk(KERN_ERR "%s: drive not ready for command\n", drive->name);
- goto kill_rq;
- }
+ goto kill_rq;
+ }
- if (!ata_ops(drive)) {
- printk(KERN_WARNING "%s: device type %d not supported\n",
- drive->name, drive->type);
- goto kill_rq;
- }
+ if (!ata_ops(drive)) {
+ printk(KERN_WARNING "%s: device type %d not supported\n",
+ drive->name, drive->type);
+ goto kill_rq;
+ }
- /* The normal way of execution is to pass and execute the request
- * handler down to the device type driver.
- */
+ /* The normal way of execution is to pass and execute the request
+ * handler down to the device type driver.
+ */
- if (ata_ops(drive)->do_request) {
- ret = ata_ops(drive)->do_request(drive, rq, block);
- } else {
+ if (ata_ops(drive)->do_request) {
+ ret = ata_ops(drive)->do_request(drive, rq, block);
+ } else {
kill_rq:
- if (ata_ops(drive) && ata_ops(drive)->end_request)
- ata_ops(drive)->end_request(drive, rq, 0);
- else
- ata_end_request(drive, rq, 0, 0);
- ret = ATA_OP_FINISHED;
-
- }
- spin_lock_irq(ch->lock);
-
- /* continue if command started, so we are busy */
- } while (ret != ATA_OP_CONTINUES);
- /* make sure the BUSY bit is set */
- /* FIXME: perhaps there is some place where we miss to set it? */
-// set_bit(IDE_BUSY, ch->active);
-}
+ if (ata_ops(drive) && ata_ops(drive)->end_request)
+ ata_ops(drive)->end_request(drive, rq, 0);
+ else
+ ata_end_request(drive, rq, 0, 0);
+ ret = ATA_OP_FINISHED;
-void do_ide_request(request_queue_t *q)
-{
- struct ata_channel *ch = q->queuedata;
+ }
+ spin_lock_irq(ch->lock);
- while (!test_and_set_bit(IDE_BUSY, ch->active)) {
- do_request(ch);
+ /* continue if command started, so we are busy */
+ } while (ret != ATA_OP_CONTINUES);
+ /* make sure the BUSY bit is set */
+ /* FIXME: perhaps there is some place where we miss to set it? */
+ // set_bit(IDE_BUSY, ch->active);
}
}
/*
* This is our timeout function for all drive operations. But note that it can
* also be invoked as a result of a "sleep" operation triggered by the
- * mod_timer() call in do_request.
+ * mod_timer() call in do_ide_request.
*
* FIXME: This should take a drive context instead of a channel.
* FIXME: This should not explicitly reenter the request handling engine.
@@ -893,7 +886,8 @@ void ide_timer_expiry(unsigned long data
if (ret == ATA_OP_FINISHED) {
/* Reenter the request handling engine. */
- do_request(ch);
+ clear_bit(IDE_BUSY, ch->active);
+ do_ide_request(&drive->queue);
}
}
spin_unlock_irqrestore(ch->lock, flags);
@@ -1050,9 +1044,10 @@ void ata_irq_request(int irq, void *data
* another interrupt.
*/
- if (!ch->handler)
- do_request(ch);
- else
+ if (!ch->handler) {
+ clear_bit(IDE_BUSY, ch->active);
+ do_ide_request(&drive->queue);
+ } else
printk("%s: %s: huh? expected NULL handler on exit\n",
drive->name, __FUNCTION__);
}
prev parent reply other threads:[~2002-07-26 13:36 UTC|newest]
Thread overview: 73+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-07-24 21:13 Linux-2.5.28 Linus Torvalds
2002-07-24 21:46 ` Linux-2.5.28 Paul Larson
2002-07-24 21:57 ` Linux-2.5.28 Paul Larson
2002-07-24 22:11 ` Linux-2.5.28 Robert Love
2002-07-24 22:14 ` Linux-2.5.28 William Lee Irwin III
2002-07-24 22:20 ` Linux-2.5.28 Paul Larson
2002-07-24 23:31 ` Linux-2.5.28 Alessandro Suardi
2002-07-24 22:22 ` Linux-2.5.28 Robert Love
2002-07-24 22:49 ` Linux-2.5.28 Paul Larson
2002-07-24 22:32 ` Linux-2.5.28 Linus Torvalds
2002-07-24 22:30 ` Linux-2.5.28 Daniel Egger
2002-07-24 22:52 ` Linux-2.5.28 Linus Torvalds
2002-07-24 23:31 ` Linux-2.5.28 Daniel Egger
2002-07-25 1:08 ` Linux-2.5.28 Linus Torvalds
2002-07-25 1:54 ` Linux-2.5.28 Bartlomiej Zolnierkiewicz
2002-07-25 3:34 ` Linux-2.5.28 link problem jeff millar
2002-07-26 5:18 ` Linux-2.5.27-28 "undefined reference to local symbols in discarded section .text.exit" jeff millar
2002-07-27 13:53 ` 2.5.27-28-29 linker error: " jeff millar
2002-07-26 5:24 ` Linux-2.5.28 link problem Adrian Bunk
2002-07-25 9:21 ` Linux-2.5.28 Daniel Egger
2002-07-27 23:57 ` Linux-2.5.28 Andries Brouwer
2002-07-28 2:02 ` Linux-2.5.28 Alan Cox
2002-07-28 2:47 ` Linux-2.5.28 Linus Torvalds
2002-07-28 4:40 ` Linux-2.5.28 Linus Torvalds
2002-07-28 4:47 ` Linux-2.5.28 Larry McVoy
2002-07-28 12:50 ` Linux-2.5.28 Bartlomiej Zolnierkiewicz
2002-07-28 15:11 ` Linux-2.5.28 Andries Brouwer
2002-07-28 2:47 ` Linux-2.5.28 Greg KH
2002-07-28 15:56 ` Linux-2.5.28 Andries Brouwer
2002-07-28 18:53 ` Linux-2.5.28 Greg KH
2002-07-28 21:13 ` Linux-2.5.28 Andries Brouwer
2002-07-29 10:16 ` Linux-2.5.28 Marcin Dalecki
2002-07-29 18:15 ` Linux-2.5.28 Greg KH
[not found] ` <200207282203.g6SM3KI15155@fachschaft.cup.uni-muenchen.de>
2002-07-28 23:34 ` Linux-2.5.28 Andries Brouwer
2002-07-24 23:06 ` Linux-2.5.28 Jonathan Corbet
2002-07-25 5:56 ` Linux-2.5.28 Jens Axboe
2002-07-25 7:36 ` Linux-2.5.28 Marcin Dalecki
2002-07-24 22:43 ` Linux-2.5.28 Russell King
2002-07-24 23:02 ` Linux-2.5.28 Linus Torvalds
2002-07-24 23:55 ` Linux-2.5.28 Skip Ford
2002-07-24 23:15 ` Linux-2.5.28 Dave Jones
2002-07-24 23:19 ` Linux-2.5.28 Linus Torvalds
2002-07-25 10:16 ` Linux-2.5.28 Alexander Hoogerhuis
2002-07-25 0:37 ` i810_audio.c cli/sti fix Greg KH
2002-07-25 1:17 ` Linus Torvalds
2002-07-25 6:01 ` Greg KH
2002-07-25 6:19 ` cli-sti-removal.txt fixup Greg KH
2002-07-25 7:16 ` Thunder from the hill
2002-07-25 9:40 ` Ingo Molnar
2002-07-25 6:14 ` i810_audio.c cli/sti fix Doug Ledford
2002-07-27 9:10 ` Ingo Molnar
2002-07-27 12:35 ` Alan Cox
2002-07-28 6:13 ` Doug Ledford
2002-07-26 6:03 ` [PATCH] 2.5.28 small REQ_SPECIAL abstraction Marcin Dalecki
2002-07-26 14:38 ` Jens Axboe
2002-07-26 15:09 ` Marcin Dalecki
2002-07-28 19:25 ` Jens Axboe
2002-07-28 23:32 ` Linus Torvalds
2002-07-29 5:39 ` Jens Axboe
2002-07-29 5:50 ` Linus Torvalds
2002-07-29 10:24 ` Marcin Dalecki
2002-07-29 10:44 ` Jens Axboe
2002-07-29 11:05 ` Marcin Dalecki
2002-07-26 6:48 ` [PATCH] 2.5.28 IDE 102 Marcin Dalecki
2002-07-26 7:10 ` [PATCH] 2.5.28 IDE 103 Marcin Dalecki
2002-07-26 7:23 ` [PATCH] IDE 104 Marcin Dalecki
2002-07-26 10:13 ` Alan Cox
2002-07-26 9:07 ` Marcin Dalecki
2002-07-26 10:46 ` Alan Cox
2002-07-26 9:56 ` Marcin Dalecki
2002-07-26 7:57 ` Linux-2.5.28 Marcin Dalecki
2002-07-26 8:43 ` [PATCH] IDE 106 Marcin Dalecki
2002-07-26 13:34 ` Marcin Dalecki [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3D414FE7.2070807@evision.ag \
--to=dalecki@evision.ag \
--cc=linux-kernel@vger.kernel.org \
--cc=martin@dalecki.de \
--cc=torvalds@transmeta.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.