Module Name: src
Committed By: jdolecek
Date: Sat Mar 17 00:28:03 UTC 2018
Modified Files:
src/sys/dev/ic: nvme.c
Log Message:
switch handling of passthrough commands to use queue, instead of polling
should fix PR kern/53059 by Frank Kardel
To generate a diff of this commit:
cvs rdiff -u -r1.34 -r1.35 src/sys/dev/ic/nvme.c
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.34 src/sys/dev/ic/nvme.c:1.35
--- src/sys/dev/ic/nvme.c:1.34 Fri Mar 16 23:31:19 2018
+++ src/sys/dev/ic/nvme.c Sat Mar 17 00:28:03 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: nvme.c,v 1.34 2018/03/16 23:31:19 jdolecek Exp $ */
+/* $NetBSD: nvme.c,v 1.35 2018/03/17 00:28:03 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.34 2018/03/16 23:31:19 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvme.c,v 1.35 2018/03/17 00:28:03 jdolecek Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -929,12 +929,18 @@ nvme_ns_free(struct nvme_softc *sc, uint
kmem_free(identify, sizeof(*identify));
}
+struct nvme_pt_state {
+ struct nvme_pt_command *pt;
+ bool finished;
+};
+
static void
nvme_pt_fill(struct nvme_queue *q, struct nvme_ccb *ccb, void *slot)
{
struct nvme_softc *sc = q->q_sc;
struct nvme_sqe *sqe = slot;
- struct nvme_pt_command *pt = ccb->ccb_cookie;
+ struct nvme_pt_state *state = ccb->ccb_cookie;
+ struct nvme_pt_command *pt = state->pt;
bus_dmamap_t dmap = ccb->ccb_dmamap;
int i;
@@ -976,7 +982,8 @@ static void
nvme_pt_done(struct nvme_queue *q, struct nvme_ccb *ccb, struct nvme_cqe *cqe)
{
struct nvme_softc *sc = q->q_sc;
- struct nvme_pt_command *pt = ccb->ccb_cookie;
+ struct nvme_pt_state *state = ccb->ccb_cookie;
+ struct nvme_pt_command *pt = state->pt;
bus_dmamap_t dmap = ccb->ccb_dmamap;
if (pt->buf != NULL && pt->len > 0) {
@@ -995,6 +1002,18 @@ nvme_pt_done(struct nvme_queue *q, struc
pt->cpl.cdw0 = lemtoh32(&cqe->cdw0);
pt->cpl.flags = lemtoh16(&cqe->flags) & ~NVME_CQE_PHASE;
+
+ state->finished = true;
+
+ nvme_ccb_put(q, ccb);
+}
+
+static bool
+nvme_pt_finished(void *cookie)
+{
+ struct nvme_pt_state *state = cookie;
+
+ return state->finished;
}
static int
@@ -1004,6 +1023,7 @@ nvme_command_passthrough(struct nvme_sof
struct nvme_queue *q;
struct nvme_ccb *ccb;
void *buf = NULL;
+ struct nvme_pt_state state;
int error;
/* limit command size to maximum data transfer size */
@@ -1034,24 +1054,30 @@ nvme_command_passthrough(struct nvme_sof
pt->is_read ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
}
+ memset(&state, 0, sizeof(state));
+ state.pt = pt;
+ state.finished = false;
+
ccb->ccb_done = nvme_pt_done;
- ccb->ccb_cookie = pt;
+ ccb->ccb_cookie = &state;
pt->cmd.nsid = nsid;
- if (nvme_poll(sc, q, ccb, nvme_pt_fill, NVME_TIMO_PT)) {
- error = EIO;
- goto out;
- }
+
+ nvme_q_submit(sc, q, ccb, nvme_pt_fill);
+
+ /* wait for completion */
+ nvme_q_wait_complete(sc, q, nvme_pt_finished, &state);
+ KASSERT(state.finished);
error = 0;
-out:
+
if (buf != NULL) {
if (error == 0 && pt->is_read)
error = copyout(buf, pt->buf, pt->len);
kmem_free:
kmem_free(buf, pt->len);
}
- nvme_ccb_put(q, ccb);
+
return error;
}