Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev Improve the downgrade logic:



details:   https://anonhg.NetBSD.org/src/rev/14ec4c64ffdd
branches:  trunk
changeset: 480621:14ec4c64ffdd
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Mon Jan 17 00:01:00 2000 +0000

description:
Improve the downgrade logic:
- If UDMA 2 is failing try UDMA 1 first, it helps in some cases
- downgrade if we get an error in the first 4000 xfers, or if we get
  4 errors in 4000 xfers if the first 4000 went without troubles.

While I'm there commit a local change I have since some time to get my CD
probed: issue a "blanck" IDENTIFY before the one used to detect slave ghosts,
with my drive the first IDENTIFY following a controller reset fails with an
aborted command ...

diffstat:

 sys/dev/ata/ata.c          |  26 +++++++++++++++++++++++++-
 sys/dev/ata/ata_wdc.c      |  14 +++++---------
 sys/dev/ata/atavar.h       |  11 +++++++----
 sys/dev/ic/wdc.c           |  18 +++++++++++++-----
 sys/dev/scsipi/atapi_wdc.c |  32 +++++++++++++++-----------------
 5 files changed, 65 insertions(+), 36 deletions(-)

diffs (291 lines):

diff -r dd785f767847 -r 14ec4c64ffdd sys/dev/ata/ata.c
--- a/sys/dev/ata/ata.c Sun Jan 16 23:30:13 2000 +0000
+++ b/sys/dev/ata/ata.c Mon Jan 17 00:01:00 2000 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: ata.c,v 1.10 1999/11/26 12:39:43 bouyer Exp $      */
+/*      $NetBSD: ata.c,v 1.11 2000/01/17 00:01:00 bouyer Exp $      */
 /*
  * Copyright (c) 1998 Manuel Bouyer.  All rights reserved.
  *
@@ -163,6 +163,30 @@
 }
 
 void
+ata_dmaerr(drvp)
+       struct ata_drive_datas *drvp;
+{
+       /*
+        * Downgrade decision: if we get NERRS_MAX in NXFER.
+        * We start with n_dmaerrs set to NERRS_MAX-1 so that the
+        * first error within the first NXFER ops will immediatly trigger
+        * a downgrade.
+        * If we got an error and n_xfers is bigger than NXFER reset counters.
+        */
+       drvp->n_dmaerrs++;
+       if (drvp->n_dmaerrs >= NERRS_MAX && drvp->n_xfers <= NXFER) {
+               wdc_downgrade_mode(drvp);
+               drvp->n_dmaerrs = NERRS_MAX-1;
+               drvp->n_xfers = 0;
+               return;
+       }
+       if (drvp->n_xfers > NXFER) {
+               drvp->n_dmaerrs = 1; /* just got an error */
+               drvp->n_xfers = 1; /* restart counting from this error */
+       }
+}
+
+void
 ata_perror(drvp, errno, buf)
        struct ata_drive_datas *drvp;
        int errno;
diff -r dd785f767847 -r 14ec4c64ffdd sys/dev/ata/ata_wdc.c
--- a/sys/dev/ata/ata_wdc.c     Sun Jan 16 23:30:13 2000 +0000
+++ b/sys/dev/ata/ata_wdc.c     Mon Jan 17 00:01:00 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ata_wdc.c,v 1.22 1999/10/20 15:22:24 enami Exp $       */
+/*     $NetBSD: ata_wdc.c,v 1.23 2000/01/17 00:01:00 bouyer Exp $      */
 
 /*
  * Copyright (c) 1998 Manuel Bouyer.
@@ -222,6 +222,8 @@
        }
 
        if (xfer->c_flags & C_DMA) {
+               if (drvp->n_xfers <= NXFER)
+                       drvp->n_xfers++;
                dma_flags = (ata_bio->flags & ATA_READ) ?  WDC_DMA_READ : 0;
                dma_flags |= (ata_bio->flags & ATA_POLL) ?  WDC_DMA_POLL : 0;
        }
@@ -453,7 +455,7 @@
                if (xfer->c_flags & C_DMA) {
                        (*chp->wdc->dma_finish)(chp->wdc->dma_arg,
                            chp->channel, xfer->drive, dma_flags);
-                       drvp->n_dmaerrs++;
+                       ata_dmaerr(drvp);
                }
                ata_bio->error = TIMEOUT;
                wdc_ata_bio_done(chp, xfer);
@@ -498,7 +500,7 @@
                }
                if (drv_err != WDC_ATA_ERR)
                        goto end;
-               drvp->n_dmaerrs++;
+               ata_dmaerr(drvp);
        }
 
        /* if we had an error, end */
