public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
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__);
 	}

      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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox