Source-Changes-HG archive

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

[src/jdolecek-ncq]: src/sys/dev/ic move mvsata_quetag_get() to the start rout...



details:   https://anonhg.NetBSD.org/src/rev/096a8a838c79
branches:  jdolecek-ncq
changeset: 823032:096a8a838c79
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Mon Sep 25 22:50:20 2017 +0000

description:
move mvsata_quetag_get() to the start routines, so that it always matches
the active list of ata queue; important during error recovery, fixes
panics when calling

in mvsata_edma_handle() ignore events for non-active xfers

fix some missing ata_channel_unlock() on error path in mvsata_bio_intr()
and mvsata_atapi_intr(), fixes 'locking against myself' with LOCKDEBUG

with this, mvsata(4) finally survives full fio run with wdcdebug_wd_cnt == 200

diffstat:

 sys/dev/ic/mvsata.c |  39 ++++++++++++++++++++++++++-------------
 1 files changed, 26 insertions(+), 13 deletions(-)

diffs (154 lines):

diff -r 22c494f64cf5 -r 096a8a838c79 sys/dev/ic/mvsata.c
--- a/sys/dev/ic/mvsata.c       Mon Sep 25 22:43:46 2017 +0000
+++ b/sys/dev/ic/mvsata.c       Mon Sep 25 22:50:20 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mvsata.c,v 1.35.6.28 2017/09/22 20:19:08 jdolecek Exp $        */
+/*     $NetBSD: mvsata.c,v 1.35.6.29 2017/09/25 22:50:20 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.28 2017/09/22 20:19:08 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.35.6.29 2017/09/25 22:50:20 jdolecek Exp $");
 
 #include "opt_mvsata.h"
 
@@ -1086,7 +1086,6 @@
 mvsata_bio(struct ata_drive_datas *drvp, struct ata_xfer *xfer)
 {
        struct ata_channel *chp = drvp->chnl_softc;
-       struct mvsata_port *mvport = (struct mvsata_port *)chp;
        struct atac_softc *atac = chp->ch_atac;
        struct ata_bio *ata_bio = &xfer->c_bio;
 
@@ -1095,8 +1094,6 @@
            ", bcount=%ld\n", device_xname(atac->atac_dev), chp->ch_channel,
            drvp->drive, ata_bio->blkno, ata_bio->bcount));
 
-       mvsata_quetag_get(mvport, xfer->c_slot);
-
        if (atac->atac_cap & ATAC_CAP_NOIRQ)
                ata_bio->flags |= ATA_POLL;
        if (ata_bio->flags & ATA_POLL)
@@ -1135,6 +1132,8 @@
 
        ata_channel_lock_owned(chp);
 
+       mvsata_quetag_get(mvport, xfer->c_slot);
+
        if (xfer->c_flags & C_DMA)
                if (drvp->n_xfers <= NXFER)
                        drvp->n_xfers++;
@@ -1410,8 +1409,10 @@
        if (!(xfer->c_flags & C_DMA) &&
            (wdc_wait_for_unbusy(chp, (irq == 0) ? ATA_DELAY : 0, AT_POLL, &tfd)
                                                        == WDCWAIT_TOUT)) {
-               if (irq && (xfer->c_flags & C_TIMEOU) == 0)
+               if (irq && (xfer->c_flags & C_TIMEOU) == 0) {
+                       ata_channel_unlock(chp);
                        return 0;       /* IRQ was not for us */
+               }
                aprint_error_dev(atac->atac_dev,
                    "channel %d: drive %d timeout, c_bcount=%d, c_skip%d\n",
                    chp->ch_channel, xfer->c_drive, xfer->c_bcount,
@@ -1570,6 +1571,8 @@
 
        flags |= AT_POLL;       /* XXX */
 
+       ata_channel_lock_owned(chp);
+
        /*
         * disable interrupts, all commands here should be quick
         * enough to be able to poll, and we don't go here that often
@@ -1682,8 +1685,6 @@
            drvp->drive, ata_c->bcount, ata_c->r_lba, ata_c->r_count,
            ata_c->r_features, ata_c->r_device, ata_c->r_command));
 
-       mvsata_quetag_get(mvport, xfer->c_slot);
-
        if (ata_c->flags & AT_POLL)
                xfer->c_flags |= C_POLL;
        if (ata_c->flags & AT_WAIT)
@@ -1736,6 +1737,8 @@
 
        ata_channel_lock_owned(chp);
 
+       mvsata_quetag_get(mvport, xfer->c_slot);
+
        /* First, EDMA disable, if enabled this channel. */
        KASSERT((chp->ch_flags & ATACH_NCQ) == 0);
        if (mvport->port_edmamode_curr != nodma)
@@ -2050,7 +2053,6 @@
        struct atac_softc *atac = &sc->sc_wdcdev.sc_atac;
        struct ata_channel *chp = atac->atac_channels[chan->chan_channel];
        struct ata_xfer *xfer;
-       struct mvsata_port *mvport = (struct mvsata_port *)chp;
        int drive, s;
 
         switch (req) {
@@ -2071,8 +2073,6 @@
                        return;
                }
 
-               mvsata_quetag_get(mvport, xfer->c_slot);
-
                if (sc_xfer->xs_control & XS_CTL_POLL)
                        xfer->c_flags |= C_POLL;
                xfer->c_drive = drive;
@@ -2122,6 +2122,8 @@
 
        ata_channel_lock_owned(chp);
 
+       mvsata_quetag_get(mvport, xfer->c_slot);
+
        KASSERT((chp->ch_flags  & ATACH_NCQ) == 0);
        if (mvport->port_edmamode_curr != nodma)
                mvsata_edma_disable(mvport, 10 /* ms */, wait_flags);
@@ -2426,6 +2428,7 @@
                        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;
@@ -2883,8 +2886,15 @@
                        mvsata_print_crpb(mvport, erpqop);
 #endif
                crpb = mvport->port_crpb + erpqop;
+               MVSATA_EDMAQ_INC(erpqop);
+
                quetag = CRPB_CHOSTQUETAG(le16toh(crpb->id));
 
+               if ((mvport->port_quetagidx & __BIT(quetag)) == 0) {
+                       /* not actually executing */
+                       continue;
+               }
+
                xfer = ata_queue_hwslot_to_xfer(chp, quetag);
 
                bus_dmamap_sync(mvport->port_dmat, mvport->port_eprd_dmamap,
@@ -2905,7 +2915,6 @@
                        ata_bio->error = ERR_DMA;
 
                mvsata_dma_bufunload(mvport, quetag, ata_bio->flags);
-               MVSATA_EDMAQ_INC(erpqop);
 
 #if 1  /* XXXX: flags clears here, because necessary the atabus layer. */
                erqqip = (MVSATA_EDMA_READ_4(mvport, EDMA_REQQIP) &
@@ -3322,7 +3331,11 @@
 mvsata_quetag_get(struct mvsata_port *mvport, uint8_t quetag)
 {
        KASSERT(quetag <= 32);
-       KASSERT((mvport->port_quetagidx & __BIT(quetag)) == 0);
+
+       /*
+        * Do not check whether it's already set, can happen when
+        * postponing bio or atapi xfer to thread.
+        */
        mvport->port_quetagidx |= __BIT(quetag);
 }
 



Home | Main Index | Thread Index | Old Index