xref: /freebsd/sys/dev/nvmf/nvmf_transport.h (revision 365b89e8ea4af34a05f68aa28e77573e89fa00b2)
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 /* Controller-specific APIs. */
85 
86 /*
87  * A controller calls this function to check for any
88  * transport-specific errors (invalid fields) in a received command
89  * capsule.  The callback returns a generic command status value:
90  * NVME_SC_SUCCESS if no error is found.
91  */
92 uint8_t	nvmf_validate_command_capsule(struct nvmf_capsule *nc);
93 
94 /*
95  * A controller calls this function to query the amount of data
96  * associated with a command capsule.
97  */
98 size_t	nvmf_capsule_data_len(const struct nvmf_capsule *cc);
99 
100 /*
101  * A controller calls this function to receive data associated with a
102  * command capsule (e.g. the data for a WRITE command).  This can
103  * either return in-capsule data or fetch data from the host
104  * (e.g. using a R2T PDU over TCP).  The received command capsule
105  * should be passed in 'nc'.  The received data is stored in 'mem'.
106  * If this function returns success, then the callback will be invoked
107  * once the operation has completed.  Note that the callback might be
108  * invoked before this function returns.
109  */
110 int	nvmf_receive_controller_data(struct nvmf_capsule *nc,
111     uint32_t data_offset, struct memdesc *mem, size_t len,
112     nvmf_io_complete_t *complete_cb, void *cb_arg);
113 
114 /*
115  * A controller calls this function to send data in response to a
116  * command prior to sending a response capsule.  If an error occurs,
117  * the function returns a generic status completion code to be sent in
118  * the following CQE.  Note that the transfer might send a subset of
119  * the data requested by nc.  If the transfer succeeds, this function
120  * can return one of the following values:
121  *
122  * - NVME_SC_SUCCESS: The transfer has completed successfully and the
123  *   caller should send a success CQE in a response capsule.
124  *
125  * - NVMF_SUCCESS_SENT: The transfer has completed successfully and
126  *   the transport layer has sent an implicit success CQE to the
127  *   remote host (e.g. the SUCCESS flag for TCP).  The caller should
128  *   not send a response capsule.
129  *
130  * - NVMF_MORE: The transfer has completed successfully, but the
131  *   transfer did not complete the data buffer.
132  *
133  * The mbuf chain in 'm' is consumed by this function even if an error
134  * is returned.
135  */
136 u_int	nvmf_send_controller_data(struct nvmf_capsule *nc,
137     uint32_t data_offset, struct mbuf *m, size_t len);
138 
139 #define	NVMF_SUCCESS_SENT	0x100
140 #define	NVMF_MORE		0x101
141 
142 /* Helper APIs for nvlists used in icotls. */
143 
144 /*
145  * Pack the nvlist nvl and copyout to the buffer described by nv.
146  */
147 int	nvmf_pack_ioc_nvlist(const nvlist_t *nvl, struct nvmf_ioc_nv *nv);
148 
149 /*
150  * Copyin and unpack an nvlist described by nv.  The unpacked nvlist
151  * is returned in *nvlp on success.
152  */
153 int	nvmf_unpack_ioc_nvlist(const struct nvmf_ioc_nv *nv, nvlist_t **nvlp);
154 
155 /*
156  * Returns true if a qpair handoff nvlist has all the required
157  * transport-independent values.
158  */
159 bool	nvmf_validate_qpair_nvlist(const nvlist_t *nvl, bool controller);
160 
161 #endif /* !__NVMF_TRANSPORT_H__ */
162