have nvme_poll return the status bigs from the completion ring
authordlg <dlg@openbsd.org>
Wed, 16 Apr 2014 00:26:59 +0000 (00:26 +0000)
committerdlg <dlg@openbsd.org>
Wed, 16 Apr 2014 00:26:59 +0000 (00:26 +0000)
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.

sys/dev/ic/nvme.c
sys/dev/ic/nvmereg.h

index eb99e32..740b41c 100644 (file)
@@ -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)
 {
index 951758b..97703c9 100644 (file)
@@ -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 */