diff --git a/sys/dev/nvmf/nvmf_transport.c b/sys/dev/nvmf/nvmf_transport.c new file mode 100644 index 000000000000..14d526192270 --- /dev/null +++ b/sys/dev/nvmf/nvmf_transport.c @@ -0,0 +1,344 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022-2024 Chelsio Communications, Inc. + * Written by: John Baldwin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Transport-independent support for fabrics queue pairs and commands. */ + +struct nvmf_transport { + struct nvmf_transport_ops *nt_ops; + + volatile u_int nt_active_qpairs; + SLIST_ENTRY(nvmf_transport) nt_link; +}; + +/* nvmf_transports[nvmf_trtype] is sorted by priority */ +static SLIST_HEAD(, nvmf_transport) nvmf_transports[NVMF_TRTYPE_TCP + 1]; +static struct sx nvmf_transports_lock; + +static MALLOC_DEFINE(M_NVMF_TRANSPORT, "nvmf_xport", + "NVMe over Fabrics transport"); + +SYSCTL_NODE(_kern, OID_AUTO, nvmf, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, + "NVMe over Fabrics"); + +static bool +nvmf_supported_trtype(enum nvmf_trtype trtype) +{ + return (trtype < nitems(nvmf_transports)); +} + +struct nvmf_qpair * +nvmf_allocate_qpair(enum nvmf_trtype trtype, bool controller, + const struct nvmf_handoff_qpair_params *params, + nvmf_qpair_error_t *error_cb, void *error_cb_arg, + nvmf_capsule_receive_t *receive_cb, void *receive_cb_arg) +{ + struct nvmf_transport *nt; + struct nvmf_qpair *qp; + + if (!nvmf_supported_trtype(trtype)) + return (NULL); + + sx_slock(&nvmf_transports_lock); + SLIST_FOREACH(nt, &nvmf_transports[trtype], nt_link) { + qp = nt->nt_ops->allocate_qpair(controller, params); + if (qp != NULL) { + refcount_acquire(&nt->nt_active_qpairs); + break; + } + } + sx_sunlock(&nvmf_transports_lock); + if (qp == NULL) + return (NULL); + + qp->nq_transport = nt; + qp->nq_ops = nt->nt_ops; + qp->nq_controller = controller; + qp->nq_error = error_cb; + qp->nq_error_arg = error_cb_arg; + qp->nq_receive = receive_cb; + qp->nq_receive_arg = receive_cb_arg; + qp->nq_admin = params->admin; + return (qp); +} + +void +nvmf_free_qpair(struct nvmf_qpair *qp) +{ + struct nvmf_transport *nt; + + nt = qp->nq_transport; + qp->nq_ops->free_qpair(qp); + if (refcount_release(&nt->nt_active_qpairs)) + wakeup(nt); +} + +struct nvmf_capsule * +nvmf_allocate_command(struct nvmf_qpair *qp, const void *sqe, int how) +{ + struct nvmf_capsule *nc; + + KASSERT(how == M_WAITOK || how == M_NOWAIT, + ("%s: invalid how", __func__)); + nc = qp->nq_ops->allocate_capsule(qp, how); + if (nc == NULL) + return (NULL); + + nc->nc_qpair = qp; + nc->nc_qe_len = sizeof(struct nvme_command); + memcpy(&nc->nc_sqe, sqe, nc->nc_qe_len); + + /* 4.2 of NVMe base spec: Fabrics always uses SGL. */ + nc->nc_sqe.fuse &= ~NVMEM(NVME_CMD_PSDT); + nc->nc_sqe.fuse |= NVMEF(NVME_CMD_PSDT, NVME_PSDT_SGL); + return (nc); +} + +struct nvmf_capsule * +nvmf_allocate_response(struct nvmf_qpair *qp, const void *cqe, int how) +{ + struct nvmf_capsule *nc; + + KASSERT(how == M_WAITOK || how == M_NOWAIT, + ("%s: invalid how", __func__)); + nc = qp->nq_ops->allocate_capsule(qp, how); + if (nc == NULL) + return (NULL); + + nc->nc_qpair = qp; + nc->nc_qe_len = sizeof(struct nvme_completion); + memcpy(&nc->nc_cqe, cqe, nc->nc_qe_len); + return (nc); +} + +int +nvmf_capsule_append_data(struct nvmf_capsule *nc, struct memdesc *mem, + size_t len, bool send, nvmf_io_complete_t *complete_cb, + void *cb_arg) +{ + if (nc->nc_data.io_len != 0) + return (EBUSY); + + nc->nc_send_data = send; + nc->nc_data.io_mem = *mem; + nc->nc_data.io_len = len; + nc->nc_data.io_complete = complete_cb; + nc->nc_data.io_complete_arg = cb_arg; + return (0); +} + +void +nvmf_free_capsule(struct nvmf_capsule *nc) +{ + nc->nc_qpair->nq_ops->free_capsule(nc); +} + +int +nvmf_transmit_capsule(struct nvmf_capsule *nc) +{ + return (nc->nc_qpair->nq_ops->transmit_capsule(nc)); +} + +void +nvmf_abort_capsule_data(struct nvmf_capsule *nc, int error) +{ + if (nc->nc_data.io_len != 0) + nvmf_complete_io_request(&nc->nc_data, 0, error); +} + +void * +nvmf_capsule_sqe(struct nvmf_capsule *nc) +{ + KASSERT(nc->nc_qe_len == sizeof(struct nvme_command), + ("%s: capsule %p is not a command capsule", __func__, nc)); + return (&nc->nc_sqe); +} + +void * +nvmf_capsule_cqe(struct nvmf_capsule *nc) +{ + KASSERT(nc->nc_qe_len == sizeof(struct nvme_completion), + ("%s: capsule %p is not a response capsule", __func__, nc)); + return (&nc->nc_cqe); +} + +uint8_t +nvmf_validate_command_capsule(struct nvmf_capsule *nc) +{ + KASSERT(nc->nc_qe_len == sizeof(struct nvme_command), + ("%s: capsule %p is not a command capsule", __func__, nc)); + + if (NVMEV(NVME_CMD_PSDT, nc->nc_sqe.fuse) != NVME_PSDT_SGL) + return (NVME_SC_INVALID_FIELD); + + return (nc->nc_qpair->nq_ops->validate_command_capsule(nc)); +} + +size_t +nvmf_capsule_data_len(const struct nvmf_capsule *nc) +{ + return (nc->nc_qpair->nq_ops->capsule_data_len(nc)); +} + +int +nvmf_receive_controller_data(struct nvmf_capsule *nc, uint32_t data_offset, + struct memdesc *mem, size_t len, nvmf_io_complete_t *complete_cb, + void *cb_arg) +{ + struct nvmf_io_request io; + + io.io_mem = *mem; + io.io_len = len; + io.io_complete = complete_cb; + io.io_complete_arg = cb_arg; + return (nc->nc_qpair->nq_ops->receive_controller_data(nc, data_offset, + &io)); +} + +u_int +nvmf_send_controller_data(struct nvmf_capsule *nc, uint32_t data_offset, + struct mbuf *m, size_t len) +{ + MPASS(m_length(m, NULL) == len); + return (nc->nc_qpair->nq_ops->send_controller_data(nc, data_offset, m, + len)); +} + +int +nvmf_transport_module_handler(struct module *mod, int what, void *arg) +{ + struct nvmf_transport_ops *ops = arg; + struct nvmf_transport *nt, *nt2, *prev; + int error; + + switch (what) { + case MOD_LOAD: + if (!nvmf_supported_trtype(ops->trtype)) { + printf("NVMF: Unsupported transport %u", ops->trtype); + return (EINVAL); + } + + nt = malloc(sizeof(*nt), M_NVMF_TRANSPORT, M_WAITOK | M_ZERO); + nt->nt_ops = arg; + + sx_xlock(&nvmf_transports_lock); + if (SLIST_EMPTY(&nvmf_transports[ops->trtype])) { + SLIST_INSERT_HEAD(&nvmf_transports[ops->trtype], nt, + nt_link); + } else { + prev = NULL; + SLIST_FOREACH(nt2, &nvmf_transports[ops->trtype], + nt_link) { + if (ops->priority > nt2->nt_ops->priority) + break; + prev = nt2; + } + if (prev == NULL) + SLIST_INSERT_HEAD(&nvmf_transports[ops->trtype], + nt, nt_link); + else + SLIST_INSERT_AFTER(prev, nt, nt_link); + } + sx_xunlock(&nvmf_transports_lock); + return (0); + + case MOD_QUIESCE: + if (!nvmf_supported_trtype(ops->trtype)) + return (0); + + sx_slock(&nvmf_transports_lock); + SLIST_FOREACH(nt, &nvmf_transports[ops->trtype], nt_link) { + if (nt->nt_ops == ops) + break; + } + if (nt == NULL) { + sx_sunlock(&nvmf_transports_lock); + return (0); + } + if (nt->nt_active_qpairs != 0) { + sx_sunlock(&nvmf_transports_lock); + return (EBUSY); + } + sx_sunlock(&nvmf_transports_lock); + return (0); + + case MOD_UNLOAD: + if (!nvmf_supported_trtype(ops->trtype)) + return (0); + + sx_xlock(&nvmf_transports_lock); + prev = NULL; + SLIST_FOREACH(nt, &nvmf_transports[ops->trtype], nt_link) { + if (nt->nt_ops == ops) + break; + prev = nt; + } + if (nt == NULL) { + KASSERT(nt->nt_active_qpairs == 0, + ("unregistered transport has connections")); + sx_xunlock(&nvmf_transports_lock); + return (0); + } + + if (prev == NULL) + SLIST_REMOVE_HEAD(&nvmf_transports[ops->trtype], + nt_link); + else + SLIST_REMOVE_AFTER(prev, nt_link); + + error = 0; + while (nt->nt_active_qpairs != 0 && error == 0) + error = sx_sleep(nt, &nvmf_transports_lock, PCATCH, + "nftunld", 0); + sx_xunlock(&nvmf_transports_lock); + if (error != 0) + return (error); + free(nt, M_NVMF_TRANSPORT); + return (0); + + default: + return (EOPNOTSUPP); + } +} + +static int +nvmf_transport_modevent(module_t mod __unused, int what, void *arg __unused) +{ + switch (what) { + case MOD_LOAD: + for (u_int i = 0; i < nitems(nvmf_transports); i++) + SLIST_INIT(&nvmf_transports[i]); + sx_init(&nvmf_transports_lock, "nvmf transports"); + return (0); + default: + return (EOPNOTSUPP); + } +} + +static moduledata_t nvmf_transport_mod = { + "nvmf_transport", + nvmf_transport_modevent, + 0 +}; + +DECLARE_MODULE(nvmf_transport, nvmf_transport_mod, SI_SUB_DRIVERS, + SI_ORDER_FIRST); +MODULE_VERSION(nvmf_transport, 1); diff --git a/sys/dev/nvmf/nvmf_transport.h b/sys/dev/nvmf/nvmf_transport.h new file mode 100644 index 000000000000..549170b25940 --- /dev/null +++ b/sys/dev/nvmf/nvmf_transport.h @@ -0,0 +1,140 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022-2024 Chelsio Communications, Inc. + * Written by: John Baldwin + */ + +#ifndef __NVMF_TRANSPORT_H__ +#define __NVMF_TRANSPORT_H__ + +/* + * Interface used by the Fabrics host (initiator) and controller + * (target) to send and receive capsules and associated data. + */ + +#include +#include + +struct mbuf; +struct memdesc; +struct nvmf_capsule; +struct nvmf_connection; +struct nvmf_qpair; +struct nvmf_handoff_qpair_params; + +SYSCTL_DECL(_kern_nvmf); + +/* + * Callback to invoke when an error occurs on a qpair. The last + * parameter is an error value. If the error value is zero, the qpair + * has been closed at the transport level rather than a transport + * error occuring. + */ +typedef void nvmf_qpair_error_t(void *, int); + +/* Callback to invoke when a capsule is received. */ +typedef void nvmf_capsule_receive_t(void *, struct nvmf_capsule *); + +/* + * Callback to invoke when an I/O request has completed. The second + * parameter is the amount of data transferred. The last parameter is + * an error value which is non-zero if the request did not complete + * successfully. A request with an error may complete partially. + */ +typedef void nvmf_io_complete_t(void *, size_t, int); + +/* + * A queue pair represents either an Admin or I/O + * submission/completion queue pair. The params contains negotiated + * values passed in from userland. + * + * Unlike libnvmf in userland, the kernel transport interface does not + * have any notion of an association. Instead, qpairs are + * independent. + */ +struct nvmf_qpair *nvmf_allocate_qpair(enum nvmf_trtype trtype, + bool controller, const struct nvmf_handoff_qpair_params *params, + nvmf_qpair_error_t *error_cb, void *error_cb_arg, + nvmf_capsule_receive_t *receive_cb, void *receive_cb_arg); +void nvmf_free_qpair(struct nvmf_qpair *qp); + +/* + * Capsules are either commands (host -> controller) or responses + * (controller -> host). A data buffer may be associated with a + * command capsule. Transmitted data is not copied by this API but + * instead must be preserved until the completion callback is invoked + * to indicate capsule transmission has completed. + */ +struct nvmf_capsule *nvmf_allocate_command(struct nvmf_qpair *qp, + const void *sqe, int how); +struct nvmf_capsule *nvmf_allocate_response(struct nvmf_qpair *qp, + const void *cqe, int how); +void nvmf_free_capsule(struct nvmf_capsule *nc); +int nvmf_capsule_append_data(struct nvmf_capsule *nc, + struct memdesc *mem, size_t len, bool send, + nvmf_io_complete_t *complete_cb, void *cb_arg); +int nvmf_transmit_capsule(struct nvmf_capsule *nc); +void nvmf_abort_capsule_data(struct nvmf_capsule *nc, int error); +void *nvmf_capsule_sqe(struct nvmf_capsule *nc); +void *nvmf_capsule_cqe(struct nvmf_capsule *nc); + +/* Controller-specific APIs. */ + +/* + * 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: + * NVME_SC_SUCCESS if no error is found. + */ +uint8_t nvmf_validate_command_capsule(struct nvmf_capsule *nc); + +/* + * A controller calls this function to query the amount of data + * associated with a command capsule. + */ +size_t nvmf_capsule_data_len(const struct nvmf_capsule *cc); + +/* + * A controller calls this function to receive data associated with a + * command capsule (e.g. the data for a WRITE command). This can + * either return in-capsule data or fetch data from the host + * (e.g. using a R2T PDU over TCP). The received command capsule + * should be passed in 'nc'. The received data is stored in 'mem'. + * If this function returns success, then the callback will be invoked + * once the operation has completed. Note that the callback might be + * invoked before this function returns. + */ +int nvmf_receive_controller_data(struct nvmf_capsule *nc, + uint32_t data_offset, struct memdesc *mem, size_t len, + nvmf_io_complete_t *complete_cb, void *cb_arg); + +/* + * A controller calls this function to send data in response to a + * command prior to sending a response capsule. If an error occurs, + * the function returns a generic status completion code to be sent in + * the following CQE. Note that the transfer might send a subset of + * the data requested by nc. If the transfer succeeds, this function + * can return one of the following values: + * + * - NVME_SC_SUCCESS: The transfer has completed successfully and the + * caller should send a success CQE in a response capsule. + * + * - NVMF_SUCCESS_SENT: The transfer has completed successfully and + * the transport layer has sent an implicit success CQE to the + * remote host (e.g. the SUCCESS flag for TCP). The caller should + * not send a response capsule. + * + * - NVMF_MORE: The transfer has completed successfully, but the + * transfer did not complete the data buffer. + * + * The mbuf chain in 'm' is consumed by this function even if an error + * is returned. + */ +u_int nvmf_send_controller_data(struct nvmf_capsule *nc, + uint32_t data_offset, struct mbuf *m, size_t len); + +#define NVMF_SUCCESS_SENT 0x100 +#define NVMF_MORE 0x101 + +#endif /* !__NVMF_TRANSPORT_H__ */ diff --git a/sys/dev/nvmf/nvmf_transport_internal.h b/sys/dev/nvmf/nvmf_transport_internal.h new file mode 100644 index 000000000000..0be427ee0690 --- /dev/null +++ b/sys/dev/nvmf/nvmf_transport_internal.h @@ -0,0 +1,128 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022-2024 Chelsio Communications, Inc. + * Written by: John Baldwin + */ + +#ifndef __NVMF_TRANSPORT_INTERNAL_H__ +#define __NVMF_TRANSPORT_INTERNAL_H__ + +#include + +/* + * Interface between the transport-independent APIs in + * nvmf_transport.c and individual transports. + */ + +struct module; +struct nvmf_io_request; + +struct nvmf_transport_ops { + /* Queue pair management. */ + struct nvmf_qpair *(*allocate_qpair)(bool controller, + const struct nvmf_handoff_qpair_params *params); + void (*free_qpair)(struct nvmf_qpair *qp); + + /* Capsule operations. */ + struct nvmf_capsule *(*allocate_capsule)(struct nvmf_qpair *qp, + int how); + void (*free_capsule)(struct nvmf_capsule *nc); + int (*transmit_capsule)(struct nvmf_capsule *nc); + uint8_t (*validate_command_capsule)(struct nvmf_capsule *nc); + + /* Transferring controller data. */ + size_t (*capsule_data_len)(const struct nvmf_capsule *nc); + int (*receive_controller_data)(struct nvmf_capsule *nc, + uint32_t data_offset, struct nvmf_io_request *io); + u_int (*send_controller_data)(struct nvmf_capsule *nc, + uint32_t data_offset, struct mbuf *m, size_t len); + + enum nvmf_trtype trtype; + int priority; +}; + +/* Either an Admin or I/O Submission/Completion Queue pair. */ +struct nvmf_qpair { + struct nvmf_transport *nq_transport; + struct nvmf_transport_ops *nq_ops; + bool nq_controller; + + /* Callback to invoke for a received capsule. */ + nvmf_capsule_receive_t *nq_receive; + void *nq_receive_arg; + + /* Callback to invoke for an error. */ + nvmf_qpair_error_t *nq_error; + void *nq_error_arg; + + bool nq_admin; +}; + +struct nvmf_io_request { + /* + * Data buffer contains io_len bytes in the backing store + * described by mem. + */ + struct memdesc io_mem; + size_t io_len; + nvmf_io_complete_t *io_complete; + void *io_complete_arg; +}; + +/* + * Fabrics Command and Response Capsules. The Fabrics host + * (initiator) and controller (target) drivers work with capsules that + * are transmitted and received by a specific transport. + */ +struct nvmf_capsule { + struct nvmf_qpair *nc_qpair; + + /* Either a SQE or CQE. */ + union { + struct nvme_command nc_sqe; + struct nvme_completion nc_cqe; + }; + int nc_qe_len; + + /* + * Is SQHD in received capsule valid? False for locally- + * synthesized responses. + */ + bool nc_sqhd_valid; + + bool nc_send_data; + struct nvmf_io_request nc_data; +}; + +static void __inline +nvmf_qpair_error(struct nvmf_qpair *nq, int error) +{ + nq->nq_error(nq->nq_error_arg, error); +} + +static void __inline +nvmf_capsule_received(struct nvmf_qpair *nq, struct nvmf_capsule *nc) +{ + nq->nq_receive(nq->nq_receive_arg, nc); +} + +static void __inline +nvmf_complete_io_request(struct nvmf_io_request *io, size_t xfered, int error) +{ + io->io_complete(io->io_complete_arg, xfered, error); +} + +int nvmf_transport_module_handler(struct module *, int, void *); + +#define NVMF_TRANSPORT(name, ops) \ +static moduledata_t nvmf_transport_##name##_mod = { \ + "nvmf/" #name, \ + nvmf_transport_module_handler, \ + &(ops) \ +}; \ +DECLARE_MODULE(nvmf_transport_##name, nvmf_transport_##name##_mod, \ + SI_SUB_DRIVERS, SI_ORDER_ANY); \ +MODULE_DEPEND(nvmf_transport_##name, nvmf_transport, 1, 1, 1) + +#endif /* !__NVMF_TRANSPORT_INTERNAL_H__ */ diff --git a/sys/modules/Makefile b/sys/modules/Makefile index d65eb3706ef1..37db75349cf1 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -1,933 +1,934 @@ SYSDIR?=${SRCTOP}/sys .include "${SYSDIR}/conf/kern.opts.mk" SUBDIR_PARALLEL= # Modules that include binary-only blobs of microcode should be selectable by # MK_SOURCELESS_UCODE option (see below). .include "${SYSDIR}/conf/config.mk" .if defined(MODULES_OVERRIDE) && !defined(ALL_MODULES) SUBDIR=${MODULES_OVERRIDE} .else SUBDIR= \ ${_3dfx} \ ${_3dfx_linux} \ ${_aac} \ ${_aacraid} \ accf_data \ accf_dns \ accf_http \ accf_tls \ acl_nfs4 \ acl_posix1e \ ${_acpi} \ ae \ ${_aesni} \ age \ ${_agp} \ ahci \ aic7xxx \ alc \ ale \ alq \ ${_amd_ecc_inject} \ ${_amdgpio} \ ${_amdsbwd} \ ${_amdsmn} \ ${_amdtemp} \ ${_aout} \ ${_arcmsr} \ ${_allwinner} \ ${_armv8crypto} \ ${_armv8_rng} \ ${_asmc} \ ata \ ath \ ath_dfs \ ath_hal \ ath_hal_ar5210 \ ath_hal_ar5211 \ ath_hal_ar5212 \ ath_hal_ar5416 \ ath_hal_ar9300 \ ath_main \ ath_rate \ ${_autofs} \ axgbe \ backlight \ ${_bce} \ ${_bcm283x_clkman} \ ${_bcm283x_pwm} \ bfe \ bge \ bhnd \ ${_bxe} \ ${_bios} \ ${_blake2} \ ${_bnxt} \ bridgestp \ bwi \ bwn \ ${_bytgpio} \ ${_chvgpio} \ cam \ ${_cardbus} \ ${_carp} \ cas \ ${_cbb} \ cc \ ${_ccp} \ cd9660 \ cd9660_iconv \ ${_cfi} \ ${_chromebook_platform} \ ${_ciss} \ ${_coretemp} \ ${_cpsw} \ ${_cpuctl} \ ${_cpufreq} \ ${_crypto} \ ${_cryptodev} \ ctl \ ${_cxgb} \ ${_cxgbe} \ dc \ dcons \ dcons_crom \ ${_dpaa2} \ ${_dpdk_lpm4} \ ${_dpdk_lpm6} \ ${_dpms} \ dummynet \ ${_dwwdt} \ ${_e6000sw} \ ${_efirt} \ ${_em} \ ${_ena} \ ${_enic} \ ${_enetc} \ ${_et} \ evdev \ ${_exca} \ ext2fs \ fdc \ fdescfs \ ${_felix} \ ${_ffec} \ ${_fib_dxr} \ filemon \ firewire \ firmware \ flash \ ${_ftgpio} \ ${_ftwd} \ fusefs \ ${_fxp} \ gem \ geom \ ${_glxiic} \ ${_glxsb} \ gpio \ ${_gve} \ hid \ hifn \ ${_hpt27xx} \ ${_hptiop} \ ${_hptmv} \ ${_hptnr} \ ${_hptrr} \ hwpmc \ ${_hyperv} \ i2c \ ${_iavf} \ ${_ibcore} \ ${_ichwd} \ ${_ice} \ ${_ice_ddp} \ ${_irdma} \ ${_ida} \ if_bridge \ ${_if_cgem} \ if_disc \ if_edsc \ ${_if_enc} \ if_epair \ ${_genet} \ ${_if_gif} \ ${_if_gre} \ ${_if_me} \ if_infiniband \ if_lagg \ if_ovpn \ ${_if_stf} \ if_tuntap \ if_vlan \ if_vxlan \ ${_if_wg} \ iflib \ ${_igc} \ imgact_binmisc \ ${_intelspi} \ ${_io} \ ${_ioat} \ ${_ipoib} \ ipdivert \ ${_ipfilter} \ ${_ipfw} \ ipfw_nat \ ${_ipfw_nat64} \ ${_ipfw_nptv6} \ ${_ipfw_pmod} \ ${_ipmi} \ ip6_mroute_mod \ ip_mroute_mod \ ${_ips} \ ${_ipsec} \ ${_ipw} \ ${_ipwfw} \ ${_isci} \ ${_iser} \ isp \ ${_ispfw} \ ${_itwd} \ ${_iwi} \ ${_iwifw} \ ${_iwlwifi} \ ${_iwlwififw} \ ${_iwm} \ ${_iwmfw} \ ${_iwn} \ ${_iwnfw} \ ${_ix} \ ${_ixv} \ ${_ixl} \ jme \ kbdmux \ kgssapi \ kgssapi_krb5 \ khelp \ krpc \ ksyms \ le \ lge \ libalias \ libiconv \ libmchain \ lindebugfs \ linuxkpi \ linuxkpi_hdmi \ linuxkpi_video \ linuxkpi_wlan \ ${_lio} \ lpt \ ${_mac_biba} \ ${_mac_bsdextended} \ ${_mac_ddb} \ ${_mac_ifoff} \ ${_mac_ipacl} \ ${_mac_lomac} \ ${_mac_mls} \ ${_mac_none} \ ${_mac_ntpd} \ ${_mac_partition} \ ${_mac_pimd} \ ${_mac_portacl} \ ${_mac_priority} \ ${_mac_seeotheruids} \ ${_mac_stub} \ ${_mac_test} \ ${_mac_veriexec} \ ${_mac_veriexec_sha1} \ ${_mac_veriexec_sha256} \ ${_mac_veriexec_sha384} \ ${_mac_veriexec_sha512} \ ${_malo} \ ${_mana} \ md \ mdio \ ${_mgb} \ mem \ mfi \ mii \ mlx \ mlxfw \ ${_mlx4} \ ${_mlx4ib} \ ${_mlx4en} \ ${_mlx5} \ ${_mlx5en} \ ${_mlx5ib} \ mmc \ mmcsd \ ${_mpi3mr} \ ${_mpr} \ ${_mps} \ mpt \ mqueue \ mrsas \ msdosfs \ msdosfs_iconv \ msk \ ${_mthca} \ mvs \ mwl \ ${_mwlfw} \ mxge \ my \ ${_nctgpio} \ ${_ncthwm} \ ${_neta} \ netlink \ ${_netgraph} \ ${_nfe} \ nfscl \ nfscommon \ nfsd \ nfslockd \ nfssvc \ nlsysevent \ nge \ nmdm \ nullfs \ ${_ntb} \ nvd \ ${_nvdimm} \ nvme \ + nvmf \ ${_nvram} \ oce \ ${_ocs_fc} \ ${_ossl} \ otus \ ${_otusfw} \ ow \ ${_padlock} \ ${_padlock_rng} \ ${_pchtherm} \ ${_pcfclock} \ ${_pf} \ ${_pflog} \ ${_pflow} \ ${_pfsync} \ plip \ ${_pms} \ ppbus \ ppc \ ppi \ pps \ procfs \ proto \ pseudofs \ ${_pst} \ pty \ puc \ pwm \ ${_qat} \ ${_qatfw} \ ${_qat_c2xxx} \ ${_qat_c2xxxfw} \ ${_qlxge} \ ${_qlxgb} \ ${_qlxgbe} \ ${_qlnx} \ ral \ ${_ralfw} \ ${_random_fortuna} \ ${_random_other} \ rc4 \ ${_rdma} \ ${_rdrand_rng} \ re \ rl \ ${_rockchip} \ rtsx \ ${_rtw88} \ rtwn \ rtwn_pci \ rtwn_usb \ ${_rtwnfw} \ ${_s3} \ ${_safe} \ safexcel \ ${_sbni} \ scc \ ${_sctp} \ sdhci \ ${_sdhci_acpi} \ ${_sdhci_fdt} \ sdhci_pci \ sdio \ ${_sff} \ sem \ send \ ${_sfxge} \ sge \ ${_sgx} \ ${_sgx_linux} \ siftr \ siis \ sis \ sk \ ${_smartpqi} \ smbfs \ snp \ sound \ ${_speaker} \ spi \ ${_splash} \ ste \ stge \ ${_sume} \ ${_superio} \ ${_p2sb} \ sym \ ${_syscons} \ sysvipc \ tarfs \ tcp \ ${_ti} \ tmpfs \ ${_toecore} \ ${_tpm} \ tws \ uart \ udf \ udf_iconv \ ufs \ uinput \ unionfs \ usb \ ${_vesa} \ ${_vf_i2c} \ virtio \ vge \ ${_viawd} \ videomode \ vkbd \ ${_vmd} \ ${_vmm} \ ${_vmware} \ vr \ vte \ ${_wbwd} \ ${_wdatwd} \ wlan \ wlan_acl \ wlan_amrr \ wlan_ccmp \ wlan_rssadapt \ wlan_tkip \ wlan_wep \ wlan_xauth \ ${_wpi} \ ${_wpifw} \ ${_x86bios} \ xdr \ xl \ xz \ zlib .if ${MK_AUTOFS} != "no" || defined(ALL_MODULES) _autofs= autofs .endif .if ${MK_DTRACE} != "no" || defined(ALL_MODULES) .if ${KERN_OPTS:MKDTRACE_HOOKS} SUBDIR+= dtrace .endif SUBDIR+= opensolaris .endif # Requires bus_space_read_8 .if ${MACHINE_ARCH} != "i386" _bnxt= bnxt .endif .if ${MK_CRYPT} != "no" || defined(ALL_MODULES) .if exists(${SRCTOP}/sys/opencrypto) _crypto= crypto _cryptodev= cryptodev _random_fortuna=random_fortuna _random_other= random_other .endif .endif .if ${MK_CUSE} != "no" || defined(ALL_MODULES) SUBDIR+= cuse .endif .if ${MK_EFI} != "no" .if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" _efirt= efirt .endif .endif .if (${MK_INET_SUPPORT} != "no" || ${MK_INET6_SUPPORT} != "no") || \ defined(ALL_MODULES) _carp= carp _toecore= toecore _if_enc= if_enc _if_gif= if_gif _if_gre= if_gre .if ${MK_CRYPT} != "no" || defined(ALL_MODULES) _if_wg= if_wg .endif _ipfw_pmod= ipfw_pmod .if ${KERN_OPTS:MIPSEC_SUPPORT} && !${KERN_OPTS:MIPSEC} _ipsec= ipsec .endif .if ${KERN_OPTS:MSCTP_SUPPORT} || ${KERN_OPTS:MSCTP} _sctp= sctp .endif .endif .if (${MK_INET_SUPPORT} != "no" && ${MK_INET6_SUPPORT} != "no") || \ defined(ALL_MODULES) _if_stf= if_stf .endif .if ${MK_INET_SUPPORT} != "no" || defined(ALL_MODULES) _if_me= if_me _ipfw= ipfw .if ${MK_INET6_SUPPORT} != "no" || defined(ALL_MODULES) _ipfw_nat64= ipfw_nat64 .endif .endif .if ${MK_INET6_SUPPORT} != "no" || defined(ALL_MODULES) _ipfw_nptv6= ipfw_nptv6 .endif .if ${MK_IPFILTER} != "no" || defined(ALL_MODULES) _ipfilter= ipfilter .endif .if ${MK_INET_SUPPORT} != "no" && ${KERN_OPTS:MFIB_ALGO} _dpdk_lpm4= dpdk_lpm4 _fib_dxr= fib_dxr .endif .if ${MK_INET6_SUPPORT} != "no" && ${KERN_OPTS:MFIB_ALGO} _dpdk_lpm6= dpdk_lpm6 .endif .if ${MK_ISCSI} != "no" || defined(ALL_MODULES) SUBDIR+= cfiscsi SUBDIR+= iscsi .endif .if !empty(OPT_FDT) SUBDIR+= fdt .endif # Linuxulator .if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" || \ ${MACHINE_CPUARCH} == "i386" SUBDIR+= linprocfs SUBDIR+= linsysfs .endif .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" SUBDIR+= linux .endif .if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" SUBDIR+= linux64 SUBDIR+= linux_common .endif .if ${MACHINE_CPUARCH} != "arm" .if ${MK_OFED} != "no" || defined(ALL_MODULES) _ibcore= ibcore _ipoib= ipoib _iser= iser _mthca= mthca _rdma= rdma .endif .endif .if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" || \ ${MACHINE_CPUARCH} == "i386" || ${MACHINE_ARCH:Mpowerpc64*} != "" _ipmi= ipmi _mlx4= mlx4 _mlx5= mlx5 .if (${MK_INET_SUPPORT} != "no" && ${MK_INET6_SUPPORT} != "no") || \ defined(ALL_MODULES) _mlx4en= mlx4en _mlx5en= mlx5en .endif .if ${MK_OFED} != "no" || defined(ALL_MODULES) _mlx4ib= mlx4ib _mlx5ib= mlx5ib .endif .endif .if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" || \ ${MACHINE_CPUARCH} == "i386" _ena= ena _gve= gve _iwlwifi= iwlwifi .if ${MK_SOURCELESS_UCODE} != "no" _iwlwififw= iwlwififw .endif _rtw88= rtw88 _vmware= vmware .endif .if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" || \ ${MACHINE_CPUARCH} == "i386" || ${MACHINE_ARCH} == "armv7" _ossl= ossl .endif # MAC framework .if ${KERN_OPTS:MMAC} || defined(ALL_MODULES) _mac_biba= mac_biba _mac_bsdextended= mac_bsdextended .if ${KERN_OPTS:MDDB} || defined(ALL_MODULES) _mac_ddb= mac_ddb .endif _mac_ifoff= mac_ifoff _mac_ipacl= mac_ipacl _mac_lomac= mac_lomac _mac_mls= mac_mls _mac_none= mac_none _mac_ntpd= mac_ntpd _mac_partition= mac_partition _mac_pimd= mac_pimd _mac_portacl= mac_portacl _mac_priority= mac_priority _mac_seeotheruids= mac_seeotheruids _mac_stub= mac_stub _mac_test= mac_test .if ${MK_VERIEXEC} != "no" || defined(ALL_MODULES) _mac_veriexec= mac_veriexec _mac_veriexec_sha1= mac_veriexec_sha1 _mac_veriexec_sha256= mac_veriexec_sha256 _mac_veriexec_sha384= mac_veriexec_sha384 _mac_veriexec_sha512= mac_veriexec_sha512 .endif .endif .if ${MK_NETGRAPH} != "no" || defined(ALL_MODULES) _netgraph= netgraph .endif .if (${MK_PF} != "no" && (${MK_INET_SUPPORT} != "no" || \ ${MK_INET6_SUPPORT} != "no")) || defined(ALL_MODULES) _pf= pf _pflog= pflog _pflow= pflow .if ${MK_INET_SUPPORT} != "no" _pfsync= pfsync .endif .endif .if ${MK_SOURCELESS_UCODE} != "no" _bce= bce _fxp= fxp _ispfw= ispfw _ti= ti _mwlfw= mwlfw _otusfw= otusfw _ralfw= ralfw _rtwnfw= rtwnfw .endif .if ${MK_SOURCELESS_UCODE} != "no" && ${MACHINE_CPUARCH} != "arm" && \ ${MACHINE_ARCH} != "powerpc" && ${MACHINE_ARCH} != "powerpcspe" && \ ${MACHINE_CPUARCH} != "riscv" _cxgbe= cxgbe .endif # This has only been tested on amd64 and arm64 .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "aarch64" _mpi3mr=mpi3mr .endif # Specific to the Raspberry Pi. .if ${MACHINE_CPUARCH} == "aarch64" _genet= genet .endif .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "aarch64" || \ ${MACHINE_ARCH:Mpowerpc64*} _ice= ice .if ${MK_SOURCELESS_UCODE} != "no" _ice_ddp= ice_ddp .endif .if ${MK_OFED} != "no" || defined(ALL_MODULES) .if ${MK_INET_SUPPORT} != "no" && ${MK_INET6_SUPPORT} != "no" _irdma= irdma .endif .endif .endif .if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm" || \ ${MACHINE_CPUARCH} == "riscv" .if !empty(OPT_FDT) _if_cgem= if_cgem .endif .endif # These rely on 64bit atomics .if ${MACHINE_ARCH} != "powerpc" && ${MACHINE_ARCH} != "powerpcspe" _mps= mps _mpr= mpr .endif .if ${MK_TESTS} != "no" || defined(ALL_MODULES) SUBDIR+= ktest SUBDIR+= tests .endif .if ${MK_ZFS} != "no" || defined(ALL_MODULES) SUBDIR+= zfs .endif .if ${MK_SOURCELESS_UCODE} != "no" _cxgb= cxgb .endif .if ${MACHINE_CPUARCH} == "aarch64" _armv8crypto= armv8crypto _armv8_rng= armv8_rng _dpaa2= dpaa2 _sff= sff _em= em _hyperv= hyperv _vf_i2c= vf_i2c .if !empty(OPT_FDT) _allwinner= allwinner _dwwdt= dwwdt _enetc= enetc _felix= felix _rockchip= rockchip .endif .endif .if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm" .if !empty(OPT_FDT) _sdhci_fdt= sdhci_fdt .endif _e6000sw= e6000sw _neta= neta .endif .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" _agp= agp .if ${MACHINE_CPUARCH} == "i386" || !empty(COMPAT_FREEBSD32_ENABLED) _aout= aout .endif _bios= bios .if ${MK_SOURCELESS_UCODE} != "no" _bxe= bxe .endif _cardbus= cardbus _cbb= cbb _cpuctl= cpuctl _cpufreq= cpufreq _dpms= dpms _em= em _et= et _ftgpio= ftgpio _ftwd= ftwd _exca= exca _igc= igc _io= io _itwd= itwd _ix= ix _ixv= ixv .if ${MK_SOURCELESS_UCODE} != "no" _lio= lio .endif _mana= mana _mgb= mgb _nctgpio= nctgpio _ncthwm= ncthwm _ntb= ntb _ocs_fc= ocs_fc _p2sb= p2sb _qat_c2xxx= qat_c2xxx _qat_c2xxxfw= qat_c2xxxfw _safe= safe _speaker= speaker _splash= splash _syscons= syscons _wbwd= wbwd _wdatwd= wdatwd _aac= aac _aacraid= aacraid _acpi= acpi .if ${MK_CRYPT} != "no" || defined(ALL_MODULES) _aesni= aesni .endif _amd_ecc_inject=amd_ecc_inject _amdsbwd= amdsbwd _amdsmn= amdsmn _amdtemp= amdtemp _arcmsr= arcmsr _asmc= asmc .if ${MK_CRYPT} != "no" || defined(ALL_MODULES) _blake2= blake2 .endif _bytgpio= bytgpio _chvgpio= chvgpio _ciss= ciss _chromebook_platform= chromebook_platform _coretemp= coretemp .if ${MK_SOURCELESS_HOST} != "no" && empty(KCSAN_ENABLED) _hpt27xx= hpt27xx .endif _hptiop= hptiop .if ${MK_SOURCELESS_HOST} != "no" && empty(KCSAN_ENABLED) _hptmv= hptmv _hptnr= hptnr _hptrr= hptrr .endif _hyperv= hyperv _ichwd= ichwd _ida= ida _intelspi= intelspi _ips= ips _isci= isci _ipw= ipw _iwi= iwi _iwm= iwm _iwn= iwn .if ${MK_SOURCELESS_UCODE} != "no" _ipwfw= ipwfw _iwifw= iwifw _iwmfw= iwmfw _iwnfw= iwnfw .endif _nfe= nfe _nvram= nvram .if ${MK_CRYPT} != "no" || defined(ALL_MODULES) _padlock= padlock _padlock_rng= padlock_rng _rdrand_rng= rdrand_rng .endif _pchtherm = pchtherm _s3= s3 _sdhci_acpi= sdhci_acpi _superio= superio _tpm= tpm _vesa= vesa _viawd= viawd _vmd= vmd _wpi= wpi .if ${MK_SOURCELESS_UCODE} != "no" _wpifw= wpifw .endif _x86bios= x86bios .endif .if ${MACHINE_CPUARCH} == "amd64" _amdgpio= amdgpio _ccp= ccp _enic= enic _iavf= iavf _ioat= ioat _ixl= ixl _nvdimm= nvdimm _pms= pms _qat= qat .if ${MK_SOURCELESS_UCODE} != "no" _qatfw= qatfw .endif _qlxge= qlxge _qlxgb= qlxgb _sume= sume .if ${MK_SOURCELESS_UCODE} != "no" _qlxgbe= qlxgbe _qlnx= qlnx .endif _sfxge= sfxge _sgx= sgx _sgx_linux= sgx_linux _smartpqi= smartpqi _p2sb= p2sb .endif .if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" .if ${MK_BHYVE} != "no" || defined(ALL_MODULES) .if ${KERN_OPTS:MSMP} _vmm= vmm .endif .endif .endif .if ${MACHINE_CPUARCH} == "i386" # XXX some of these can move to the general case when de-i386'ed # XXX some of these can move now, but are untested on other architectures. _3dfx= 3dfx _3dfx_linux= 3dfx_linux _glxiic= glxiic _glxsb= glxsb _pcfclock= pcfclock _pst= pst _sbni= sbni .endif .if ${MACHINE_ARCH} == "armv7" _cfi= cfi _cpsw= cpsw .endif .if ${MACHINE_CPUARCH} == "powerpc" _aacraid= aacraid _agp= agp _an= an _cardbus= cardbus _cbb= cbb _cfi= cfi _cpufreq= cpufreq _exca= exca _ffec= ffec .endif .if ${MACHINE_ARCH:Mpowerpc64*} != "" _ixl= ixl _nvram= opal_nvram .endif .if ${MACHINE_CPUARCH} == "powerpc" && ${MACHINE_ARCH} != "powerpcspe" # Don't build powermac_nvram for powerpcspe, it's never supported. _nvram+= powermac_nvram .endif .if ${MACHINE_CPUARCH} == "arm" || ${MACHINE_CPUARCH} == "aarch64" _bcm283x_clkman= bcm283x_clkman _bcm283x_pwm= bcm283x_pwm .endif .if !(${COMPILER_TYPE} == "clang" && ${COMPILER_VERSION} < 110000) # LLVM 10 crashes when building if_malo_pci.c, fixed in LLVM11: # https://bugs.llvm.org/show_bug.cgi?id=44351 _malo= malo .endif SUBDIR+=${MODULES_EXTRA} .for reject in ${WITHOUT_MODULES} SUBDIR:= ${SUBDIR:N${reject}} .endfor .endif # MODULES_OVERRIDE -- Keep last # Calling kldxref(8) for each module is expensive. .if !defined(NO_XREF) .MAKEFLAGS+= -DNO_XREF afterinstall: .PHONY ${KLDXREF_CMD} ${DESTDIR}${KMODDIR} .if defined(NO_ROOT) && defined(METALOG) echo ".${DISTBASE}${KMODDIR}/linker.hints type=file mode=0644 uname=root gname=wheel" | \ cat -l >> ${METALOG} .endif .endif SUBDIR:= ${SUBDIR:u:O} .include diff --git a/sys/modules/nvmf/Makefile b/sys/modules/nvmf/Makefile new file mode 100644 index 000000000000..b1be042f4385 --- /dev/null +++ b/sys/modules/nvmf/Makefile @@ -0,0 +1,3 @@ +SUBDIR= nvmf_transport + +.include diff --git a/sys/modules/nvmf/nvmf_transport/Makefile b/sys/modules/nvmf/nvmf_transport/Makefile new file mode 100644 index 000000000000..f0edfac5ac35 --- /dev/null +++ b/sys/modules/nvmf/nvmf_transport/Makefile @@ -0,0 +1,9 @@ +.PATH: ${SRCTOP}/sys/dev/nvmf + +KMOD= nvmf_transport + +SRCS= nvmf_transport.c + +EXPORT_SYMS= YES + +.include