Module Name: src Committed By: jdolecek Date: Tue Nov 1 14:24:36 UTC 2016
Modified Files: src/sys/dev/ic: nvme.c nvmevar.h Log Message: tighter queue control - according to spec actual cap on number of commands in flight is actually one less then queue size, head == tail means empty queue To generate a diff of this commit: cvs rdiff -u -r1.19 -r1.20 src/sys/dev/ic/nvme.c cvs rdiff -u -r1.9 -r1.10 src/sys/dev/ic/nvmevar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/ic/nvme.c diff -u src/sys/dev/ic/nvme.c:1.19 src/sys/dev/ic/nvme.c:1.20 --- src/sys/dev/ic/nvme.c:1.19 Thu Oct 20 19:20:40 2016 +++ src/sys/dev/ic/nvme.c Tue Nov 1 14:24:35 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: nvme.c,v 1.19 2016/10/20 19:20:40 jdolecek Exp $ */ +/* $NetBSD: nvme.c,v 1.20 2016/11/01 14:24:35 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.19 2016/10/20 19:20:40 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nvme.c,v 1.20 2016/11/01 14:24:35 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -58,7 +58,7 @@ static int nvme_identify(struct nvme_sof static void nvme_fill_identify(struct nvme_queue *, struct nvme_ccb *, void *); -static int nvme_ccbs_alloc(struct nvme_queue *, u_int); +static int nvme_ccbs_alloc(struct nvme_queue *, uint16_t); static void nvme_ccbs_free(struct nvme_queue *); static struct nvme_ccb * @@ -333,8 +333,8 @@ nvme_attach(struct nvme_softc *sc) uint32_t reg; u_int dstrd; u_int mps = PAGE_SHIFT; - int adminq_entries = nvme_adminq_size; - int ioq_entries = nvme_ioq_size; + uint16_t adminq_entries = nvme_adminq_size; + uint16_t ioq_entries = nvme_ioq_size; int i; reg = nvme_read4(sc, NVME_VS); @@ -1079,7 +1079,8 @@ nvme_q_complete(struct nvme_softc *sc, s /* NOTREACHED */ } #endif - rv = 1; + + rv++; /* * Unlock the mutex before calling the ccb_done callback @@ -1098,6 +1099,12 @@ nvme_q_complete(struct nvme_softc *sc, s mutex_exit(&q->q_cq_mtx); + if (rv) { + mutex_enter(&q->q_ccb_mtx); + q->q_nccbs_avail += rv; + mutex_exit(&q->q_ccb_mtx); + } + return rv; } @@ -1263,7 +1270,7 @@ nvme_fill_identify(struct nvme_queue *q, } static int -nvme_ccbs_alloc(struct nvme_queue *q, u_int nccbs) +nvme_ccbs_alloc(struct nvme_queue *q, uint16_t nccbs) { struct nvme_softc *sc = q->q_sc; struct nvme_ccb *ccb; @@ -1279,6 +1286,7 @@ nvme_ccbs_alloc(struct nvme_queue *q, u_ return 1; q->q_nccbs = nccbs; + q->q_nccbs_avail = nccbs; q->q_ccb_prpls = nvme_dmamem_alloc(sc, sizeof(*prpl) * sc->sc_max_sgl * nccbs); @@ -1315,11 +1323,14 @@ free_maps: static struct nvme_ccb * nvme_ccb_get(struct nvme_queue *q) { - struct nvme_ccb *ccb; + struct nvme_ccb *ccb = NULL; mutex_enter(&q->q_ccb_mtx); - ccb = SIMPLEQ_FIRST(&q->q_ccb_list); - if (ccb != NULL) { + if (q->q_nccbs_avail > 0) { + ccb = SIMPLEQ_FIRST(&q->q_ccb_list); + KASSERT(ccb != NULL); + q->q_nccbs_avail--; + SIMPLEQ_REMOVE_HEAD(&q->q_ccb_list, ccb_entry); #ifdef DEBUG ccb->ccb_cookie = NULL; @@ -1397,7 +1408,12 @@ nvme_q_alloc(struct nvme_softc *sc, uint nvme_dmamem_sync(sc, q->q_sq_dmamem, BUS_DMASYNC_PREWRITE); nvme_dmamem_sync(sc, q->q_cq_dmamem, BUS_DMASYNC_PREREAD); - if (nvme_ccbs_alloc(q, entries) != 0) { + /* + * Due to definition of full and empty queue (queue is empty + * when head == tail, full when tail is one less then head), + * we can actually only have (entries - 1) in-flight commands. + */ + if (nvme_ccbs_alloc(q, entries - 1) != 0) { aprint_error_dev(sc->sc_dev, "unable to allocate ccbs\n"); goto free_cq; } Index: src/sys/dev/ic/nvmevar.h diff -u src/sys/dev/ic/nvmevar.h:1.9 src/sys/dev/ic/nvmevar.h:1.10 --- src/sys/dev/ic/nvmevar.h:1.9 Thu Oct 20 19:20:40 2016 +++ src/sys/dev/ic/nvmevar.h Tue Nov 1 14:24:35 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: nvmevar.h,v 1.9 2016/10/20 19:20:40 jdolecek Exp $ */ +/* $NetBSD: nvmevar.h,v 1.10 2016/11/01 14:24:35 jdolecek Exp $ */ /* $OpenBSD: nvmevar.h,v 1.8 2016/04/14 11:18:32 dlg Exp $ */ /* @@ -86,7 +86,8 @@ struct nvme_queue { uint16_t q_cq_phase; kmutex_t q_ccb_mtx; - u_int q_nccbs; + uint16_t q_nccbs; /* total number of ccbs */ + uint16_t q_nccbs_avail; /* available ccbs */ struct nvme_ccb *q_ccbs; SIMPLEQ_HEAD(, nvme_ccb) q_ccb_list; struct nvme_dmamem *q_ccb_prpls;