patch-2.3.26 linux/drivers/block/ide.c

Next file: linux/drivers/block/loop.c
Previous file: linux/drivers/block/ide-tape.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.25/linux/drivers/block/ide.c linux/drivers/block/ide.c
@@ -498,25 +498,14 @@
 }
 
 /*
- * The below two are helpers used when modifying the drive timeout.
- */
-static inline unsigned long set_timeout(ide_drive_t *drive, unsigned long timeout)
-{
-	unsigned long foo = drive->timeout;
-	drive->timeout = timeout;
-	return foo;
-}
-
-#define restore_timeout(drive, old)	(drive->timeout = old)
-
-/*
  * This should get invoked any time we exit the driver to
  * wait for an interrupt response from a drive.  handler() points
  * at the appropriate code to handle the next interrupt, and a
  * timer is started to prevent us from waiting forever in case
  * something goes wrong (see the ide_timer_expiry() handler later on).
  */
-void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler)
+void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
+		      unsigned int timeout, ide_expiry_t *expiry)
 {
 	unsigned long flags;
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
@@ -528,12 +517,10 @@
 			drive->name, hwgroup->handler, handler);
 	}
 #endif
-	hwgroup->handler       = handler;
-	/* 0 means don't timeout */
-	if (drive->timeout && !timer_pending(&hwgroup->timer)) {
-		hwgroup->timer.expires = jiffies + drive->timeout;
-		add_timer(&(hwgroup->timer));
-	}
+	hwgroup->handler	= handler;
+	hwgroup->expiry		= expiry;
+	hwgroup->timer.expires	= jiffies + timeout;
+	add_timer(&(hwgroup->timer));
 	spin_unlock_irqrestore(&hwgroup->spinlock, flags);
 }
 
@@ -580,7 +567,6 @@
 static void atapi_reset_pollfunc (ide_drive_t *drive)
 {
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
-	unsigned long old_timeout;
 	byte stat;
 
 	SELECT_DRIVE(HWIF(drive),drive);
@@ -590,9 +576,7 @@
 		printk("%s: ATAPI reset complete\n", drive->name);
 	} else {
 		if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) {
-			old_timeout = set_timeout(drive, HZ / 20);
-			ide_set_handler (drive, &atapi_reset_pollfunc);
-			restore_timeout(drive, old_timeout);
+			ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL);
 			return;	/* continue polling */
 		}
 		hwgroup->poll_timeout = 0;	/* end of polling */
@@ -613,14 +597,11 @@
 {
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
 	ide_hwif_t *hwif = HWIF(drive);
-	unsigned long old_timeout;
 	byte tmp;
 
 	if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) {
 		if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) {
-			old_timeout = set_timeout(drive, HZ / 20);
-			ide_set_handler (drive, &reset_pollfunc);
-			restore_timeout(drive, old_timeout);
+			ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL);
 			return;	/* continue polling */
 		}
 		printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp);
@@ -688,7 +669,6 @@
 	unsigned long flags;
 	ide_hwif_t *hwif = HWIF(drive);
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
-	unsigned long old_timeout;
 
 	__save_flags(flags);	/* local CPU only */
 	__cli();		/* local CPU only */
@@ -700,9 +680,7 @@
 		udelay (20);
 		OUT_BYTE (WIN_SRST, IDE_COMMAND_REG);
 		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
-		old_timeout = set_timeout(drive, HZ / 20);
-		ide_set_handler (drive, &atapi_reset_pollfunc);
-		restore_timeout(drive, old_timeout);
+		ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL);
 		__restore_flags (flags);	/* local CPU only */
 		return;
 	}
@@ -732,9 +710,7 @@
 	OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG);	/* clear SRST, leave nIEN */
 	udelay(10);			/* more than enough time */
 	hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
-	old_timeout = set_timeout(drive, HZ / 20);
-	ide_set_handler (drive, &reset_pollfunc);
-	restore_timeout(drive, old_timeout);
+	ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL);
 
 	/*
 	 * Some weird controller like resetting themselves to a strange
@@ -934,7 +910,7 @@
  */
 void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
 {
-	ide_set_handler (drive, handler);
+	ide_set_handler (drive, handler, WAIT_CMD, NULL);
 	if (IDE_CONTROL_REG)
 		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);	/* clear nIEN */
 	OUT_BYTE(nsect,IDE_NSECTOR_REG);
@@ -1425,7 +1401,9 @@
 	ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data;
 	ide_drive_t   *drive;
 	ide_handler_t *handler;
+	ide_expiry_t  *expiry;
 	unsigned long flags;
+	unsigned long wait;
 
 	spin_lock_irqsave(&hwgroup->spinlock, flags);
 	drive = hwgroup->drive;
@@ -1434,9 +1412,22 @@
 		do_hwgroup_request(hwgroup);
 		return;
 	}
+
 	hwgroup->busy = 1;	/* should already be "1" */
+
+	if ((expiry = hwgroup->expiry) != NULL) {
+		/* continue */
+		if ((wait = expiry(drive)) != 0) {
+			/* reset timer */
+			hwgroup->timer.expires	= jiffies + wait;
+			add_timer(&(hwgroup->timer));
+			spin_unlock_irqrestore(&hwgroup->spinlock, flags);
+			return;
+		}
+	}
+
 	hwgroup->handler = NULL;
-	/* polling in progress or just don't timeout */
+
 	if (hwgroup->poll_timeout != 0) {
 		spin_unlock_irqrestore(&hwgroup->spinlock, flags);
 		handler(drive);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)