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