1*2da066efSJohn Baldwin /*- 2*2da066efSJohn Baldwin * SPDX-License-Identifier: BSD-2-Clause 3*2da066efSJohn Baldwin * 4*2da066efSJohn Baldwin * Copyright (c) 2022-2024 Chelsio Communications, Inc. 5*2da066efSJohn Baldwin * Written by: John Baldwin <jhb@FreeBSD.org> 6*2da066efSJohn Baldwin */ 7*2da066efSJohn Baldwin 8*2da066efSJohn Baldwin #include <sys/refcount.h> 9*2da066efSJohn Baldwin #include <assert.h> 10*2da066efSJohn Baldwin #include <errno.h> 11*2da066efSJohn Baldwin #include <stdarg.h> 12*2da066efSJohn Baldwin #include <stdio.h> 13*2da066efSJohn Baldwin #include <stdlib.h> 14*2da066efSJohn Baldwin #include <string.h> 15*2da066efSJohn Baldwin 16*2da066efSJohn Baldwin #include "libnvmf.h" 17*2da066efSJohn Baldwin #include "internal.h" 18*2da066efSJohn Baldwin 19*2da066efSJohn Baldwin struct nvmf_association * 20*2da066efSJohn Baldwin nvmf_allocate_association(enum nvmf_trtype trtype, bool controller, 21*2da066efSJohn Baldwin const struct nvmf_association_params *params) 22*2da066efSJohn Baldwin { 23*2da066efSJohn Baldwin struct nvmf_transport_ops *ops; 24*2da066efSJohn Baldwin struct nvmf_association *na; 25*2da066efSJohn Baldwin 26*2da066efSJohn Baldwin switch (trtype) { 27*2da066efSJohn Baldwin case NVMF_TRTYPE_TCP: 28*2da066efSJohn Baldwin ops = &tcp_ops; 29*2da066efSJohn Baldwin break; 30*2da066efSJohn Baldwin default: 31*2da066efSJohn Baldwin errno = EINVAL; 32*2da066efSJohn Baldwin return (NULL); 33*2da066efSJohn Baldwin } 34*2da066efSJohn Baldwin 35*2da066efSJohn Baldwin na = ops->allocate_association(controller, params); 36*2da066efSJohn Baldwin if (na == NULL) 37*2da066efSJohn Baldwin return (NULL); 38*2da066efSJohn Baldwin 39*2da066efSJohn Baldwin na->na_ops = ops; 40*2da066efSJohn Baldwin na->na_trtype = trtype; 41*2da066efSJohn Baldwin na->na_controller = controller; 42*2da066efSJohn Baldwin na->na_params = *params; 43*2da066efSJohn Baldwin na->na_last_error = NULL; 44*2da066efSJohn Baldwin refcount_init(&na->na_refs, 1); 45*2da066efSJohn Baldwin return (na); 46*2da066efSJohn Baldwin } 47*2da066efSJohn Baldwin 48*2da066efSJohn Baldwin void 49*2da066efSJohn Baldwin nvmf_update_assocation(struct nvmf_association *na, 50*2da066efSJohn Baldwin const struct nvme_controller_data *cdata) 51*2da066efSJohn Baldwin { 52*2da066efSJohn Baldwin na->na_ops->update_association(na, cdata); 53*2da066efSJohn Baldwin } 54*2da066efSJohn Baldwin 55*2da066efSJohn Baldwin void 56*2da066efSJohn Baldwin nvmf_free_association(struct nvmf_association *na) 57*2da066efSJohn Baldwin { 58*2da066efSJohn Baldwin if (refcount_release(&na->na_refs)) { 59*2da066efSJohn Baldwin free(na->na_last_error); 60*2da066efSJohn Baldwin na->na_ops->free_association(na); 61*2da066efSJohn Baldwin } 62*2da066efSJohn Baldwin } 63*2da066efSJohn Baldwin 64*2da066efSJohn Baldwin const char * 65*2da066efSJohn Baldwin nvmf_association_error(const struct nvmf_association *na) 66*2da066efSJohn Baldwin { 67*2da066efSJohn Baldwin return (na->na_last_error); 68*2da066efSJohn Baldwin } 69*2da066efSJohn Baldwin 70*2da066efSJohn Baldwin void 71*2da066efSJohn Baldwin na_clear_error(struct nvmf_association *na) 72*2da066efSJohn Baldwin { 73*2da066efSJohn Baldwin free(na->na_last_error); 74*2da066efSJohn Baldwin na->na_last_error = NULL; 75*2da066efSJohn Baldwin } 76*2da066efSJohn Baldwin 77*2da066efSJohn Baldwin void 78*2da066efSJohn Baldwin na_error(struct nvmf_association *na, const char *fmt, ...) 79*2da066efSJohn Baldwin { 80*2da066efSJohn Baldwin va_list ap; 81*2da066efSJohn Baldwin char *str; 82*2da066efSJohn Baldwin 83*2da066efSJohn Baldwin if (na->na_last_error != NULL) 84*2da066efSJohn Baldwin return; 85*2da066efSJohn Baldwin va_start(ap, fmt); 86*2da066efSJohn Baldwin vasprintf(&str, fmt, ap); 87*2da066efSJohn Baldwin va_end(ap); 88*2da066efSJohn Baldwin na->na_last_error = str; 89*2da066efSJohn Baldwin } 90*2da066efSJohn Baldwin 91*2da066efSJohn Baldwin struct nvmf_qpair * 92*2da066efSJohn Baldwin nvmf_allocate_qpair(struct nvmf_association *na, 93*2da066efSJohn Baldwin const struct nvmf_qpair_params *params) 94*2da066efSJohn Baldwin { 95*2da066efSJohn Baldwin struct nvmf_qpair *qp; 96*2da066efSJohn Baldwin 97*2da066efSJohn Baldwin na_clear_error(na); 98*2da066efSJohn Baldwin qp = na->na_ops->allocate_qpair(na, params); 99*2da066efSJohn Baldwin if (qp == NULL) 100*2da066efSJohn Baldwin return (NULL); 101*2da066efSJohn Baldwin 102*2da066efSJohn Baldwin refcount_acquire(&na->na_refs); 103*2da066efSJohn Baldwin qp->nq_association = na; 104*2da066efSJohn Baldwin qp->nq_admin = params->admin; 105*2da066efSJohn Baldwin TAILQ_INIT(&qp->nq_rx_capsules); 106*2da066efSJohn Baldwin return (qp); 107*2da066efSJohn Baldwin } 108*2da066efSJohn Baldwin 109*2da066efSJohn Baldwin void 110*2da066efSJohn Baldwin nvmf_free_qpair(struct nvmf_qpair *qp) 111*2da066efSJohn Baldwin { 112*2da066efSJohn Baldwin struct nvmf_association *na; 113*2da066efSJohn Baldwin struct nvmf_capsule *nc, *tc; 114*2da066efSJohn Baldwin 115*2da066efSJohn Baldwin TAILQ_FOREACH_SAFE(nc, &qp->nq_rx_capsules, nc_link, tc) { 116*2da066efSJohn Baldwin TAILQ_REMOVE(&qp->nq_rx_capsules, nc, nc_link); 117*2da066efSJohn Baldwin nvmf_free_capsule(nc); 118*2da066efSJohn Baldwin } 119*2da066efSJohn Baldwin na = qp->nq_association; 120*2da066efSJohn Baldwin na->na_ops->free_qpair(qp); 121*2da066efSJohn Baldwin nvmf_free_association(na); 122*2da066efSJohn Baldwin } 123*2da066efSJohn Baldwin 124*2da066efSJohn Baldwin struct nvmf_capsule * 125*2da066efSJohn Baldwin nvmf_allocate_command(struct nvmf_qpair *qp, const void *sqe) 126*2da066efSJohn Baldwin { 127*2da066efSJohn Baldwin struct nvmf_capsule *nc; 128*2da066efSJohn Baldwin 129*2da066efSJohn Baldwin nc = qp->nq_association->na_ops->allocate_capsule(qp); 130*2da066efSJohn Baldwin if (nc == NULL) 131*2da066efSJohn Baldwin return (NULL); 132*2da066efSJohn Baldwin 133*2da066efSJohn Baldwin nc->nc_qpair = qp; 134*2da066efSJohn Baldwin nc->nc_qe_len = sizeof(struct nvme_command); 135*2da066efSJohn Baldwin memcpy(&nc->nc_sqe, sqe, nc->nc_qe_len); 136*2da066efSJohn Baldwin 137*2da066efSJohn Baldwin /* 4.2 of NVMe base spec: Fabrics always uses SGL. */ 138*2da066efSJohn Baldwin nc->nc_sqe.fuse &= ~NVMEM(NVME_CMD_PSDT); 139*2da066efSJohn Baldwin nc->nc_sqe.fuse |= NVMEF(NVME_CMD_PSDT, NVME_PSDT_SGL); 140*2da066efSJohn Baldwin return (nc); 141*2da066efSJohn Baldwin } 142*2da066efSJohn Baldwin 143*2da066efSJohn Baldwin struct nvmf_capsule * 144*2da066efSJohn Baldwin nvmf_allocate_response(struct nvmf_qpair *qp, const void *cqe) 145*2da066efSJohn Baldwin { 146*2da066efSJohn Baldwin struct nvmf_capsule *nc; 147*2da066efSJohn Baldwin 148*2da066efSJohn Baldwin nc = qp->nq_association->na_ops->allocate_capsule(qp); 149*2da066efSJohn Baldwin if (nc == NULL) 150*2da066efSJohn Baldwin return (NULL); 151*2da066efSJohn Baldwin 152*2da066efSJohn Baldwin nc->nc_qpair = qp; 153*2da066efSJohn Baldwin nc->nc_qe_len = sizeof(struct nvme_completion); 154*2da066efSJohn Baldwin memcpy(&nc->nc_cqe, cqe, nc->nc_qe_len); 155*2da066efSJohn Baldwin return (nc); 156*2da066efSJohn Baldwin } 157*2da066efSJohn Baldwin 158*2da066efSJohn Baldwin int 159*2da066efSJohn Baldwin nvmf_capsule_append_data(struct nvmf_capsule *nc, void *buf, size_t len, 160*2da066efSJohn Baldwin bool send) 161*2da066efSJohn Baldwin { 162*2da066efSJohn Baldwin if (nc->nc_qe_len == sizeof(struct nvme_completion)) 163*2da066efSJohn Baldwin return (EINVAL); 164*2da066efSJohn Baldwin if (nc->nc_data_len != 0) 165*2da066efSJohn Baldwin return (EBUSY); 166*2da066efSJohn Baldwin 167*2da066efSJohn Baldwin nc->nc_data = buf; 168*2da066efSJohn Baldwin nc->nc_data_len = len; 169*2da066efSJohn Baldwin nc->nc_send_data = send; 170*2da066efSJohn Baldwin return (0); 171*2da066efSJohn Baldwin } 172*2da066efSJohn Baldwin 173*2da066efSJohn Baldwin void 174*2da066efSJohn Baldwin nvmf_free_capsule(struct nvmf_capsule *nc) 175*2da066efSJohn Baldwin { 176*2da066efSJohn Baldwin nc->nc_qpair->nq_association->na_ops->free_capsule(nc); 177*2da066efSJohn Baldwin } 178*2da066efSJohn Baldwin 179*2da066efSJohn Baldwin int 180*2da066efSJohn Baldwin nvmf_transmit_capsule(struct nvmf_capsule *nc) 181*2da066efSJohn Baldwin { 182*2da066efSJohn Baldwin return (nc->nc_qpair->nq_association->na_ops->transmit_capsule(nc)); 183*2da066efSJohn Baldwin } 184*2da066efSJohn Baldwin 185*2da066efSJohn Baldwin int 186*2da066efSJohn Baldwin nvmf_receive_capsule(struct nvmf_qpair *qp, struct nvmf_capsule **ncp) 187*2da066efSJohn Baldwin { 188*2da066efSJohn Baldwin return (qp->nq_association->na_ops->receive_capsule(qp, ncp)); 189*2da066efSJohn Baldwin } 190*2da066efSJohn Baldwin 191*2da066efSJohn Baldwin const void * 192*2da066efSJohn Baldwin nvmf_capsule_sqe(const struct nvmf_capsule *nc) 193*2da066efSJohn Baldwin { 194*2da066efSJohn Baldwin assert(nc->nc_qe_len == sizeof(struct nvme_command)); 195*2da066efSJohn Baldwin return (&nc->nc_sqe); 196*2da066efSJohn Baldwin } 197*2da066efSJohn Baldwin 198*2da066efSJohn Baldwin const void * 199*2da066efSJohn Baldwin nvmf_capsule_cqe(const struct nvmf_capsule *nc) 200*2da066efSJohn Baldwin { 201*2da066efSJohn Baldwin assert(nc->nc_qe_len == sizeof(struct nvme_completion)); 202*2da066efSJohn Baldwin return (&nc->nc_cqe); 203*2da066efSJohn Baldwin } 204*2da066efSJohn Baldwin 205*2da066efSJohn Baldwin uint8_t 206*2da066efSJohn Baldwin nvmf_validate_command_capsule(const struct nvmf_capsule *nc) 207*2da066efSJohn Baldwin { 208*2da066efSJohn Baldwin assert(nc->nc_qe_len == sizeof(struct nvme_command)); 209*2da066efSJohn Baldwin 210*2da066efSJohn Baldwin if (NVMEV(NVME_CMD_PSDT, nc->nc_sqe.fuse) != NVME_PSDT_SGL) 211*2da066efSJohn Baldwin return (NVME_SC_INVALID_FIELD); 212*2da066efSJohn Baldwin 213*2da066efSJohn Baldwin return (nc->nc_qpair->nq_association->na_ops->validate_command_capsule(nc)); 214*2da066efSJohn Baldwin } 215*2da066efSJohn Baldwin 216*2da066efSJohn Baldwin size_t 217*2da066efSJohn Baldwin nvmf_capsule_data_len(const struct nvmf_capsule *nc) 218*2da066efSJohn Baldwin { 219*2da066efSJohn Baldwin return (nc->nc_qpair->nq_association->na_ops->capsule_data_len(nc)); 220*2da066efSJohn Baldwin } 221*2da066efSJohn Baldwin 222*2da066efSJohn Baldwin int 223*2da066efSJohn Baldwin nvmf_receive_controller_data(const struct nvmf_capsule *nc, 224*2da066efSJohn Baldwin uint32_t data_offset, void *buf, size_t len) 225*2da066efSJohn Baldwin { 226*2da066efSJohn Baldwin return (nc->nc_qpair->nq_association->na_ops->receive_controller_data(nc, 227*2da066efSJohn Baldwin data_offset, buf, len)); 228*2da066efSJohn Baldwin } 229*2da066efSJohn Baldwin 230*2da066efSJohn Baldwin int 231*2da066efSJohn Baldwin nvmf_send_controller_data(const struct nvmf_capsule *nc, const void *buf, 232*2da066efSJohn Baldwin size_t len) 233*2da066efSJohn Baldwin { 234*2da066efSJohn Baldwin return (nc->nc_qpair->nq_association->na_ops->send_controller_data(nc, 235*2da066efSJohn Baldwin buf, len)); 236*2da066efSJohn Baldwin } 237*2da066efSJohn Baldwin 238*2da066efSJohn Baldwin int 239*2da066efSJohn Baldwin nvmf_kernel_handoff_params(struct nvmf_qpair *qp, 240*2da066efSJohn Baldwin struct nvmf_handoff_qpair_params *qparams) 241*2da066efSJohn Baldwin { 242*2da066efSJohn Baldwin memset(qparams, 0, sizeof(*qparams)); 243*2da066efSJohn Baldwin qparams->admin = qp->nq_admin; 244*2da066efSJohn Baldwin qparams->sq_flow_control = qp->nq_flow_control; 245*2da066efSJohn Baldwin qparams->qsize = qp->nq_qsize; 246*2da066efSJohn Baldwin qparams->sqhd = qp->nq_sqhd; 247*2da066efSJohn Baldwin qparams->sqtail = qp->nq_sqtail; 248*2da066efSJohn Baldwin return (qp->nq_association->na_ops->kernel_handoff_params(qp, qparams)); 249*2da066efSJohn Baldwin } 250*2da066efSJohn Baldwin 251*2da066efSJohn Baldwin const char * 252*2da066efSJohn Baldwin nvmf_transport_type(uint8_t trtype) 253*2da066efSJohn Baldwin { 254*2da066efSJohn Baldwin static _Thread_local char buf[8]; 255*2da066efSJohn Baldwin 256*2da066efSJohn Baldwin switch (trtype) { 257*2da066efSJohn Baldwin case NVMF_TRTYPE_RDMA: 258*2da066efSJohn Baldwin return ("RDMA"); 259*2da066efSJohn Baldwin case NVMF_TRTYPE_FC: 260*2da066efSJohn Baldwin return ("Fibre Channel"); 261*2da066efSJohn Baldwin case NVMF_TRTYPE_TCP: 262*2da066efSJohn Baldwin return ("TCP"); 263*2da066efSJohn Baldwin case NVMF_TRTYPE_INTRA_HOST: 264*2da066efSJohn Baldwin return ("Intra-host"); 265*2da066efSJohn Baldwin default: 266*2da066efSJohn Baldwin snprintf(buf, sizeof(buf), "0x%02x\n", trtype); 267*2da066efSJohn Baldwin return (buf); 268*2da066efSJohn Baldwin } 269*2da066efSJohn Baldwin } 270