Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/ic support DIOCSCACHE + DKCACHE_WRITE if volatile wr...



details:   https://anonhg.NetBSD.org/src/rev/9eef07991590
branches:  trunk
changeset: 446351:9eef07991590
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Sat Dec 01 15:07:58 2018 +0000

description:
support DIOCSCACHE + DKCACHE_WRITE if volatile write cache is present

fix the Get Features call for DIOCGCACHE to actually retrieve the current
value properly

diffstat:

 sys/dev/ic/ld_nvme.c |   16 ++++++-
 sys/dev/ic/nvme.c    |  104 +++++++++++++++++++++++++++++++++++++++++++++++++-
 sys/dev/ic/nvmereg.h |   10 +++-
 sys/dev/ic/nvmevar.h |    3 +-
 4 files changed, 124 insertions(+), 9 deletions(-)

diffs (243 lines):

diff -r ed73001dea93 -r 9eef07991590 sys/dev/ic/ld_nvme.c
--- a/sys/dev/ic/ld_nvme.c      Sat Dec 01 14:05:33 2018 +0000
+++ b/sys/dev/ic/ld_nvme.c      Sat Dec 01 15:07:58 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ld_nvme.c,v 1.20 2018/04/18 10:11:45 nonaka Exp $      */
+/*     $NetBSD: ld_nvme.c,v 1.21 2018/12/01 15:07:58 jdolecek Exp $    */
 
 /*-
  * Copyright (C) 2016 NONAKA Kimihiro <nonaka%netbsd.org@localhost>
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ld_nvme.c,v 1.20 2018/04/18 10:11:45 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ld_nvme.c,v 1.21 2018/12/01 15:07:58 jdolecek Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -200,6 +200,14 @@
 }
 
 static int
+ld_nvme_setcache(struct ld_softc *ld, int addr)
+{
+       struct ld_nvme_softc *sc = device_private(ld->sc_dv);
+
+       return nvme_admin_setcache(sc->sc_nvme, addr);
+}
+
+static int
 ld_nvme_ioctl(struct ld_softc *ld, u_long cmd, void *addr, int32_t flag, bool poll)
 {
        int error;
@@ -213,6 +221,10 @@
                error = ld_nvme_getcache(ld, (int *)addr);
                break;
 
+       case DIOCSCACHE:
+               error = ld_nvme_setcache(ld, *(int *)addr);
+               break;
+
        default:
                error = EPASSTHROUGH;
                break;
diff -r ed73001dea93 -r 9eef07991590 sys/dev/ic/nvme.c
--- a/sys/dev/ic/nvme.c Sat Dec 01 14:05:33 2018 +0000
+++ b/sys/dev/ic/nvme.c Sat Dec 01 15:07:58 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvme.c,v 1.40 2018/12/01 08:03:44 jdolecek Exp $       */
+/*     $NetBSD: nvme.c,v 1.41 2018/12/01 15:07:58 jdolecek Exp $       */
 /*     $OpenBSD: nvme.c,v 1.49 2016/04/18 05:59:50 dlg Exp $ */
 
 /*
@@ -18,7 +18,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvme.c,v 1.40 2018/12/01 08:03:44 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvme.c,v 1.41 2018/12/01 15:07:58 jdolecek Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -902,6 +902,7 @@
 
        sqe->opcode = NVM_ADMIN_GET_FEATURES;
        htolem32(&sqe->cdw10, NVM_FEATURE_VOLATILE_WRITE_CACHE);
+       htolem32(&sqe->cdw11, NVM_VOLATILE_WRITE_CACHE_WCE);
 }
 
 static void
@@ -922,7 +923,7 @@
                 */ 
                result = DKCACHE_FUA;
 
-               if (cdw0 & NVME_CQE_CDW0_VWC_WCE)
+               if (cdw0 & NVM_VOLATILE_WRITE_CACHE_WCE)
                        result |= DKCACHE_WRITE;
 
                /*
@@ -930,6 +931,14 @@
                 * settable.
                 */
                result |= DKCACHE_WCHANGE;
+
+               /*
+                * ONCS field indicates whether the optional SAVE is also
+                * supported for Set Features. According to spec v1.3,
+                * Volatile Write Cache however doesn't support persistency
+                * across power cycle/reset.
+                */
+
        } else {
                result = -1;
        }
@@ -939,6 +948,95 @@
        nvme_ccb_put(q, ccb);
 }
 
