Hi Linus,

This patch fixes some timing issues with ppa.

Tim.
*/

2000-12-13  Tim Waugh  <[EMAIL PROTECTED]>

        * drivers/scsi/ppa.c, drivers/scsi/ppa.h: Timing fixes.  New
        parameter "recon_tmo=".  This is 2.07-for-2.4.x.

--- linux-2.4.0-test12/drivers/scsi/ppa.c.ppa207        Tue Dec 12 13:03:27 2000
+++ linux-2.4.0-test12/drivers/scsi/ppa.c       Thu Dec 14 17:18:53 2000
@@ -31,6 +31,7 @@
     Scsi_Cmnd *cur_cmd;                /* Current queued command       */
     struct tq_struct ppa_tq;   /* Polling interupt stuff       */
     unsigned long jstart;      /* Jiffies at start             */
+    unsigned long recon_tmo;    /* How many usecs to wait for reconnection (6th bit) 
+*/
     unsigned int failed:1;     /* Failure flag                 */
     unsigned int p_busy:1;     /* Parport sharing busy flag    */
 } ppa_struct;
@@ -43,6 +44,7 @@
        cur_cmd:        NULL,           \
        ppa_tq:         { routine: ppa_interrupt },     \
        jstart:         0,              \
+       recon_tmo:      PPA_RECON_TMO,  \
        failed:         0,              \
        p_busy:         0               \
 }
@@ -248,6 +250,12 @@
        ppa_hosts[hostno].mode = x;
        return length;
     }
+    if ((length > 10) && (strncmp(buffer, "recon_tmo=", 10) == 0)) {
+       x = simple_strtoul(buffer + 10, NULL, 0);
+       ppa_hosts[hostno].recon_tmo = x;
+        printk("ppa: recon_tmo set to %ld\n", x);
+       return length;
+    }
     printk("ppa /proc: invalid variable\n");
     return (-EINVAL);
 }
@@ -268,6 +276,9 @@
     len += sprintf(buffer + len, "Version : %s\n", PPA_VERSION);
     len += sprintf(buffer + len, "Parport : %s\n", ppa_hosts[i].dev->port->name);
     len += sprintf(buffer + len, "Mode    : %s\n", 
PPA_MODE_STRING[ppa_hosts[i].mode]);
+#if PPA_DEBUG > 0
+    len += sprintf(buffer + len, "recon_tmo : %lu\n", ppa_hosts[i].recon_tmo);
+#endif
 
     /* Request for beyond end of buffer */
     if (offset > length)
@@ -556,6 +567,7 @@
     k = PPA_SELECT_TMO;
     do {
        k--;
+       udelay(1);
     } while ((r_str(ppb) & 0x40) && (k));
     if (!k)
        return 0;
@@ -569,6 +581,7 @@
     k = PPA_SELECT_TMO;
     do {
        k--;
+       udelay(1);
     }
     while (!(r_str(ppb) & 0x40) && (k));
     if (!k)
@@ -652,6 +665,7 @@
      *  1     Finished data transfer
      */
     int host_no = cmd->host->unique_id;
+    unsigned short ppb = PPA_BASE(host_no);
     unsigned long start_jiffies = jiffies;
 
     unsigned char r, v;
@@ -663,7 +677,11 @@
            (v == WRITE_6) ||
            (v == WRITE_10));
 
-    r = ppa_wait(host_no); /* Need a ppa_wait() - PJC */
+    /*
+     * We only get here if the drive is ready to comunicate,
+     * hence no need for a full ppa_wait.
+     */
+    r = (r_str(ppb) & 0xf0);
 
     while (r != (unsigned char) 0xf0) {
        /*
@@ -673,12 +691,36 @@
        if (time_after(jiffies, start_jiffies + 1))
            return 0;
 
-       if (((r & 0xc0) != 0xc0) || (cmd->SCp.this_residual <= 0)) {
+       if ((cmd->SCp.this_residual <= 0)) {
            ppa_fail(host_no, DID_ERROR);
            return -1;          /* ERROR_RETURN */
        }
