Source-Changes-HG archive

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

[src/jdolecek-ncq]: src/sys/dev/ata add sysctls to control if NCQ is being us...



details:   https://anonhg.NetBSD.org/src/rev/08aa2ccb38f9
branches:  jdolecek-ncq
changeset: 352791:08aa2ccb38f9
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Thu Sep 28 20:34:23 2017 +0000

description:
add sysctls to control if NCQ is being used, and how many max tags;
I have a drive which is significantly slower with NCQ than non-NCQ,
and it's generally useful to have this easily overridable

while here, also move the frequency settings for WD_CHAOS_MONKEY
to a sysctl and make it per-drive

diffstat:

 sys/dev/ata/TODO.ncq |    2 -
 sys/dev/ata/wd.c     |  109 ++++++++++++++++++++++++++++++++++++++++++++------
 sys/dev/ata/wdvar.h  |   16 +++++++-
 3 files changed, 110 insertions(+), 17 deletions(-)

diffs (232 lines):

diff -r 98860e038f2f -r 08aa2ccb38f9 sys/dev/ata/TODO.ncq
--- a/sys/dev/ata/TODO.ncq      Thu Sep 28 20:25:45 2017 +0000
+++ b/sys/dev/ata/TODO.ncq      Thu Sep 28 20:34:23 2017 +0000
@@ -32,8 +32,6 @@
   is too much for emergency crash dump code path
 - old bug - kern/16789
 
-add nibble to control number of tags (1==disable NCQ)?
-
 add support for the NCQ TRIM if supported by device?
 
 implement DIOCGCACHE/DIOCCACHESYNC for ld@ataraid? just passthrough, like ccd
diff -r 98860e038f2f -r 08aa2ccb38f9 sys/dev/ata/wd.c
--- a/sys/dev/ata/wd.c  Thu Sep 28 20:25:45 2017 +0000
+++ b/sys/dev/ata/wd.c  Thu Sep 28 20:34:23 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wd.c,v 1.428.2.34 2017/08/13 15:12:04 jdolecek Exp $ */
+/*     $NetBSD: wd.c,v 1.428.2.35 2017/09/28 20:34:23 jdolecek Exp $ */
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
@@ -54,7 +54,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.428.2.34 2017/08/13 15:12:04 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.428.2.35 2017/09/28 20:34:23 jdolecek Exp $");
 
 #include "opt_ata.h"
 #include "opt_wd.h"
@@ -116,11 +116,6 @@
 #define ATADEBUG_PRINT(args, level)
 #endif
 
-#ifdef WD_CHAOS_MONKEY
-int wdcdebug_wd_cnt = 0;
-int wdcdebug_wd_chaos = 0;
-#endif
-
 int    wdprobe(device_t, cfdata_t, void *);
 void   wdattach(device_t, device_t, void *);
 int    wddetach(device_t, int);
@@ -211,6 +206,9 @@
 int   wd_getcache(struct wd_softc *, int *);
 int   wd_setcache(struct wd_softc *, int);
 
+static void wd_sysctl_attach(struct wd_softc *);
+static void wd_sysctl_detach(struct wd_softc *);
+
 struct dkdriver wddkdriver = {
        .d_strategy = wdstrategy,
        .d_minphys = wdminphys
@@ -450,6 +448,8 @@
 
        if (!pmf_device_register1(self, wd_suspend, NULL, wd_shutdown))
                aprint_error_dev(self, "couldn't establish power handler\n");
+
+       wd_sysctl_attach(wd);
 }
 
 static bool
@@ -520,6 +520,8 @@
 
        pmf_device_deregister(self);
 
+       wd_sysctl_detach(sc);
+
        /* Unhook the entropy source. */
        rnd_detach_source(&sc->rnd_source);
 
@@ -663,8 +665,7 @@
        while (bufq_peek(wd->sc_q) != NULL) {
                /* First try to get xfer. Limit to drive openings iff NCQ. */
                xfer = ata_get_xfer_ext(wd->drvp->chnl_softc, 0,
-                   ISSET(wd->drvp->drive_flags, ATA_DRIVE_NCQ)
-                       ? wd->drvp->drv_openings : 0);
+                   WD_USE_NCQ(wd) ? WD_MAX_OPENINGS(wd) : 0);
                if (xfer == NULL)
                        break;
 
@@ -708,8 +709,8 @@
         * the command be clipped, or otherwise misinterpreted, by the
         * driver or controller.
         */
