diff options
Diffstat (limited to 'sys/dev/nvmf')
| -rw-r--r-- | sys/dev/nvmf/controller/nvmft_controller.c | 16 | ||||
| -rw-r--r-- | sys/dev/nvmf/controller/nvmft_qpair.c | 6 | ||||
| -rw-r--r-- | sys/dev/nvmf/controller/nvmft_var.h | 1 | ||||
| -rw-r--r-- | sys/dev/nvmf/host/nvmf.c | 16 | ||||
| -rw-r--r-- | sys/dev/nvmf/host/nvmf_ns.c | 3 | ||||
| -rw-r--r-- | sys/dev/nvmf/host/nvmf_qpair.c | 6 | ||||
| -rw-r--r-- | sys/dev/nvmf/host/nvmf_var.h | 1 | ||||
| -rw-r--r-- | sys/dev/nvmf/nvmf_tcp.c | 14 | ||||
| -rw-r--r-- | sys/dev/nvmf/nvmf_transport.c | 12 | ||||
| -rw-r--r-- | sys/dev/nvmf/nvmf_transport.h | 14 | ||||
| -rw-r--r-- | sys/dev/nvmf/nvmf_transport_internal.h | 6 |
11 files changed, 91 insertions, 4 deletions
diff --git a/sys/dev/nvmf/controller/nvmft_controller.c b/sys/dev/nvmf/controller/nvmft_controller.c index 390467534ca2..1618c1f96dac 100644 --- a/sys/dev/nvmf/controller/nvmft_controller.c +++ b/sys/dev/nvmf/controller/nvmft_controller.c @@ -31,7 +31,7 @@ nvmft_printf(struct nvmft_controller *ctrlr, const char *fmt, ...) va_list ap; size_t retval; - sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN); + sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN | SBUF_INCLUDENUL); sbuf_set_drain(&sb, sbuf_printf_drain, &retval); sbuf_printf(&sb, "nvmft%u: ", ctrlr->cntlid); @@ -103,6 +103,19 @@ nvmft_keep_alive_timer(void *arg) callout_schedule_sbt(&ctrlr->ka_timer, ctrlr->ka_sbt, 0, C_HARDCLOCK); } +static void +nvmft_update_cdata(struct nvmft_controller *ctrlr) +{ + uint32_t ioccsz, val; + + val = nvmft_max_ioccsz(ctrlr->admin); + if (val != 0) { + ioccsz = le32toh(ctrlr->cdata.ioccsz) * 16; + if (val < ioccsz) + ctrlr->cdata.ioccsz = htole32(val / 16); + } +} + int nvmft_handoff_admin_queue(struct nvmft_port *np, enum nvmf_trtype trtype, const nvlist_t *params, const struct nvmf_fabric_connect_cmd *cmd, @@ -160,6 +173,7 @@ nvmft_handoff_admin_queue(struct nvmft_port *np, enum nvmf_trtype trtype, (int)sizeof(data->hostnqn), data->hostnqn); ctrlr->admin = qp; ctrlr->trtype = trtype; + nvmft_update_cdata(ctrlr); /* * The spec requires a non-zero KeepAlive timer, but allow a diff --git a/sys/dev/nvmf/controller/nvmft_qpair.c b/sys/dev/nvmf/controller/nvmft_qpair.c index 73c7bb280780..1300c9ec91fc 100644 --- a/sys/dev/nvmf/controller/nvmft_qpair.c +++ b/sys/dev/nvmf/controller/nvmft_qpair.c @@ -182,6 +182,12 @@ nvmft_qpair_name(struct nvmft_qpair *qp) return (qp->name); } +uint32_t +nvmft_max_ioccsz(struct nvmft_qpair *qp) +{ + return (nvmf_max_ioccsz(qp->qp)); +} + static int _nvmft_send_response(struct nvmft_qpair *qp, const void *cqe) { diff --git a/sys/dev/nvmf/controller/nvmft_var.h b/sys/dev/nvmf/controller/nvmft_var.h index 85032b2dc55f..b3a5278a639c 100644 --- a/sys/dev/nvmf/controller/nvmft_var.h +++ b/sys/dev/nvmf/controller/nvmft_var.h @@ -145,6 +145,7 @@ struct nvmft_controller *nvmft_qpair_ctrlr(struct nvmft_qpair *qp); void nvmft_qpair_datamove(struct nvmft_qpair *qp, union ctl_io *io); uint16_t nvmft_qpair_id(struct nvmft_qpair *qp); const char *nvmft_qpair_name(struct nvmft_qpair *qp); +uint32_t nvmft_max_ioccsz(struct nvmft_qpair *qp); void nvmft_command_completed(struct nvmft_qpair *qp, struct nvmf_capsule *nc); int nvmft_send_response(struct nvmft_qpair *qp, const void *cqe); diff --git a/sys/dev/nvmf/host/nvmf.c b/sys/dev/nvmf/host/nvmf.c index 1ac0d142443b..8ed801524089 100644 --- a/sys/dev/nvmf/host/nvmf.c +++ b/sys/dev/nvmf/host/nvmf.c @@ -498,7 +498,7 @@ nvmf_attach(device_t dev) nvlist_t *nvl = device_get_ivars(dev); const nvlist_t * const *io; struct sysctl_oid *oid; - uint64_t val; + uint64_t mpsmin, val; u_int i; int error; @@ -545,13 +545,20 @@ nvmf_attach(device_t dev) sc->vs = val; /* Honor MDTS if it is set. */ + mpsmin = (uint64_t)1 << (NVME_MPS_SHIFT + + NVME_CAP_HI_MPSMIN(sc->cap >> 32)); sc->max_xfer_size = maxphys; if (sc->cdata->mdts != 0) { sc->max_xfer_size = ulmin(sc->max_xfer_size, - 1 << (sc->cdata->mdts + NVME_MPS_SHIFT + - NVME_CAP_HI_MPSMIN(sc->cap >> 32))); + mpsmin << sc->cdata->mdts); } + /* Honor any transfer size restriction imposed by the transport. */ + val = nvmf_max_xfer_size_qp(sc->io[0]); + if (val >= mpsmin) + sc->max_xfer_size = ulmin(sc->max_xfer_size, + rounddown2(val, mpsmin)); + io = nvlist_get_nvlist_array(nvl, "io", NULL); sc->max_pending_io = nvlist_get_number(io[0], "qsize") * sc->num_io_queues; @@ -1230,6 +1237,9 @@ nvmf_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int flag, case NVME_GET_CONTROLLER_DATA: memcpy(arg, sc->cdata, sizeof(*sc->cdata)); return (0); + case DIOCGIDENT: + nvme_cdata_get_disk_ident(sc->cdata, (uint8_t *)arg); + return (0); case NVMF_RECONNECT_PARAMS: nv = (struct nvmf_ioc_nv *)arg; return (nvmf_reconnect_params(sc, nv)); diff --git a/sys/dev/nvmf/host/nvmf_ns.c b/sys/dev/nvmf/host/nvmf_ns.c index 4215c8295d2e..d57280e19d41 100644 --- a/sys/dev/nvmf/host/nvmf_ns.c +++ b/sys/dev/nvmf/host/nvmf_ns.c @@ -278,6 +278,9 @@ nvmf_ns_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, sizeof(gnsid->cdev)); gnsid->nsid = ns->id; return (0); + case DIOCGIDENT: + nvme_cdata_get_disk_ident(ns->sc->cdata, (uint8_t *)arg); + return (0); case DIOCGMEDIASIZE: *(off_t *)arg = ns->size; return (0); diff --git a/sys/dev/nvmf/host/nvmf_qpair.c b/sys/dev/nvmf/host/nvmf_qpair.c index 2f511cf0406d..adb57e52d002 100644 --- a/sys/dev/nvmf/host/nvmf_qpair.c +++ b/sys/dev/nvmf/host/nvmf_qpair.c @@ -416,6 +416,12 @@ nvmf_destroy_qp(struct nvmf_host_qpair *qp) free(qp, M_NVMF); } +uint64_t +nvmf_max_xfer_size_qp(struct nvmf_host_qpair *qp) +{ + return (nvmf_max_xfer_size(qp->qp)); +} + void nvmf_submit_request(struct nvmf_request *req) { diff --git a/sys/dev/nvmf/host/nvmf_var.h b/sys/dev/nvmf/host/nvmf_var.h index 606245b3969c..9190da300d85 100644 --- a/sys/dev/nvmf/host/nvmf_var.h +++ b/sys/dev/nvmf/host/nvmf_var.h @@ -210,6 +210,7 @@ struct nvmf_host_qpair *nvmf_init_qp(struct nvmf_softc *sc, enum nvmf_trtype trtype, const nvlist_t *nvl, const char *name, u_int qid); void nvmf_shutdown_qp(struct nvmf_host_qpair *qp); void nvmf_destroy_qp(struct nvmf_host_qpair *qp); +uint64_t nvmf_max_xfer_size_qp(struct nvmf_host_qpair *qp); struct nvmf_request *nvmf_allocate_request(struct nvmf_host_qpair *qp, void *sqe, nvmf_request_complete_t *cb, void *cb_arg, int how); void nvmf_submit_request(struct nvmf_request *req); diff --git a/sys/dev/nvmf/nvmf_tcp.c b/sys/dev/nvmf/nvmf_tcp.c index e50d7ff48d2b..481c769cedcb 100644 --- a/sys/dev/nvmf/nvmf_tcp.c +++ b/sys/dev/nvmf/nvmf_tcp.c @@ -1602,6 +1602,18 @@ tcp_free_qpair(struct nvmf_qpair *nq) tcp_release_qpair(qp); } +static uint32_t +tcp_max_ioccsz(struct nvmf_qpair *nq) +{ + return (0); +} + +static uint64_t +tcp_max_xfer_size(struct nvmf_qpair *nq) +{ + return (0); +} + static struct nvmf_capsule * tcp_allocate_capsule(struct nvmf_qpair *nq, int how) { @@ -1872,6 +1884,8 @@ tcp_send_controller_data(struct nvmf_capsule *nc, uint32_t data_offset, struct nvmf_transport_ops tcp_ops = { .allocate_qpair = tcp_allocate_qpair, .free_qpair = tcp_free_qpair, + .max_ioccsz = tcp_max_ioccsz, + .max_xfer_size = tcp_max_xfer_size, .allocate_capsule = tcp_allocate_capsule, .free_capsule = tcp_free_capsule, .transmit_capsule = tcp_transmit_capsule, diff --git a/sys/dev/nvmf/nvmf_transport.c b/sys/dev/nvmf/nvmf_transport.c index 1d3f5ea4cf69..92d71d1b13fd 100644 --- a/sys/dev/nvmf/nvmf_transport.c +++ b/sys/dev/nvmf/nvmf_transport.c @@ -188,6 +188,18 @@ nvmf_sqhd_valid(struct nvmf_capsule *nc) return (nc->nc_sqhd_valid); } +uint64_t +nvmf_max_xfer_size(struct nvmf_qpair *qp) +{ + return (qp->nq_ops->max_xfer_size(qp)); +} + +uint32_t +nvmf_max_ioccsz(struct nvmf_qpair *qp) +{ + return (qp->nq_ops->max_ioccsz(qp)); +} + uint8_t nvmf_validate_command_capsule(struct nvmf_capsule *nc) { diff --git a/sys/dev/nvmf/nvmf_transport.h b/sys/dev/nvmf/nvmf_transport.h index b192baeaccc1..495e0dbc8c37 100644 --- a/sys/dev/nvmf/nvmf_transport.h +++ b/sys/dev/nvmf/nvmf_transport.h @@ -81,9 +81,23 @@ void *nvmf_capsule_sqe(struct nvmf_capsule *nc); void *nvmf_capsule_cqe(struct nvmf_capsule *nc); bool nvmf_sqhd_valid(struct nvmf_capsule *nc); +/* Host-specific APIs. */ + +/* + * Largest I/O request size for a single command supported by the + * transport. If the transport does not have a limit, returns 0. + */ +uint64_t nvmf_max_xfer_size(struct nvmf_qpair *qp); + /* Controller-specific APIs. */ /* + * Largest I/O command capsule size (IOCCSZ) supported by the + * transport. If the transport does not have a limit, returns 0. + */ +uint32_t nvmf_max_ioccsz(struct nvmf_qpair *qp); + +/* * A controller calls this function to check for any * transport-specific errors (invalid fields) in a received command * capsule. The callback returns a generic command status value: diff --git a/sys/dev/nvmf/nvmf_transport_internal.h b/sys/dev/nvmf/nvmf_transport_internal.h index eb819a5c83b9..9b459716168a 100644 --- a/sys/dev/nvmf/nvmf_transport_internal.h +++ b/sys/dev/nvmf/nvmf_transport_internal.h @@ -25,6 +25,12 @@ struct nvmf_transport_ops { const nvlist_t *nvl); void (*free_qpair)(struct nvmf_qpair *qp); + /* Limit on I/O command capsule size. */ + uint32_t (*max_ioccsz)(struct nvmf_qpair *qp); + + /* Limit on transfer size. */ + uint64_t (*max_xfer_size)(struct nvmf_qpair *qp); + /* Capsule operations. */ struct nvmf_capsule *(*allocate_capsule)(struct nvmf_qpair *qp, int how); |
