Module Name: src Committed By: jdolecek Date: Thu Sep 28 20:34:23 UTC 2017
Modified Files: src/sys/dev/ata [jdolecek-ncq]: TODO.ncq wd.c wdvar.h Log Message: 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 To generate a diff of this commit: cvs rdiff -u -r1.1.2.45 -r1.1.2.46 src/sys/dev/ata/TODO.ncq cvs rdiff -u -r1.428.2.34 -r1.428.2.35 src/sys/dev/ata/wd.c cvs rdiff -u -r1.43.4.8 -r1.43.4.9 src/sys/dev/ata/wdvar.h 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/TODO.ncq diff -u src/sys/dev/ata/TODO.ncq:1.1.2.45 src/sys/dev/ata/TODO.ncq:1.1.2.46 --- src/sys/dev/ata/TODO.ncq:1.1.2.45 Thu Sep 28 20:25:45 2017 +++ src/sys/dev/ata/TODO.ncq Thu Sep 28 20:34:23 2017 @@ -32,8 +32,6 @@ set 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 Index: src/sys/dev/ata/wd.c diff -u src/sys/dev/ata/wd.c:1.428.2.34 src/sys/dev/ata/wd.c:1.428.2.35 --- src/sys/dev/ata/wd.c:1.428.2.34 Sun Aug 13 15:12:04 2017 +++ src/sys/dev/ata/wd.c Thu Sep 28 20:34:23 2017 @@ -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 @@ int wdcdebug_wd_mask = 0x0; #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 @@ bool wd_shutdown(device_t, int); 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 @@ out: 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 @@ wddetach(device_t self, int flags) pmf_device_deregister(self); + wd_sysctl_detach(sc); + /* Unhook the entropy source. */ rnd_detach_source(&sc->rnd_source); @@ -663,8 +665,7 @@ wdstart(device_t self) 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 @@ wdstart1(struct wd_softc *wd, struct buf * 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 @@ wdstart1(struct wd_softc *wd, struct buf * 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 @@ wd_getcache(struct wd_softc *wd, int *bi 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 @@ out2: 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); +} + Index: src/sys/dev/ata/wdvar.h diff -u src/sys/dev/ata/wdvar.h:1.43.4.8 src/sys/dev/ata/wdvar.h:1.43.4.9 --- src/sys/dev/ata/wdvar.h:1.43.4.8 Sat Sep 2 12:01:25 2017 +++ src/sys/dev/ata/wdvar.h Thu Sep 28 20:34:23 2017 @@ -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 @@ struct wd_softc { 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_ */