1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2022-2024 Chelsio Communications, Inc. 5 * Written by: John Baldwin <jhb@FreeBSD.org> 6 */ 7 8 #ifndef __NVMF_TRANSPORT_H__ 9 #define __NVMF_TRANSPORT_H__ 10 11 /* 12 * Interface used by the Fabrics host (initiator) and controller 13 * (target) to send and receive capsules and associated data. 14 */ 15 16 #include <sys/_nv.h> 17 #include <sys/sysctl.h> 18 #include <dev/nvmf/nvmf_proto.h> 19 20 struct mbuf; 21 struct memdesc; 22 struct nvmf_capsule; 23 struct nvmf_connection; 24 struct nvmf_ioc_nv; 25 struct nvmf_qpair; 26 27 SYSCTL_DECL(_kern_nvmf); 28 29 /* 30 * Callback to invoke when an error occurs on a qpair. The last 31 * parameter is an error value. If the error value is zero, the qpair 32 * has been closed at the transport level rather than a transport 33 * error occuring. 34 */ 35 typedef void nvmf_qpair_error_t(void *, int); 36 37 /* Callback to invoke when a capsule is received. */ 38 typedef void nvmf_capsule_receive_t(void *, struct nvmf_capsule *); 39 40 /* 41 * Callback to invoke when an I/O request has completed. The second 42 * parameter is the amount of data transferred. The last parameter is 43 * an error value which is non-zero if the request did not complete 44 * successfully. A request with an error may complete partially. 45 */ 46 typedef void nvmf_io_complete_t(void *, size_t, int); 47 48 /* 49 * A queue pair represents either an Admin or I/O 50 * submission/completion queue pair. The params contains negotiated 51 * values passed in from userland. 52 * 53 * Unlike libnvmf in userland, the kernel transport interface does not 54 * have any notion of an association. Instead, qpairs are 55 * independent. 56 */ 57 struct nvmf_qpair *nvmf_allocate_qpair(enum nvmf_trtype trtype, 58 bool controller, const nvlist_t *params, 59 nvmf_qpair_error_t *error_cb, void *error_cb_arg, 60 nvmf_capsule_receive_t *receive_cb, void *receive_cb_arg); 61 void nvmf_free_qpair(struct nvmf_qpair *qp); 62 63 /* 64 * Capsules are either commands (host -> controller) or responses 65 * (controller -> host). A data buffer may be associated with a 66 * command capsule. Transmitted data is not copied by this API but 67 * instead must be preserved until the completion callback is invoked 68 * to indicate capsule transmission has completed. 69 */ 70 struct nvmf_capsule *nvmf_allocate_command(struct nvmf_qpair *qp, 71 const void *sqe, int how); 72 struct nvmf_capsule *nvmf_allocate_response(struct nvmf_qpair *qp, 73 const void *cqe, int how); 74 void nvmf_free_capsule(struct nvmf_capsule *nc); 75 int nvmf_capsule_append_data(struct nvmf_capsule *nc, 76 struct memdesc *mem, size_t len, bool send, 77 nvmf_io_complete_t *complete_cb, void *cb_arg); 78 int nvmf_transmit_capsule(struct nvmf_capsule *nc); 79 void nvmf_abort_capsule_data(struct nvmf_capsule *nc, int error); 80 void *nvmf_capsule_sqe(struct nvmf_capsule *nc); 81 void *nvmf_capsule_cqe(struct nvmf_capsule *nc); 82 bool nvmf_sqhd_valid(struct nvmf_capsule *nc); 83 84 /* Host-specific APIs. */ 85 86 /* 87 * Largest I/O request size for a single command supported by the 88 * transport. If the transport does not have a limit, returns 0. 89 */ 90 uint64_t nvmf_max_xfer_size(struct nvmf_qpair *qp); 91 92 /* Controller-specific APIs. */ 93 94 /* 95 * Largest I/O command capsule size (IOCCSZ) supported by the 96 * transport. If the transport does not have a limit, returns 0. 97 */ 98 uint32_t nvmf_max_ioccsz(struct nvmf_qpair *qp); 99 100 /* 101 * A controller calls this function to check for any 102 * transport-specific errors (invalid fields) in a received command 103 * capsule. The callback returns a generic command status value: 104 * NVME_SC_SUCCESS if no error is found. 105 */ 106 uint8_t nvmf_validate_command_capsule(struct nvmf_capsule *nc); 107 108 /* 109 * A controller calls this function to query the amount of data 110 * associated with a command capsule. 111 */ 112 size_t nvmf_capsule_data_len(const struct nvmf_capsule *cc); 113 114 /* 115 * A controller calls this function to receive data associated with a 116 * command capsule (e.g. the data for a WRITE command). This can 117 * either return in-capsule data or fetch data from the host 118 * (e.g. using a R2T PDU over TCP). The received command capsule 119 * should be passed in 'nc'. The received data is stored in 'mem'. 120 * If this function returns success, then the callback will be invoked 121 * once the operation has completed. Note that the callback might be 122 * invoked before this function returns. 123 */ 124 int nvmf_receive_controller_data(struct nvmf_capsule *nc, 125 uint32_t data_offset, struct memdesc *mem, size_t len, 126 nvmf_io_complete_t *complete_cb, void *cb_arg); 127 128 /* 129 * A controller calls this function to send data in response to a 130 * command prior to sending a response capsule. If an error occurs, 131 * the function returns a generic status completion code to be sent in 132 * the following CQE. Note that the transfer might send a subset of 133 * the data requested by nc. If the transfer succeeds, this function 134 * can return one of the following values: 135 * 136 * - NVME_SC_SUCCESS: The transfer has completed successfully and the 137 * caller should send a success CQE in a response capsule. 138 * 139 * - NVMF_SUCCESS_SENT: The transfer has completed successfully and 140 * the transport layer has sent an implicit success CQE to the 141 * remote host (e.g. the SUCCESS flag for TCP). The caller should 142 * not send a response capsule. 143 * 144 * - NVMF_MORE: The transfer has completed successfully, but the 145 * transfer did not complete the data buffer. 146 * 147 * The mbuf chain in 'm' is consumed by this function even if an error 148 * is returned. 149 */ 150 u_int nvmf_send_controller_data(struct nvmf_capsule *nc, 151 uint32_t data_offset, struct mbuf *m, size_t len); 152 153 #define NVMF_SUCCESS_SENT 0x100 154 #define NVMF_MORE 0x101 155 156 /* Helper APIs for nvlists used in icotls. */ 157 158 /* 159 * Pack the nvlist nvl and copyout to the buffer described by nv. 160 */ 161 int nvmf_pack_ioc_nvlist(const nvlist_t *nvl, struct nvmf_ioc_nv *nv); 162 163 /* 164 * Copyin and unpack an nvlist described by nv. The unpacked nvlist 165 * is returned in *nvlp on success. 166 */ 167 int nvmf_unpack_ioc_nvlist(const struct nvmf_ioc_nv *nv, nvlist_t **nvlp); 168 169 /* 170 * Returns true if a qpair handoff nvlist has all the required 171 * transport-independent values. 172 */ 173 bool nvmf_validate_qpair_nvlist(const nvlist_t *nvl, bool controller); 174 175 #endif /* !__NVMF_TRANSPORT_H__ */ 176