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_INTERNAL_H__
9 #define __NVMF_TRANSPORT_INTERNAL_H__
10
11 #include <sys/_nv.h>
12 #include <sys/memdesc.h>
13
14 /*
15 * Interface between the transport-independent APIs in
16 * nvmf_transport.c and individual transports.
17 */
18
19 struct module;
20 struct nvmf_io_request;
21
22 struct nvmf_transport_ops {
23 /* Queue pair management. */
24 struct nvmf_qpair *(*allocate_qpair)(bool controller,
25 const nvlist_t *nvl);
26 void (*free_qpair)(struct nvmf_qpair *qp);
27
28 /* Capsule operations. */
29 struct nvmf_capsule *(*allocate_capsule)(struct nvmf_qpair *qp,
30 int how);
31 void (*free_capsule)(struct nvmf_capsule *nc);
32 int (*transmit_capsule)(struct nvmf_capsule *nc);
33 uint8_t (*validate_command_capsule)(struct nvmf_capsule *nc);
34
35 /* Transferring controller data. */
36 size_t (*capsule_data_len)(const struct nvmf_capsule *nc);
37 int (*receive_controller_data)(struct nvmf_capsule *nc,
38 uint32_t data_offset, struct nvmf_io_request *io);
39 u_int (*send_controller_data)(struct nvmf_capsule *nc,
40 uint32_t data_offset, struct mbuf *m, size_t len);
41
42 enum nvmf_trtype trtype;
43 int priority;
44 };
45
46 /* Either an Admin or I/O Submission/Completion Queue pair. */
47 struct nvmf_qpair {
48 struct nvmf_transport *nq_transport;
49 struct nvmf_transport_ops *nq_ops;
50 bool nq_controller;
51
52 /* Callback to invoke for a received capsule. */
53 nvmf_capsule_receive_t *nq_receive;
54 void *nq_receive_arg;
55
56 /* Callback to invoke for an error. */
57 nvmf_qpair_error_t *nq_error;
58 void *nq_error_arg;
59
60 bool nq_admin;
61 };
62
63 struct nvmf_io_request {
64 /*
65 * Data buffer contains io_len bytes in the backing store
66 * described by mem.
67 */
68 struct memdesc io_mem;
69 size_t io_len;
70 nvmf_io_complete_t *io_complete;
71 void *io_complete_arg;
72 };
73
74 /*
75 * Fabrics Command and Response Capsules. The Fabrics host
76 * (initiator) and controller (target) drivers work with capsules that
77 * are transmitted and received by a specific transport.
78 */
79 struct nvmf_capsule {
80 struct nvmf_qpair *nc_qpair;
81
82 /* Either a SQE or CQE. */
83 union {
84 struct nvme_command nc_sqe;
85 struct nvme_completion nc_cqe;
86 };
87 int nc_qe_len;
88
89 /*
90 * Is SQHD in received capsule valid? False for locally-
91 * synthesized responses.
92 */
93 bool nc_sqhd_valid;
94
95 bool nc_send_data;
96 struct nvmf_io_request nc_data;
97 };
98
99 static void __inline
nvmf_qpair_error(struct nvmf_qpair * nq,int error)100 nvmf_qpair_error(struct nvmf_qpair *nq, int error)
101 {
102 nq->nq_error(nq->nq_error_arg, error);
103 }
104
105 static void __inline
nvmf_capsule_received(struct nvmf_qpair * nq,struct nvmf_capsule * nc)106 nvmf_capsule_received(struct nvmf_qpair *nq, struct nvmf_capsule *nc)
107 {
108 nq->nq_receive(nq->nq_receive_arg, nc);
109 }
110
111 static void __inline
nvmf_complete_io_request(struct nvmf_io_request * io,size_t xfered,int error)112 nvmf_complete_io_request(struct nvmf_io_request *io, size_t xfered, int error)
113 {
114 io->io_complete(io->io_complete_arg, xfered, error);
115 }
116
117 int nvmf_transport_module_handler(struct module *, int, void *);
118
119 #define NVMF_TRANSPORT(name, ops) \
120 static moduledata_t nvmf_transport_##name##_mod = { \
121 "nvmf/" #name, \
122 nvmf_transport_module_handler, \
123 &(ops) \
124 }; \
125 DECLARE_MODULE(nvmf_transport_##name, nvmf_transport_##name##_mod, \
126 SI_SUB_DRIVERS, SI_ORDER_ANY); \
127 MODULE_DEPEND(nvmf_transport_##name, nvmf_transport, 1, 1, 1)
128
129 #endif /* !__NVMF_TRANSPORT_INTERNAL_H__ */
130