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;