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, ¶ms);
error = ata_get_params(&chp->ch_drive[i], AT_POLL, ¶ms);
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