[5270] in linux-scsi channel archive

home help back first fref pref prev next nref lref last post

Re: scsi code and jiffy wraps

daemon@ATHENA.MIT.EDU (Andrea Arcangeli)
Thu Dec 3 14:08:48 1998

Date: 	Thu, 3 Dec 1998 13:50:55 +0100 (CET)
From: Andrea Arcangeli <andrea@e-mind.com>
To: Linus Torvalds <torvalds@transmeta.com>
cc: linux-scsi@vger.rutgers.edu, eric@aib.com, linux-kernel@vger.rutgers.edu
In-Reply-To: <Pine.LNX.3.96.981203123214.1479A-100000@dragon.bogus>

On Thu, 3 Dec 1998, Andrea Arcangeli wrote:

>in. It avoids that the scsi system hangs the machine after ~0UL jiffies
>from the latest scsi reset. I tested it in the only way I was able to do.

Woops, please reject/forget the scsi-2.1.130 patch in the last email. I
fixed a little bug + a cleanup and I rediffed against 2.1.131: 

Index: linux/drivers/scsi/scsi.c
diff -u linux/drivers/scsi/scsi.c:1.1.1.1 linux/drivers/scsi/scsi.c:1.1.1.1.2.3
--- linux/drivers/scsi/scsi.c:1.1.1.1	Fri Nov 20 00:02:39 1998
+++ linux/drivers/scsi/scsi.c	Thu Dec  3 12:29:40 1998
@@ -30,6 +30,8 @@
  *  Leonard N. Zubkoff <lnz@dandelion.com>
  *
  *  Converted cli() code to spinlocks, Ingo Molnar
+ *
+ *  Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
  */
 
 #include <linux/config.h>
@@ -1297,7 +1299,7 @@
      */
     timeout = host->last_reset + MIN_RESET_DELAY;
 
