Only downgrade modes due to an actual CRC error. Downgrading on other errors

is anti-social -- especially given that there's no way to upgrade again short
of rebooting.

Also, downgrade UDMA modes more slowly.  It's entirely possible that they're
using an 80-wire cable, but it's just too long for the higher modes, or there
is minor crosstalk.
This commit is contained in:
mycroft 2004-06-01 19:32:30 +00:00
parent c7d300d20b
commit a4135d1d48
3 changed files with 11 additions and 37 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ata_wdc.c,v 1.54 2004/05/08 15:03:32 bouyer Exp $ */
/* $NetBSD: ata_wdc.c,v 1.55 2004/06/01 19:32:30 mycroft Exp $ */
/*
* Copyright (c) 1998, 2001, 2003 Manuel Bouyer.
@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.54 2004/05/08 15:03:32 bouyer Exp $");
__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.55 2004/06/01 19:32:30 mycroft Exp $");
#ifndef WDCDEBUG
#define WDCDEBUG
@ -613,11 +613,6 @@ wdc_ata_bio_intr(struct wdc_channel *chp, struct ata_xfer *xfer, int irq)
printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip%d\n",
wdc->sc_dev.dv_xname, chp->ch_channel, xfer->c_drive,
xfer->c_bcount, xfer->c_skip);
/* if we were using DMA, flag a DMA error */
if (xfer->c_flags & C_DMA) {
ata_dmaerr(drvp,
(xfer->c_flags & C_POLL) ? AT_POLL : 0);
}
ata_bio->error = TIMEOUT;
wdc_ata_bio_done(chp, xfer);
return 1;
@ -661,9 +656,10 @@ wdc_ata_bio_intr(struct wdc_channel *chp, struct ata_xfer *xfer, int irq)
drv_err = WDC_ATA_ERR;
}
}
if (ata_bio->r_error & WDCE_CRC)
ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0);
if (drv_err != WDC_ATA_ERR)
goto end;
ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0);
}
/* if we had an error, end */
@ -805,14 +801,6 @@ wdc_ata_err(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)
if (chp->ch_status & WDCS_ERR) {
ata_bio->error = ERROR;
ata_bio->r_error = chp->ch_error;
if (drvp->drive_flags & DRIVE_UDMA &&
(ata_bio->r_error & WDCE_CRC)) {
/*
* Record the CRC error, to avoid downgrading to
* multiword DMA
*/
drvp->drive_flags |= DRIVE_DMAERR;
}
if (ata_bio->r_error & (WDCE_BBK | WDCE_UNC | WDCE_IDNF |
WDCE_ABRT | WDCE_TK0NF | WDCE_AMNF))
return WDC_ATA_ERR;

View File

@ -1,4 +1,4 @@
/* $NetBSD: atavar.h,v 1.42 2004/05/27 02:23:12 thorpej Exp $ */
/* $NetBSD: atavar.h,v 1.43 2004/06/01 19:32:30 mycroft Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer.
@ -111,7 +111,6 @@ struct ata_drive_datas {
#define DRIVE_UDMA 0x0020
#define DRIVE_MODE 0x0040 /* the drive reported its mode */
#define DRIVE_RESET 0x0080 /* reset the drive state at next xfer */
#define DRIVE_DMAERR 0x0100 /* Udma transfer had crc error, don't try DMA */
#define DRIVE_ATAPIST 0x0200 /* device is an ATAPI tape drive */
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: wdc.c,v 1.179 2004/05/27 16:47:35 mycroft Exp $ */
/* $NetBSD: wdc.c,v 1.180 2004/06/01 19:32:30 mycroft Exp $ */
/*
* Copyright (c) 1998, 2001, 2003 Manuel Bouyer. All rights reserved.
@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.179 2004/05/27 16:47:35 mycroft Exp $");
__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.180 2004/06/01 19:32:30 mycroft Exp $");
#ifndef WDCDEBUG
#define WDCDEBUG
@ -1541,31 +1541,18 @@ wdc_downgrade_mode(struct ata_drive_datas *drvp, int flags)
return 0;
/*
* 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 we were using Ultra-DMA mode, downgrade to the next lower mode.
*/
if ((drvp->drive_flags & DRIVE_UDMA) && drvp->UDMA_mode >= 2) {
drvp->UDMA_mode = (drvp->UDMA_mode == 2) ? 1 : 2;
drvp->UDMA_mode--;
printf("%s: transfer error, downgrading to Ultra-DMA mode %d\n",
drv_dev->dv_xname, drvp->UDMA_mode);
}
/*
* If we were using ultra-DMA, don't downgrade to multiword DMA
* if we noticed a CRC error. It has been noticed that CRC errors
* in ultra-DMA lead to silent data corruption in multiword DMA.
* Data corruption is less likely to occur in PIO mode.
* If we were using ultra-DMA, don't downgrade to multiword DMA.
*/
else if ((drvp->drive_flags & DRIVE_UDMA) &&
(drvp->drive_flags & DRIVE_DMAERR) == 0) {
drvp->drive_flags &= ~DRIVE_UDMA;
drvp->drive_flags |= DRIVE_DMA;
drvp->DMA_mode = drvp->DMA_cap;
printf("%s: transfer error, downgrading to DMA mode %d\n",
drv_dev->dv_xname, drvp->DMA_mode);
} else if (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) {
else if (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) {
drvp->drive_flags &= ~(DRIVE_DMA | DRIVE_UDMA);
drvp->PIO_mode = drvp->PIO_cap;
printf("%s: transfer error, downgrading to PIO mode %d\n",