support DIOCSCACHE + DKCACHE_WRITE if volatile write cache is present
fix the Get Features call for DIOCGCACHE to actually retrieve the current value properly
This commit is contained in:
parent
6bb18810c6
commit
b7a0ea19e0
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -199,6 +199,14 @@ ld_nvme_getcache(struct ld_softc *ld, int *addr)
|
|||
return nvme_admin_getcache(sc->sc_nvme, addr);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -213,6 +221,10 @@ ld_nvme_ioctl(struct ld_softc *ld, u_long cmd, void *addr, int32_t flag, bool po
|
|||
error = ld_nvme_getcache(ld, (int *)addr);
|
||||
break;
|
||||
|
||||
case DIOCSCACHE:
|
||||
error = ld_nvme_setcache(ld, *(int *)addr);
|
||||
break;
|
||||
|
||||
default:
|
||||
error = EPASSTHROUGH;
|
||||
break;
|
||||
|
|
|
@ -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 @@ nvme_getcache_fill(struct nvme_queue *q, struct nvme_ccb *ccb, void *slot)
|
|||
|
||||
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 @@ nvme_getcache_done(struct nvme_queue *q, struct nvme_ccb *ccb,
|
|||
*/
|
||||
result = DKCACHE_FUA;
|
||||
|
||||
if (cdw0 & NVME_CQE_CDW0_VWC_WCE)
|
||||
if (cdw0 & NVM_VOLATILE_WRITE_CACHE_WCE)
|
||||
result |= DKCACHE_WRITE;
|
||||
|
||||
/*
|
||||
|
@ -930,6 +931,14 @@ nvme_getcache_done(struct nvme_queue *q, struct nvme_ccb *ccb,
|
|||
* 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_getcache_done(struct nvme_queue *q, struct nvme_ccb *ccb,
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -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 @@ NVME_CTASSERT(sizeof(struct nvme_sqe_io) == 64, "bad size for nvme_sqe_io");
|
|||
|
||||
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 @@ NVME_CTASSERT(sizeof(struct nvme_cqe) == 16, "bad size for nvme_cqe");
|
|||
/* 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 @@ struct nvm_identify_controller {
|
|||
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)
|
||||
|
|
|
@ -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 @@ int nvme_ns_dobio(struct nvme_softc *, uint16_t, void *,
|
|||
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);
|
||||
|
|
Loading…
Reference in New Issue