Module Name: src Committed By: jdolecek Date: Sat Sep 30 21:32:32 UTC 2017
Modified Files: src/sys/dev/ata [jdolecek-ncq]: ata_wdc.c src/sys/dev/ic [jdolecek-ncq]: mvsata.c src/sys/dev/scsipi [jdolecek-ncq]: atapi_wdc.c Log Message: must drop channel lock before calling ata_dmaerr() to avoid 'locking against myself' in case of consecutive errors from ata_reset_channel() called via ata_downgrade_mode() To generate a diff of this commit: cvs rdiff -u -r1.105.6.11 -r1.105.6.12 src/sys/dev/ata/ata_wdc.c cvs rdiff -u -r1.35.6.31 -r1.35.6.32 src/sys/dev/ic/mvsata.c cvs rdiff -u -r1.123.4.13 -r1.123.4.14 src/sys/dev/scsipi/atapi_wdc.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.105.6.11 src/sys/dev/ata/ata_wdc.c:1.105.6.12 --- src/sys/dev/ata/ata_wdc.c:1.105.6.11 Tue Sep 26 20:15:36 2017 +++ src/sys/dev/ata/ata_wdc.c Sat Sep 30 21:32:31 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ata_wdc.c,v 1.105.6.11 2017/09/26 20:15:36 jdolecek Exp $ */ +/* $NetBSD: ata_wdc.c,v 1.105.6.12 2017/09/30 21:32:31 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.105.6.11 2017/09/26 20:15:36 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.105.6.12 2017/09/30 21:32:31 jdolecek Exp $"); #include "opt_ata.h" #include "opt_wdc.h" @@ -718,14 +718,18 @@ wdc_ata_bio_intr(struct ata_channel *chp } if (drv_err != WDC_ATA_ERR) goto end; - if (ata_bio->r_error & WDCE_CRC || ata_bio->error == ERR_DMA) + if (ata_bio->r_error & WDCE_CRC || ata_bio->error == ERR_DMA) { + ata_channel_unlock(chp); ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); + goto err; + } } #endif /* NATA_DMA */ /* if we had an error, end */ if (drv_err == WDC_ATA_ERR) { ata_channel_unlock(chp); +err: wdc_ata_bio_done(chp, xfer); return 1; } Index: src/sys/dev/ic/mvsata.c diff -u src/sys/dev/ic/mvsata.c:1.35.6.31 src/sys/dev/ic/mvsata.c:1.35.6.32 --- src/sys/dev/ic/mvsata.c:1.35.6.31 Wed Sep 27 07:19:34 2017 +++ src/sys/dev/ic/mvsata.c Sat Sep 30 21:32:31 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: mvsata.c,v 1.35.6.31 2017/09/27 07:19:34 jdolecek Exp $ */ +/* $NetBSD: mvsata.c,v 1.35.6.32 2017/09/30 21:32:31 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.35.6.31 2017/09/27 07:19:34 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.35.6.32 2017/09/30 21:32:31 jdolecek Exp $"); #include "opt_mvsata.h" @@ -1426,14 +1426,18 @@ mvsata_bio_intr(struct ata_channel *chp, if (xfer->c_flags & C_DMA) { if (ata_bio->error == NOERROR) goto end; - if (ata_bio->error == ERR_DMA) + if (ata_bio->error == ERR_DMA) { + ata_channel_unlock(chp); ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); + goto err; + } } /* if we had an error, end */ if (ata_bio->error != NOERROR) { ata_channel_unlock(chp); +err: mvsata_bio_done(chp, xfer); return 1; } @@ -2349,10 +2353,10 @@ mvsata_atapi_intr(struct ata_channel *ch aprint_error_dev(atac->atac_dev, "channel %d: device timeout, c_bcount=%d, c_skip=%d\n", chp->ch_channel, xfer->c_bcount, xfer->c_skip); + ata_channel_unlock(chp); if (xfer->c_flags & C_DMA) ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); - ata_channel_unlock(chp); sc_xfer->error = XS_TIMEOUT; mvsata_atapi_reset(chp, xfer); return 1; @@ -2363,8 +2367,8 @@ mvsata_atapi_intr(struct ata_channel *ch * and reset device. */ if ((xfer->c_flags & C_TIMEOU) && (xfer->c_flags & C_DMA)) { - ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); ata_channel_unlock(chp); + ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); sc_xfer->error = XS_RESET; mvsata_atapi_reset(chp, xfer); return (1); @@ -2425,10 +2429,10 @@ again: aprint_error_dev(atac->atac_dev, "channel %d drive %d: bad data phase DATAOUT\n", chp->ch_channel, xfer->c_drive); + ata_channel_unlock(chp); if (xfer->c_flags & C_DMA) ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); - ata_channel_unlock(chp); sc_xfer->error = XS_TIMEOUT; mvsata_atapi_reset(chp, xfer); return 1; @@ -2461,10 +2465,10 @@ again: aprint_error_dev(atac->atac_dev, "channel %d drive %d: bad data phase DATAIN\n", chp->ch_channel, xfer->c_drive); + ata_channel_unlock(chp); if (xfer->c_flags & C_DMA) ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); - ata_channel_unlock(chp); sc_xfer->error = XS_TIMEOUT; mvsata_atapi_reset(chp, xfer); return 1; @@ -2515,10 +2519,10 @@ again: sc_xfer->error = XS_SHORTSENSE; sc_xfer->sense.atapi_sense = ATACH_ERR(tfd); } else { + ata_channel_unlock(chp); if (xfer->c_flags & C_DMA) ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); - ata_channel_unlock(chp); sc_xfer->error = XS_RESET; mvsata_atapi_reset(chp, xfer); return (1); @@ -2655,9 +2659,9 @@ mvsata_atapi_phase_complete(struct ata_x sc_xfer->status = SCSI_CHECK; } else if (wdc->dma_status & (WDC_DMAST_NOIRQ | WDC_DMAST_ERR)) { + ata_channel_unlock(chp); ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); - ata_channel_unlock(chp); sc_xfer->error = XS_RESET; mvsata_atapi_reset(chp, xfer); return; Index: src/sys/dev/scsipi/atapi_wdc.c diff -u src/sys/dev/scsipi/atapi_wdc.c:1.123.4.13 src/sys/dev/scsipi/atapi_wdc.c:1.123.4.14 --- src/sys/dev/scsipi/atapi_wdc.c:1.123.4.13 Sun Sep 10 19:31:15 2017 +++ src/sys/dev/scsipi/atapi_wdc.c Sat Sep 30 21:32:32 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: atapi_wdc.c,v 1.123.4.13 2017/09/10 19:31:15 jdolecek Exp $ */ +/* $NetBSD: atapi_wdc.c,v 1.123.4.14 2017/09/30 21:32:32 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.123.4.13 2017/09/10 19:31:15 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.123.4.14 2017/09/30 21:32:32 jdolecek Exp $"); #ifndef ATADEBUG #define ATADEBUG @@ -800,13 +800,13 @@ wdc_atapi_intr(struct ata_channel *chp, printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip=%d\n", device_xname(atac->atac_dev), chp->ch_channel, xfer->c_drive, xfer->c_bcount, xfer->c_skip); + ata_channel_unlock(chp); #if NATA_DMA if (xfer->c_flags & C_DMA) { ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); } #endif - ata_channel_unlock(chp); sc_xfer->error = XS_TIMEOUT; wdc_atapi_reset(chp, xfer); return 1; @@ -820,8 +820,8 @@ wdc_atapi_intr(struct ata_channel *chp, * and reset device. */ if ((xfer->c_flags & C_TIMEOU) && (xfer->c_flags & C_DMA)) { - ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); ata_channel_unlock(chp); + ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); sc_xfer->error = XS_RESET; wdc_atapi_reset(chp, xfer); return (1); @@ -895,11 +895,11 @@ again: if ((sc_xfer->xs_control & XS_CTL_DATA_OUT) == 0 || (xfer->c_flags & C_DMA) != 0) { printf("wdc_atapi_intr: bad data phase DATAOUT\n"); + ata_channel_unlock(chp); if (xfer->c_flags & C_DMA) { ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); } - ata_channel_unlock(chp); sc_xfer->error = XS_TIMEOUT; wdc_atapi_reset(chp, xfer); return 1; @@ -945,11 +945,11 @@ again: if ((sc_xfer->xs_control & XS_CTL_DATA_IN) == 0 || (xfer->c_flags & C_DMA) != 0) { printf("wdc_atapi_intr: bad data phase DATAIN\n"); + ata_channel_unlock(chp); if (xfer->c_flags & C_DMA) { ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); } - ata_channel_unlock(chp); sc_xfer->error = XS_TIMEOUT; wdc_atapi_reset(chp, xfer); return 1; @@ -1016,13 +1016,13 @@ again: sc_xfer->error = XS_SHORTSENSE; sc_xfer->sense.atapi_sense = ATACH_ERR(tfd); } else { + ata_channel_unlock(chp); #if NATA_DMA if (xfer->c_flags & C_DMA) { ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); } #endif - ata_channel_unlock(chp); sc_xfer->error = XS_RESET; wdc_atapi_reset(chp, xfer); return (1); @@ -1102,11 +1102,11 @@ wdc_atapi_phase_complete(struct ata_xfer #if NATA_DMA || NATA_PIOBM else if (wdc->dma_status & (WDC_DMAST_NOIRQ | WDC_DMAST_ERR)) { + ata_channel_unlock(chp); #if NATA_DMA ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); #endif - ata_channel_unlock(chp); sc_xfer->error = XS_RESET; wdc_atapi_reset(chp, xfer); return;