Commit | Line | Data |
---|---|---|
03bee01d LL |
1 | /* |
2 | * Copyright (C) 2017, Microsoft Corporation. | |
3 | * | |
4 | * Author(s): Long Li <longli@microsoft.com> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | |
14 | * the GNU General Public License for more details. | |
15 | */ | |
16 | #ifndef _SMBDIRECT_H | |
17 | #define _SMBDIRECT_H | |
18 | ||
f198186a LL |
19 | #ifdef CONFIG_CIFS_SMB_DIRECT |
20 | #define cifs_rdma_enabled(server) ((server)->rdma) | |
21 | ||
22 | #include "cifsglob.h" | |
23 | #include <rdma/ib_verbs.h> | |
24 | #include <rdma/rdma_cm.h> | |
25 | #include <linux/mempool.h> | |
26 | ||
6b314714 SF |
27 | extern int rdma_readwrite_threshold; |
28 | extern int smbd_max_frmr_depth; | |
29 | extern int smbd_keep_alive_interval; | |
30 | extern int smbd_max_receive_size; | |
31 | extern int smbd_max_fragmented_recv_size; | |
32 | extern int smbd_max_send_size; | |
33 | extern int smbd_send_credit_target; | |
34 | extern int smbd_receive_credit_max; | |
35 | ||
f198186a LL |
36 | enum keep_alive_status { |
37 | KEEP_ALIVE_NONE, | |
38 | KEEP_ALIVE_PENDING, | |
39 | KEEP_ALIVE_SENT, | |
40 | }; | |
41 | ||
42 | enum smbd_connection_status { | |
43 | SMBD_CREATED, | |
44 | SMBD_CONNECTING, | |
45 | SMBD_CONNECTED, | |
46 | SMBD_NEGOTIATE_FAILED, | |
47 | SMBD_DISCONNECTING, | |
48 | SMBD_DISCONNECTED, | |
49 | SMBD_DESTROYED | |
50 | }; | |
51 | ||
52 | /* | |
53 | * The context for the SMBDirect transport | |
54 | * Everything related to the transport is here. It has several logical parts | |
55 | * 1. RDMA related structures | |
56 | * 2. SMBDirect connection parameters | |
57 | * 3. Memory registrations | |
58 | * 4. Receive and reassembly queues for data receive path | |
59 | * 5. mempools for allocating packets | |
60 | */ | |
61 | struct smbd_connection { | |
62 | enum smbd_connection_status transport_status; | |
63 | ||
64 | /* RDMA related */ | |
65 | struct rdma_cm_id *id; | |
66 | struct ib_qp_init_attr qp_attr; | |
67 | struct ib_pd *pd; | |
68 | struct ib_cq *send_cq, *recv_cq; | |
69 | struct ib_device_attr dev_attr; | |
70 | int ri_rc; | |
71 | struct completion ri_done; | |
72 | wait_queue_head_t conn_wait; | |
050b8c37 | 73 | wait_queue_head_t disconn_wait; |
f198186a LL |
74 | |
75 | struct completion negotiate_completion; | |
76 | bool negotiate_done; | |
77 | ||
f198186a LL |
78 | struct work_struct disconnect_work; |
79 | struct work_struct recv_done_work; | |
80 | struct work_struct post_send_credits_work; | |
81 | ||
82 | spinlock_t lock_new_credits_offered; | |
83 | int new_credits_offered; | |
84 | ||
85 | /* Connection parameters defined in [MS-SMBD] 3.1.1.1 */ | |
86 | int receive_credit_max; | |
87 | int send_credit_target; | |
88 | int max_send_size; | |
89 | int max_fragmented_recv_size; | |
90 | int max_fragmented_send_size; | |
91 | int max_receive_size; | |
92 | int keep_alive_interval; | |
93 | int max_readwrite_size; | |
94 | enum keep_alive_status keep_alive_requested; | |
95 | int protocol; | |
96 | atomic_t send_credits; | |
97 | atomic_t receive_credits; | |
98 | int receive_credit_target; | |
99 | int fragment_reassembly_remaining; | |
100 | ||
c7398583 LL |
101 | /* Memory registrations */ |
102 | /* Maximum number of RDMA read/write outstanding on this connection */ | |
103 | int responder_resources; | |
104 | /* Maximum number of SGEs in a RDMA write/read */ | |
105 | int max_frmr_depth; | |
106 | /* | |
107 | * If payload is less than or equal to the threshold, | |
108 | * use RDMA send/recv to send upper layer I/O. | |
109 | * If payload is more than the threshold, | |
110 | * use RDMA read/write through memory registration for I/O. | |
111 | */ | |
112 | int rdma_readwrite_threshold; | |
113 | enum ib_mr_type mr_type; | |
114 | struct list_head mr_list; | |
115 | spinlock_t mr_list_lock; | |
116 | /* The number of available MRs ready for memory registration */ | |
117 | atomic_t mr_ready_count; | |
118 | atomic_t mr_used_count; | |
119 | wait_queue_head_t wait_mr; | |
120 | struct work_struct mr_recovery_work; | |
121 | /* Used by transport to wait until all MRs are returned */ | |
122 | wait_queue_head_t wait_for_mr_cleanup; | |
123 | ||
f198186a | 124 | /* Activity accoutning */ |
f198186a LL |
125 | atomic_t send_pending; |
126 | wait_queue_head_t wait_send_pending; | |
127 | atomic_t send_payload_pending; | |
128 | wait_queue_head_t wait_send_payload_pending; | |
129 | ||
130 | /* Receive queue */ | |
131 | struct list_head receive_queue; | |
132 | int count_receive_queue; | |
133 | spinlock_t receive_queue_lock; | |
134 | ||
135 | struct list_head empty_packet_queue; | |
136 | int count_empty_packet_queue; | |
137 | spinlock_t empty_packet_queue_lock; | |
138 | ||
139 | wait_queue_head_t wait_receive_queues; | |
140 | ||
141 | /* Reassembly queue */ | |
142 | struct list_head reassembly_queue; | |
143 | spinlock_t reassembly_queue_lock; | |
144 | wait_queue_head_t wait_reassembly_queue; | |
145 | ||
146 | /* total data length of reassembly queue */ | |
147 | int reassembly_data_length; | |
148 | int reassembly_queue_length; | |
149 | /* the offset to first buffer in reassembly queue */ | |
150 | int first_entry_offset; | |
151 | ||
152 | bool send_immediate; | |
153 | ||
154 | wait_queue_head_t wait_send_queue; | |
155 | ||
156 | /* | |
157 | * Indicate if we have received a full packet on the connection | |
158 | * This is used to identify the first SMBD packet of a assembled | |
159 | * payload (SMB packet) in reassembly queue so we can return a | |
160 | * RFC1002 length to upper layer to indicate the length of the SMB | |
161 | * packet received | |
162 | */ | |
163 | bool full_packet_received; | |
164 | ||
165 | struct workqueue_struct *workqueue; | |
166 | struct delayed_work idle_timer_work; | |
167 | struct delayed_work send_immediate_work; | |
168 | ||
169 | /* Memory pool for preallocating buffers */ | |
170 | /* request pool for RDMA send */ | |
171 | struct kmem_cache *request_cache; | |
172 | mempool_t *request_mempool; | |
173 | ||
174 | /* response pool for RDMA receive */ | |
175 | struct kmem_cache *response_cache; | |
176 | mempool_t *response_mempool; | |
177 | ||
178 | /* for debug purposes */ | |
179 | unsigned int count_get_receive_buffer; | |
180 | unsigned int count_put_receive_buffer; | |
181 | unsigned int count_reassembly_queue; | |
182 | unsigned int count_enqueue_reassembly_queue; | |
183 | unsigned int count_dequeue_reassembly_queue; | |
184 | unsigned int count_send_empty; | |
185 | }; | |
186 | ||
187 | enum smbd_message_type { | |
188 | SMBD_NEGOTIATE_RESP, | |
189 | SMBD_TRANSFER_DATA, | |
190 | }; | |
191 | ||
192 | #define SMB_DIRECT_RESPONSE_REQUESTED 0x0001 | |
193 | ||
194 | /* SMBD negotiation request packet [MS-SMBD] 2.2.1 */ | |
195 | struct smbd_negotiate_req { | |
196 | __le16 min_version; | |
197 | __le16 max_version; | |
198 | __le16 reserved; | |
199 | __le16 credits_requested; | |
200 | __le32 preferred_send_size; | |
201 | __le32 max_receive_size; | |
202 | __le32 max_fragmented_size; | |
203 | } __packed; | |
204 | ||
205 | /* SMBD negotiation response packet [MS-SMBD] 2.2.2 */ | |
206 | struct smbd_negotiate_resp { | |
207 | __le16 min_version; | |
208 | __le16 max_version; | |
209 | __le16 negotiated_version; | |
210 | __le16 reserved; | |
211 | __le16 credits_requested; | |
212 | __le16 credits_granted; | |
213 | __le32 status; | |
214 | __le32 max_readwrite_size; | |
215 | __le32 preferred_send_size; | |
216 | __le32 max_receive_size; | |
217 | __le32 max_fragmented_size; | |
218 | } __packed; | |
219 | ||
220 | /* SMBD data transfer packet with payload [MS-SMBD] 2.2.3 */ | |
221 | struct smbd_data_transfer { | |
222 | __le16 credits_requested; | |
223 | __le16 credits_granted; | |
224 | __le16 flags; | |
225 | __le16 reserved; | |
226 | __le32 remaining_data_length; | |
227 | __le32 data_offset; | |
228 | __le32 data_length; | |
229 | __le32 padding; | |
230 | __u8 buffer[]; | |
231 | } __packed; | |
232 | ||
233 | /* The packet fields for a registered RDMA buffer */ | |
234 | struct smbd_buffer_descriptor_v1 { | |
235 | __le64 offset; | |
236 | __le32 token; | |
237 | __le32 length; | |
238 | } __packed; | |
239 | ||
03bee01d LL |
240 | /* Default maximum number of SGEs in a RDMA send/recv */ |
241 | #define SMBDIRECT_MAX_SGE 16 | |
f198186a LL |
242 | /* The context for a SMBD request */ |
243 | struct smbd_request { | |
244 | struct smbd_connection *info; | |
245 | struct ib_cqe cqe; | |
246 | ||
247 | /* true if this request carries upper layer payload */ | |
248 | bool has_payload; | |
249 | ||
250 | /* the SGE entries for this packet */ | |
251 | struct ib_sge sge[SMBDIRECT_MAX_SGE]; | |
252 | int num_sge; | |
253 | ||
254 | /* SMBD packet header follows this structure */ | |
255 | u8 packet[]; | |
256 | }; | |
257 | ||
258 | /* The context for a SMBD response */ | |
259 | struct smbd_response { | |
260 | struct smbd_connection *info; | |
261 | struct ib_cqe cqe; | |
262 | struct ib_sge sge; | |
263 | ||
264 | enum smbd_message_type type; | |
265 | ||
266 | /* Link to receive queue or reassembly queue */ | |
267 | struct list_head list; | |
268 | ||
269 | /* Indicate if this is the 1st packet of a payload */ | |
270 | bool first_segment; | |
271 | ||
272 | /* SMBD packet header and payload follows this structure */ | |
273 | u8 packet[]; | |
274 | }; | |
275 | ||
399f9539 LL |
276 | /* Create a SMBDirect session */ |
277 | struct smbd_connection *smbd_get_connection( | |
278 | struct TCP_Server_Info *server, struct sockaddr *dstaddr); | |
279 | ||
ad57b8e1 LL |
280 | /* Reconnect SMBDirect session */ |
281 | int smbd_reconnect(struct TCP_Server_Info *server); | |
8ef130f9 | 282 | /* Destroy SMBDirect session */ |
050b8c37 | 283 | void smbd_destroy(struct TCP_Server_Info *server); |
ad57b8e1 | 284 | |
f64b78fd LL |
285 | /* Interface for carrying upper layer I/O through send/recv */ |
286 | int smbd_recv(struct smbd_connection *info, struct msghdr *msg); | |
81f39f95 | 287 | int smbd_send(struct TCP_Server_Info *server, struct smb_rqst *rqst); |
f64b78fd | 288 | |
c7398583 LL |
289 | enum mr_state { |
290 | MR_READY, | |
291 | MR_REGISTERED, | |
292 | MR_INVALIDATED, | |
293 | MR_ERROR | |
294 | }; | |
295 | ||
296 | struct smbd_mr { | |
297 | struct smbd_connection *conn; | |
298 | struct list_head list; | |
299 | enum mr_state state; | |
300 | struct ib_mr *mr; | |
301 | struct scatterlist *sgl; | |
302 | int sgl_count; | |
303 | enum dma_data_direction dir; | |
304 | union { | |
305 | struct ib_reg_wr wr; | |
306 | struct ib_send_wr inv_wr; | |
307 | }; | |
308 | struct ib_cqe cqe; | |
309 | bool need_invalidate; | |
310 | struct completion invalidate_done; | |
311 | }; | |
312 | ||
313 | /* Interfaces to register and deregister MR for RDMA read/write */ | |
314 | struct smbd_mr *smbd_register_mr( | |
315 | struct smbd_connection *info, struct page *pages[], int num_pages, | |
7cf20bce | 316 | int offset, int tailsz, bool writing, bool need_invalidate); |
c7398583 LL |
317 | int smbd_deregister_mr(struct smbd_mr *mr); |
318 | ||
f198186a LL |
319 | #else |
320 | #define cifs_rdma_enabled(server) 0 | |
321 | struct smbd_connection {}; | |
399f9539 LL |
322 | static inline void *smbd_get_connection( |
323 | struct TCP_Server_Info *server, struct sockaddr *dstaddr) {return NULL;} | |
ad57b8e1 | 324 | static inline int smbd_reconnect(struct TCP_Server_Info *server) {return -1; } |
050b8c37 | 325 | static inline void smbd_destroy(struct TCP_Server_Info *server) {} |
f64b78fd | 326 | static inline int smbd_recv(struct smbd_connection *info, struct msghdr *msg) {return -1; } |
81f39f95 | 327 | static inline int smbd_send(struct TCP_Server_Info *server, struct smb_rqst *rqst) {return -1; } |
f198186a LL |
328 | #endif |
329 | ||
03bee01d | 330 | #endif |