-    if (jiffies < timeout) {
+    if (host->resetting && time_before(jiffies, timeout)) {
 	int ticks_remaining = timeout - jiffies;
 	/*
 	 * NOTE: This may be executed from within an interrupt
@@ -1310,7 +1312,7 @@
 	 */
 	spin_unlock_irq(&io_request_lock);
 	while (--ticks_remaining >= 0) mdelay(1+999/HZ);
-	host->last_reset = jiffies - MIN_RESET_DELAY;
+        host->resetting = 0;
 	spin_lock_irq(&io_request_lock);
     }
 
@@ -1367,7 +1369,7 @@
 #ifdef DEBUG_DELAY
 	clock = jiffies + 4 * HZ;
 	spin_unlock_irq(&io_request_lock);
-	while (jiffies < clock) barrier();
+	while (time_before(jiffies, clock)) barrier();
 	spin_lock_irq(&io_request_lock);
 	printk("done(host = %d, result = %04x) : routine at %p\n",
 	       host->host_no, temp, host->hostt->command);
Index: linux/drivers/scsi/hosts.c
diff -u linux/drivers/scsi/hosts.c:1.1.1.1 linux/drivers/scsi/hosts.c:1.1.1.1.2.5
--- linux/drivers/scsi/hosts.c:1.1.1.1	Fri Nov 20 00:02:39 1998
+++ linux/drivers/scsi/hosts.c	Thu Dec  3 12:29:39 1998
@@ -7,6 +7,8 @@
  *      Subsequent revisions: Eric Youngdale
  *
  *  <drew@colorado.edu>
+ *
+ *  Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
  */
 
 
@@ -581,7 +583,8 @@
     next_scsi_host++;
     retval->host_queue = NULL;
     retval->host_wait = NULL;
-    retval->last_reset = 0;
+    retval->resetting = 0;
+    /* retval->last_reset don' t need to be set because resetting is 0 -arca */
     retval->irq = 0;
     retval->dma_channel = 0xff;
 
Index: linux/drivers/scsi/hosts.h
diff -u linux/drivers/scsi/hosts.h:1.1.1.1 linux/drivers/scsi/hosts.h:1.1.1.1.2.2
--- linux/drivers/scsi/hosts.h:1.1.1.1	Fri Nov 20 00:02:39 1998
+++ linux/drivers/scsi/hosts.h	Thu Dec  3 12:29:40 1998
@@ -14,6 +14,8 @@
  *
  *  Further modified by Eric Youngdale to support multiple host adapters
  *  of the same type.
+ *
+ *  Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
  */
 
 #ifndef _HOSTS_H
@@ -320,6 +322,7 @@
 /* public: */
     unsigned short extra_bytes;
     unsigned short host_no;  /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */
+    int resetting; /* if set, it means that last_reset is a valid value */
     unsigned long last_reset;
 
 
Index: linux/drivers/scsi/scsi_error.c
diff -u linux/drivers/scsi/scsi_error.c:1.1.1.1 linux/drivers/scsi/scsi_error.c:1.1.1.1.2.1
--- linux/drivers/scsi/scsi_error.c:1.1.1.1	Fri Nov 20 00:02:54 1998
+++ linux/drivers/scsi/scsi_error.c	Fri Nov 20 00:15:31 1998
@@ -142,7 +142,6 @@
   SCSI_LOG_ERROR_RECOVERY(5,printk("Clearing timer for command %p\n", SCset));
 
   SCset->eh_timeout.data = (unsigned long) NULL;
-  SCset->eh_timeout.expires = 0;
   SCset->eh_timeout.function = NULL;
 
   return rtn;
Index: linux/drivers/scsi/scsi_obsolete.c
diff -u linux/drivers/scsi/scsi_obsolete.c:1.1.1.2 linux/drivers/scsi/scsi_obsolete.c:1.1.1.1.2.5
--- linux/drivers/scsi/scsi_obsolete.c:1.1.1.2	Thu Dec  3 12:53:28 1998
+++ linux/drivers/scsi/scsi_obsolete.c	Thu Dec  3 14:01:03 1998
@@ -604,21 +604,18 @@
 	printk("In MAYREDO, allowing %d retries, have %d\n",
 	       SCpnt->allowed, SCpnt->retries);
 #endif
-	if ((++SCpnt->retries) < SCpnt->allowed)
-	{
-	    if ((SCpnt->retries >= (SCpnt->allowed >> 1))
-		/* FIXME: last_reset == 0 is allowed */
-                && time_after(jiffies, SCpnt->host->last_reset
-                              + MIN_RESET_PERIOD)
-		&& !(SCpnt->flags & WAS_RESET))
-	    {
-		printk("scsi%d channel %d : resetting for second half of retries.\n",
-		       SCpnt->host->host_no, SCpnt->channel);
-		scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS);
-		break;
-	    }
-
-	}
+	if (++SCpnt->retries < SCpnt->allowed &&
+	    SCpnt->retries >= (SCpnt->allowed >> 1)
+            && !(SCpnt->host->resetting &&
+                 time_before(jiffies, SCpnt->host->last_reset
+                             + MIN_RESET_PERIOD))
+            && !(SCpnt->flags & WAS_RESET))
+        {
+	    printk("scsi%d channel %d : resetting for second half of retries.\n",
+                   SCpnt->host->host_no, SCpnt->channel);
+	    scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS);
+	    break;
+        }
 	else
 	{
 	    status = CMD_FINISHED;
@@ -935,6 +932,12 @@
                 }
 
 		host->last_reset = jiffies;
+                host->resetting = 1;
+                /*
+                 * I suppose that the host reset callback will not play
+                 * with the resetting field. We have just set the resetting
+                 * flag here. -arca
+                 */
 		temp = host->hostt->reset(SCpnt, reset_flags);
 		/*
 		  This test allows the driver to introduce an additional bus
@@ -953,7 +956,13 @@
 	    {
 		if (!host->block) host->host_busy++;
 		host->last_reset = jiffies;
+		host->resetting = 1;
 	        SCpnt->flags |= (WAS_RESET | IS_RESETTING);
+                /*
+                 * I suppose that the host reset callback will not play
+                 * with the resetting field. We have just set the resetting
+                 * flag here. -arca
+                 */
 		temp = host->hostt->reset(SCpnt, reset_flags);
 		if (time_before(host->last_reset, jiffies) ||
 		    (time_after(host->last_reset, jiffies + 20 * HZ)))

Andrea Arcangeli


-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.rutgers.edu

home help back first fref pref prev next nref lref last post