Source-Changes-HG archive

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

[src/jdolecek-ncq]: src/sys/dev must drop channel lock before calling ata_dma...



details:   https://anonhg.NetBSD.org/src/rev/4f431b3784ff
branches:  jdolecek-ncq
changeset: 823045:4f431b3784ff
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Sat Sep 30 21:32:31 2017 +0000

description:
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()

diffstat:

 sys/dev/ata/ata_wdc.c      |  10 +++++++---
 sys/dev/ic/mvsata.c        |  22 +++++++++++++---------
 sys/dev/scsipi/atapi_wdc.c |  16 ++++++++--------
 3 files changed, 28 insertions(+), 20 deletions(-)

diffs (242 lines):

diff -r b837719b3f5b -r 4f431b3784ff sys/dev/ata/ata_wdc.c
--- a/sys/dev/ata/ata_wdc.c     Fri Sep 29 20:07:40 2017 +0000
+++ b/sys/dev/ata/ata_wdc.c     Sat Sep 30 21:32:31 2017 +0000
@@ -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 @@
                }
                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;
        }
diff -r b837719b3f5b -r 4f431b3784ff sys/dev/ic/mvsata.c
--- a/sys/dev/ic/mvsata.c       Fri Sep 29 20:07:40 2017 +0000
+++ b/sys/dev/ic/mvsata.c       Sat Sep 30 21:32:31 2017 +0000
@@ -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 @@
        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 @@
                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 @@
         * and reset device.
         */
        if ((xfer->c_flags & C_TIMEOU) && (xfer->c_flags & C_DMA)) {
+               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 (1);
@@ -2425,10 +2429,10 @@
                        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 @@
                        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 @@
                        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 @@
                        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;
diff -r b837719b3f5b -r 4f431b3784ff sys/dev/scsipi/atapi_wdc.c
--- a/sys/dev/scsipi/atapi_wdc.c        Fri Sep 29 20:07:40 2017 +0000
+++ b/sys/dev/scsipi/atapi_wdc.c        Sat Sep 30 21:32:31 2017 +0000
@@ -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 @@
                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 @@
         * and reset device.
         */
        if ((xfer->c_flags & C_TIMEOU) && (xfer->c_flags & C_DMA)) {
+               ata_channel_unlock(chp);
                ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0);
-               ata_channel_unlock(chp);
                sc_xfer->error = XS_RESET;
                wdc_atapi_reset(chp, xfer);
                return (1);
@@ -895,11 +895,11 @@
                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 @@
                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 @@
                        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 @@
 #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;



Home | Main Index | Thread Index | Old Index