Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src Add NVMe command passthrough support.
details: https://anonhg.NetBSD.org/src/rev/705396b33cb5
branches: trunk
changeset: 345666:705396b33cb5
user: nonaka <nonaka%NetBSD.org@localhost>
date: Sat Jun 04 16:11:50 2016 +0000
description:
Add NVMe command passthrough support.
diffstat:
distrib/sets/lists/comp/mi | 4 +-
etc/MAKEDEV.tmpl | 20 ++-
etc/etc.amd64/MAKEDEV.conf | 6 +-
sys/conf/majors | 4 +-
sys/dev/ic/Makefile | 5 +-
sys/dev/ic/nvme.c | 331 ++++++++++++++++++++++++++++++++++++++++++++-
sys/dev/ic/nvmeio.h | 97 +++++++++++++
sys/dev/ic/nvmereg.h | 7 +-
sys/dev/ic/nvmevar.h | 5 +-
9 files changed, 469 insertions(+), 10 deletions(-)
diffs (truncated from 641 to 300 lines):
diff -r 3eee8208c0ff -r 705396b33cb5 distrib/sets/lists/comp/mi
--- a/distrib/sets/lists/comp/mi Sat Jun 04 15:27:11 2016 +0000
+++ b/distrib/sets/lists/comp/mi Sat Jun 04 16:11:50 2016 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.2038 2016/06/03 21:55:50 joerg Exp $
+# $NetBSD: mi,v 1.2039 2016/06/04 16:11:50 nonaka Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
./etc/mtree/set.comp comp-sys-root
@@ -498,6 +498,8 @@
./usr/include/dev/ic/nec765reg.h comp-obsolete obsolete
./usr/include/dev/ic/ns16450reg.h comp-obsolete obsolete
./usr/include/dev/ic/ns16550reg.h comp-obsolete obsolete
+./usr/include/dev/ic/nvmeio.h comp-c-include
+./usr/include/dev/ic/nvmereg.h comp-c-include
./usr/include/dev/ic/opl3sa3.h comp-obsolete obsolete
./usr/include/dev/ic/opl3sa3reg.h comp-obsolete obsolete
./usr/include/dev/ic/pcdisplay.h comp-obsolete obsolete
diff -r 3eee8208c0ff -r 705396b33cb5 etc/MAKEDEV.tmpl
--- a/etc/MAKEDEV.tmpl Sat Jun 04 15:27:11 2016 +0000
+++ b/etc/MAKEDEV.tmpl Sat Jun 04 16:11:50 2016 +0000
@@ -1,5 +1,5 @@
#!/bin/sh -
-# $NetBSD: MAKEDEV.tmpl,v 1.179 2016/01/28 19:06:39 riz Exp $
+# $NetBSD: MAKEDEV.tmpl,v 1.180 2016/06/04 16:11:50 nonaka Exp $
#
# Copyright (c) 2003,2007,2008 The NetBSD Foundation, Inc.
# All rights reserved.
@@ -264,6 +264,8 @@
# np* UNIBUS Ethernet co-processor interface, for downloading.
# npf NPF packet filter
# nsmb* SMB requester
+# nvme* Non-Volatile Memory Host Controller Interface device driver
+# nvme*ns* Non-Volatile Memory namespace
# openfirm OpenFirmware accessor
# pad* Pseudo-audio device driver
# pci* PCI bus access devices
@@ -2201,6 +2203,22 @@
mkdev vchiq c %vchiq_chr% 0 600
;;
+nvme[0-9]*ns[0-9]*)
+ unit=${i#nvme}
+ unit=${unit%ns*}
+ subunit=${i#nvme${unit}ns}
+ if [ 0$subunit -le 0 -o 0$subunit -ge 65536 ]; then
+ warn "bad nsid for $i: $subunit"
+ break
+ fi
+ mkdev nvme${unit}ns$subunit c %nvmens_chr% $(($unit * 65536 + $subunit))
+ ;;
+
+nvme[0-9]*)
+ unit=${i#nvme}
+ mkdev nvme$unit c %nvme_chr% $unit
+ ;;
+
midevend)
%MI_DEVICES_END%
local)
diff -r 3eee8208c0ff -r 705396b33cb5 etc/etc.amd64/MAKEDEV.conf
--- a/etc/etc.amd64/MAKEDEV.conf Sat Jun 04 15:27:11 2016 +0000
+++ b/etc/etc.amd64/MAKEDEV.conf Sat Jun 04 16:11:50 2016 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: MAKEDEV.conf,v 1.21 2015/02/22 14:42:44 christos Exp $
+# $NetBSD: MAKEDEV.conf,v 1.22 2016/06/04 16:11:50 nonaka Exp $
# As of 2003-04-17, the "init" case must not create more than 890 entries.
all_md)
@@ -12,6 +12,10 @@
makedev ccd0 md0 random
makedev cgd0 cgd1
makedev amr0 iop0 mfi0 mlx0 mly0 dpti0 dpt0 twe0
+ makedev nvme0 nvme0ns1 nvme0ns2 nvme0ns3 nvme0ns4
+ makedev nvme1 nvme1ns1 nvme1ns2 nvme1ns3 nvme1ns4
+ makedev nvme2 nvme2ns1 nvme2ns2 nvme1ns3 nvme2ns4
+ makedev nvme3 nvme3ns1 nvme3ns2 nvme1ns3 nvme3ns4
makedev raid0 raid1 raid2 raid3
makedev ld0 ld1 ld2 ld3
makedev xbd0 xbd1 xbd2 xbd3 xen
diff -r 3eee8208c0ff -r 705396b33cb5 sys/conf/majors
--- a/sys/conf/majors Sat Jun 04 15:27:11 2016 +0000
+++ b/sys/conf/majors Sat Jun 04 16:11:50 2016 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: majors,v 1.73 2016/05/13 07:41:47 skrll Exp $
+# $NetBSD: majors,v 1.74 2016/06/04 16:11:50 nonaka Exp $
#
# Device majors for Machine-Independent drivers.
#
@@ -72,3 +72,5 @@
# 310-339 reserved for previously not MI storage devices
device-major hdmicec char 340 hdmicec
+device-major nvme char 341 nvme
+device-major nvmens char 342 nvmens
diff -r 3eee8208c0ff -r 705396b33cb5 sys/dev/ic/Makefile
--- a/sys/dev/ic/Makefile Sat Jun 04 15:27:11 2016 +0000
+++ b/sys/dev/ic/Makefile Sat Jun 04 16:11:50 2016 +0000
@@ -1,9 +1,10 @@
-# $NetBSD: Makefile,v 1.24 2005/12/11 12:21:25 christos Exp $
+# $NetBSD: Makefile,v 1.25 2016/06/04 16:11:51 nonaka Exp $
INCSDIR= /usr/include/dev/ic
# Only install includes which are used by userland
INCS= athioctl.h bt8xx.h hd44780var.h icpreg.h icp_ioctl.h isp_ioctl.h \
- mlxreg.h mlxio.h rrunnerreg.h rrunnervar.h wdcreg.h wi_ieee.h
+ mlxreg.h mlxio.h nvmeio.h nvmereg.h rrunnerreg.h rrunnervar.h \
+ wdcreg.h wi_ieee.h
.include <bsd.kinc.mk>
diff -r 3eee8208c0ff -r 705396b33cb5 sys/dev/ic/nvme.c
--- a/sys/dev/ic/nvme.c Sat Jun 04 15:27:11 2016 +0000
+++ b/sys/dev/ic/nvme.c Sat Jun 04 16:11:50 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nvme.c,v 1.2 2016/05/02 19:18:29 christos Exp $ */
+/* $NetBSD: nvme.c,v 1.3 2016/06/04 16:11:51 nonaka 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.2 2016/05/02 19:18:29 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvme.c,v 1.3 2016/06/04 16:11:51 nonaka Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -26,14 +26,19 @@
#include <sys/atomic.h>
#include <sys/bus.h>
#include <sys/buf.h>
+#include <sys/conf.h>
#include <sys/device.h>
#include <sys/kmem.h>
#include <sys/once.h>
+#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/mutex.h>
+#include <uvm/uvm_extern.h>
+
#include <dev/ic/nvmereg.h>
#include <dev/ic/nvmevar.h>
+#include <dev/ic/nvmeio.h>
int nvme_adminq_size = 128;
int nvme_ioq_size = 128;
@@ -95,6 +100,13 @@
static void nvme_ns_sync_done(struct nvme_queue *, struct nvme_ccb *,
struct nvme_cqe *);
+static void nvme_pt_fill(struct nvme_queue *, struct nvme_ccb *,
+ void *);
+static void nvme_pt_done(struct nvme_queue *, struct nvme_ccb *,
+ struct nvme_cqe *);
+static int nvme_command_passthrough(struct nvme_softc *,
+ struct nvme_pt_command *, uint16_t, struct lwp *, bool);
+
#define nvme_read4(_s, _r) \
bus_space_read_4((_s)->sc_iot, (_s)->sc_ioh, (_r))
#define nvme_write4(_s, _r, _v) \
@@ -729,6 +741,136 @@
}
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;
+ bus_dmamap_t dmap = ccb->ccb_dmamap;
+ int i;
+
+ sqe->opcode = pt->cmd.opcode;
+ htolem32(&sqe->nsid, pt->cmd.nsid);
+
+ if (pt->buf != NULL && pt->len > 0) {
+ htolem64(&sqe->entry.prp[0], dmap->dm_segs[0].ds_addr);
+ switch (dmap->dm_nsegs) {
+ case 1:
+ break;
+ case 2:
+ htolem64(&sqe->entry.prp[1], dmap->dm_segs[1].ds_addr);
+ break;
+ default:
+ 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(q->q_ccb_prpls),
+ ccb->ccb_prpl_off,
+ sizeof(*ccb->ccb_prpl) * dmap->dm_nsegs - 1,
+ BUS_DMASYNC_PREWRITE);
+ htolem64(&sqe->entry.prp[1], ccb->ccb_prpl_dva);
+ break;
+ }
+ }
+
+ htolem32(&sqe->cdw10, pt->cmd.cdw10);
+ htolem32(&sqe->cdw11, pt->cmd.cdw11);
+ htolem32(&sqe->cdw12, pt->cmd.cdw12);
+ htolem32(&sqe->cdw13, pt->cmd.cdw13);
+ htolem32(&sqe->cdw14, pt->cmd.cdw14);
+ htolem32(&sqe->cdw15, pt->cmd.cdw15);
+}
+
+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;
+ bus_dmamap_t dmap = ccb->ccb_dmamap;
+
+ if (pt->buf != NULL && pt->len > 0) {
+ if (dmap->dm_nsegs > 2) {
+ bus_dmamap_sync(sc->sc_dmat,
+ NVME_DMA_MAP(q->q_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,
+ pt->is_read ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_dmat, dmap);
+ }
+
+ pt->cpl.cdw0 = cqe->cdw0;
+ pt->cpl.flags = cqe->flags & ~NVME_CQE_PHASE;
+}
+
+static int
+nvme_command_passthrough(struct nvme_softc *sc, struct nvme_pt_command *pt,
+ uint16_t nsid, struct lwp *l, bool is_adminq)
+{
+ struct nvme_queue *q;
+ struct nvme_ccb *ccb;
+ void *buf = NULL;
+ int error;
+
+ if ((pt->buf == NULL && pt->len > 0) ||
+ (pt->buf != NULL && pt->len == 0))
+ return EINVAL;
+
+ q = is_adminq ? sc->sc_admin_q : nvme_get_q(sc);
+ ccb = nvme_ccb_get(q);
+ if (ccb == NULL)
+ return EBUSY;
+
+ if (pt->buf != NULL && pt->len > 0) {
+ buf = kmem_alloc(pt->len, KM_SLEEP);
+ if (buf == NULL) {
+ error = ENOMEM;
+ goto ccb_put;
+ }
+ if (!pt->is_read) {
+ error = copyin(pt->buf, buf, pt->len);
+ if (error)
+ goto kmem_free;
+ }
+ error = bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmamap, buf,
+ pt->len, NULL,
+ BUS_DMA_WAITOK |
+ (pt->is_read ? BUS_DMA_READ : BUS_DMA_WRITE));
+ if (error)
+ goto kmem_free;
+ bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap,
+ 0, ccb->ccb_dmamap->dm_mapsize,
+ pt->is_read ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
+ }
+
+ ccb->ccb_done = nvme_pt_done;
+ ccb->ccb_cookie = pt;
+
+ pt->cmd.nsid = nsid;
+ if (nvme_poll(sc, q, ccb, nvme_pt_fill)) {
+ error = EIO;
+ goto out;
+ }
+
+ 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);
+ }
+ccb_put:
+ nvme_ccb_put(q, ccb);
+ return error;
+}
+
+static void
nvme_q_submit(struct nvme_softc *sc, struct nvme_queue *q, struct nvme_ccb *ccb,
void (*fill)(struct nvme_queue *, struct nvme_ccb *, void *))
{
Home |
Main Index |
Thread Index |
Old Index