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; }