+struct nvme_setcache_state {
+       int dkcache;
+       int result;
+};
+
+static bool
+nvme_setcache_finished(void *xc)
+{
+       struct nvme_setcache_state *st = xc;
+
+       return (st->result != 0);
+}
+
+static void
+nvme_setcache_fill(struct nvme_queue *q, struct nvme_ccb *ccb, void *slot)
+{
+       struct nvme_sqe *sqe = slot;
+       struct nvme_setcache_state *st = ccb->ccb_cookie;
+
+       sqe->opcode = NVM_ADMIN_SET_FEATURES;
+       htolem32(&sqe->cdw10, NVM_FEATURE_VOLATILE_WRITE_CACHE);
+       if (st->dkcache & DKCACHE_WRITE)
+               htolem32(&sqe->cdw11, NVM_VOLATILE_WRITE_CACHE_WCE);
+}
+
+static void
+nvme_setcache_done(struct nvme_queue *q, struct nvme_ccb *ccb,
+    struct nvme_cqe *cqe)
+{
+       struct nvme_setcache_state *st = ccb->ccb_cookie;
+       uint16_t status = NVME_CQE_SC(lemtoh16(&cqe->flags));
+
+       if (status == NVME_CQE_SC_SUCCESS) {
+               st->result = 1;
+       } else {
+               st->result = -1;
+       }
+
+       nvme_ccb_put(q, ccb);
+}
+
+/*
+ * Set status of volatile write cache. Always asynchronous.
+ */
+int
+nvme_admin_setcache(struct nvme_softc *sc, int dkcache)
+{
+       struct nvme_ccb *ccb;
+       struct nvme_queue *q = sc->sc_admin_q;
+       int error;
+       struct nvme_setcache_state st;
+
+       if (!nvme_has_volatile_write_cache(sc)) {
+               /* cache simply not present */
+               return EOPNOTSUPP;
+       }
+
+       if (dkcache & ~(DKCACHE_WRITE)) {
+               /* unsupported parameters */
+               return EOPNOTSUPP;
+       }
+
+       ccb = nvme_ccb_get(q, true);
+       KASSERT(ccb != NULL);
+
+       memset(&st, 0, sizeof(st));
+       st.dkcache = dkcache;
+
+       ccb->ccb_done = nvme_setcache_done;
+       ccb->ccb_cookie = &st;
+
+       /* namespace context */
+       ccb->nnc_flags = 0;
+       ccb->nnc_done = NULL;
+
+       nvme_q_submit(sc, q, ccb, nvme_setcache_fill);
+
+       /* wait for completion */
+       nvme_q_wait_complete(sc, q, nvme_setcache_finished, &st);
+       KASSERT(st.result != 0);
+
+       if (st.result > 0)
+               error = 0;
+       else
+               error = EINVAL;
+
+       return error;
+}
+
 void
 nvme_ns_free(struct nvme_softc *sc, uint16_t nsid)
 {
diff -r ed73001dea93 -r 9eef07991590 sys/dev/ic/nvmereg.h
--- a/sys/dev/ic/nvmereg.h      Sat Dec 01 14:05:33 2018 +0000
+++ b/sys/dev/ic/nvmereg.h      Sat Dec 01 15:07:58 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvmereg.h,v 1.11 2018/04/18 10:10:26 nonaka Exp $      */
+/*     $NetBSD: nvmereg.h,v 1.12 2018/12/01 15:07:58 jdolecek Exp $    */
 /*     $OpenBSD: nvmereg.h,v 1.10 2016/04/14 11:18:32 dlg Exp $ */
 
 /*
@@ -230,7 +230,6 @@
 
 struct nvme_cqe {
        uint32_t        cdw0;
-#define NVME_CQE_CDW0_VWC_WCE  __BIT(1)        /* Volatile Write Cache Enable */
 
        uint32_t        _reserved;
 
@@ -369,6 +368,10 @@
 /* 0x84-0xBF - command set specific (reserved) */
 /* 0xC0-0xFF - vendor specific */
 
+#define NVM_SET_FEATURES_SV            __BIT(31)       /* Persist */
+
+#define NVM_VOLATILE_WRITE_CACHE_WCE   __BIT(0)        /* Write Cache Enable */
+
 /* Power State Descriptor Data */
 struct nvm_identify_psd {
        uint16_t        mp;             /* Max Power */
@@ -514,8 +517,9 @@
        uint32_t        nn;             /* Number of Namespaces */
 
        uint16_t        oncs;           /* Optional NVM Command Support */
+#define        NVME_ID_CTRLR_ONCS_TIMESTAMP    __BIT(6)
 #define        NVME_ID_CTRLR_ONCS_RESERVATION  __BIT(5)
-#define        NVME_ID_CTRLR_ONCS_SET_FEATURES __BIT(4)
+#define        NVME_ID_CTRLR_ONCS_SAVE         __BIT(4)
 #define        NVME_ID_CTRLR_ONCS_WRITE_ZERO   __BIT(3)
 #define        NVME_ID_CTRLR_ONCS_DSM          __BIT(2)
 #define        NVME_ID_CTRLR_ONCS_WRITE_UNC    __BIT(1)
diff -r ed73001dea93 -r 9eef07991590 sys/dev/ic/nvmevar.h
--- a/sys/dev/ic/nvmevar.h      Sat Dec 01 14:05:33 2018 +0000
+++ b/sys/dev/ic/nvmevar.h      Sat Dec 01 15:07:58 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvmevar.h,v 1.17 2018/04/19 21:50:08 christos Exp $    */
+/*     $NetBSD: nvmevar.h,v 1.18 2018/12/01 15:07:58 jdolecek Exp $    */
 /*     $OpenBSD: nvmevar.h,v 1.8 2016/04/14 11:18:32 dlg Exp $ */
 
 /*
@@ -186,3 +186,4 @@
     struct buf *, void *, size_t, int, daddr_t, int, nvme_nnc_done);
 int    nvme_ns_sync(struct nvme_softc *, uint16_t, int);
 int    nvme_admin_getcache(struct nvme_softc *, int *);
+int    nvme_admin_setcache(struct nvme_softc *, int);



Home | Main Index | Thread Index | Old Index