From be69487882da979e198f0d06445a802c90851628 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 21 Aug 2022 00:31:21 +0000 Subject: [PATCH] WIP: nvme(4): Add sysctl hw.nvmeN.ioqM.check=1 trigger. This triggers checking the queue as if an interrupt had arrived. Should not usually be necessary but this may help diagnose driver or device bugs. --- sys/dev/ic/nvme.c | 43 +++++++++++++++++++++++++++++++++++++++++++ sys/dev/ic/nvmevar.h | 3 +++ 2 files changed, 46 insertions(+) diff --git a/sys/dev/ic/nvme.c b/sys/dev/ic/nvme.c index c54925c04958..c6d52f89e628 100644 --- a/sys/dev/ic/nvme.c +++ b/sys/dev/ic/nvme.c @@ -33,6 +33,7 @@ __KERNEL_RCSID(0, "$NetBSD: nvme.c,v 1.63 2022/08/15 10:15:59 riastradh Exp $"); #include #include #include +#include #include @@ -445,6 +446,12 @@ nvme_attach(struct nvme_softc *sc) sc->sc_nq = nsq; } + sysctl_createv(&sc->sc_sysctllog, 0, NULL, &sc->sc_sysctlnode, + CTLFLAG_PERMANENT, CTLTYPE_NODE, device_xname(sc->sc_dev), + SYSCTL_DESCR("nvme device"), + NULL, 0, NULL, 0, + CTL_HW, CTL_CREATE, CTL_EOL); + sc->sc_q = kmem_zalloc(sizeof(*sc->sc_q) * sc->sc_nq, KM_SLEEP); for (i = 0; i < sc->sc_nq; i++) { sc->sc_q[i] = nvme_q_alloc(sc, i + 1, ioq_entries, @@ -1942,6 +1949,24 @@ nvme_ccbs_free(struct nvme_queue *q) mutex_destroy(&q->q_ccb_mtx); } +static int +nvme_q_sysctl(SYSCTLFN_ARGS) +{ + struct sysctlnode node = *rnode; + struct nvme_queue *q = node.sysctl_data; + int arg = 0; + int error; + + node.sysctl_data = &arg; + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (error || newp == NULL) + return error; + if (arg) + nvme_q_complete(q->q_sc, q); + + return 0; +} + static struct nvme_queue * nvme_q_alloc(struct nvme_softc *sc, uint16_t id, u_int entries, u_int dstrd) { @@ -1990,6 +2015,24 @@ nvme_q_alloc(struct nvme_softc *sc, uint16_t id, u_int entries, u_int dstrd) goto free_cq; } + { + char qname[128]; + const struct sysctlnode *qnode; + + if (id == NVME_ADMIN_Q) + snprintf(qname, sizeof qname, "adminq"); + else + snprintf(qname, sizeof qname, "ioq%u", id); + sysctl_createv(&sc->sc_sysctllog, 0, &sc->sc_sysctlnode, &qnode, + CTLFLAG_PERMANENT, CTLTYPE_NODE, qname, + SYSCTL_DESCR("Queue stuff"), + NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL); + sysctl_createv(&sc->sc_sysctllog, 0, &qnode, NULL, + CTLFLAG_PERMANENT, CTLTYPE_INT, "check", + SYSCTL_DESCR("Check queue as if we received an interrupt"), + &nvme_q_sysctl, 0, (int *)q, 0, CTL_CREATE, CTL_EOL); + } + return q; free_cq: diff --git a/sys/dev/ic/nvmevar.h b/sys/dev/ic/nvmevar.h index 0920ab644767..13ef4f4f90d5 100644 --- a/sys/dev/ic/nvmevar.h +++ b/sys/dev/ic/nvmevar.h @@ -169,6 +169,9 @@ struct nvme_softc { #define NVME_QUIRK_NOMSI __BIT(1) char sc_modelname[81]; + + struct sysctllog *sc_sysctllog; + const struct sysctlnode *sc_sysctlnode; }; #define lemtoh16(p) le16toh(*((uint16_t *)(p)))