@@ -606,7 +608,6 @@
 {
        struct ata_bio *ata_bio = xfer->cmd;
        int drive = xfer->drive;
-       struct ata_drive_datas *drvp = &chp->ch_drive[drive];
 
        WDCDEBUG_PRINT(("wdc_ata_bio_done %s:%d:%d: flags 0x%x\n",
            chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive, 
@@ -614,11 +615,6 @@
            DEBUG_XFERS);
 
        untimeout(wdctimeout, chp);
-       if (ata_bio->error == NOERROR)
-               drvp->n_dmaerrs = 0;
-       else if (drvp->n_dmaerrs >= NERRS_MAX) {
-               wdc_downgrade_mode(drvp);
-       }
 
        /* feed back residual bcount to our caller */
        ata_bio->bcount = xfer->c_bcount;
diff -r dd785f767847 -r 14ec4c64ffdd sys/dev/ata/atavar.h
--- a/sys/dev/ata/atavar.h      Sun Jan 16 23:30:13 2000 +0000
+++ b/sys/dev/ata/atavar.h      Mon Jan 17 00:01:00 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: atavar.h,v 1.14 1999/10/20 15:22:25 enami Exp $        */
+/*     $NetBSD: atavar.h,v 1.15 2000/01/17 00:01:00 bouyer Exp $       */
 
 /*
  * Copyright (c) 1998 Manuel Bouyer.
@@ -68,10 +68,12 @@
      */
     u_int8_t state;
 
-    /* Number of DMA errors. Reset to 0 after every successful transfers. */
+    /* numbers of xfers and DMA errs. Used by ata_dmaerr() */
     u_int8_t n_dmaerrs;
-    /* downgrade mode after this many successive errors */
-#define NERRS_MAX 2
+    u_int32_t n_xfers;
+    /* Downgrade after NERRS_MAX errors in at most NXFER xfers */
+#define NERRS_MAX 4
+#define NXFER 4000
 
     struct device *drv_softc; /* ATA drives softc, if any */
     void* chnl_softc; /* channel softc */
@@ -164,4 +166,5 @@
 #define CMD_ERR   1
 #define CMD_AGAIN 2
 
+void ata_dmaerr __P((struct ata_drive_datas *));
 void ata_perror __P((struct ata_drive_datas *, int, char *));
diff -r dd785f767847 -r 14ec4c64ffdd sys/dev/ic/wdc.c
--- a/sys/dev/ic/wdc.c  Sun Jan 16 23:30:13 2000 +0000
+++ b/sys/dev/ic/wdc.c  Mon Jan 17 00:01:00 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wdc.c,v 1.77 1999/11/28 20:04:22 bouyer Exp $ */
+/*     $NetBSD: wdc.c,v 1.78 2000/01/17 00:01:01 bouyer Exp $ */
 
 
 /*
@@ -303,6 +303,12 @@
        for (i = 0; i < 2; i++) {
                chp->ch_drive[i].chnl_softc = chp;
                chp->ch_drive[i].drive = i;
+               /*
+                * Init error counter so that an error withing the first xfers
+                * will trigger a downgrade
+                */
+               chp->ch_drive[i].n_dmaerrs = NERRS_MAX-1;
+
                /* If controller can't do 16bit flag the drives as 32bit */
                if ((chp->wdc->cap &
                    (WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32)) ==
@@ -312,6 +318,7 @@
                        continue;
 
                /* Issue a IDENTIFY command, to try to detect slave ghost */
+               ata_get_params(&chp->ch_drive[i], AT_POLL, &params);
                error = ata_get_params(&chp->ch_drive[i], AT_POLL, &params);
                if (error == CMD_OK) {
                        /* If IDENTIFY succeded, this is not an OLD ctrl */
@@ -1116,10 +1123,12 @@
        /*
         * If we were using Ultra-DMA mode > 2, downgrade to mode 2 first.
         * Maybe we didn't properly notice the cable type
+        * If we were using Ultra-DMA mode 2, downgrade to mode 1 first.
+        * It helps in some cases.
         */
-       if ((drvp->drive_flags & DRIVE_UDMA) && drvp->UDMA_mode > 2) {
-               drvp->UDMA_mode = 2;
-               printf("%s: transfer error, downgrading to DMA mode %d\n",
+       if ((drvp->drive_flags & DRIVE_UDMA) && drvp->UDMA_mode >= 2) {
+               drvp->UDMA_mode = (drvp->UDMA_mode == 2) ? 1 : 2;
+               printf("%s: transfer error, downgrading to Ultra-DMA mode %d\n",
                    drv_dev->dv_xname, drvp->UDMA_mode);
        }
 
@@ -1129,7 +1138,6 @@
         * in ultra-DMA lead to silent data corruption in multiword DMA.
         * Data corruption is less likely to occur in PIO mode.
         */
-
        else if ((drvp->drive_flags & DRIVE_UDMA) &&
            (drvp->drive_flags & DRIVE_DMAERR) == 0) {
                drvp->drive_flags &= ~DRIVE_UDMA;
diff -r dd785f767847 -r 14ec4c64ffdd sys/dev/scsipi/atapi_wdc.c
--- a/sys/dev/scsipi/atapi_wdc.c        Sun Jan 16 23:30:13 2000 +0000
+++ b/sys/dev/scsipi/atapi_wdc.c        Mon Jan 17 00:01:00 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: atapi_wdc.c,v 1.29 1999/11/04 21:16:53 bouyer Exp $    */
+/*     $NetBSD: atapi_wdc.c,v 1.30 2000/01/17 00:01:01 bouyer Exp $    */
 
 /*
  * Copyright (c) 1998 Manuel Bouyer.
@@ -270,10 +270,13 @@
            sc_xfer->xs_control), DEBUG_XFERS);
        /* Adjust C_DMA, it may have changed if we are requesting sense */
        if ((drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) &&
-           (sc_xfer->datalen > 0 || (xfer->c_flags & C_SENSE)))
+           (sc_xfer->datalen > 0 || (xfer->c_flags & C_SENSE))) {
+               if (drvp->n_xfers <= NXFER)
+                       drvp->n_xfers++;
                xfer->c_flags |= C_DMA;
-       else
+       } else {
                xfer->c_flags &= ~C_DMA;
+       }
        /* start timeout machinery */
        if ((sc_xfer->xs_control & XS_CTL_POLL) == 0)
                timeout(wdctimeout, chp, sc_xfer->timeout * hz / 1000);
@@ -381,14 +384,14 @@
                    chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
                    xfer->c_bcount, xfer->c_skip);
                if (xfer->c_flags & C_DMA)
-                       drvp->n_dmaerrs++;
+                       ata_dmaerr(drvp);
                sc_xfer->error = XS_TIMEOUT;
                wdc_atapi_reset(chp, xfer);
                return 1;
        }
        /* If we missed an IRQ and were using DMA, flag it as a DMA error */
        if ((xfer->c_flags & C_TIMEOU) && (xfer->c_flags & C_DMA))
-               drvp->n_dmaerrs++;
+               ata_dmaerr(drvp);
        /* 
         * if the request sense command was aborted, report the short sense
         * previously recorded, else continue normal processing
@@ -486,7 +489,7 @@
                        if (xfer->c_flags & C_DMA) {
                                (*chp->wdc->dma_finish)(chp->wdc->dma_arg,
                                    chp->channel, xfer->drive, dma_flags);
-                               drvp->n_dmaerrs++;
+                               ata_dmaerr(drvp);
                        }
                        sc_xfer->error = XS_TIMEOUT;
                        wdc_atapi_reset(chp, xfer);
@@ -564,7 +567,7 @@
                        if (xfer->c_flags & C_DMA) {
                                (*chp->wdc->dma_finish)(chp->wdc->dma_arg,
                                    chp->channel, xfer->drive, dma_flags);
-                               drvp->n_dmaerrs++;
+                               ata_dmaerr(drvp);
                        }
                        sc_xfer->error = XS_TIMEOUT;
                        wdc_atapi_reset(chp, xfer);
@@ -649,8 +652,8 @@
                                 * request sense failed ! it's not suppossed
                                 * to be possible
                                 */
-                               if (dma_err < 0)
-                                       drvp->n_dmaerrs++;
+                               if (xfer->c_flags & C_DMA)
+                                       ata_dmaerr(drvp);
                                sc_xfer->error = XS_RESET;
                                wdc_atapi_reset(chp, xfer);
                                return (1);
@@ -687,7 +690,7 @@
                                        return 1;
                                }
                        } else if (dma_err < 0) {
-                               drvp->n_dmaerrs++;
+                               ata_dmaerr(drvp);
                                sc_xfer->error = XS_RESET;
                                wdc_atapi_reset(chp, xfer);
                                return (1);
@@ -719,6 +722,8 @@
                        sc_xfer->error = XS_SHORTSENSE;
                        sc_xfer->sense.atapi_sense = chp->ch_error;
                } else {
+                       if (xfer->c_flags & C_DMA)
+                               ata_dmaerr(drvp);
                        sc_xfer->error = XS_RESET;
                        wdc_atapi_reset(chp, xfer);
                        return (1);
@@ -838,7 +843,6 @@
        struct wdc_xfer *xfer;
 {
        struct scsipi_xfer *sc_xfer = xfer->cmd;
-       struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
 
        WDCDEBUG_PRINT(("wdc_atapi_done %s:%d:%d: flags 0x%x\n",
            chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
@@ -847,12 +851,6 @@
        /* remove this command from xfer queue */
        wdc_free_xfer(chp, xfer);
        sc_xfer->xs_status |= XS_STS_DONE;
-       if (drvp->n_dmaerrs ||
-         (sc_xfer->error != XS_NOERROR && sc_xfer->error != XS_SENSE &&
-         sc_xfer->error != XS_SHORTSENSE)) {
-               drvp->n_dmaerrs = 0;
-               wdc_downgrade_mode(drvp);
-       }
            
        WDCDEBUG_PRINT(("wdc_atapi_done: scsipi_done\n"), DEBUG_XFERS);
        scsipi_done(sc_xfer);



Home | Main Index | Thread Index | Old Index