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