Module Name: src Committed By: jdolecek Date: Tue May 19 08:08:51 UTC 2020
Modified Files: src/sys/dev/ata: ata_wdc.c src/sys/dev/ic: mvsata.c Log Message: only start the timeout machinery once the I/O is completely setup and successful, particularly after PIO write is finished fixes crashes in case the setup is so slow that timeout is triggered e.g. while still waiting in wdc_wait_for_unbusy() or shortly after, without drive actually having chance to complete the I/O, as seen in some configuration under QEMU by Paul Ripke To generate a diff of this commit: cvs rdiff -u -r1.116 -r1.117 src/sys/dev/ata/ata_wdc.c cvs rdiff -u -r1.56 -r1.57 src/sys/dev/ic/mvsata.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/ata/ata_wdc.c diff -u src/sys/dev/ata/ata_wdc.c:1.116 src/sys/dev/ata/ata_wdc.c:1.117 --- src/sys/dev/ata/ata_wdc.c:1.116 Fri May 15 16:58:28 2020 +++ src/sys/dev/ata/ata_wdc.c Tue May 19 08:08:51 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: ata_wdc.c,v 1.116 2020/05/15 16:58:28 jdolecek Exp $ */ +/* $NetBSD: ata_wdc.c,v 1.117 2020/05/19 08:08:51 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001, 2003 Manuel Bouyer. @@ -54,7 +54,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.116 2020/05/15 16:58:28 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.117 2020/05/19 08:08:51 jdolecek Exp $"); #include "opt_ata.h" #include "opt_wdc.h" @@ -478,10 +478,6 @@ _wdc_ata_bio_start(struct ata_channel *c (*wdc->dma_start)(wdc->dma_arg, chp->ch_channel, xfer->c_drive); chp->ch_flags |= ATACH_DMA_WAIT; - /* start timeout machinery */ - if ((xfer->c_flags & C_POLL) == 0) - callout_reset(&chp->c_timo_callout, - ATA_DELAY / 1000 * hz, wdctimeout, chp); /* wait for irq */ goto intr; } /* else not DMA */ @@ -549,10 +545,6 @@ _wdc_ata_bio_start(struct ata_channel *c (drvp->lp->d_type == DKTYPE_ST506) ? drvp->lp->d_precompcyl / 4 : 0); } - /* start timeout machinery */ - if ((xfer->c_flags & C_POLL) == 0) - callout_reset(&chp->c_timo_callout, - ATA_DELAY / 1000 * hz, wdctimeout, chp); } else if (ata_bio->nblks > 1) { /* The number of blocks in the last stretch may be smaller. */ nblks = xfer->c_bcount / drvp->lp->d_secsize; @@ -598,7 +590,10 @@ _wdc_ata_bio_start(struct ata_channel *c intr: #endif /* Wait for IRQ (either real or polled) */ - if ((ata_bio->flags & ATA_POLL) == 0) { + if ((xfer->c_flags & C_POLL) == 0) { + /* start timeout machinery */ + callout_reset(&chp->c_timo_callout, + ATA_DELAY / 1000 * hz, wdctimeout, chp); chp->ch_flags |= ATACH_IRQ_WAIT; return ATASTART_STARTED; } else { Index: src/sys/dev/ic/mvsata.c diff -u src/sys/dev/ic/mvsata.c:1.56 src/sys/dev/ic/mvsata.c:1.57 --- src/sys/dev/ic/mvsata.c:1.56 Mon Apr 13 10:49:34 2020 +++ src/sys/dev/ic/mvsata.c Tue May 19 08:08:51 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: mvsata.c,v 1.56 2020/04/13 10:49:34 jdolecek Exp $ */ +/* $NetBSD: mvsata.c,v 1.57 2020/05/19 08:08:51 jdolecek Exp $ */ /* * Copyright (c) 2008 KIYOHARA Takashi * All rights reserved. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.56 2020/04/13 10:49:34 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.57 2020/05/19 08:08:51 jdolecek Exp $"); #include "opt_mvsata.h" @@ -1108,10 +1108,6 @@ mvsata_bio_start(struct ata_channel *chp return ATASTART_ABORT; } chp->ch_flags |= ATACH_DMA_WAIT; - /* start timeout machinery */ - if ((xfer->c_flags & C_POLL) == 0) - callout_reset(&chp->c_timo_callout, - mstohz(ATA_DELAY), ata_timeout, chp); /* wait for irq */ goto intr; } /* else not DMA */ @@ -1192,11 +1188,6 @@ do_pio: head, sect, nblks, (drvp->lp->d_type == DKTYPE_ST506) ? drvp->lp->d_precompcyl / 4 : 0); - - /* start timeout machinery */ - if ((xfer->c_flags & C_POLL) == 0) - callout_reset(&chp->c_timo_callout, - mstohz(ATA_DELAY), wdctimeout, chp); } else if (ata_bio->nblks > 1) { /* The number of blocks in the last stretch may be smaller. */ nblks = xfer->c_bcount / drvp->lp->d_secsize; @@ -1238,9 +1229,12 @@ intr: xfer->c_flags, mvport->port_edmamode_curr, nodma); /* Wait for IRQ (either real or polled) */ - if ((ata_bio->flags & ATA_POLL) != 0) + if ((ata_bio->flags & ATA_POLL) != 0) { + /* start timeout machinery */ + callout_reset(&chp->c_timo_callout, + mstohz(ATA_DELAY), wdctimeout, chp); return ATASTART_POLL; - else + } else return ATASTART_STARTED; timeout: @@ -2116,11 +2110,6 @@ ready: MVSATA_WDC_WRITE_1(mvport, SRB_CAS, WDCTL_4BIT); delay(10); /* some drives need a little delay here */ } - /* start timeout machinery */ - if ((sc_xfer->xs_control & XS_CTL_POLL) == 0) - callout_reset(&chp->c_timo_callout, mstohz(sc_xfer->timeout), - wdctimeout, chp); - MVSATA_WDC_WRITE_1(mvport, SRB_H, WDSD_IBM); if (wdc_wait_for_unbusy(chp, ATAPI_DELAY, wait_flags, &tfd) != 0) { aprint_error_dev(atac->atac_dev, "not ready, st = %02x\n", @@ -2129,6 +2118,11 @@ ready: return ATASTART_ABORT; } + /* start timeout machinery */ + if ((sc_xfer->xs_control & XS_CTL_POLL) == 0) + callout_reset(&chp->c_timo_callout, mstohz(sc_xfer->timeout), + wdctimeout, chp); + /* * Even with WDCS_ERR, the device should accept a command packet * Limit length to what can be stuffed into the cylinder register