summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2014-04-16 00:27:00 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2014-04-16 00:27:00 +0000
commit6c1876ab0a19fd8d65086cb8860c3a25784cc8d2 (patch)
tree425eb1f09305b63e330dcc9656463c15df595873 /sys
parente0141c26819310ad828aa6c945e8d197a6e245c6 (diff)
have nvme_poll return the status bigs from the completion ring
entry. if i ever implement timeouts ill use high bits in the int or the phase bit to indicate non chip related errors. a successful chip status conveniently maps to 0. how handy. this lets me move the completion handling for the controller identification commands back into the caller. at the moment im just printing out controller and firmware details like we do on mfi/mpii/mfii.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ic/nvme.c65
-rw-r--r--sys/dev/ic/nvmereg.h34
2 files changed, 64 insertions, 35 deletions
diff --git a/sys/dev/ic/nvme.c b/sys/dev/ic/nvme.c
index eb99e3276af..740b41ca62a 100644
--- a/sys/dev/ic/nvme.c
+++ b/sys/dev/ic/nvme.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nvme.c,v 1.2 2014/04/15 10:28:07 dlg Exp $ */
+/* $OpenBSD: nvme.c,v 1.3 2014/04/16 00:26:59 dlg Exp $ */
/*
* Copyright (c) 2014 David Gwynne <dlg@openbsd.org>
@@ -49,8 +49,6 @@ void nvme_dumpregs(struct nvme_softc *);
int nvme_identify(struct nvme_softc *);
void nvme_fill_identify(struct nvme_softc *,
struct nvme_ccb *, void *);
-void nvme_identify_done(struct nvme_softc *,
- struct nvme_ccb *, struct nvme_cqe *);
int nvme_ccbs_alloc(struct nvme_softc *, u_int);
void nvme_ccbs_free(struct nvme_softc *);
@@ -66,6 +64,8 @@ void nvme_poll_fill(struct nvme_softc *,
struct nvme_ccb *, void *);
void nvme_poll_done(struct nvme_softc *,
struct nvme_ccb *, struct nvme_cqe *);
+void nvme_empty_done(struct nvme_softc *,
+ struct nvme_ccb *, struct nvme_cqe *);
struct nvme_queue * nvme_q_alloc(struct nvme_softc *,
u_int, u_int, u_int);
@@ -354,6 +354,7 @@ nvme_poll(struct nvme_softc *sc, struct nvme_queue *q, struct nvme_ccb *ccb,
struct nvme_poll_state state;
void (*done)(struct nvme_softc *, struct nvme_ccb *, struct nvme_cqe *);
void *cookie;
+ u_int16_t flags;
memset(&state, 0, sizeof(state));
state.s.cid = ccb->ccb_id;
@@ -376,7 +377,9 @@ nvme_poll(struct nvme_softc *sc, struct nvme_queue *q, struct nvme_ccb *ccb,
ccb->ccb_cookie = cookie;
done(sc, ccb, &state.c);
- return (0);
+ flags = lemtoh16(&state.c.flags);
+
+ return (NVME_CQE_SCT(flags) | NVME_CQE_SC(flags));
}
void
@@ -398,6 +401,12 @@ nvme_poll_done(struct nvme_softc *sc, struct nvme_ccb *ccb,
state->c = *cqe;
}
+void
+nvme_empty_done(struct nvme_softc *sc, struct nvme_ccb *ccb,
+ struct nvme_cqe *cqe)
+{
+}
+
int
nvme_q_complete(struct nvme_softc *sc, struct nvme_queue *q)
{
@@ -438,23 +447,41 @@ nvme_q_complete(struct nvme_softc *sc, struct nvme_queue *q)
int
nvme_identify(struct nvme_softc *sc)
{
- struct nvme_ccb *ccb;
+ char sn[41], mn[81], fr[17];
+ struct nvm_identify_controller *identify;
struct nvme_dmamem *mem;
+ struct nvme_ccb *ccb;
int rv = 1;
ccb = nvme_ccb_get(sc);
if (ccb == NULL)
panic("nvme_identify: nvme_ccb_get returned NULL");
- mem = nvme_dmamem_alloc(sc, sizeof(struct nvm_identify_controller));
+ mem = nvme_dmamem_alloc(sc, sizeof(*identify));
if (mem == NULL)
return (1);
- ccb->ccb_done = nvme_identify_done;
+ identify = NVME_DMA_KVA(mem);
+
+ ccb->ccb_done = nvme_empty_done;
ccb->ccb_cookie = mem;
+ bus_dmamap_sync(sc->sc_dmat, NVME_DMA_MAP(mem),
+ 0, sizeof(*identify), BUS_DMASYNC_PREREAD);
rv = nvme_poll(sc, sc->sc_admin_q, ccb, nvme_fill_identify);
+ bus_dmamap_sync(sc->sc_dmat, NVME_DMA_MAP(mem),
+ 0, sizeof(*identify), BUS_DMASYNC_POSTREAD);
+ if (rv != 0)
+ goto done;
+
+ scsi_strvis(sn, identify->sn, sizeof(identify->sn));
+ scsi_strvis(mn, identify->mn, sizeof(identify->mn));
+ scsi_strvis(fr, identify->fr, sizeof(identify->fr));
+
+ printf("%s: %s, firmware %s, serial %s\n", DEVNAME(sc), mn, fr, sn);
+
+done:
nvme_dmamem_free(sc, mem);
return (rv);
@@ -465,36 +492,12 @@ nvme_fill_identify(struct nvme_softc *sc, struct nvme_ccb *ccb, void *slot)
{
struct nvme_sqe *sqe = slot;
struct nvme_dmamem *mem = ccb->ccb_cookie;
- struct nvm_identify_controller *identify = NVME_DMA_KVA(mem);
-
- bus_dmamap_sync(sc->sc_dmat, NVME_DMA_MAP(mem),
- 0, sizeof(*identify), BUS_DMASYNC_PREREAD);
sqe->opcode = NVM_ADMIN_IDENTIFY;
htolem64(&sqe->entry.prp[0], NVME_DMA_DVA(mem));
htolem32(&sqe->cdw10, 1);
}
-void
-nvme_identify_done(struct nvme_softc *sc, struct nvme_ccb *ccb,
- struct nvme_cqe *cqe)
-{
- struct nvme_dmamem *mem = ccb->ccb_cookie;
- struct nvm_identify_controller *identify = NVME_DMA_KVA(mem);
- u_int64_t flags = lemtoh16(&cqe->flags);
-
- bus_dmamap_sync(sc->sc_dmat, NVME_DMA_MAP(mem),
- 0, sizeof(*identify), BUS_DMASYNC_POSTREAD);
-
- printf("%s: dnr %c m %c sqt %x sc %x\n", DEVNAME(sc),
- ISSET(flags, NVME_CQE_DNR) ? 'Y' : 'N',
- ISSET(flags, NVME_CQE_M) ? 'Y' : 'N',
- NVME_CQE_SQT(flags), NVME_CQE_SC(flags));
-
- printf("%s: identify %p sn %s mn %s fr %s\n", DEVNAME(sc), mem,
- identify->sn, identify->mn, identify->fr);
-}
-
int
nvme_ccbs_alloc(struct nvme_softc *sc, u_int nccbs)
{
diff --git a/sys/dev/ic/nvmereg.h b/sys/dev/ic/nvmereg.h
index 951758b342f..97703c972bb 100644
--- a/sys/dev/ic/nvmereg.h
+++ b/sys/dev/ic/nvmereg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: nvmereg.h,v 1.3 2014/04/15 10:28:07 dlg Exp $ */
+/* $OpenBSD: nvmereg.h,v 1.4 2014/04/16 00:26:59 dlg Exp $ */
/*
* Copyright (c) 2014 David Gwynne <dlg@openbsd.org>
@@ -140,8 +140,34 @@ struct nvme_cqe {
u_int16_t flags;
#define NVME_CQE_DNR (1 << 15)
#define NVME_CQE_M (1 << 14)
-#define NVME_CQE_SQT(_f) (((_f) >> 8) & 0x7)
-#define NVME_CQE_SC(_f) (((_f) >> 1) & 0x7f)
+#define NVME_CQE_SCT(_f) ((_f) & (0x07 << 8))
+#define NVME_CQE_SCT_GENERIC (0x00 << 8)
+#define NVME_CQE_SCT_COMMAND (0x01 << 8)
+#define NVME_CQE_SCT_MEDIAERR (0x02 << 8)
+#define NVME_CQE_SCT_VENDOR (0x07 << 8)
+#define NVME_CQE_SC(_f) ((_f) & (0x7f << 1))
+#define NVME_CQE_SC_SUCCESS (0x00 << 1)
+#define NVME_CQE_SC_INVALID_OPCODE (0x01 << 1)
+#define NVME_CQE_SC_INVALID_FIELD (0x02 << 1)
+#define NVME_CQE_SC_CID_CONFLICT (0x03 << 1)
+#define NVME_CQE_SC_DATA_XFER_ERR (0x04 << 1)
+#define NVME_CQE_SC_ABRT_BY_NO_PWR (0x05 << 1)
+#define NVME_CQE_SC_INTERNAL_DEV_ERR (0x06 << 1)
+#define NVME_CQE_SC_CMD_ABRT_REQD (0x07 << 1)
+#define NVME_CQE_SC_CMD_ABDR_SQ_DEL (0x08 << 1)
+#define NVME_CQE_SC_CMD_ABDR_FUSE_ERR (0x09 << 1)
+#define NVME_CQE_SC_CMD_ABDR_FUSE_MISS (0x0a << 1)
+#define NVME_CQE_SC_INVALID_NS (0x0b << 1)
+#define NVME_CQE_SC_CMD_SEQ_ERR (0x0c << 1)
+#define NVME_CQE_SC_INVALID_LAST_SGL (0x0d << 1)
+#define NVME_CQE_SC_INVALID_NUM_SGL (0x0e << 1)
+#define NVME_CQE_SC_DATA_SGL_LEN (0x0f << 1)
+#define NVME_CQE_SC_MDATA_SGL_LEN (0x10 << 1)
+#define NVME_CQE_SC_SGL_TYPE_INVALID (0x11 << 1)
+#define NVME_CQE_SC_LBA_RANGE (0x80 << 1)
+#define NVME_CQE_SC_CAP_EXCEEDED (0x81 << 1)
+#define NVME_CQE_NS_NOT_RDY (0x82 << 1)
+#define NVME_CQE_RSV_CONFLICT (0x83 << 1)
#define NVME_CQE_PHASE (1 << 0)
} __packed __aligned(8);
@@ -183,7 +209,7 @@ struct nvm_identify_controller {
u_int8_t sn[20]; /* Serial Number */
u_int8_t mn[40]; /* Model Number */
- u_int8_t fr[40]; /* Firmware Revision */
+ u_int8_t fr[8]; /* Firmware Revision */
u_int8_t rab; /* Recommended Arbitration Burst */
u_int8_t ieee[3]; /* IEEE OUI Identifier */