xref: /kernel/linux/linux-5.10/fs/cifs/smbdirect.h (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *   Copyright (C) 2017, Microsoft Corporation.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *   Author(s): Long Li <longli@microsoft.com>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci#ifndef _SMBDIRECT_H
88c2ecf20Sopenharmony_ci#define _SMBDIRECT_H
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#ifdef CONFIG_CIFS_SMB_DIRECT
118c2ecf20Sopenharmony_ci#define cifs_rdma_enabled(server)	((server)->rdma)
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include "cifsglob.h"
148c2ecf20Sopenharmony_ci#include <rdma/ib_verbs.h>
158c2ecf20Sopenharmony_ci#include <rdma/rdma_cm.h>
168c2ecf20Sopenharmony_ci#include <linux/mempool.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ciextern int rdma_readwrite_threshold;
198c2ecf20Sopenharmony_ciextern int smbd_max_frmr_depth;
208c2ecf20Sopenharmony_ciextern int smbd_keep_alive_interval;
218c2ecf20Sopenharmony_ciextern int smbd_max_receive_size;
228c2ecf20Sopenharmony_ciextern int smbd_max_fragmented_recv_size;
238c2ecf20Sopenharmony_ciextern int smbd_max_send_size;
248c2ecf20Sopenharmony_ciextern int smbd_send_credit_target;
258c2ecf20Sopenharmony_ciextern int smbd_receive_credit_max;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cienum keep_alive_status {
288c2ecf20Sopenharmony_ci	KEEP_ALIVE_NONE,
298c2ecf20Sopenharmony_ci	KEEP_ALIVE_PENDING,
308c2ecf20Sopenharmony_ci	KEEP_ALIVE_SENT,
318c2ecf20Sopenharmony_ci};
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_cienum smbd_connection_status {
348c2ecf20Sopenharmony_ci	SMBD_CREATED,
358c2ecf20Sopenharmony_ci	SMBD_CONNECTING,
368c2ecf20Sopenharmony_ci	SMBD_CONNECTED,
378c2ecf20Sopenharmony_ci	SMBD_NEGOTIATE_FAILED,
388c2ecf20Sopenharmony_ci	SMBD_DISCONNECTING,
398c2ecf20Sopenharmony_ci	SMBD_DISCONNECTED,
408c2ecf20Sopenharmony_ci	SMBD_DESTROYED
418c2ecf20Sopenharmony_ci};
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/*
448c2ecf20Sopenharmony_ci * The context for the SMBDirect transport
458c2ecf20Sopenharmony_ci * Everything related to the transport is here. It has several logical parts
468c2ecf20Sopenharmony_ci * 1. RDMA related structures
478c2ecf20Sopenharmony_ci * 2. SMBDirect connection parameters
488c2ecf20Sopenharmony_ci * 3. Memory registrations
498c2ecf20Sopenharmony_ci * 4. Receive and reassembly queues for data receive path
508c2ecf20Sopenharmony_ci * 5. mempools for allocating packets
518c2ecf20Sopenharmony_ci */
528c2ecf20Sopenharmony_cistruct smbd_connection {
538c2ecf20Sopenharmony_ci	enum smbd_connection_status transport_status;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	/* RDMA related */
568c2ecf20Sopenharmony_ci	struct rdma_cm_id *id;
578c2ecf20Sopenharmony_ci	struct ib_qp_init_attr qp_attr;
588c2ecf20Sopenharmony_ci	struct ib_pd *pd;
598c2ecf20Sopenharmony_ci	struct ib_cq *send_cq, *recv_cq;
608c2ecf20Sopenharmony_ci	struct ib_device_attr dev_attr;
618c2ecf20Sopenharmony_ci	int ri_rc;
628c2ecf20Sopenharmony_ci	struct completion ri_done;
638c2ecf20Sopenharmony_ci	wait_queue_head_t conn_wait;
648c2ecf20Sopenharmony_ci	wait_queue_head_t disconn_wait;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	struct completion negotiate_completion;
678c2ecf20Sopenharmony_ci	bool negotiate_done;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	struct work_struct disconnect_work;
708c2ecf20Sopenharmony_ci	struct work_struct post_send_credits_work;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	spinlock_t lock_new_credits_offered;
738c2ecf20Sopenharmony_ci	int new_credits_offered;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	/* Connection parameters defined in [MS-SMBD] 3.1.1.1 */
768c2ecf20Sopenharmony_ci	int receive_credit_max;
778c2ecf20Sopenharmony_ci	int send_credit_target;
788c2ecf20Sopenharmony_ci	int max_send_size;
798c2ecf20Sopenharmony_ci	int max_fragmented_recv_size;
808c2ecf20Sopenharmony_ci	int max_fragmented_send_size;
818c2ecf20Sopenharmony_ci	int max_receive_size;
828c2ecf20Sopenharmony_ci	int keep_alive_interval;
838c2ecf20Sopenharmony_ci	int max_readwrite_size;
848c2ecf20Sopenharmony_ci	enum keep_alive_status keep_alive_requested;
858c2ecf20Sopenharmony_ci	int protocol;
868c2ecf20Sopenharmony_ci	atomic_t send_credits;
878c2ecf20Sopenharmony_ci	atomic_t receive_credits;
888c2ecf20Sopenharmony_ci	int receive_credit_target;
898c2ecf20Sopenharmony_ci	int fragment_reassembly_remaining;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	/* Memory registrations */
928c2ecf20Sopenharmony_ci	/* Maximum number of RDMA read/write outstanding on this connection */
938c2ecf20Sopenharmony_ci	int responder_resources;
948c2ecf20Sopenharmony_ci	/* Maximum number of SGEs in a RDMA write/read */
958c2ecf20Sopenharmony_ci	int max_frmr_depth;
968c2ecf20Sopenharmony_ci	/*
978c2ecf20Sopenharmony_ci	 * If payload is less than or equal to the threshold,
988c2ecf20Sopenharmony_ci	 * use RDMA send/recv to send upper layer I/O.
998c2ecf20Sopenharmony_ci	 * If payload is more than the threshold,
1008c2ecf20Sopenharmony_ci	 * use RDMA read/write through memory registration for I/O.
1018c2ecf20Sopenharmony_ci	 */
1028c2ecf20Sopenharmony_ci	int rdma_readwrite_threshold;
1038c2ecf20Sopenharmony_ci	enum ib_mr_type mr_type;
1048c2ecf20Sopenharmony_ci	struct list_head mr_list;
1058c2ecf20Sopenharmony_ci	spinlock_t mr_list_lock;
1068c2ecf20Sopenharmony_ci	/* The number of available MRs ready for memory registration */
1078c2ecf20Sopenharmony_ci	atomic_t mr_ready_count;
1088c2ecf20Sopenharmony_ci	atomic_t mr_used_count;
1098c2ecf20Sopenharmony_ci	wait_queue_head_t wait_mr;
1108c2ecf20Sopenharmony_ci	struct work_struct mr_recovery_work;
1118c2ecf20Sopenharmony_ci	/* Used by transport to wait until all MRs are returned */
1128c2ecf20Sopenharmony_ci	wait_queue_head_t wait_for_mr_cleanup;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	/* Activity accoutning */
1158c2ecf20Sopenharmony_ci	atomic_t send_pending;
1168c2ecf20Sopenharmony_ci	wait_queue_head_t wait_send_pending;
1178c2ecf20Sopenharmony_ci	wait_queue_head_t wait_post_send;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	/* Receive queue */
1208c2ecf20Sopenharmony_ci	struct list_head receive_queue;
1218c2ecf20Sopenharmony_ci	int count_receive_queue;
1228c2ecf20Sopenharmony_ci	spinlock_t receive_queue_lock;
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	struct list_head empty_packet_queue;
1258c2ecf20Sopenharmony_ci	int count_empty_packet_queue;
1268c2ecf20Sopenharmony_ci	spinlock_t empty_packet_queue_lock;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	wait_queue_head_t wait_receive_queues;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	/* Reassembly queue */
1318c2ecf20Sopenharmony_ci	struct list_head reassembly_queue;
1328c2ecf20Sopenharmony_ci	spinlock_t reassembly_queue_lock;
1338c2ecf20Sopenharmony_ci	wait_queue_head_t wait_reassembly_queue;
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	/* total data length of reassembly queue */
1368c2ecf20Sopenharmony_ci	int reassembly_data_length;
1378c2ecf20Sopenharmony_ci	int reassembly_queue_length;
1388c2ecf20Sopenharmony_ci	/* the offset to first buffer in reassembly queue */
1398c2ecf20Sopenharmony_ci	int first_entry_offset;
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	bool send_immediate;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	wait_queue_head_t wait_send_queue;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	/*
1468c2ecf20Sopenharmony_ci	 * Indicate if we have received a full packet on the connection
1478c2ecf20Sopenharmony_ci	 * This is used to identify the first SMBD packet of a assembled
1488c2ecf20Sopenharmony_ci	 * payload (SMB packet) in reassembly queue so we can return a
1498c2ecf20Sopenharmony_ci	 * RFC1002 length to upper layer to indicate the length of the SMB
1508c2ecf20Sopenharmony_ci	 * packet received
1518c2ecf20Sopenharmony_ci	 */
1528c2ecf20Sopenharmony_ci	bool full_packet_received;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	struct workqueue_struct *workqueue;
1558c2ecf20Sopenharmony_ci	struct delayed_work idle_timer_work;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	/* Memory pool for preallocating buffers */
1588c2ecf20Sopenharmony_ci	/* request pool for RDMA send */
1598c2ecf20Sopenharmony_ci	struct kmem_cache *request_cache;
1608c2ecf20Sopenharmony_ci	mempool_t *request_mempool;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	/* response pool for RDMA receive */
1638c2ecf20Sopenharmony_ci	struct kmem_cache *response_cache;
1648c2ecf20Sopenharmony_ci	mempool_t *response_mempool;
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	/* for debug purposes */
1678c2ecf20Sopenharmony_ci	unsigned int count_get_receive_buffer;
1688c2ecf20Sopenharmony_ci	unsigned int count_put_receive_buffer;
1698c2ecf20Sopenharmony_ci	unsigned int count_reassembly_queue;
1708c2ecf20Sopenharmony_ci	unsigned int count_enqueue_reassembly_queue;
1718c2ecf20Sopenharmony_ci	unsigned int count_dequeue_reassembly_queue;
1728c2ecf20Sopenharmony_ci	unsigned int count_send_empty;
1738c2ecf20Sopenharmony_ci};
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_cienum smbd_message_type {
1768c2ecf20Sopenharmony_ci	SMBD_NEGOTIATE_RESP,
1778c2ecf20Sopenharmony_ci	SMBD_TRANSFER_DATA,
1788c2ecf20Sopenharmony_ci};
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci#define SMB_DIRECT_RESPONSE_REQUESTED 0x0001
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci/* SMBD negotiation request packet [MS-SMBD] 2.2.1 */
1838c2ecf20Sopenharmony_cistruct smbd_negotiate_req {
1848c2ecf20Sopenharmony_ci	__le16 min_version;
1858c2ecf20Sopenharmony_ci	__le16 max_version;
1868c2ecf20Sopenharmony_ci	__le16 reserved;
1878c2ecf20Sopenharmony_ci	__le16 credits_requested;
1888c2ecf20Sopenharmony_ci	__le32 preferred_send_size;
1898c2ecf20Sopenharmony_ci	__le32 max_receive_size;
1908c2ecf20Sopenharmony_ci	__le32 max_fragmented_size;
1918c2ecf20Sopenharmony_ci} __packed;
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci/* SMBD negotiation response packet [MS-SMBD] 2.2.2 */
1948c2ecf20Sopenharmony_cistruct smbd_negotiate_resp {
1958c2ecf20Sopenharmony_ci	__le16 min_version;
1968c2ecf20Sopenharmony_ci	__le16 max_version;
1978c2ecf20Sopenharmony_ci	__le16 negotiated_version;
1988c2ecf20Sopenharmony_ci	__le16 reserved;
1998c2ecf20Sopenharmony_ci	__le16 credits_requested;
2008c2ecf20Sopenharmony_ci	__le16 credits_granted;
2018c2ecf20Sopenharmony_ci	__le32 status;
2028c2ecf20Sopenharmony_ci	__le32 max_readwrite_size;
2038c2ecf20Sopenharmony_ci	__le32 preferred_send_size;
2048c2ecf20Sopenharmony_ci	__le32 max_receive_size;
2058c2ecf20Sopenharmony_ci	__le32 max_fragmented_size;
2068c2ecf20Sopenharmony_ci} __packed;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci/* SMBD data transfer packet with payload [MS-SMBD] 2.2.3 */
2098c2ecf20Sopenharmony_cistruct smbd_data_transfer {
2108c2ecf20Sopenharmony_ci	__le16 credits_requested;
2118c2ecf20Sopenharmony_ci	__le16 credits_granted;
2128c2ecf20Sopenharmony_ci	__le16 flags;
2138c2ecf20Sopenharmony_ci	__le16 reserved;
2148c2ecf20Sopenharmony_ci	__le32 remaining_data_length;
2158c2ecf20Sopenharmony_ci	__le32 data_offset;
2168c2ecf20Sopenharmony_ci	__le32 data_length;
2178c2ecf20Sopenharmony_ci	__le32 padding;
2188c2ecf20Sopenharmony_ci	__u8 buffer[];
2198c2ecf20Sopenharmony_ci} __packed;
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci/* The packet fields for a registered RDMA buffer */
2228c2ecf20Sopenharmony_cistruct smbd_buffer_descriptor_v1 {
2238c2ecf20Sopenharmony_ci	__le64 offset;
2248c2ecf20Sopenharmony_ci	__le32 token;
2258c2ecf20Sopenharmony_ci	__le32 length;
2268c2ecf20Sopenharmony_ci} __packed;
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci/* Default maximum number of SGEs in a RDMA send/recv */
2298c2ecf20Sopenharmony_ci#define SMBDIRECT_MAX_SGE	16
2308c2ecf20Sopenharmony_ci/* The context for a SMBD request */
2318c2ecf20Sopenharmony_cistruct smbd_request {
2328c2ecf20Sopenharmony_ci	struct smbd_connection *info;
2338c2ecf20Sopenharmony_ci	struct ib_cqe cqe;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	/* the SGE entries for this packet */
2368c2ecf20Sopenharmony_ci	struct ib_sge sge[SMBDIRECT_MAX_SGE];
2378c2ecf20Sopenharmony_ci	int num_sge;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	/* SMBD packet header follows this structure */
2408c2ecf20Sopenharmony_ci	u8 packet[];
2418c2ecf20Sopenharmony_ci};
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci/* The context for a SMBD response */
2448c2ecf20Sopenharmony_cistruct smbd_response {
2458c2ecf20Sopenharmony_ci	struct smbd_connection *info;
2468c2ecf20Sopenharmony_ci	struct ib_cqe cqe;
2478c2ecf20Sopenharmony_ci	struct ib_sge sge;
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	enum smbd_message_type type;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	/* Link to receive queue or reassembly queue */
2528c2ecf20Sopenharmony_ci	struct list_head list;
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	/* Indicate if this is the 1st packet of a payload */
2558c2ecf20Sopenharmony_ci	bool first_segment;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	/* SMBD packet header and payload follows this structure */
2588c2ecf20Sopenharmony_ci	u8 packet[];
2598c2ecf20Sopenharmony_ci};
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci/* Create a SMBDirect session */
2628c2ecf20Sopenharmony_cistruct smbd_connection *smbd_get_connection(
2638c2ecf20Sopenharmony_ci	struct TCP_Server_Info *server, struct sockaddr *dstaddr);
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci/* Reconnect SMBDirect session */
2668c2ecf20Sopenharmony_ciint smbd_reconnect(struct TCP_Server_Info *server);
2678c2ecf20Sopenharmony_ci/* Destroy SMBDirect session */
2688c2ecf20Sopenharmony_civoid smbd_destroy(struct TCP_Server_Info *server);
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci/* Interface for carrying upper layer I/O through send/recv */
2718c2ecf20Sopenharmony_ciint smbd_recv(struct smbd_connection *info, struct msghdr *msg);
2728c2ecf20Sopenharmony_ciint smbd_send(struct TCP_Server_Info *server,
2738c2ecf20Sopenharmony_ci	int num_rqst, struct smb_rqst *rqst);
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cienum mr_state {
2768c2ecf20Sopenharmony_ci	MR_READY,
2778c2ecf20Sopenharmony_ci	MR_REGISTERED,
2788c2ecf20Sopenharmony_ci	MR_INVALIDATED,
2798c2ecf20Sopenharmony_ci	MR_ERROR
2808c2ecf20Sopenharmony_ci};
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_cistruct smbd_mr {
2838c2ecf20Sopenharmony_ci	struct smbd_connection	*conn;
2848c2ecf20Sopenharmony_ci	struct list_head	list;
2858c2ecf20Sopenharmony_ci	enum mr_state		state;
2868c2ecf20Sopenharmony_ci	struct ib_mr		*mr;
2878c2ecf20Sopenharmony_ci	struct scatterlist	*sgl;
2888c2ecf20Sopenharmony_ci	int			sgl_count;
2898c2ecf20Sopenharmony_ci	enum dma_data_direction	dir;
2908c2ecf20Sopenharmony_ci	union {
2918c2ecf20Sopenharmony_ci		struct ib_reg_wr	wr;
2928c2ecf20Sopenharmony_ci		struct ib_send_wr	inv_wr;
2938c2ecf20Sopenharmony_ci	};
2948c2ecf20Sopenharmony_ci	struct ib_cqe		cqe;
2958c2ecf20Sopenharmony_ci	bool			need_invalidate;
2968c2ecf20Sopenharmony_ci	struct completion	invalidate_done;
2978c2ecf20Sopenharmony_ci};
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci/* Interfaces to register and deregister MR for RDMA read/write */
3008c2ecf20Sopenharmony_cistruct smbd_mr *smbd_register_mr(
3018c2ecf20Sopenharmony_ci	struct smbd_connection *info, struct page *pages[], int num_pages,
3028c2ecf20Sopenharmony_ci	int offset, int tailsz, bool writing, bool need_invalidate);
3038c2ecf20Sopenharmony_ciint smbd_deregister_mr(struct smbd_mr *mr);
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci#else
3068c2ecf20Sopenharmony_ci#define cifs_rdma_enabled(server)	0
3078c2ecf20Sopenharmony_cistruct smbd_connection {};
3088c2ecf20Sopenharmony_cistatic inline void *smbd_get_connection(
3098c2ecf20Sopenharmony_ci	struct TCP_Server_Info *server, struct sockaddr *dstaddr) {return NULL;}
3108c2ecf20Sopenharmony_cistatic inline int smbd_reconnect(struct TCP_Server_Info *server) {return -1; }
3118c2ecf20Sopenharmony_cistatic inline void smbd_destroy(struct TCP_Server_Info *server) {}
3128c2ecf20Sopenharmony_cistatic inline int smbd_recv(struct smbd_connection *info, struct msghdr *msg) {return -1; }
3138c2ecf20Sopenharmony_cistatic inline int smbd_send(struct TCP_Server_Info *server, int num_rqst, struct smb_rqst *rqst) {return -1; }
3148c2ecf20Sopenharmony_ci#endif
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci#endif
317