Source-Changes-HG archive

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

[src/jdolecek-ncqfixes]: src/sys/dev change the SATA/NCQ recovery to run in t...



details:   https://anonhg.NetBSD.org/src/rev/eab9edd86f17
branches:  jdolecek-ncqfixes
changeset: 445166:eab9edd86f17
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Mon Oct 15 21:18:53 2018 +0000

description:
change the SATA/NCQ recovery to run in the atabus thread

diffstat:

 sys/dev/ata/TODO.ncq       |   3 -
 sys/dev/ata/ata.c          |  73 +++++++++++++++++++++++++++++++++------------
 sys/dev/ata/ata_recovery.c |  23 ++++++++------
 sys/dev/ata/ata_wdc.c      |   5 +-
 sys/dev/ata/atavar.h       |  17 ++++++----
 sys/dev/ic/ahcisata_core.c |  41 +++++++++++--------------
 sys/dev/ic/mvsata.c        |  39 +++++++++++------------
 sys/dev/ic/siisata.c       |  32 ++++++++-----------
 sys/dev/usb/umass_isdata.c |   5 +-
 9 files changed, 132 insertions(+), 106 deletions(-)

diffs (truncated from 675 to 300 lines):

diff -r a793e28b1da3 -r eab9edd86f17 sys/dev/ata/TODO.ncq
--- a/sys/dev/ata/TODO.ncq      Sun Oct 14 16:13:51 2018 +0000
+++ b/sys/dev/ata/TODO.ncq      Mon Oct 15 21:18:53 2018 +0000
@@ -1,9 +1,6 @@
 jdolecek-ncqfixes goals:
 - re-check READ LOG EXT handling under native and Parallels to make sure
   the NOERROR under Parallels is their bug and not ours
-- run recovery via atathread, move to new function and share ahci/siisata/mvsata
-- maybe do device error handling in not-interrupt-context (maybe this should be
-  done on a mpata branch?)
 
 Bugs
 ----
diff -r a793e28b1da3 -r eab9edd86f17 sys/dev/ata/ata.c
--- a/sys/dev/ata/ata.c Sun Oct 14 16:13:51 2018 +0000
+++ b/sys/dev/ata/ata.c Mon Oct 15 21:18:53 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ata.c,v 1.141.6.17 2018/10/14 16:13:51 jdolecek Exp $  */
+/*     $NetBSD: ata.c,v 1.141.6.18 2018/10/15 21:18:53 jdolecek Exp $  */
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.141.6.17 2018/10/14 16:13:51 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.141.6.18 2018/10/15 21:18:53 jdolecek Exp $");
 
 #include "opt_ata.h"
 
@@ -129,7 +129,6 @@
 static void atabusconfig_thread(void *);
 
 static void ata_channel_idle(struct ata_channel *);
-static void ata_channel_thaw_locked(struct ata_channel *);
 static void ata_activate_xfer_locked(struct ata_channel *, struct ata_xfer *);
 static void ata_channel_freeze_locked(struct ata_channel *);
 static void ata_thread_wake_locked(struct ata_channel *);
@@ -463,7 +462,7 @@
        ata_channel_lock(chp);
        for (;;) {
                if ((chp->ch_flags & (ATACH_TH_RESET | ATACH_TH_DRIVE_RESET
-                   | ATACH_SHUTDOWN)) == 0 &&
+                   | ATACH_TH_RECOVERY | ATACH_SHUTDOWN)) == 0 &&
                    (chq->queue_active == 0 || chq->queue_freeze == 0)) {
                        chp->ch_flags &= ~ATACH_TH_RUN;
                        cv_wait(&chp->ch_thr_idle, &chp->ch_lock);
@@ -483,6 +482,7 @@
                        ata_thread_run(chp, AT_WAIT,
                            ATACH_TH_RESET, ATACH_NODRIVE);
                } else if (chp->ch_flags & ATACH_TH_DRIVE_RESET) {
+                       /* this will unfreeze the channel */
                        for (i = 0; i < chp->ch_ndrives; i++) {
                                struct ata_drive_datas *drvp;
 
@@ -494,6 +494,16 @@
                                }
                        }
                        chp->ch_flags &= ~ATACH_TH_DRIVE_RESET;