-       /* determine if we should use burst I/O */ fast = (bulk && 
(cmd->SCp.this_residual >= PPA_BURST_SIZE))
-           ? PPA_BURST_SIZE : 1;
+
+       /* On some hardware we have SCSI disconnected (6th bit low)
+        * for about 100usecs. It is too expensive to wait a 
+        * tick on every loop so we busy wait for no more than
+        * 500usecs to give the drive a chance first. We do not 
+        * change things for "normal" hardware since generally 
+        * the 6th bit is always high.
+        * This makes the CPU load higher on some hardware 
+        * but otherwise we can not get more then 50K/secs 
+        * on this problem hardware.
+        */
+       if ((r & 0xc0) != 0xc0) {
+          /* Wait for reconnection should be no more than 
+           * jiffy/2 = 5ms = 5000 loops
+           */
+          unsigned long k = ppa_hosts[host_no].recon_tmo; 
+          for (; k && ((r = (r_str(ppb) & 0xf0)) & 0xc0) != 0xc0; k--)
+            udelay(1);
+
+          if(!k) 
+            return 0;
+       }          
+
+       /* determine if we should use burst I/O */ 
+       fast = (bulk && (cmd->SCp.this_residual >= PPA_BURST_SIZE)) 
+            ? PPA_BURST_SIZE : 1;
 
        if (r == (unsigned char) 0xc0)
            status = ppa_out(host_no, cmd->SCp.ptr, fast);
@@ -701,7 +743,7 @@
            }
        }
        /* Now check to see if the drive is ready to comunicate */
-       r = ppa_wait(host_no); /* need ppa_wait() - PJC */
+       r = (r_str(ppb) & 0xf0);
        /* If not, drop back down to the scheduler and wait a timer tick */
        if (!(r & 0x80))
            return 0;
--- linux-2.4.0-test12/drivers/scsi/ppa.h.ppa207        Tue Dec 12 13:03:27 2000
+++ linux-2.4.0-test12/drivers/scsi/ppa.h       Thu Dec 14 17:19:16 2000
@@ -10,7 +10,7 @@
 #ifndef _PPA_H
 #define _PPA_H
 
-#define   PPA_VERSION   "2.06 (for Linux 2.2.x)"
+#define   PPA_VERSION   "2.07 (for Linux 2.4.x)"
 
 /* 
  * this driver has been hacked by Matteo Frigo ([EMAIL PROTECTED])
@@ -56,11 +56,20 @@
  * Add ppa_wait() calls to ppa_completion()
  *  by Peter Cherriman <[EMAIL PROTECTED]> and
  *     Tim Waugh <[EMAIL PROTECTED]>
- *                                                      [2.04]
+ *                                                     [2.04]
+ *
  * Fix kernel panic on scsi timeout, 2000-08-18                [2.05]
  *
  * Avoid io_request_lock problems.
  * John Cavan <[EMAIL PROTECTED]>                     [2.06]
+ *
+ * Busy wait for connected status bit in ppa_completion()
+ *  in order to cope with some hardware that has this bit low
+ *  for short periods of time.
+ * Add udelay() to ppa_select()
+ *  by Peter Cherriman <[EMAIL PROTECTED]> and
+ *     Oleg Makarenko <[EMAIL PROTECTED]>         
+ *                                                      [2.07]
  */
 /* ------ END OF USER CONFIGURABLE PARAMETERS ----- */
 
@@ -116,6 +125,7 @@
 #define PPA_BURST_SIZE 512     /* data burst size */
 #define PPA_SELECT_TMO  5000   /* how long to wait for target ? */
 #define PPA_SPIN_TMO    50000  /* ppa_wait loop limiter */
+#define PPA_RECON_TMO   500    /* scsi reconnection loop limiter */
 #define PPA_DEBUG      0       /* debuging option */
 #define IN_EPP_MODE(x) (x == PPA_EPP_8 || x == PPA_EPP_16 || x == PPA_EPP_32)
 
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/

Reply via email to