diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2016-04-14 06:23:21 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2016-04-14 06:23:21 +0000 |
commit | 8383767e7eac6536f2e262d04c97c6b5be037cde (patch) | |
tree | ac624e9f71998e608cb7380533077dfce649febb /sys/dev | |
parent | e0d60a5cb8dbc453e468b8b7b3afc09bea5918ea (diff) |
if io needs more than two prpe slots, overflow into the ccb prpl
this should be enough to make io reliable
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ic/nvme.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/sys/dev/ic/nvme.c b/sys/dev/ic/nvme.c index 0d47e298871..2b13fdf47dc 100644 --- a/sys/dev/ic/nvme.c +++ b/sys/dev/ic/nvme.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nvme.c,v 1.42 2016/04/14 06:20:34 dlg Exp $ */ +/* $OpenBSD: nvme.c,v 1.43 2016/04/14 06:23:20 dlg Exp $ */ /* * Copyright (c) 2014 David Gwynne <dlg@openbsd.org> @@ -499,6 +499,7 @@ nvme_scsi_io(struct scsi_xfer *xs, struct nvme_softc *sc = link->adapter_softc; struct nvme_ccb *ccb = xs->io; bus_dmamap_t dmap = ccb->ccb_dmamap; + int i; ccb->ccb_done = nvme_scsi_io_done; ccb->ccb_cookie = xs; @@ -512,6 +513,18 @@ nvme_scsi_io(struct scsi_xfer *xs, ISSET(xs->flags, SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); + if (dmap->dm_nsegs > 2) { + for (i = 1; i < dmap->dm_nsegs; i++) { + htolem64(&ccb->ccb_prpl[i - 1], + dmap->dm_segs[i].ds_addr); + } + bus_dmamap_sync(sc->sc_dmat, + NVME_DMA_MAP(sc->sc_ccb_prpls), + ccb->ccb_prpl_off, + sizeof(*ccb->ccb_prpl) * dmap->dm_nsegs - 1, + BUS_DMASYNC_PREWRITE); + } + if (ISSET(xs->flags, SCSI_POLL)) { nvme_poll(sc, sc->sc_q, ccb, fill); return; @@ -565,7 +578,9 @@ nvme_scsi_io_fill(struct nvme_softc *sc, struct nvme_ccb *ccb, htolem64(&sqe->entry.prp[1], dmap->dm_segs[1].ds_addr); break; default: - panic("not yet"); + /* the prp list is already set up and synced */ + htolem64(&sqe->entry.prp[1], ccb->ccb_prpl_dva); + break; } htolem64(&sqe->slba, lba); @@ -580,6 +595,14 @@ nvme_scsi_io_done(struct nvme_softc *sc, struct nvme_ccb *ccb, bus_dmamap_t dmap = ccb->ccb_dmamap; u_int16_t flags; + if (dmap->dm_nsegs > 2) { + bus_dmamap_sync(sc->sc_dmat, + NVME_DMA_MAP(sc->sc_ccb_prpls), + ccb->ccb_prpl_off, + sizeof(*ccb->ccb_prpl) * dmap->dm_nsegs - 1, + BUS_DMASYNC_POSTWRITE); + } + bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, ISSET(xs->flags, SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); |