-       if (BUF_ISREAD(bp) && xfer->c_retries == 0 && wdcdebug_wd_cnt > 0 &&
-           (++wdcdebug_wd_chaos % wdcdebug_wd_cnt) == 0) {
+       if (BUF_ISREAD(bp) && xfer->c_retries == 0 && wd->drv_chaos_freq > 0 &&
+           (++wd->drv_chaos_cnt % wd->drv_chaos_freq) == 0) {
                aprint_normal_dev(wd->sc_dev, "%s: chaos xfer %d\n",
                    __func__, xfer->c_slot);
                xfer->c_bio.blkno = 7777777 + wd->sc_capacity;
@@ -745,8 +746,7 @@
         * the semantics - FUA would not be honored. In that case, continue
         * retrying with NCQ.
         */
-       if (wd->drvp->drive_flags & ATA_DRIVE_NCQ &&
-           (xfer->c_retries < WDIORETRIES_SINGLE ||
+       if (WD_USE_NCQ(wd) && (xfer->c_retries < WDIORETRIES_SINGLE ||
            (bp->b_flags & B_MEDIA_FUA) != 0)) {
                xfer->c_bio.flags |= ATA_LBA48;
                xfer->c_flags |= C_NCQ;
@@ -1856,7 +1856,7 @@
        if (params.atap_cmd1_en & WDC_CMD1_CACHE)
                *bitsp |= DKCACHE_WRITE;
 
-       if (wd->drvp->drive_flags & (ATA_DRIVE_NCQ|ATA_DRIVE_WFUA))
+       if (WD_USE_NCQ(wd) || (wd->drvp->drive_flags & ATA_DRIVE_WFUA))
                *bitsp |= DKCACHE_FUA;
 
        return 0;
@@ -2315,3 +2315,84 @@
                bp->b_resid = bp->b_bcount;
        biodone(bp);
 }
+
+static void
+wd_sysctl_attach(struct wd_softc *wd)
+{
+       const struct sysctlnode *node;
+       int error;
+
+       /* sysctl set-up */
+       if (sysctl_createv(&wd->nodelog, 0, NULL, &node,
+                               0, CTLTYPE_NODE, device_xname(wd->sc_dev),
+                               SYSCTL_DESCR("wd driver settings"),
+                               NULL, 0, NULL, 0,
+                               CTL_HW, CTL_CREATE, CTL_EOL) != 0) {
+               aprint_error_dev(wd->sc_dev,
+                   "could not create %s.%s sysctl node\n",
+                   "hw", device_xname(wd->sc_dev));
+               return;
+       }
+
+       wd->drv_max_tags = ATA_MAX_OPENINGS;
+       if ((error = sysctl_createv(&wd->nodelog, 0, NULL, NULL,
+                               CTLFLAG_READWRITE, CTLTYPE_INT, "max_tags",
+                               SYSCTL_DESCR("max number of NCQ tags to use"),
+                               NULL, 0, &wd->drv_max_tags, 0,
+                               CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
+                               != 0) {
+               aprint_error_dev(wd->sc_dev,
+                   "could not create %s.%s.max_tags sysctl - error %d\n",
+                   "hw", device_xname(wd->sc_dev), error);
+               return;
+       }
+
+       wd->drv_ncq = true;
+       if ((error = sysctl_createv(&wd->nodelog, 0, NULL, NULL,
+                               CTLFLAG_READWRITE, CTLTYPE_BOOL, "use_ncq",
+                               SYSCTL_DESCR("use NCQ if supported"),
+                               NULL, 0, &wd->drv_ncq, 0,
+                               CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
+                               != 0) {
+               aprint_error_dev(wd->sc_dev,
+                   "could not create %s.%s.use_ncq sysctl - error %d\n",
+                   "hw", device_xname(wd->sc_dev), error);
+               return;
+       }
+
+#ifdef WD_CHAOS_MONKEY
+       wd->drv_chaos_freq = 0;
+       if ((error = sysctl_createv(&wd->nodelog, 0, NULL, NULL,
+                               CTLFLAG_READWRITE, CTLTYPE_INT, "chaos_freq",
+                               SYSCTL_DESCR("simulated bio read error rate"),
+                               NULL, 0, &wd->drv_chaos_freq, 0,
+                               CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
+                               != 0) {
+               aprint_error_dev(wd->sc_dev,
+                   "could not create %s.%s.chaos_freq sysctl - error %d\n",
+                   "hw", device_xname(wd->sc_dev), error);
+               return;
+       }
+
+       wd->drv_chaos_cnt = 0;
+       if ((error = sysctl_createv(&wd->nodelog, 0, NULL, NULL,
+                               CTLFLAG_READONLY, CTLTYPE_INT, "chaos_cnt",
+                               SYSCTL_DESCR("number of processed bio reads"),
+                               NULL, 0, &wd->drv_chaos_cnt, 0,
+                               CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
+                               != 0) {
+               aprint_error_dev(wd->sc_dev,
+                   "could not create %s.%s.chaos_cnt sysctl - error %d\n",
+                   "hw", device_xname(wd->sc_dev), error);
+               return;
+       }
+#endif
+
+}
+
+static void
+wd_sysctl_detach(struct wd_softc *wd)
+{
+       sysctl_teardown(&wd->nodelog);
+}
+
diff -r 98860e038f2f -r 08aa2ccb38f9 sys/dev/ata/wdvar.h
--- a/sys/dev/ata/wdvar.h       Thu Sep 28 20:25:45 2017 +0000
+++ b/sys/dev/ata/wdvar.h       Thu Sep 28 20:34:23 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wdvar.h,v 1.43.4.8 2017/09/02 12:01:25 jdolecek Exp $  */
+/*     $NetBSD: wdvar.h,v 1.43.4.9 2017/09/28 20:34:23 jdolecek Exp $  */
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -32,6 +32,7 @@
 #endif
 
 #include <sys/rndsource.h>
+#include <sys/sysctl.h>
 
 struct wd_softc {
        /* General disk infos */
@@ -68,6 +69,19 @@
        u_int sc_bscount;
 #endif
        krndsource_t    rnd_source;
+
+       /* Sysctl nodes specific for the disk */
+       struct sysctllog *nodelog;
+       int drv_max_tags;
+#define WD_MAX_OPENINGS(wd)    \
+       (MAX(1, MIN((wd)->drvp->drv_openings, (wd)->drv_max_tags)))
+       bool drv_ncq;
+#define WD_USE_NCQ(wd) \
+       ((wd)->drv_ncq && ((wd)->drvp->drive_flags & ATA_DRIVE_NCQ))
+#ifdef WD_CHAOS_MONKEY
+       int drv_chaos_freq;             /* frequency of simulated bio errors */
+       int drv_chaos_cnt;              /* count of processed bio read xfers */
+#endif
 };
 
 #endif /* _DEV_ATA_WDVAR_H_ */



Home | Main Index | Thread Index | Old Index