+               } else if (chp->ch_flags & ATACH_TH_RECOVERY) {
+                       /*
+                        * This will unfreeze the channel; drops locks during
+                        * run, so must wrap in splbio()/splx() to avoid
+                        * spurious interrupts. XXX MPSAFE
+                        */
+                       int s = splbio();
+                       ata_thread_run(chp, AT_WAIT, ATACH_TH_RECOVERY,
+                           chp->recovery_tfd);
+                       splx(s);
                } else if (chq->queue_active > 0 && chq->queue_freeze == 1) {
                        /*
                         * Caller has bumped queue_freeze, decrease it. This
@@ -522,10 +532,12 @@
                } else if (chq->queue_freeze > 1)
                        panic("%s: queue_freeze", __func__);
 
-               /* Try to run down the queue once after each event is handled */
-               ata_channel_unlock(chp);
-               atastart(chp);
-               ata_channel_lock(chp);
+               /* Try to run down the queue once channel is unfrozen */
+               if (chq->queue_freeze == 0) {
+                       ata_channel_unlock(chp);
+                       atastart(chp);
+                       ata_channel_lock(chp);
+               }
        }
        chp->ch_thread = NULL;
        cv_signal(&chp->ch_thr_idle);
@@ -1499,7 +1511,7 @@
        ata_channel_unlock(chp);
 }
 
-static void
+void
 ata_channel_thaw_locked(struct ata_channel *chp)
 {
        KASSERT(mutex_owned(&chp->ch_lock));
@@ -1511,21 +1523,13 @@
            chp->ch_queue->queue_freeze), DEBUG_FUNCS | DEBUG_XFERS);
 }
 
-void
-ata_channel_thaw(struct ata_channel *chp)
-{
-       ata_channel_lock(chp);
-       ata_channel_thaw_locked(chp);
-       ata_channel_unlock(chp);
-}
-
 /*
  * ata_thread_run:
  *
- *     Reset and ATA channel. Channel lock must be held.
+ *     Reset and ATA channel. Channel lock must be held. arg is type-specific.
  */
 void
-ata_thread_run(struct ata_channel *chp, int flags, int type, int drive)
+ata_thread_run(struct ata_channel *chp, int flags, int type, int arg)
 {
        struct atac_softc *atac = chp->ch_atac;
        bool threset = false;
@@ -1548,6 +1552,9 @@
                        }
                        break;
                case ATACH_TH_DRIVE_RESET:
+                   {
+                       int drive = arg;
+
                        KASSERT(drive <= chp->ch_ndrives);
                        drvp = &chp->ch_drive[drive];
 
@@ -1557,6 +1564,15 @@
                        }
                        drvp->drive_flags |= ATA_DRIVE_TH_RESET;
                        break;
+                   }
+               case ATACH_TH_RECOVERY:
+                   {
+                       uint32_t tfd = (uint32_t)arg;
+
+                       KASSERT((chp->ch_flags & ATACH_RECOVERING) == 0);
+                       chp->recovery_tfd = tfd;
+                       break;
+                   }
                default:
                        panic("%s: unknown type: %x", __func__, type);
                        /* NOTREACHED */
@@ -1591,16 +1607,33 @@
                (*atac->atac_bustype_ata->ata_reset_channel)(chp, flags);
 
                KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL);
-               for (drive = 0; drive < chp->ch_ndrives; drive++)
+               for (int drive = 0; drive < chp->ch_ndrives; drive++)
                        chp->ch_drive[drive].state = 0;
                break;
 
        case ATACH_TH_DRIVE_RESET:
+           {
+               int drive = arg;
+
                KASSERT(drive <= chp->ch_ndrives);
                drvp = &chp->ch_drive[drive];
                (*atac->atac_bustype_ata->ata_reset_drive)(drvp, flags, NULL);
                drvp->state = 0;
                break;
+           }
+
+       case ATACH_TH_RECOVERY:
+           {
+               uint32_t tfd = (uint32_t)arg;
+
+               KASSERT((chp->ch_flags & ATACH_RECOVERING) == 0);
+               KASSERT(atac->atac_bustype_ata->ata_recovery != NULL);
+
+               SET(chp->ch_flags, ATACH_RECOVERING);
+               (*atac->atac_bustype_ata->ata_recovery)(chp, flags, tfd);
+               CLR(chp->ch_flags, ATACH_RECOVERING);
+               break;
+           }
 
        default:
                panic("%s: unknown type: %x", __func__, type);
