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/62537f05564d
branches: trunk
changeset: 995003:62537f05564d
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 c24eac122418 -r 62537f05564d 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 c24eac122418 -r 62537f05564d 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 c24eac122418 -r 62537f05564d 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 c24eac122418 -r 62537f05564d 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