diff -r a793e28b1da3 -r eab9edd86f17 sys/dev/ata/ata_recovery.c
--- a/sys/dev/ata/ata_recovery.c        Sun Oct 14 16:13:51 2018 +0000
+++ b/sys/dev/ata/ata_recovery.c        Mon Oct 15 21:18:53 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ata_recovery.c,v 1.1.2.1 2018/10/11 20:57:51 jdolecek Exp $    */
+/*     $NetBSD: ata_recovery.c,v 1.1.2.2 2018/10/15 21:18:53 jdolecek Exp $    */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ata_recovery.c,v 1.1.2.1 2018/10/11 20:57:51 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata_recovery.c,v 1.1.2.2 2018/10/15 21:18:53 jdolecek Exp $");
 
 #include "opt_ata.h"
 
@@ -67,9 +67,9 @@
 ata_read_log_ext_ncq(struct ata_drive_datas *drvp, uint8_t flags,
     uint8_t *slot, uint8_t *status, uint8_t *err)
 {
-       struct ata_xfer *xfer = &drvp->recovery_xfer;
        int rv;
        struct ata_channel *chp = drvp->chnl_softc;
+       struct ata_xfer *xfer = &chp->recovery_xfer;
        struct atac_softc *atac = chp->ch_atac;
        uint8_t *tb, cksum, page;
 
@@ -82,8 +82,8 @@
 
        memset(xfer, 0, sizeof(*xfer));
 
-       tb = drvp->recovery_blk;
-       memset(tb, 0, sizeof(drvp->recovery_blk));
+       tb = chp->recovery_blk;
+       memset(tb, 0, sizeof(chp->recovery_blk));
 
        /*
         * We could use READ LOG DMA EXT if drive supports it (i.e.
@@ -101,7 +101,7 @@
        xfer->c_ata_c.flags = AT_READ | AT_LBA | AT_LBA48 | flags;
        xfer->c_ata_c.timeout = 1000; /* 1s */
        xfer->c_ata_c.data = tb;
-       xfer->c_ata_c.bcount = sizeof(drvp->recovery_blk);
+       xfer->c_ata_c.bcount = sizeof(chp->recovery_blk);
 
        if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
                                                xfer) != ATACMD_COMPLETE) {
@@ -114,7 +114,7 @@
        }
 
        cksum = 0;
-       for (int i = 0; i < sizeof(drvp->recovery_blk); i++)
+       for (int i = 0; i < sizeof(chp->recovery_blk); i++)
                cksum += tb[i];
        if (cksum != 0) {
                device_printf(drvp->drv_softc,
@@ -167,13 +167,16 @@
        struct ata_xfer *xfer;
        const uint8_t ch_openings = ata_queue_openings(chp);
 
-       ata_channel_lock(chp);
+       ata_channel_lock_owned(chp);
+
        ata_queue_hold(chp);
-       ata_channel_unlock(chp);
 
        KASSERT(drive < chp->ch_ndrives);
        drvp = &chp->ch_drive[drive];
 
+       /* Drop the lock for the READ LOG EXT request */
+       ata_channel_unlock(chp);
+
        /*
         * When running NCQ commands, READ LOG EXT is necessary to clear the
         * error condition and unblock the device.
@@ -243,5 +246,5 @@
 
 out:
        /* Nothing more to do */
-       return;
+       ata_channel_lock(chp);
 }
diff -r a793e28b1da3 -r eab9edd86f17 sys/dev/ata/ata_wdc.c
--- a/sys/dev/ata/ata_wdc.c     Sun Oct 14 16:13:51 2018 +0000
+++ b/sys/dev/ata/ata_wdc.c     Mon Oct 15 21:18:53 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ata_wdc.c,v 1.110.4.3 2018/09/17 20:54:41 jdolecek Exp $       */
+/*     $NetBSD: ata_wdc.c,v 1.110.4.4 2018/10/15 21:18:53 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.110.4.3 2018/09/17 20:54:41 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.110.4.4 2018/10/15 21:18:53 jdolecek Exp $");
 
 #include "opt_ata.h"
 #include "opt_wdc.h"
@@ -128,6 +128,7 @@
        wdc_ata_addref,
        wdc_ata_delref,
        ata_kill_pending,
+       NULL,
 };
 
 static const struct ata_xfer_ops wdc_bio_xfer_ops = {
diff -r a793e28b1da3 -r eab9edd86f17 sys/dev/ata/atavar.h
--- a/sys/dev/ata/atavar.h      Sun Oct 14 16:13:51 2018 +0000
+++ b/sys/dev/ata/atavar.h      Mon Oct 15 21:18:53 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: atavar.h,v 1.99.2.11 2018/10/11 20:57:51 jdolecek Exp $        */
+/*     $NetBSD: atavar.h,v 1.99.2.12 2018/10/15 21:18:53 jdolecek Exp $        */



Home | Main Index | Thread Index | Old Index