138c8a9a5SSteve French // SPDX-License-Identifier: GPL-2.0-or-later 238c8a9a5SSteve French /* 338c8a9a5SSteve French * Copyright (C) 2017, Microsoft Corporation. 438c8a9a5SSteve French * Copyright (C) 2018, LG Electronics. 538c8a9a5SSteve French * 638c8a9a5SSteve French * Author(s): Long Li <longli@microsoft.com>, 738c8a9a5SSteve French * Hyunchul Lee <hyc.lee@gmail.com> 838c8a9a5SSteve French */ 938c8a9a5SSteve French 1038c8a9a5SSteve French #define SUBMOD_NAME "smb_direct" 1138c8a9a5SSteve French 1238c8a9a5SSteve French #include <linux/kthread.h> 1338c8a9a5SSteve French #include <linux/list.h> 1438c8a9a5SSteve French #include <linux/mempool.h> 1538c8a9a5SSteve French #include <linux/highmem.h> 1638c8a9a5SSteve French #include <linux/scatterlist.h> 1738c8a9a5SSteve French #include <rdma/ib_verbs.h> 1838c8a9a5SSteve French #include <rdma/rdma_cm.h> 1938c8a9a5SSteve French #include <rdma/rw.h> 2038c8a9a5SSteve French 2138c8a9a5SSteve French #include "glob.h" 2238c8a9a5SSteve French #include "connection.h" 2338c8a9a5SSteve French #include "smb_common.h" 2438c8a9a5SSteve French #include "smbstatus.h" 2538c8a9a5SSteve French #include "transport_rdma.h" 2638c8a9a5SSteve French 2738c8a9a5SSteve French #define SMB_DIRECT_PORT_IWARP 5445 2838c8a9a5SSteve French #define SMB_DIRECT_PORT_INFINIBAND 445 2938c8a9a5SSteve French 3038c8a9a5SSteve French #define SMB_DIRECT_VERSION_LE cpu_to_le16(0x0100) 3138c8a9a5SSteve French 3238c8a9a5SSteve French /* SMB_DIRECT negotiation timeout in seconds */ 3338c8a9a5SSteve French #define SMB_DIRECT_NEGOTIATE_TIMEOUT 120 3438c8a9a5SSteve French 3538c8a9a5SSteve French #define SMB_DIRECT_MAX_SEND_SGES 6 3638c8a9a5SSteve French #define SMB_DIRECT_MAX_RECV_SGES 1 3738c8a9a5SSteve French 3838c8a9a5SSteve French /* 3938c8a9a5SSteve French * Default maximum number of RDMA read/write outstanding on this connection 4038c8a9a5SSteve French * This value is possibly decreased during QP creation on hardware limit 4138c8a9a5SSteve French */ 4238c8a9a5SSteve French #define SMB_DIRECT_CM_INITIATOR_DEPTH 8 4338c8a9a5SSteve French 4438c8a9a5SSteve French /* Maximum number of retries on data transfer operations */ 4538c8a9a5SSteve French #define SMB_DIRECT_CM_RETRY 6 4638c8a9a5SSteve French /* No need to retry on Receiver Not Ready since SMB_DIRECT manages credits */ 4738c8a9a5SSteve French #define SMB_DIRECT_CM_RNR_RETRY 0 4838c8a9a5SSteve French 4938c8a9a5SSteve French /* 5038c8a9a5SSteve French * User configurable initial values per SMB_DIRECT transport connection 5138c8a9a5SSteve French * as defined in [MS-SMBD] 3.1.1.1 5238c8a9a5SSteve French * Those may change after a SMB_DIRECT negotiation 5338c8a9a5SSteve French */ 5438c8a9a5SSteve French 5538c8a9a5SSteve French /* Set 445 port to SMB Direct port by default */ 5638c8a9a5SSteve French static int smb_direct_port = SMB_DIRECT_PORT_INFINIBAND; 5738c8a9a5SSteve French 5838c8a9a5SSteve French /* The local peer's maximum number of credits to grant to the peer */ 5938c8a9a5SSteve French static int smb_direct_receive_credit_max = 255; 6038c8a9a5SSteve French 6138c8a9a5SSteve French /* The remote peer's credit request of local peer */ 6238c8a9a5SSteve French static int smb_direct_send_credit_target = 255; 6338c8a9a5SSteve French 6438c8a9a5SSteve French /* The maximum single message size can be sent to remote peer */ 6538c8a9a5SSteve French static int smb_direct_max_send_size = 1364; 6638c8a9a5SSteve French 6738c8a9a5SSteve French /* The maximum fragmented upper-layer payload receive size supported */ 6838c8a9a5SSteve French static int smb_direct_max_fragmented_recv_size = 1024 * 1024; 6938c8a9a5SSteve French 7038c8a9a5SSteve French /* The maximum single-message size which can be received */ 7138c8a9a5SSteve French static int smb_direct_max_receive_size = 1364; 7238c8a9a5SSteve French 7338c8a9a5SSteve French static int smb_direct_max_read_write_size = SMBD_DEFAULT_IOSIZE; 7438c8a9a5SSteve French 7538c8a9a5SSteve French static LIST_HEAD(smb_direct_device_list); 7638c8a9a5SSteve French static DEFINE_RWLOCK(smb_direct_device_lock); 7738c8a9a5SSteve French 7838c8a9a5SSteve French struct smb_direct_device { 7938c8a9a5SSteve French struct ib_device *ib_dev; 8038c8a9a5SSteve French struct list_head list; 8138c8a9a5SSteve French }; 8238c8a9a5SSteve French 8338c8a9a5SSteve French static struct smb_direct_listener { 8438c8a9a5SSteve French struct rdma_cm_id *cm_id; 8538c8a9a5SSteve French } smb_direct_listener; 8638c8a9a5SSteve French 8738c8a9a5SSteve French static struct workqueue_struct *smb_direct_wq; 8838c8a9a5SSteve French 8938c8a9a5SSteve French enum smb_direct_status { 9038c8a9a5SSteve French SMB_DIRECT_CS_NEW = 0, 9138c8a9a5SSteve French SMB_DIRECT_CS_CONNECTED, 9238c8a9a5SSteve French SMB_DIRECT_CS_DISCONNECTING, 9338c8a9a5SSteve French SMB_DIRECT_CS_DISCONNECTED, 9438c8a9a5SSteve French }; 9538c8a9a5SSteve French 9638c8a9a5SSteve French struct smb_direct_transport { 9738c8a9a5SSteve French struct ksmbd_transport transport; 9838c8a9a5SSteve French 9938c8a9a5SSteve French enum smb_direct_status status; 10038c8a9a5SSteve French bool full_packet_received; 10138c8a9a5SSteve French wait_queue_head_t wait_status; 10238c8a9a5SSteve French 10338c8a9a5SSteve French struct rdma_cm_id *cm_id; 10438c8a9a5SSteve French struct ib_cq *send_cq; 10538c8a9a5SSteve French struct ib_cq *recv_cq; 10638c8a9a5SSteve French struct ib_pd *pd; 10738c8a9a5SSteve French struct ib_qp *qp; 10838c8a9a5SSteve French 10938c8a9a5SSteve French int max_send_size; 11038c8a9a5SSteve French int max_recv_size; 11138c8a9a5SSteve French int max_fragmented_send_size; 11238c8a9a5SSteve French int max_fragmented_recv_size; 11338c8a9a5SSteve French int max_rdma_rw_size; 11438c8a9a5SSteve French 11538c8a9a5SSteve French spinlock_t reassembly_queue_lock; 11638c8a9a5SSteve French struct list_head reassembly_queue; 11738c8a9a5SSteve French int reassembly_data_length; 11838c8a9a5SSteve French int reassembly_queue_length; 11938c8a9a5SSteve French int first_entry_offset; 12038c8a9a5SSteve French wait_queue_head_t wait_reassembly_queue; 12138c8a9a5SSteve French 12238c8a9a5SSteve French spinlock_t receive_credit_lock; 12338c8a9a5SSteve French int recv_credits; 12438c8a9a5SSteve French int count_avail_recvmsg; 12538c8a9a5SSteve French int recv_credit_max; 12638c8a9a5SSteve French int recv_credit_target; 12738c8a9a5SSteve French 12838c8a9a5SSteve French spinlock_t recvmsg_queue_lock; 12938c8a9a5SSteve French struct list_head recvmsg_queue; 13038c8a9a5SSteve French 13138c8a9a5SSteve French spinlock_t empty_recvmsg_queue_lock; 13238c8a9a5SSteve French struct list_head empty_recvmsg_queue; 13338c8a9a5SSteve French 13438c8a9a5SSteve French int send_credit_target; 13538c8a9a5SSteve French atomic_t send_credits; 13638c8a9a5SSteve French spinlock_t lock_new_recv_credits; 13738c8a9a5SSteve French int new_recv_credits; 13838c8a9a5SSteve French int max_rw_credits; 13938c8a9a5SSteve French int pages_per_rw_credit; 14038c8a9a5SSteve French atomic_t rw_credits; 14138c8a9a5SSteve French 14238c8a9a5SSteve French wait_queue_head_t wait_send_credits; 14338c8a9a5SSteve French wait_queue_head_t wait_rw_credits; 14438c8a9a5SSteve French 14538c8a9a5SSteve French mempool_t *sendmsg_mempool; 14638c8a9a5SSteve French struct kmem_cache *sendmsg_cache; 14738c8a9a5SSteve French mempool_t *recvmsg_mempool; 14838c8a9a5SSteve French struct kmem_cache *recvmsg_cache; 14938c8a9a5SSteve French 15038c8a9a5SSteve French wait_queue_head_t wait_send_pending; 15138c8a9a5SSteve French atomic_t send_pending; 15238c8a9a5SSteve French 15338c8a9a5SSteve French struct delayed_work post_recv_credits_work; 15438c8a9a5SSteve French struct work_struct send_immediate_work; 15538c8a9a5SSteve French struct work_struct disconnect_work; 15638c8a9a5SSteve French 15738c8a9a5SSteve French bool negotiation_requested; 15838c8a9a5SSteve French }; 15938c8a9a5SSteve French 16038c8a9a5SSteve French #define KSMBD_TRANS(t) ((struct ksmbd_transport *)&((t)->transport)) 16138c8a9a5SSteve French 16238c8a9a5SSteve French enum { 16338c8a9a5SSteve French SMB_DIRECT_MSG_NEGOTIATE_REQ = 0, 16438c8a9a5SSteve French SMB_DIRECT_MSG_DATA_TRANSFER 16538c8a9a5SSteve French }; 16638c8a9a5SSteve French 16738c8a9a5SSteve French static struct ksmbd_transport_ops ksmbd_smb_direct_transport_ops; 16838c8a9a5SSteve French 16938c8a9a5SSteve French struct smb_direct_send_ctx { 17038c8a9a5SSteve French struct list_head msg_list; 17138c8a9a5SSteve French int wr_cnt; 17238c8a9a5SSteve French bool need_invalidate_rkey; 17338c8a9a5SSteve French unsigned int remote_key; 17438c8a9a5SSteve French }; 17538c8a9a5SSteve French 17638c8a9a5SSteve French struct smb_direct_sendmsg { 17738c8a9a5SSteve French struct smb_direct_transport *transport; 17838c8a9a5SSteve French struct ib_send_wr wr; 17938c8a9a5SSteve French struct list_head list; 18038c8a9a5SSteve French int num_sge; 18138c8a9a5SSteve French struct ib_sge sge[SMB_DIRECT_MAX_SEND_SGES]; 18238c8a9a5SSteve French struct ib_cqe cqe; 18338c8a9a5SSteve French u8 packet[]; 18438c8a9a5SSteve French }; 18538c8a9a5SSteve French 18638c8a9a5SSteve French struct smb_direct_recvmsg { 18738c8a9a5SSteve French struct smb_direct_transport *transport; 18838c8a9a5SSteve French struct list_head list; 18938c8a9a5SSteve French int type; 19038c8a9a5SSteve French struct ib_sge sge; 19138c8a9a5SSteve French struct ib_cqe cqe; 19238c8a9a5SSteve French bool first_segment; 19338c8a9a5SSteve French u8 packet[]; 19438c8a9a5SSteve French }; 19538c8a9a5SSteve French 19638c8a9a5SSteve French struct smb_direct_rdma_rw_msg { 19738c8a9a5SSteve French struct smb_direct_transport *t; 19838c8a9a5SSteve French struct ib_cqe cqe; 19938c8a9a5SSteve French int status; 20038c8a9a5SSteve French struct completion *completion; 20138c8a9a5SSteve French struct list_head list; 20238c8a9a5SSteve French struct rdma_rw_ctx rw_ctx; 20338c8a9a5SSteve French struct sg_table sgt; 20438c8a9a5SSteve French struct scatterlist sg_list[]; 20538c8a9a5SSteve French }; 20638c8a9a5SSteve French 20738c8a9a5SSteve French void init_smbd_max_io_size(unsigned int sz) 20838c8a9a5SSteve French { 20938c8a9a5SSteve French sz = clamp_val(sz, SMBD_MIN_IOSIZE, SMBD_MAX_IOSIZE); 21038c8a9a5SSteve French smb_direct_max_read_write_size = sz; 21138c8a9a5SSteve French } 21238c8a9a5SSteve French 21338c8a9a5SSteve French unsigned int get_smbd_max_read_write_size(void) 21438c8a9a5SSteve French { 21538c8a9a5SSteve French return smb_direct_max_read_write_size; 21638c8a9a5SSteve French } 21738c8a9a5SSteve French 21838c8a9a5SSteve French static inline int get_buf_page_count(void *buf, int size) 21938c8a9a5SSteve French { 22038c8a9a5SSteve French return DIV_ROUND_UP((uintptr_t)buf + size, PAGE_SIZE) - 22138c8a9a5SSteve French (uintptr_t)buf / PAGE_SIZE; 22238c8a9a5SSteve French } 22338c8a9a5SSteve French 22438c8a9a5SSteve French static void smb_direct_destroy_pools(struct smb_direct_transport *transport); 22538c8a9a5SSteve French static void smb_direct_post_recv_credits(struct work_struct *work); 22638c8a9a5SSteve French static int smb_direct_post_send_data(struct smb_direct_transport *t, 22738c8a9a5SSteve French struct smb_direct_send_ctx *send_ctx, 22838c8a9a5SSteve French struct kvec *iov, int niov, 22938c8a9a5SSteve French int remaining_data_length); 23038c8a9a5SSteve French 23138c8a9a5SSteve French static inline struct smb_direct_transport * 23238c8a9a5SSteve French smb_trans_direct_transfort(struct ksmbd_transport *t) 23338c8a9a5SSteve French { 23438c8a9a5SSteve French return container_of(t, struct smb_direct_transport, transport); 23538c8a9a5SSteve French } 23638c8a9a5SSteve French 23738c8a9a5SSteve French static inline void 23838c8a9a5SSteve French *smb_direct_recvmsg_payload(struct smb_direct_recvmsg *recvmsg) 23938c8a9a5SSteve French { 24038c8a9a5SSteve French return (void *)recvmsg->packet; 24138c8a9a5SSteve French } 24238c8a9a5SSteve French 24338c8a9a5SSteve French static inline bool is_receive_credit_post_required(int receive_credits, 24438c8a9a5SSteve French int avail_recvmsg_count) 24538c8a9a5SSteve French { 24638c8a9a5SSteve French return receive_credits <= (smb_direct_receive_credit_max >> 3) && 24738c8a9a5SSteve French avail_recvmsg_count >= (receive_credits >> 2); 24838c8a9a5SSteve French } 24938c8a9a5SSteve French 25038c8a9a5SSteve French static struct 25138c8a9a5SSteve French smb_direct_recvmsg *get_free_recvmsg(struct smb_direct_transport *t) 25238c8a9a5SSteve French { 25338c8a9a5SSteve French struct smb_direct_recvmsg *recvmsg = NULL; 25438c8a9a5SSteve French 25538c8a9a5SSteve French spin_lock(&t->recvmsg_queue_lock); 25638c8a9a5SSteve French if (!list_empty(&t->recvmsg_queue)) { 25738c8a9a5SSteve French recvmsg = list_first_entry(&t->recvmsg_queue, 25838c8a9a5SSteve French struct smb_direct_recvmsg, 25938c8a9a5SSteve French list); 26038c8a9a5SSteve French list_del(&recvmsg->list); 26138c8a9a5SSteve French } 26238c8a9a5SSteve French spin_unlock(&t->recvmsg_queue_lock); 26338c8a9a5SSteve French return recvmsg; 26438c8a9a5SSteve French } 26538c8a9a5SSteve French 26638c8a9a5SSteve French static void put_recvmsg(struct smb_direct_transport *t, 26738c8a9a5SSteve French struct smb_direct_recvmsg *recvmsg) 26838c8a9a5SSteve French { 26938c8a9a5SSteve French ib_dma_unmap_single(t->cm_id->device, recvmsg->sge.addr, 27038c8a9a5SSteve French recvmsg->sge.length, DMA_FROM_DEVICE); 27138c8a9a5SSteve French 27238c8a9a5SSteve French spin_lock(&t->recvmsg_queue_lock); 27338c8a9a5SSteve French list_add(&recvmsg->list, &t->recvmsg_queue); 27438c8a9a5SSteve French spin_unlock(&t->recvmsg_queue_lock); 27538c8a9a5SSteve French } 27638c8a9a5SSteve French 27738c8a9a5SSteve French static struct 27838c8a9a5SSteve French smb_direct_recvmsg *get_empty_recvmsg(struct smb_direct_transport *t) 27938c8a9a5SSteve French { 28038c8a9a5SSteve French struct smb_direct_recvmsg *recvmsg = NULL; 28138c8a9a5SSteve French 28238c8a9a5SSteve French spin_lock(&t->empty_recvmsg_queue_lock); 28338c8a9a5SSteve French if (!list_empty(&t->empty_recvmsg_queue)) { 28438c8a9a5SSteve French recvmsg = list_first_entry(&t->empty_recvmsg_queue, 28538c8a9a5SSteve French struct smb_direct_recvmsg, list); 28638c8a9a5SSteve French list_del(&recvmsg->list); 28738c8a9a5SSteve French } 28838c8a9a5SSteve French spin_unlock(&t->empty_recvmsg_queue_lock); 28938c8a9a5SSteve French return recvmsg; 29038c8a9a5SSteve French } 29138c8a9a5SSteve French 29238c8a9a5SSteve French static void put_empty_recvmsg(struct smb_direct_transport *t, 29338c8a9a5SSteve French struct smb_direct_recvmsg *recvmsg) 29438c8a9a5SSteve French { 29538c8a9a5SSteve French ib_dma_unmap_single(t->cm_id->device, recvmsg->sge.addr, 29638c8a9a5SSteve French recvmsg->sge.length, DMA_FROM_DEVICE); 29738c8a9a5SSteve French 29838c8a9a5SSteve French spin_lock(&t->empty_recvmsg_queue_lock); 29938c8a9a5SSteve French list_add_tail(&recvmsg->list, &t->empty_recvmsg_queue); 30038c8a9a5SSteve French spin_unlock(&t->empty_recvmsg_queue_lock); 30138c8a9a5SSteve French } 30238c8a9a5SSteve French 30338c8a9a5SSteve French static void enqueue_reassembly(struct smb_direct_transport *t, 30438c8a9a5SSteve French struct smb_direct_recvmsg *recvmsg, 30538c8a9a5SSteve French int data_length) 30638c8a9a5SSteve French { 30738c8a9a5SSteve French spin_lock(&t->reassembly_queue_lock); 30838c8a9a5SSteve French list_add_tail(&recvmsg->list, &t->reassembly_queue); 30938c8a9a5SSteve French t->reassembly_queue_length++; 31038c8a9a5SSteve French /* 31138c8a9a5SSteve French * Make sure reassembly_data_length is updated after list and 31238c8a9a5SSteve French * reassembly_queue_length are updated. On the dequeue side 31338c8a9a5SSteve French * reassembly_data_length is checked without a lock to determine 31438c8a9a5SSteve French * if reassembly_queue_length and list is up to date 31538c8a9a5SSteve French */ 31638c8a9a5SSteve French virt_wmb(); 31738c8a9a5SSteve French t->reassembly_data_length += data_length; 31838c8a9a5SSteve French spin_unlock(&t->reassembly_queue_lock); 31938c8a9a5SSteve French } 32038c8a9a5SSteve French 32138c8a9a5SSteve French static struct smb_direct_recvmsg *get_first_reassembly(struct smb_direct_transport *t) 32238c8a9a5SSteve French { 32338c8a9a5SSteve French if (!list_empty(&t->reassembly_queue)) 32438c8a9a5SSteve French return list_first_entry(&t->reassembly_queue, 32538c8a9a5SSteve French struct smb_direct_recvmsg, list); 32638c8a9a5SSteve French else 32738c8a9a5SSteve French return NULL; 32838c8a9a5SSteve French } 32938c8a9a5SSteve French 33038c8a9a5SSteve French static void smb_direct_disconnect_rdma_work(struct work_struct *work) 33138c8a9a5SSteve French { 33238c8a9a5SSteve French struct smb_direct_transport *t = 33338c8a9a5SSteve French container_of(work, struct smb_direct_transport, 33438c8a9a5SSteve French disconnect_work); 33538c8a9a5SSteve French 33638c8a9a5SSteve French if (t->status == SMB_DIRECT_CS_CONNECTED) { 33738c8a9a5SSteve French t->status = SMB_DIRECT_CS_DISCONNECTING; 33838c8a9a5SSteve French rdma_disconnect(t->cm_id); 33938c8a9a5SSteve French } 34038c8a9a5SSteve French } 34138c8a9a5SSteve French 34238c8a9a5SSteve French static void 34338c8a9a5SSteve French smb_direct_disconnect_rdma_connection(struct smb_direct_transport *t) 34438c8a9a5SSteve French { 34538c8a9a5SSteve French if (t->status == SMB_DIRECT_CS_CONNECTED) 34638c8a9a5SSteve French queue_work(smb_direct_wq, &t->disconnect_work); 34738c8a9a5SSteve French } 34838c8a9a5SSteve French 34938c8a9a5SSteve French static void smb_direct_send_immediate_work(struct work_struct *work) 35038c8a9a5SSteve French { 35138c8a9a5SSteve French struct smb_direct_transport *t = container_of(work, 35238c8a9a5SSteve French struct smb_direct_transport, send_immediate_work); 35338c8a9a5SSteve French 35438c8a9a5SSteve French if (t->status != SMB_DIRECT_CS_CONNECTED) 35538c8a9a5SSteve French return; 35638c8a9a5SSteve French 35738c8a9a5SSteve French smb_direct_post_send_data(t, NULL, NULL, 0, 0); 35838c8a9a5SSteve French } 35938c8a9a5SSteve French 36038c8a9a5SSteve French static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id) 36138c8a9a5SSteve French { 36238c8a9a5SSteve French struct smb_direct_transport *t; 36338c8a9a5SSteve French struct ksmbd_conn *conn; 36438c8a9a5SSteve French 36538c8a9a5SSteve French t = kzalloc(sizeof(*t), GFP_KERNEL); 36638c8a9a5SSteve French if (!t) 36738c8a9a5SSteve French return NULL; 36838c8a9a5SSteve French 36938c8a9a5SSteve French t->cm_id = cm_id; 37038c8a9a5SSteve French cm_id->context = t; 37138c8a9a5SSteve French 37238c8a9a5SSteve French t->status = SMB_DIRECT_CS_NEW; 37338c8a9a5SSteve French init_waitqueue_head(&t->wait_status); 37438c8a9a5SSteve French 37538c8a9a5SSteve French spin_lock_init(&t->reassembly_queue_lock); 37638c8a9a5SSteve French INIT_LIST_HEAD(&t->reassembly_queue); 37738c8a9a5SSteve French t->reassembly_data_length = 0; 37838c8a9a5SSteve French t->reassembly_queue_length = 0; 37938c8a9a5SSteve French init_waitqueue_head(&t->wait_reassembly_queue); 38038c8a9a5SSteve French init_waitqueue_head(&t->wait_send_credits); 38138c8a9a5SSteve French init_waitqueue_head(&t->wait_rw_credits); 38238c8a9a5SSteve French 38338c8a9a5SSteve French spin_lock_init(&t->receive_credit_lock); 38438c8a9a5SSteve French spin_lock_init(&t->recvmsg_queue_lock); 38538c8a9a5SSteve French INIT_LIST_HEAD(&t->recvmsg_queue); 38638c8a9a5SSteve French 38738c8a9a5SSteve French spin_lock_init(&t->empty_recvmsg_queue_lock); 38838c8a9a5SSteve French INIT_LIST_HEAD(&t->empty_recvmsg_queue); 38938c8a9a5SSteve French 39038c8a9a5SSteve French init_waitqueue_head(&t->wait_send_pending); 39138c8a9a5SSteve French atomic_set(&t->send_pending, 0); 39238c8a9a5SSteve French 39338c8a9a5SSteve French spin_lock_init(&t->lock_new_recv_credits); 39438c8a9a5SSteve French 39538c8a9a5SSteve French INIT_DELAYED_WORK(&t->post_recv_credits_work, 39638c8a9a5SSteve French smb_direct_post_recv_credits); 39738c8a9a5SSteve French INIT_WORK(&t->send_immediate_work, smb_direct_send_immediate_work); 39838c8a9a5SSteve French INIT_WORK(&t->disconnect_work, smb_direct_disconnect_rdma_work); 39938c8a9a5SSteve French 40038c8a9a5SSteve French conn = ksmbd_conn_alloc(); 40138c8a9a5SSteve French if (!conn) 40238c8a9a5SSteve French goto err; 40338c8a9a5SSteve French conn->transport = KSMBD_TRANS(t); 40438c8a9a5SSteve French KSMBD_TRANS(t)->conn = conn; 40538c8a9a5SSteve French KSMBD_TRANS(t)->ops = &ksmbd_smb_direct_transport_ops; 40638c8a9a5SSteve French return t; 40738c8a9a5SSteve French err: 40838c8a9a5SSteve French kfree(t); 40938c8a9a5SSteve French return NULL; 41038c8a9a5SSteve French } 41138c8a9a5SSteve French 41238c8a9a5SSteve French static void free_transport(struct smb_direct_transport *t) 41338c8a9a5SSteve French { 41438c8a9a5SSteve French struct smb_direct_recvmsg *recvmsg; 41538c8a9a5SSteve French 41638c8a9a5SSteve French wake_up_interruptible(&t->wait_send_credits); 41738c8a9a5SSteve French 41838c8a9a5SSteve French ksmbd_debug(RDMA, "wait for all send posted to IB to finish\n"); 41938c8a9a5SSteve French wait_event(t->wait_send_pending, 42038c8a9a5SSteve French atomic_read(&t->send_pending) == 0); 42138c8a9a5SSteve French 42238c8a9a5SSteve French cancel_work_sync(&t->disconnect_work); 42338c8a9a5SSteve French cancel_delayed_work_sync(&t->post_recv_credits_work); 42438c8a9a5SSteve French cancel_work_sync(&t->send_immediate_work); 42538c8a9a5SSteve French 42638c8a9a5SSteve French if (t->qp) { 42738c8a9a5SSteve French ib_drain_qp(t->qp); 42838c8a9a5SSteve French ib_mr_pool_destroy(t->qp, &t->qp->rdma_mrs); 42938c8a9a5SSteve French ib_destroy_qp(t->qp); 43038c8a9a5SSteve French } 43138c8a9a5SSteve French 43238c8a9a5SSteve French ksmbd_debug(RDMA, "drain the reassembly queue\n"); 43338c8a9a5SSteve French do { 43438c8a9a5SSteve French spin_lock(&t->reassembly_queue_lock); 43538c8a9a5SSteve French recvmsg = get_first_reassembly(t); 43638c8a9a5SSteve French if (recvmsg) { 43738c8a9a5SSteve French list_del(&recvmsg->list); 43838c8a9a5SSteve French spin_unlock(&t->reassembly_queue_lock); 43938c8a9a5SSteve French put_recvmsg(t, recvmsg); 44038c8a9a5SSteve French } else { 44138c8a9a5SSteve French spin_unlock(&t->reassembly_queue_lock); 44238c8a9a5SSteve French } 44338c8a9a5SSteve French } while (recvmsg); 44438c8a9a5SSteve French t->reassembly_data_length = 0; 44538c8a9a5SSteve French 44638c8a9a5SSteve French if (t->send_cq) 44738c8a9a5SSteve French ib_free_cq(t->send_cq); 44838c8a9a5SSteve French if (t->recv_cq) 44938c8a9a5SSteve French ib_free_cq(t->recv_cq); 45038c8a9a5SSteve French if (t->pd) 45138c8a9a5SSteve French ib_dealloc_pd(t->pd); 45238c8a9a5SSteve French if (t->cm_id) 45338c8a9a5SSteve French rdma_destroy_id(t->cm_id); 45438c8a9a5SSteve French 45538c8a9a5SSteve French smb_direct_destroy_pools(t); 45638c8a9a5SSteve French ksmbd_conn_free(KSMBD_TRANS(t)->conn); 45738c8a9a5SSteve French kfree(t); 45838c8a9a5SSteve French } 45938c8a9a5SSteve French 46038c8a9a5SSteve French static struct smb_direct_sendmsg 46138c8a9a5SSteve French *smb_direct_alloc_sendmsg(struct smb_direct_transport *t) 46238c8a9a5SSteve French { 46338c8a9a5SSteve French struct smb_direct_sendmsg *msg; 46438c8a9a5SSteve French 46538c8a9a5SSteve French msg = mempool_alloc(t->sendmsg_mempool, GFP_KERNEL); 46638c8a9a5SSteve French if (!msg) 46738c8a9a5SSteve French return ERR_PTR(-ENOMEM); 46838c8a9a5SSteve French msg->transport = t; 46938c8a9a5SSteve French INIT_LIST_HEAD(&msg->list); 47038c8a9a5SSteve French msg->num_sge = 0; 47138c8a9a5SSteve French return msg; 47238c8a9a5SSteve French } 47338c8a9a5SSteve French 47438c8a9a5SSteve French static void smb_direct_free_sendmsg(struct smb_direct_transport *t, 47538c8a9a5SSteve French struct smb_direct_sendmsg *msg) 47638c8a9a5SSteve French { 47738c8a9a5SSteve French int i; 47838c8a9a5SSteve French 47938c8a9a5SSteve French if (msg->num_sge > 0) { 48038c8a9a5SSteve French ib_dma_unmap_single(t->cm_id->device, 48138c8a9a5SSteve French msg->sge[0].addr, msg->sge[0].length, 48238c8a9a5SSteve French DMA_TO_DEVICE); 48338c8a9a5SSteve French for (i = 1; i < msg->num_sge; i++) 48438c8a9a5SSteve French ib_dma_unmap_page(t->cm_id->device, 48538c8a9a5SSteve French msg->sge[i].addr, msg->sge[i].length, 48638c8a9a5SSteve French DMA_TO_DEVICE); 48738c8a9a5SSteve French } 48838c8a9a5SSteve French mempool_free(msg, t->sendmsg_mempool); 48938c8a9a5SSteve French } 49038c8a9a5SSteve French 49138c8a9a5SSteve French static int smb_direct_check_recvmsg(struct smb_direct_recvmsg *recvmsg) 49238c8a9a5SSteve French { 49338c8a9a5SSteve French switch (recvmsg->type) { 49438c8a9a5SSteve French case SMB_DIRECT_MSG_DATA_TRANSFER: { 49538c8a9a5SSteve French struct smb_direct_data_transfer *req = 49638c8a9a5SSteve French (struct smb_direct_data_transfer *)recvmsg->packet; 49738c8a9a5SSteve French struct smb2_hdr *hdr = (struct smb2_hdr *)(recvmsg->packet 49838c8a9a5SSteve French + le32_to_cpu(req->data_offset)); 49938c8a9a5SSteve French ksmbd_debug(RDMA, 50038c8a9a5SSteve French "CreditGranted: %u, CreditRequested: %u, DataLength: %u, RemainingDataLength: %u, SMB: %x, Command: %u\n", 50138c8a9a5SSteve French le16_to_cpu(req->credits_granted), 50238c8a9a5SSteve French le16_to_cpu(req->credits_requested), 50338c8a9a5SSteve French req->data_length, req->remaining_data_length, 50438c8a9a5SSteve French hdr->ProtocolId, hdr->Command); 50538c8a9a5SSteve French break; 50638c8a9a5SSteve French } 50738c8a9a5SSteve French case SMB_DIRECT_MSG_NEGOTIATE_REQ: { 50838c8a9a5SSteve French struct smb_direct_negotiate_req *req = 50938c8a9a5SSteve French (struct smb_direct_negotiate_req *)recvmsg->packet; 51038c8a9a5SSteve French ksmbd_debug(RDMA, 51138c8a9a5SSteve French "MinVersion: %u, MaxVersion: %u, CreditRequested: %u, MaxSendSize: %u, MaxRecvSize: %u, MaxFragmentedSize: %u\n", 51238c8a9a5SSteve French le16_to_cpu(req->min_version), 51338c8a9a5SSteve French le16_to_cpu(req->max_version), 51438c8a9a5SSteve French le16_to_cpu(req->credits_requested), 51538c8a9a5SSteve French le32_to_cpu(req->preferred_send_size), 51638c8a9a5SSteve French le32_to_cpu(req->max_receive_size), 51738c8a9a5SSteve French le32_to_cpu(req->max_fragmented_size)); 51838c8a9a5SSteve French if (le16_to_cpu(req->min_version) > 0x0100 || 51938c8a9a5SSteve French le16_to_cpu(req->max_version) < 0x0100) 52038c8a9a5SSteve French return -EOPNOTSUPP; 52138c8a9a5SSteve French if (le16_to_cpu(req->credits_requested) <= 0 || 52238c8a9a5SSteve French le32_to_cpu(req->max_receive_size) <= 128 || 52338c8a9a5SSteve French le32_to_cpu(req->max_fragmented_size) <= 52438c8a9a5SSteve French 128 * 1024) 52538c8a9a5SSteve French return -ECONNABORTED; 52638c8a9a5SSteve French 52738c8a9a5SSteve French break; 52838c8a9a5SSteve French } 52938c8a9a5SSteve French default: 53038c8a9a5SSteve French return -EINVAL; 53138c8a9a5SSteve French } 53238c8a9a5SSteve French return 0; 53338c8a9a5SSteve French } 53438c8a9a5SSteve French 53538c8a9a5SSteve French static void recv_done(struct ib_cq *cq, struct ib_wc *wc) 53638c8a9a5SSteve French { 53738c8a9a5SSteve French struct smb_direct_recvmsg *recvmsg; 53838c8a9a5SSteve French struct smb_direct_transport *t; 53938c8a9a5SSteve French 54038c8a9a5SSteve French recvmsg = container_of(wc->wr_cqe, struct smb_direct_recvmsg, cqe); 54138c8a9a5SSteve French t = recvmsg->transport; 54238c8a9a5SSteve French 54338c8a9a5SSteve French if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) { 54438c8a9a5SSteve French if (wc->status != IB_WC_WR_FLUSH_ERR) { 54538c8a9a5SSteve French pr_err("Recv error. status='%s (%d)' opcode=%d\n", 54638c8a9a5SSteve French ib_wc_status_msg(wc->status), wc->status, 54738c8a9a5SSteve French wc->opcode); 54838c8a9a5SSteve French smb_direct_disconnect_rdma_connection(t); 54938c8a9a5SSteve French } 55038c8a9a5SSteve French put_empty_recvmsg(t, recvmsg); 55138c8a9a5SSteve French return; 55238c8a9a5SSteve French } 55338c8a9a5SSteve French 55438c8a9a5SSteve French ksmbd_debug(RDMA, "Recv completed. status='%s (%d)', opcode=%d\n", 55538c8a9a5SSteve French ib_wc_status_msg(wc->status), wc->status, 55638c8a9a5SSteve French wc->opcode); 55738c8a9a5SSteve French 55838c8a9a5SSteve French ib_dma_sync_single_for_cpu(wc->qp->device, recvmsg->sge.addr, 55938c8a9a5SSteve French recvmsg->sge.length, DMA_FROM_DEVICE); 56038c8a9a5SSteve French 56138c8a9a5SSteve French switch (recvmsg->type) { 56238c8a9a5SSteve French case SMB_DIRECT_MSG_NEGOTIATE_REQ: 56338c8a9a5SSteve French if (wc->byte_len < sizeof(struct smb_direct_negotiate_req)) { 56438c8a9a5SSteve French put_empty_recvmsg(t, recvmsg); 56538c8a9a5SSteve French return; 56638c8a9a5SSteve French } 56738c8a9a5SSteve French t->negotiation_requested = true; 56838c8a9a5SSteve French t->full_packet_received = true; 56938c8a9a5SSteve French t->status = SMB_DIRECT_CS_CONNECTED; 57038c8a9a5SSteve French enqueue_reassembly(t, recvmsg, 0); 57138c8a9a5SSteve French wake_up_interruptible(&t->wait_status); 57238c8a9a5SSteve French break; 57338c8a9a5SSteve French case SMB_DIRECT_MSG_DATA_TRANSFER: { 57438c8a9a5SSteve French struct smb_direct_data_transfer *data_transfer = 57538c8a9a5SSteve French (struct smb_direct_data_transfer *)recvmsg->packet; 57638c8a9a5SSteve French unsigned int data_length; 57738c8a9a5SSteve French int avail_recvmsg_count, receive_credits; 57838c8a9a5SSteve French 57938c8a9a5SSteve French if (wc->byte_len < 58038c8a9a5SSteve French offsetof(struct smb_direct_data_transfer, padding)) { 58138c8a9a5SSteve French put_empty_recvmsg(t, recvmsg); 58238c8a9a5SSteve French return; 58338c8a9a5SSteve French } 58438c8a9a5SSteve French 58538c8a9a5SSteve French data_length = le32_to_cpu(data_transfer->data_length); 58638c8a9a5SSteve French if (data_length) { 58738c8a9a5SSteve French if (wc->byte_len < sizeof(struct smb_direct_data_transfer) + 58838c8a9a5SSteve French (u64)data_length) { 58938c8a9a5SSteve French put_empty_recvmsg(t, recvmsg); 59038c8a9a5SSteve French return; 59138c8a9a5SSteve French } 59238c8a9a5SSteve French 59338c8a9a5SSteve French if (t->full_packet_received) 59438c8a9a5SSteve French recvmsg->first_segment = true; 59538c8a9a5SSteve French 59638c8a9a5SSteve French if (le32_to_cpu(data_transfer->remaining_data_length)) 59738c8a9a5SSteve French t->full_packet_received = false; 59838c8a9a5SSteve French else 59938c8a9a5SSteve French t->full_packet_received = true; 60038c8a9a5SSteve French 60138c8a9a5SSteve French enqueue_reassembly(t, recvmsg, (int)data_length); 60238c8a9a5SSteve French wake_up_interruptible(&t->wait_reassembly_queue); 60338c8a9a5SSteve French 60438c8a9a5SSteve French spin_lock(&t->receive_credit_lock); 60538c8a9a5SSteve French receive_credits = --(t->recv_credits); 60638c8a9a5SSteve French avail_recvmsg_count = t->count_avail_recvmsg; 60738c8a9a5SSteve French spin_unlock(&t->receive_credit_lock); 60838c8a9a5SSteve French } else { 60938c8a9a5SSteve French put_empty_recvmsg(t, recvmsg); 61038c8a9a5SSteve French 61138c8a9a5SSteve French spin_lock(&t->receive_credit_lock); 61238c8a9a5SSteve French receive_credits = --(t->recv_credits); 61338c8a9a5SSteve French avail_recvmsg_count = ++(t->count_avail_recvmsg); 61438c8a9a5SSteve French spin_unlock(&t->receive_credit_lock); 61538c8a9a5SSteve French } 61638c8a9a5SSteve French 61738c8a9a5SSteve French t->recv_credit_target = 61838c8a9a5SSteve French le16_to_cpu(data_transfer->credits_requested); 61938c8a9a5SSteve French atomic_add(le16_to_cpu(data_transfer->credits_granted), 62038c8a9a5SSteve French &t->send_credits); 62138c8a9a5SSteve French 62238c8a9a5SSteve French if (le16_to_cpu(data_transfer->flags) & 62338c8a9a5SSteve French SMB_DIRECT_RESPONSE_REQUESTED) 62438c8a9a5SSteve French queue_work(smb_direct_wq, &t->send_immediate_work); 62538c8a9a5SSteve French 62638c8a9a5SSteve French if (atomic_read(&t->send_credits) > 0) 62738c8a9a5SSteve French wake_up_interruptible(&t->wait_send_credits); 62838c8a9a5SSteve French 62938c8a9a5SSteve French if (is_receive_credit_post_required(receive_credits, avail_recvmsg_count)) 63038c8a9a5SSteve French mod_delayed_work(smb_direct_wq, 63138c8a9a5SSteve French &t->post_recv_credits_work, 0); 63238c8a9a5SSteve French break; 63338c8a9a5SSteve French } 63438c8a9a5SSteve French default: 63538c8a9a5SSteve French break; 63638c8a9a5SSteve French } 63738c8a9a5SSteve French } 63838c8a9a5SSteve French 63938c8a9a5SSteve French static int smb_direct_post_recv(struct smb_direct_transport *t, 64038c8a9a5SSteve French struct smb_direct_recvmsg *recvmsg) 64138c8a9a5SSteve French { 64238c8a9a5SSteve French struct ib_recv_wr wr; 64338c8a9a5SSteve French int ret; 64438c8a9a5SSteve French 64538c8a9a5SSteve French recvmsg->sge.addr = ib_dma_map_single(t->cm_id->device, 64638c8a9a5SSteve French recvmsg->packet, t->max_recv_size, 64738c8a9a5SSteve French DMA_FROM_DEVICE); 64838c8a9a5SSteve French ret = ib_dma_mapping_error(t->cm_id->device, recvmsg->sge.addr); 64938c8a9a5SSteve French if (ret) 65038c8a9a5SSteve French return ret; 65138c8a9a5SSteve French recvmsg->sge.length = t->max_recv_size; 65238c8a9a5SSteve French recvmsg->sge.lkey = t->pd->local_dma_lkey; 65338c8a9a5SSteve French recvmsg->cqe.done = recv_done; 65438c8a9a5SSteve French 65538c8a9a5SSteve French wr.wr_cqe = &recvmsg->cqe; 65638c8a9a5SSteve French wr.next = NULL; 65738c8a9a5SSteve French wr.sg_list = &recvmsg->sge; 65838c8a9a5SSteve French wr.num_sge = 1; 65938c8a9a5SSteve French 66038c8a9a5SSteve French ret = ib_post_recv(t->qp, &wr, NULL); 66138c8a9a5SSteve French if (ret) { 66238c8a9a5SSteve French pr_err("Can't post recv: %d\n", ret); 66338c8a9a5SSteve French ib_dma_unmap_single(t->cm_id->device, 66438c8a9a5SSteve French recvmsg->sge.addr, recvmsg->sge.length, 66538c8a9a5SSteve French DMA_FROM_DEVICE); 66638c8a9a5SSteve French smb_direct_disconnect_rdma_connection(t); 66738c8a9a5SSteve French return ret; 66838c8a9a5SSteve French } 66938c8a9a5SSteve French return ret; 67038c8a9a5SSteve French } 67138c8a9a5SSteve French 67238c8a9a5SSteve French static int smb_direct_read(struct ksmbd_transport *t, char *buf, 67338c8a9a5SSteve French unsigned int size, int unused) 67438c8a9a5SSteve French { 67538c8a9a5SSteve French struct smb_direct_recvmsg *recvmsg; 67638c8a9a5SSteve French struct smb_direct_data_transfer *data_transfer; 67738c8a9a5SSteve French int to_copy, to_read, data_read, offset; 67838c8a9a5SSteve French u32 data_length, remaining_data_length, data_offset; 67938c8a9a5SSteve French int rc; 68038c8a9a5SSteve French struct smb_direct_transport *st = smb_trans_direct_transfort(t); 68138c8a9a5SSteve French 68238c8a9a5SSteve French again: 68338c8a9a5SSteve French if (st->status != SMB_DIRECT_CS_CONNECTED) { 68438c8a9a5SSteve French pr_err("disconnected\n"); 68538c8a9a5SSteve French return -ENOTCONN; 68638c8a9a5SSteve French } 68738c8a9a5SSteve French 68838c8a9a5SSteve French /* 68938c8a9a5SSteve French * No need to hold the reassembly queue lock all the time as we are 69038c8a9a5SSteve French * the only one reading from the front of the queue. The transport 69138c8a9a5SSteve French * may add more entries to the back of the queue at the same time 69238c8a9a5SSteve French */ 69338c8a9a5SSteve French if (st->reassembly_data_length >= size) { 69438c8a9a5SSteve French int queue_length; 69538c8a9a5SSteve French int queue_removed = 0; 69638c8a9a5SSteve French 69738c8a9a5SSteve French /* 69838c8a9a5SSteve French * Need to make sure reassembly_data_length is read before 69938c8a9a5SSteve French * reading reassembly_queue_length and calling 70038c8a9a5SSteve French * get_first_reassembly. This call is lock free 70138c8a9a5SSteve French * as we never read at the end of the queue which are being 70238c8a9a5SSteve French * updated in SOFTIRQ as more data is received 70338c8a9a5SSteve French */ 70438c8a9a5SSteve French virt_rmb(); 70538c8a9a5SSteve French queue_length = st->reassembly_queue_length; 70638c8a9a5SSteve French data_read = 0; 70738c8a9a5SSteve French to_read = size; 70838c8a9a5SSteve French offset = st->first_entry_offset; 70938c8a9a5SSteve French while (data_read < size) { 71038c8a9a5SSteve French recvmsg = get_first_reassembly(st); 71138c8a9a5SSteve French data_transfer = smb_direct_recvmsg_payload(recvmsg); 71238c8a9a5SSteve French data_length = le32_to_cpu(data_transfer->data_length); 71338c8a9a5SSteve French remaining_data_length = 71438c8a9a5SSteve French le32_to_cpu(data_transfer->remaining_data_length); 71538c8a9a5SSteve French data_offset = le32_to_cpu(data_transfer->data_offset); 71638c8a9a5SSteve French 71738c8a9a5SSteve French /* 71838c8a9a5SSteve French * The upper layer expects RFC1002 length at the 71938c8a9a5SSteve French * beginning of the payload. Return it to indicate 72038c8a9a5SSteve French * the total length of the packet. This minimize the 72138c8a9a5SSteve French * change to upper layer packet processing logic. This 72238c8a9a5SSteve French * will be eventually remove when an intermediate 72338c8a9a5SSteve French * transport layer is added 72438c8a9a5SSteve French */ 72538c8a9a5SSteve French if (recvmsg->first_segment && size == 4) { 72638c8a9a5SSteve French unsigned int rfc1002_len = 72738c8a9a5SSteve French data_length + remaining_data_length; 72838c8a9a5SSteve French *((__be32 *)buf) = cpu_to_be32(rfc1002_len); 72938c8a9a5SSteve French data_read = 4; 73038c8a9a5SSteve French recvmsg->first_segment = false; 73138c8a9a5SSteve French ksmbd_debug(RDMA, 73238c8a9a5SSteve French "returning rfc1002 length %d\n", 73338c8a9a5SSteve French rfc1002_len); 73438c8a9a5SSteve French goto read_rfc1002_done; 73538c8a9a5SSteve French } 73638c8a9a5SSteve French 73738c8a9a5SSteve French to_copy = min_t(int, data_length - offset, to_read); 73838c8a9a5SSteve French memcpy(buf + data_read, (char *)data_transfer + data_offset + offset, 73938c8a9a5SSteve French to_copy); 74038c8a9a5SSteve French 74138c8a9a5SSteve French /* move on to the next buffer? */ 74238c8a9a5SSteve French if (to_copy == data_length - offset) { 74338c8a9a5SSteve French queue_length--; 74438c8a9a5SSteve French /* 74538c8a9a5SSteve French * No need to lock if we are not at the 74638c8a9a5SSteve French * end of the queue 74738c8a9a5SSteve French */ 74838c8a9a5SSteve French if (queue_length) { 74938c8a9a5SSteve French list_del(&recvmsg->list); 75038c8a9a5SSteve French } else { 75138c8a9a5SSteve French spin_lock_irq(&st->reassembly_queue_lock); 75238c8a9a5SSteve French list_del(&recvmsg->list); 75338c8a9a5SSteve French spin_unlock_irq(&st->reassembly_queue_lock); 75438c8a9a5SSteve French } 75538c8a9a5SSteve French queue_removed++; 75638c8a9a5SSteve French put_recvmsg(st, recvmsg); 75738c8a9a5SSteve French offset = 0; 75838c8a9a5SSteve French } else { 75938c8a9a5SSteve French offset += to_copy; 76038c8a9a5SSteve French } 76138c8a9a5SSteve French 76238c8a9a5SSteve French to_read -= to_copy; 76338c8a9a5SSteve French data_read += to_copy; 76438c8a9a5SSteve French } 76538c8a9a5SSteve French 76638c8a9a5SSteve French spin_lock_irq(&st->reassembly_queue_lock); 76738c8a9a5SSteve French st->reassembly_data_length -= data_read; 76838c8a9a5SSteve French st->reassembly_queue_length -= queue_removed; 76938c8a9a5SSteve French spin_unlock_irq(&st->reassembly_queue_lock); 77038c8a9a5SSteve French 77138c8a9a5SSteve French spin_lock(&st->receive_credit_lock); 77238c8a9a5SSteve French st->count_avail_recvmsg += queue_removed; 77338c8a9a5SSteve French if (is_receive_credit_post_required(st->recv_credits, st->count_avail_recvmsg)) { 77438c8a9a5SSteve French spin_unlock(&st->receive_credit_lock); 77538c8a9a5SSteve French mod_delayed_work(smb_direct_wq, 77638c8a9a5SSteve French &st->post_recv_credits_work, 0); 77738c8a9a5SSteve French } else { 77838c8a9a5SSteve French spin_unlock(&st->receive_credit_lock); 77938c8a9a5SSteve French } 78038c8a9a5SSteve French 78138c8a9a5SSteve French st->first_entry_offset = offset; 78238c8a9a5SSteve French ksmbd_debug(RDMA, 78338c8a9a5SSteve French "returning to thread data_read=%d reassembly_data_length=%d first_entry_offset=%d\n", 78438c8a9a5SSteve French data_read, st->reassembly_data_length, 78538c8a9a5SSteve French st->first_entry_offset); 78638c8a9a5SSteve French read_rfc1002_done: 78738c8a9a5SSteve French return data_read; 78838c8a9a5SSteve French } 78938c8a9a5SSteve French 79038c8a9a5SSteve French ksmbd_debug(RDMA, "wait_event on more data\n"); 79138c8a9a5SSteve French rc = wait_event_interruptible(st->wait_reassembly_queue, 79238c8a9a5SSteve French st->reassembly_data_length >= size || 79338c8a9a5SSteve French st->status != SMB_DIRECT_CS_CONNECTED); 79438c8a9a5SSteve French if (rc) 79538c8a9a5SSteve French return -EINTR; 79638c8a9a5SSteve French 79738c8a9a5SSteve French goto again; 79838c8a9a5SSteve French } 79938c8a9a5SSteve French 80038c8a9a5SSteve French static void smb_direct_post_recv_credits(struct work_struct *work) 80138c8a9a5SSteve French { 80238c8a9a5SSteve French struct smb_direct_transport *t = container_of(work, 80338c8a9a5SSteve French struct smb_direct_transport, post_recv_credits_work.work); 80438c8a9a5SSteve French struct smb_direct_recvmsg *recvmsg; 80538c8a9a5SSteve French int receive_credits, credits = 0; 80638c8a9a5SSteve French int ret; 80738c8a9a5SSteve French int use_free = 1; 80838c8a9a5SSteve French 80938c8a9a5SSteve French spin_lock(&t->receive_credit_lock); 81038c8a9a5SSteve French receive_credits = t->recv_credits; 81138c8a9a5SSteve French spin_unlock(&t->receive_credit_lock); 81238c8a9a5SSteve French 81338c8a9a5SSteve French if (receive_credits < t->recv_credit_target) { 81438c8a9a5SSteve French while (true) { 81538c8a9a5SSteve French if (use_free) 81638c8a9a5SSteve French recvmsg = get_free_recvmsg(t); 81738c8a9a5SSteve French else 81838c8a9a5SSteve French recvmsg = get_empty_recvmsg(t); 81938c8a9a5SSteve French if (!recvmsg) { 82038c8a9a5SSteve French if (use_free) { 82138c8a9a5SSteve French use_free = 0; 82238c8a9a5SSteve French continue; 82338c8a9a5SSteve French } else { 82438c8a9a5SSteve French break; 82538c8a9a5SSteve French } 82638c8a9a5SSteve French } 82738c8a9a5SSteve French 82838c8a9a5SSteve French recvmsg->type = SMB_DIRECT_MSG_DATA_TRANSFER; 82938c8a9a5SSteve French recvmsg->first_segment = false; 83038c8a9a5SSteve French 83138c8a9a5SSteve French ret = smb_direct_post_recv(t, recvmsg); 83238c8a9a5SSteve French if (ret) { 83338c8a9a5SSteve French pr_err("Can't post recv: %d\n", ret); 83438c8a9a5SSteve French put_recvmsg(t, recvmsg); 83538c8a9a5SSteve French break; 83638c8a9a5SSteve French } 83738c8a9a5SSteve French credits++; 83838c8a9a5SSteve French } 83938c8a9a5SSteve French } 84038c8a9a5SSteve French 84138c8a9a5SSteve French spin_lock(&t->receive_credit_lock); 84238c8a9a5SSteve French t->recv_credits += credits; 84338c8a9a5SSteve French t->count_avail_recvmsg -= credits; 84438c8a9a5SSteve French spin_unlock(&t->receive_credit_lock); 84538c8a9a5SSteve French 84638c8a9a5SSteve French spin_lock(&t->lock_new_recv_credits); 84738c8a9a5SSteve French t->new_recv_credits += credits; 84838c8a9a5SSteve French spin_unlock(&t->lock_new_recv_credits); 84938c8a9a5SSteve French 85038c8a9a5SSteve French if (credits) 85138c8a9a5SSteve French queue_work(smb_direct_wq, &t->send_immediate_work); 85238c8a9a5SSteve French } 85338c8a9a5SSteve French 85438c8a9a5SSteve French static void send_done(struct ib_cq *cq, struct ib_wc *wc) 85538c8a9a5SSteve French { 85638c8a9a5SSteve French struct smb_direct_sendmsg *sendmsg, *sibling; 85738c8a9a5SSteve French struct smb_direct_transport *t; 85838c8a9a5SSteve French struct list_head *pos, *prev, *end; 85938c8a9a5SSteve French 86038c8a9a5SSteve French sendmsg = container_of(wc->wr_cqe, struct smb_direct_sendmsg, cqe); 86138c8a9a5SSteve French t = sendmsg->transport; 86238c8a9a5SSteve French 86338c8a9a5SSteve French ksmbd_debug(RDMA, "Send completed. status='%s (%d)', opcode=%d\n", 86438c8a9a5SSteve French ib_wc_status_msg(wc->status), wc->status, 86538c8a9a5SSteve French wc->opcode); 86638c8a9a5SSteve French 86738c8a9a5SSteve French if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) { 86838c8a9a5SSteve French pr_err("Send error. status='%s (%d)', opcode=%d\n", 86938c8a9a5SSteve French ib_wc_status_msg(wc->status), wc->status, 87038c8a9a5SSteve French wc->opcode); 87138c8a9a5SSteve French smb_direct_disconnect_rdma_connection(t); 87238c8a9a5SSteve French } 87338c8a9a5SSteve French 87438c8a9a5SSteve French if (atomic_dec_and_test(&t->send_pending)) 87538c8a9a5SSteve French wake_up(&t->wait_send_pending); 87638c8a9a5SSteve French 87738c8a9a5SSteve French /* iterate and free the list of messages in reverse. the list's head 87838c8a9a5SSteve French * is invalid. 87938c8a9a5SSteve French */ 88038c8a9a5SSteve French for (pos = &sendmsg->list, prev = pos->prev, end = sendmsg->list.next; 88138c8a9a5SSteve French prev != end; pos = prev, prev = prev->prev) { 88238c8a9a5SSteve French sibling = container_of(pos, struct smb_direct_sendmsg, list); 88338c8a9a5SSteve French smb_direct_free_sendmsg(t, sibling); 88438c8a9a5SSteve French } 88538c8a9a5SSteve French 88638c8a9a5SSteve French sibling = container_of(pos, struct smb_direct_sendmsg, list); 88738c8a9a5SSteve French smb_direct_free_sendmsg(t, sibling); 88838c8a9a5SSteve French } 88938c8a9a5SSteve French 89038c8a9a5SSteve French static int manage_credits_prior_sending(struct smb_direct_transport *t) 89138c8a9a5SSteve French { 89238c8a9a5SSteve French int new_credits; 89338c8a9a5SSteve French 89438c8a9a5SSteve French spin_lock(&t->lock_new_recv_credits); 89538c8a9a5SSteve French new_credits = t->new_recv_credits; 89638c8a9a5SSteve French t->new_recv_credits = 0; 89738c8a9a5SSteve French spin_unlock(&t->lock_new_recv_credits); 89838c8a9a5SSteve French 89938c8a9a5SSteve French return new_credits; 90038c8a9a5SSteve French } 90138c8a9a5SSteve French 90238c8a9a5SSteve French static int smb_direct_post_send(struct smb_direct_transport *t, 90338c8a9a5SSteve French struct ib_send_wr *wr) 90438c8a9a5SSteve French { 90538c8a9a5SSteve French int ret; 90638c8a9a5SSteve French 90738c8a9a5SSteve French atomic_inc(&t->send_pending); 90838c8a9a5SSteve French ret = ib_post_send(t->qp, wr, NULL); 90938c8a9a5SSteve French if (ret) { 91038c8a9a5SSteve French pr_err("failed to post send: %d\n", ret); 91138c8a9a5SSteve French if (atomic_dec_and_test(&t->send_pending)) 91238c8a9a5SSteve French wake_up(&t->wait_send_pending); 91338c8a9a5SSteve French smb_direct_disconnect_rdma_connection(t); 91438c8a9a5SSteve French } 91538c8a9a5SSteve French return ret; 91638c8a9a5SSteve French } 91738c8a9a5SSteve French 91838c8a9a5SSteve French static void smb_direct_send_ctx_init(struct smb_direct_transport *t, 91938c8a9a5SSteve French struct smb_direct_send_ctx *send_ctx, 92038c8a9a5SSteve French bool need_invalidate_rkey, 92138c8a9a5SSteve French unsigned int remote_key) 92238c8a9a5SSteve French { 92338c8a9a5SSteve French INIT_LIST_HEAD(&send_ctx->msg_list); 92438c8a9a5SSteve French send_ctx->wr_cnt = 0; 92538c8a9a5SSteve French send_ctx->need_invalidate_rkey = need_invalidate_rkey; 92638c8a9a5SSteve French send_ctx->remote_key = remote_key; 92738c8a9a5SSteve French } 92838c8a9a5SSteve French 92938c8a9a5SSteve French static int smb_direct_flush_send_list(struct smb_direct_transport *t, 93038c8a9a5SSteve French struct smb_direct_send_ctx *send_ctx, 93138c8a9a5SSteve French bool is_last) 93238c8a9a5SSteve French { 93338c8a9a5SSteve French struct smb_direct_sendmsg *first, *last; 93438c8a9a5SSteve French int ret; 93538c8a9a5SSteve French 93638c8a9a5SSteve French if (list_empty(&send_ctx->msg_list)) 93738c8a9a5SSteve French return 0; 93838c8a9a5SSteve French 93938c8a9a5SSteve French first = list_first_entry(&send_ctx->msg_list, 94038c8a9a5SSteve French struct smb_direct_sendmsg, 94138c8a9a5SSteve French list); 94238c8a9a5SSteve French last = list_last_entry(&send_ctx->msg_list, 94338c8a9a5SSteve French struct smb_direct_sendmsg, 94438c8a9a5SSteve French list); 94538c8a9a5SSteve French 94638c8a9a5SSteve French last->wr.send_flags = IB_SEND_SIGNALED; 94738c8a9a5SSteve French last->wr.wr_cqe = &last->cqe; 94838c8a9a5SSteve French if (is_last && send_ctx->need_invalidate_rkey) { 94938c8a9a5SSteve French last->wr.opcode = IB_WR_SEND_WITH_INV; 95038c8a9a5SSteve French last->wr.ex.invalidate_rkey = send_ctx->remote_key; 95138c8a9a5SSteve French } 95238c8a9a5SSteve French 95338c8a9a5SSteve French ret = smb_direct_post_send(t, &first->wr); 95438c8a9a5SSteve French if (!ret) { 95538c8a9a5SSteve French smb_direct_send_ctx_init(t, send_ctx, 95638c8a9a5SSteve French send_ctx->need_invalidate_rkey, 95738c8a9a5SSteve French send_ctx->remote_key); 95838c8a9a5SSteve French } else { 95938c8a9a5SSteve French atomic_add(send_ctx->wr_cnt, &t->send_credits); 96038c8a9a5SSteve French wake_up(&t->wait_send_credits); 96138c8a9a5SSteve French list_for_each_entry_safe(first, last, &send_ctx->msg_list, 96238c8a9a5SSteve French list) { 96338c8a9a5SSteve French smb_direct_free_sendmsg(t, first); 96438c8a9a5SSteve French } 96538c8a9a5SSteve French } 96638c8a9a5SSteve French return ret; 96738c8a9a5SSteve French } 96838c8a9a5SSteve French 96938c8a9a5SSteve French static int wait_for_credits(struct smb_direct_transport *t, 97038c8a9a5SSteve French wait_queue_head_t *waitq, atomic_t *total_credits, 97138c8a9a5SSteve French int needed) 97238c8a9a5SSteve French { 97338c8a9a5SSteve French int ret; 97438c8a9a5SSteve French 97538c8a9a5SSteve French do { 97638c8a9a5SSteve French if (atomic_sub_return(needed, total_credits) >= 0) 97738c8a9a5SSteve French return 0; 97838c8a9a5SSteve French 97938c8a9a5SSteve French atomic_add(needed, total_credits); 98038c8a9a5SSteve French ret = wait_event_interruptible(*waitq, 98138c8a9a5SSteve French atomic_read(total_credits) >= needed || 98238c8a9a5SSteve French t->status != SMB_DIRECT_CS_CONNECTED); 98338c8a9a5SSteve French 98438c8a9a5SSteve French if (t->status != SMB_DIRECT_CS_CONNECTED) 98538c8a9a5SSteve French return -ENOTCONN; 98638c8a9a5SSteve French else if (ret < 0) 98738c8a9a5SSteve French return ret; 98838c8a9a5SSteve French } while (true); 98938c8a9a5SSteve French } 99038c8a9a5SSteve French 99138c8a9a5SSteve French static int wait_for_send_credits(struct smb_direct_transport *t, 99238c8a9a5SSteve French struct smb_direct_send_ctx *send_ctx) 99338c8a9a5SSteve French { 99438c8a9a5SSteve French int ret; 99538c8a9a5SSteve French 99638c8a9a5SSteve French if (send_ctx && 99738c8a9a5SSteve French (send_ctx->wr_cnt >= 16 || atomic_read(&t->send_credits) <= 1)) { 99838c8a9a5SSteve French ret = smb_direct_flush_send_list(t, send_ctx, false); 99938c8a9a5SSteve French if (ret) 100038c8a9a5SSteve French return ret; 100138c8a9a5SSteve French } 100238c8a9a5SSteve French 100338c8a9a5SSteve French return wait_for_credits(t, &t->wait_send_credits, &t->send_credits, 1); 100438c8a9a5SSteve French } 100538c8a9a5SSteve French 100638c8a9a5SSteve French static int wait_for_rw_credits(struct smb_direct_transport *t, int credits) 100738c8a9a5SSteve French { 100838c8a9a5SSteve French return wait_for_credits(t, &t->wait_rw_credits, &t->rw_credits, credits); 100938c8a9a5SSteve French } 101038c8a9a5SSteve French 101138c8a9a5SSteve French static int calc_rw_credits(struct smb_direct_transport *t, 101238c8a9a5SSteve French char *buf, unsigned int len) 101338c8a9a5SSteve French { 101438c8a9a5SSteve French return DIV_ROUND_UP(get_buf_page_count(buf, len), 101538c8a9a5SSteve French t->pages_per_rw_credit); 101638c8a9a5SSteve French } 101738c8a9a5SSteve French 101838c8a9a5SSteve French static int smb_direct_create_header(struct smb_direct_transport *t, 101938c8a9a5SSteve French int size, int remaining_data_length, 102038c8a9a5SSteve French struct smb_direct_sendmsg **sendmsg_out) 102138c8a9a5SSteve French { 102238c8a9a5SSteve French struct smb_direct_sendmsg *sendmsg; 102338c8a9a5SSteve French struct smb_direct_data_transfer *packet; 102438c8a9a5SSteve French int header_length; 102538c8a9a5SSteve French int ret; 102638c8a9a5SSteve French 102738c8a9a5SSteve French sendmsg = smb_direct_alloc_sendmsg(t); 102838c8a9a5SSteve French if (IS_ERR(sendmsg)) 102938c8a9a5SSteve French return PTR_ERR(sendmsg); 103038c8a9a5SSteve French 103138c8a9a5SSteve French /* Fill in the packet header */ 103238c8a9a5SSteve French packet = (struct smb_direct_data_transfer *)sendmsg->packet; 103338c8a9a5SSteve French packet->credits_requested = cpu_to_le16(t->send_credit_target); 103438c8a9a5SSteve French packet->credits_granted = cpu_to_le16(manage_credits_prior_sending(t)); 103538c8a9a5SSteve French 103638c8a9a5SSteve French packet->flags = 0; 103738c8a9a5SSteve French packet->reserved = 0; 103838c8a9a5SSteve French if (!size) 103938c8a9a5SSteve French packet->data_offset = 0; 104038c8a9a5SSteve French else 104138c8a9a5SSteve French packet->data_offset = cpu_to_le32(24); 104238c8a9a5SSteve French packet->data_length = cpu_to_le32(size); 104338c8a9a5SSteve French packet->remaining_data_length = cpu_to_le32(remaining_data_length); 104438c8a9a5SSteve French packet->padding = 0; 104538c8a9a5SSteve French 104638c8a9a5SSteve French ksmbd_debug(RDMA, 104738c8a9a5SSteve French "credits_requested=%d credits_granted=%d data_offset=%d data_length=%d remaining_data_length=%d\n", 104838c8a9a5SSteve French le16_to_cpu(packet->credits_requested), 104938c8a9a5SSteve French le16_to_cpu(packet->credits_granted), 105038c8a9a5SSteve French le32_to_cpu(packet->data_offset), 105138c8a9a5SSteve French le32_to_cpu(packet->data_length), 105238c8a9a5SSteve French le32_to_cpu(packet->remaining_data_length)); 105338c8a9a5SSteve French 105438c8a9a5SSteve French /* Map the packet to DMA */ 105538c8a9a5SSteve French header_length = sizeof(struct smb_direct_data_transfer); 105638c8a9a5SSteve French /* If this is a packet without payload, don't send padding */ 105738c8a9a5SSteve French if (!size) 105838c8a9a5SSteve French header_length = 105938c8a9a5SSteve French offsetof(struct smb_direct_data_transfer, padding); 106038c8a9a5SSteve French 106138c8a9a5SSteve French sendmsg->sge[0].addr = ib_dma_map_single(t->cm_id->device, 106238c8a9a5SSteve French (void *)packet, 106338c8a9a5SSteve French header_length, 106438c8a9a5SSteve French DMA_TO_DEVICE); 106538c8a9a5SSteve French ret = ib_dma_mapping_error(t->cm_id->device, sendmsg->sge[0].addr); 106638c8a9a5SSteve French if (ret) { 106738c8a9a5SSteve French smb_direct_free_sendmsg(t, sendmsg); 106838c8a9a5SSteve French return ret; 106938c8a9a5SSteve French } 107038c8a9a5SSteve French 107138c8a9a5SSteve French sendmsg->num_sge = 1; 107238c8a9a5SSteve French sendmsg->sge[0].length = header_length; 107338c8a9a5SSteve French sendmsg->sge[0].lkey = t->pd->local_dma_lkey; 107438c8a9a5SSteve French 107538c8a9a5SSteve French *sendmsg_out = sendmsg; 107638c8a9a5SSteve French return 0; 107738c8a9a5SSteve French } 107838c8a9a5SSteve French 107938c8a9a5SSteve French static int get_sg_list(void *buf, int size, struct scatterlist *sg_list, int nentries) 108038c8a9a5SSteve French { 108138c8a9a5SSteve French bool high = is_vmalloc_addr(buf); 108238c8a9a5SSteve French struct page *page; 108338c8a9a5SSteve French int offset, len; 108438c8a9a5SSteve French int i = 0; 108538c8a9a5SSteve French 108638c8a9a5SSteve French if (size <= 0 || nentries < get_buf_page_count(buf, size)) 108738c8a9a5SSteve French return -EINVAL; 108838c8a9a5SSteve French 108938c8a9a5SSteve French offset = offset_in_page(buf); 109038c8a9a5SSteve French buf -= offset; 109138c8a9a5SSteve French while (size > 0) { 109238c8a9a5SSteve French len = min_t(int, PAGE_SIZE - offset, size); 109338c8a9a5SSteve French if (high) 109438c8a9a5SSteve French page = vmalloc_to_page(buf); 109538c8a9a5SSteve French else 109638c8a9a5SSteve French page = kmap_to_page(buf); 109738c8a9a5SSteve French 109838c8a9a5SSteve French if (!sg_list) 109938c8a9a5SSteve French return -EINVAL; 110038c8a9a5SSteve French sg_set_page(sg_list, page, len, offset); 110138c8a9a5SSteve French sg_list = sg_next(sg_list); 110238c8a9a5SSteve French 110338c8a9a5SSteve French buf += PAGE_SIZE; 110438c8a9a5SSteve French size -= len; 110538c8a9a5SSteve French offset = 0; 110638c8a9a5SSteve French i++; 110738c8a9a5SSteve French } 110838c8a9a5SSteve French return i; 110938c8a9a5SSteve French } 111038c8a9a5SSteve French 111138c8a9a5SSteve French static int get_mapped_sg_list(struct ib_device *device, void *buf, int size, 111238c8a9a5SSteve French struct scatterlist *sg_list, int nentries, 111338c8a9a5SSteve French enum dma_data_direction dir) 111438c8a9a5SSteve French { 111538c8a9a5SSteve French int npages; 111638c8a9a5SSteve French 111738c8a9a5SSteve French npages = get_sg_list(buf, size, sg_list, nentries); 111838c8a9a5SSteve French if (npages < 0) 111938c8a9a5SSteve French return -EINVAL; 112038c8a9a5SSteve French return ib_dma_map_sg(device, sg_list, npages, dir); 112138c8a9a5SSteve French } 112238c8a9a5SSteve French 112338c8a9a5SSteve French static int post_sendmsg(struct smb_direct_transport *t, 112438c8a9a5SSteve French struct smb_direct_send_ctx *send_ctx, 112538c8a9a5SSteve French struct smb_direct_sendmsg *msg) 112638c8a9a5SSteve French { 112738c8a9a5SSteve French int i; 112838c8a9a5SSteve French 112938c8a9a5SSteve French for (i = 0; i < msg->num_sge; i++) 113038c8a9a5SSteve French ib_dma_sync_single_for_device(t->cm_id->device, 113138c8a9a5SSteve French msg->sge[i].addr, msg->sge[i].length, 113238c8a9a5SSteve French DMA_TO_DEVICE); 113338c8a9a5SSteve French 113438c8a9a5SSteve French msg->cqe.done = send_done; 113538c8a9a5SSteve French msg->wr.opcode = IB_WR_SEND; 113638c8a9a5SSteve French msg->wr.sg_list = &msg->sge[0]; 113738c8a9a5SSteve French msg->wr.num_sge = msg->num_sge; 113838c8a9a5SSteve French msg->wr.next = NULL; 113938c8a9a5SSteve French 114038c8a9a5SSteve French if (send_ctx) { 114138c8a9a5SSteve French msg->wr.wr_cqe = NULL; 114238c8a9a5SSteve French msg->wr.send_flags = 0; 114338c8a9a5SSteve French if (!list_empty(&send_ctx->msg_list)) { 114438c8a9a5SSteve French struct smb_direct_sendmsg *last; 114538c8a9a5SSteve French 114638c8a9a5SSteve French last = list_last_entry(&send_ctx->msg_list, 114738c8a9a5SSteve French struct smb_direct_sendmsg, 114838c8a9a5SSteve French list); 114938c8a9a5SSteve French last->wr.next = &msg->wr; 115038c8a9a5SSteve French } 115138c8a9a5SSteve French list_add_tail(&msg->list, &send_ctx->msg_list); 115238c8a9a5SSteve French send_ctx->wr_cnt++; 115338c8a9a5SSteve French return 0; 115438c8a9a5SSteve French } 115538c8a9a5SSteve French 115638c8a9a5SSteve French msg->wr.wr_cqe = &msg->cqe; 115738c8a9a5SSteve French msg->wr.send_flags = IB_SEND_SIGNALED; 115838c8a9a5SSteve French return smb_direct_post_send(t, &msg->wr); 115938c8a9a5SSteve French } 116038c8a9a5SSteve French 116138c8a9a5SSteve French static int smb_direct_post_send_data(struct smb_direct_transport *t, 116238c8a9a5SSteve French struct smb_direct_send_ctx *send_ctx, 116338c8a9a5SSteve French struct kvec *iov, int niov, 116438c8a9a5SSteve French int remaining_data_length) 116538c8a9a5SSteve French { 116638c8a9a5SSteve French int i, j, ret; 116738c8a9a5SSteve French struct smb_direct_sendmsg *msg; 116838c8a9a5SSteve French int data_length; 116938c8a9a5SSteve French struct scatterlist sg[SMB_DIRECT_MAX_SEND_SGES - 1]; 117038c8a9a5SSteve French 117138c8a9a5SSteve French ret = wait_for_send_credits(t, send_ctx); 117238c8a9a5SSteve French if (ret) 117338c8a9a5SSteve French return ret; 117438c8a9a5SSteve French 117538c8a9a5SSteve French data_length = 0; 117638c8a9a5SSteve French for (i = 0; i < niov; i++) 117738c8a9a5SSteve French data_length += iov[i].iov_len; 117838c8a9a5SSteve French 117938c8a9a5SSteve French ret = smb_direct_create_header(t, data_length, remaining_data_length, 118038c8a9a5SSteve French &msg); 118138c8a9a5SSteve French if (ret) { 118238c8a9a5SSteve French atomic_inc(&t->send_credits); 118338c8a9a5SSteve French return ret; 118438c8a9a5SSteve French } 118538c8a9a5SSteve French 118638c8a9a5SSteve French for (i = 0; i < niov; i++) { 118738c8a9a5SSteve French struct ib_sge *sge; 118838c8a9a5SSteve French int sg_cnt; 118938c8a9a5SSteve French 119038c8a9a5SSteve French sg_init_table(sg, SMB_DIRECT_MAX_SEND_SGES - 1); 119138c8a9a5SSteve French sg_cnt = get_mapped_sg_list(t->cm_id->device, 119238c8a9a5SSteve French iov[i].iov_base, iov[i].iov_len, 119338c8a9a5SSteve French sg, SMB_DIRECT_MAX_SEND_SGES - 1, 119438c8a9a5SSteve French DMA_TO_DEVICE); 119538c8a9a5SSteve French if (sg_cnt <= 0) { 119638c8a9a5SSteve French pr_err("failed to map buffer\n"); 119738c8a9a5SSteve French ret = -ENOMEM; 119838c8a9a5SSteve French goto err; 119938c8a9a5SSteve French } else if (sg_cnt + msg->num_sge > SMB_DIRECT_MAX_SEND_SGES) { 120038c8a9a5SSteve French pr_err("buffer not fitted into sges\n"); 120138c8a9a5SSteve French ret = -E2BIG; 120238c8a9a5SSteve French ib_dma_unmap_sg(t->cm_id->device, sg, sg_cnt, 120338c8a9a5SSteve French DMA_TO_DEVICE); 120438c8a9a5SSteve French goto err; 120538c8a9a5SSteve French } 120638c8a9a5SSteve French 120738c8a9a5SSteve French for (j = 0; j < sg_cnt; j++) { 120838c8a9a5SSteve French sge = &msg->sge[msg->num_sge]; 120938c8a9a5SSteve French sge->addr = sg_dma_address(&sg[j]); 121038c8a9a5SSteve French sge->length = sg_dma_len(&sg[j]); 121138c8a9a5SSteve French sge->lkey = t->pd->local_dma_lkey; 121238c8a9a5SSteve French msg->num_sge++; 121338c8a9a5SSteve French } 121438c8a9a5SSteve French } 121538c8a9a5SSteve French 121638c8a9a5SSteve French ret = post_sendmsg(t, send_ctx, msg); 121738c8a9a5SSteve French if (ret) 121838c8a9a5SSteve French goto err; 121938c8a9a5SSteve French return 0; 122038c8a9a5SSteve French err: 122138c8a9a5SSteve French smb_direct_free_sendmsg(t, msg); 122238c8a9a5SSteve French atomic_inc(&t->send_credits); 122338c8a9a5SSteve French return ret; 122438c8a9a5SSteve French } 122538c8a9a5SSteve French 122638c8a9a5SSteve French static int smb_direct_writev(struct ksmbd_transport *t, 122738c8a9a5SSteve French struct kvec *iov, int niovs, int buflen, 122838c8a9a5SSteve French bool need_invalidate, unsigned int remote_key) 122938c8a9a5SSteve French { 123038c8a9a5SSteve French struct smb_direct_transport *st = smb_trans_direct_transfort(t); 123138c8a9a5SSteve French int remaining_data_length; 123238c8a9a5SSteve French int start, i, j; 123338c8a9a5SSteve French int max_iov_size = st->max_send_size - 123438c8a9a5SSteve French sizeof(struct smb_direct_data_transfer); 123538c8a9a5SSteve French int ret; 123638c8a9a5SSteve French struct kvec vec; 123738c8a9a5SSteve French struct smb_direct_send_ctx send_ctx; 123838c8a9a5SSteve French 123938c8a9a5SSteve French if (st->status != SMB_DIRECT_CS_CONNECTED) 124038c8a9a5SSteve French return -ENOTCONN; 124138c8a9a5SSteve French 124238c8a9a5SSteve French //FIXME: skip RFC1002 header.. 124338c8a9a5SSteve French buflen -= 4; 124438c8a9a5SSteve French 124538c8a9a5SSteve French remaining_data_length = buflen; 124638c8a9a5SSteve French ksmbd_debug(RDMA, "Sending smb (RDMA): smb_len=%u\n", buflen); 124738c8a9a5SSteve French 124838c8a9a5SSteve French smb_direct_send_ctx_init(st, &send_ctx, need_invalidate, remote_key); 1249e2b76ab8SNamjae Jeon start = i = 1; 125038c8a9a5SSteve French buflen = 0; 125138c8a9a5SSteve French while (true) { 125238c8a9a5SSteve French buflen += iov[i].iov_len; 125338c8a9a5SSteve French if (buflen > max_iov_size) { 125438c8a9a5SSteve French if (i > start) { 125538c8a9a5SSteve French remaining_data_length -= 125638c8a9a5SSteve French (buflen - iov[i].iov_len); 125738c8a9a5SSteve French ret = smb_direct_post_send_data(st, &send_ctx, 125838c8a9a5SSteve French &iov[start], i - start, 125938c8a9a5SSteve French remaining_data_length); 126038c8a9a5SSteve French if (ret) 126138c8a9a5SSteve French goto done; 126238c8a9a5SSteve French } else { 126338c8a9a5SSteve French /* iov[start] is too big, break it */ 126438c8a9a5SSteve French int nvec = (buflen + max_iov_size - 1) / 126538c8a9a5SSteve French max_iov_size; 126638c8a9a5SSteve French 126738c8a9a5SSteve French for (j = 0; j < nvec; j++) { 126838c8a9a5SSteve French vec.iov_base = 126938c8a9a5SSteve French (char *)iov[start].iov_base + 127038c8a9a5SSteve French j * max_iov_size; 127138c8a9a5SSteve French vec.iov_len = 127238c8a9a5SSteve French min_t(int, max_iov_size, 127338c8a9a5SSteve French buflen - max_iov_size * j); 127438c8a9a5SSteve French remaining_data_length -= vec.iov_len; 127538c8a9a5SSteve French ret = smb_direct_post_send_data(st, &send_ctx, &vec, 1, 127638c8a9a5SSteve French remaining_data_length); 127738c8a9a5SSteve French if (ret) 127838c8a9a5SSteve French goto done; 127938c8a9a5SSteve French } 128038c8a9a5SSteve French i++; 128138c8a9a5SSteve French if (i == niovs) 128238c8a9a5SSteve French break; 128338c8a9a5SSteve French } 128438c8a9a5SSteve French start = i; 128538c8a9a5SSteve French buflen = 0; 128638c8a9a5SSteve French } else { 128738c8a9a5SSteve French i++; 128838c8a9a5SSteve French if (i == niovs) { 128938c8a9a5SSteve French /* send out all remaining vecs */ 129038c8a9a5SSteve French remaining_data_length -= buflen; 129138c8a9a5SSteve French ret = smb_direct_post_send_data(st, &send_ctx, 129238c8a9a5SSteve French &iov[start], i - start, 129338c8a9a5SSteve French remaining_data_length); 129438c8a9a5SSteve French if (ret) 129538c8a9a5SSteve French goto done; 129638c8a9a5SSteve French break; 129738c8a9a5SSteve French } 129838c8a9a5SSteve French } 129938c8a9a5SSteve French } 130038c8a9a5SSteve French 130138c8a9a5SSteve French done: 130238c8a9a5SSteve French ret = smb_direct_flush_send_list(st, &send_ctx, true); 130338c8a9a5SSteve French 130438c8a9a5SSteve French /* 130538c8a9a5SSteve French * As an optimization, we don't wait for individual I/O to finish 130638c8a9a5SSteve French * before sending the next one. 130738c8a9a5SSteve French * Send them all and wait for pending send count to get to 0 130838c8a9a5SSteve French * that means all the I/Os have been out and we are good to return 130938c8a9a5SSteve French */ 131038c8a9a5SSteve French 131138c8a9a5SSteve French wait_event(st->wait_send_pending, 131238c8a9a5SSteve French atomic_read(&st->send_pending) == 0); 131338c8a9a5SSteve French return ret; 131438c8a9a5SSteve French } 131538c8a9a5SSteve French 131638c8a9a5SSteve French static void smb_direct_free_rdma_rw_msg(struct smb_direct_transport *t, 131738c8a9a5SSteve French struct smb_direct_rdma_rw_msg *msg, 131838c8a9a5SSteve French enum dma_data_direction dir) 131938c8a9a5SSteve French { 132038c8a9a5SSteve French rdma_rw_ctx_destroy(&msg->rw_ctx, t->qp, t->qp->port, 132138c8a9a5SSteve French msg->sgt.sgl, msg->sgt.nents, dir); 132238c8a9a5SSteve French sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE); 132338c8a9a5SSteve French kfree(msg); 132438c8a9a5SSteve French } 132538c8a9a5SSteve French 132638c8a9a5SSteve French static void read_write_done(struct ib_cq *cq, struct ib_wc *wc, 132738c8a9a5SSteve French enum dma_data_direction dir) 132838c8a9a5SSteve French { 132938c8a9a5SSteve French struct smb_direct_rdma_rw_msg *msg = container_of(wc->wr_cqe, 133038c8a9a5SSteve French struct smb_direct_rdma_rw_msg, cqe); 133138c8a9a5SSteve French struct smb_direct_transport *t = msg->t; 133238c8a9a5SSteve French 133338c8a9a5SSteve French if (wc->status != IB_WC_SUCCESS) { 133438c8a9a5SSteve French msg->status = -EIO; 133538c8a9a5SSteve French pr_err("read/write error. opcode = %d, status = %s(%d)\n", 133638c8a9a5SSteve French wc->opcode, ib_wc_status_msg(wc->status), wc->status); 133738c8a9a5SSteve French if (wc->status != IB_WC_WR_FLUSH_ERR) 133838c8a9a5SSteve French smb_direct_disconnect_rdma_connection(t); 133938c8a9a5SSteve French } 134038c8a9a5SSteve French 134138c8a9a5SSteve French complete(msg->completion); 134238c8a9a5SSteve French } 134338c8a9a5SSteve French 134438c8a9a5SSteve French static void read_done(struct ib_cq *cq, struct ib_wc *wc) 134538c8a9a5SSteve French { 134638c8a9a5SSteve French read_write_done(cq, wc, DMA_FROM_DEVICE); 134738c8a9a5SSteve French } 134838c8a9a5SSteve French 134938c8a9a5SSteve French static void write_done(struct ib_cq *cq, struct ib_wc *wc) 135038c8a9a5SSteve French { 135138c8a9a5SSteve French read_write_done(cq, wc, DMA_TO_DEVICE); 135238c8a9a5SSteve French } 135338c8a9a5SSteve French 135438c8a9a5SSteve French static int smb_direct_rdma_xmit(struct smb_direct_transport *t, 135538c8a9a5SSteve French void *buf, int buf_len, 135638c8a9a5SSteve French struct smb2_buffer_desc_v1 *desc, 135738c8a9a5SSteve French unsigned int desc_len, 135838c8a9a5SSteve French bool is_read) 135938c8a9a5SSteve French { 136038c8a9a5SSteve French struct smb_direct_rdma_rw_msg *msg, *next_msg; 136138c8a9a5SSteve French int i, ret; 136238c8a9a5SSteve French DECLARE_COMPLETION_ONSTACK(completion); 136338c8a9a5SSteve French struct ib_send_wr *first_wr; 136438c8a9a5SSteve French LIST_HEAD(msg_list); 136538c8a9a5SSteve French char *desc_buf; 136638c8a9a5SSteve French int credits_needed; 1367*e628bf93SNamjae Jeon unsigned int desc_buf_len, desc_num = 0; 136838c8a9a5SSteve French 136938c8a9a5SSteve French if (t->status != SMB_DIRECT_CS_CONNECTED) 137038c8a9a5SSteve French return -ENOTCONN; 137138c8a9a5SSteve French 1372*e628bf93SNamjae Jeon if (buf_len > t->max_rdma_rw_size) 1373*e628bf93SNamjae Jeon return -EINVAL; 1374*e628bf93SNamjae Jeon 137538c8a9a5SSteve French /* calculate needed credits */ 137638c8a9a5SSteve French credits_needed = 0; 137738c8a9a5SSteve French desc_buf = buf; 137838c8a9a5SSteve French for (i = 0; i < desc_len / sizeof(*desc); i++) { 1379*e628bf93SNamjae Jeon if (!buf_len) 1380*e628bf93SNamjae Jeon break; 1381*e628bf93SNamjae Jeon 138238c8a9a5SSteve French desc_buf_len = le32_to_cpu(desc[i].length); 1383*e628bf93SNamjae Jeon if (!desc_buf_len) 1384*e628bf93SNamjae Jeon return -EINVAL; 1385*e628bf93SNamjae Jeon 1386*e628bf93SNamjae Jeon if (desc_buf_len > buf_len) { 1387*e628bf93SNamjae Jeon desc_buf_len = buf_len; 1388*e628bf93SNamjae Jeon desc[i].length = cpu_to_le32(desc_buf_len); 1389*e628bf93SNamjae Jeon buf_len = 0; 1390*e628bf93SNamjae Jeon } 139138c8a9a5SSteve French 139238c8a9a5SSteve French credits_needed += calc_rw_credits(t, desc_buf, desc_buf_len); 139338c8a9a5SSteve French desc_buf += desc_buf_len; 1394*e628bf93SNamjae Jeon buf_len -= desc_buf_len; 1395*e628bf93SNamjae Jeon desc_num++; 139638c8a9a5SSteve French } 139738c8a9a5SSteve French 139838c8a9a5SSteve French ksmbd_debug(RDMA, "RDMA %s, len %#x, needed credits %#x\n", 139938c8a9a5SSteve French is_read ? "read" : "write", buf_len, credits_needed); 140038c8a9a5SSteve French 140138c8a9a5SSteve French ret = wait_for_rw_credits(t, credits_needed); 140238c8a9a5SSteve French if (ret < 0) 140338c8a9a5SSteve French return ret; 140438c8a9a5SSteve French 140538c8a9a5SSteve French /* build rdma_rw_ctx for each descriptor */ 140638c8a9a5SSteve French desc_buf = buf; 1407*e628bf93SNamjae Jeon for (i = 0; i < desc_num; i++) { 140838c8a9a5SSteve French msg = kzalloc(offsetof(struct smb_direct_rdma_rw_msg, sg_list) + 140938c8a9a5SSteve French sizeof(struct scatterlist) * SG_CHUNK_SIZE, GFP_KERNEL); 141038c8a9a5SSteve French if (!msg) { 141138c8a9a5SSteve French ret = -ENOMEM; 141238c8a9a5SSteve French goto out; 141338c8a9a5SSteve French } 141438c8a9a5SSteve French 141538c8a9a5SSteve French desc_buf_len = le32_to_cpu(desc[i].length); 141638c8a9a5SSteve French 141738c8a9a5SSteve French msg->t = t; 141838c8a9a5SSteve French msg->cqe.done = is_read ? read_done : write_done; 141938c8a9a5SSteve French msg->completion = &completion; 142038c8a9a5SSteve French 142138c8a9a5SSteve French msg->sgt.sgl = &msg->sg_list[0]; 142238c8a9a5SSteve French ret = sg_alloc_table_chained(&msg->sgt, 142338c8a9a5SSteve French get_buf_page_count(desc_buf, desc_buf_len), 142438c8a9a5SSteve French msg->sg_list, SG_CHUNK_SIZE); 142538c8a9a5SSteve French if (ret) { 142638c8a9a5SSteve French kfree(msg); 142738c8a9a5SSteve French ret = -ENOMEM; 142838c8a9a5SSteve French goto out; 142938c8a9a5SSteve French } 143038c8a9a5SSteve French 143138c8a9a5SSteve French ret = get_sg_list(desc_buf, desc_buf_len, 143238c8a9a5SSteve French msg->sgt.sgl, msg->sgt.orig_nents); 143338c8a9a5SSteve French if (ret < 0) { 143438c8a9a5SSteve French sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE); 143538c8a9a5SSteve French kfree(msg); 143638c8a9a5SSteve French goto out; 143738c8a9a5SSteve French } 143838c8a9a5SSteve French 143938c8a9a5SSteve French ret = rdma_rw_ctx_init(&msg->rw_ctx, t->qp, t->qp->port, 144038c8a9a5SSteve French msg->sgt.sgl, 144138c8a9a5SSteve French get_buf_page_count(desc_buf, desc_buf_len), 144238c8a9a5SSteve French 0, 144338c8a9a5SSteve French le64_to_cpu(desc[i].offset), 144438c8a9a5SSteve French le32_to_cpu(desc[i].token), 144538c8a9a5SSteve French is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE); 144638c8a9a5SSteve French if (ret < 0) { 144738c8a9a5SSteve French pr_err("failed to init rdma_rw_ctx: %d\n", ret); 144838c8a9a5SSteve French sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE); 144938c8a9a5SSteve French kfree(msg); 145038c8a9a5SSteve French goto out; 145138c8a9a5SSteve French } 145238c8a9a5SSteve French 145338c8a9a5SSteve French list_add_tail(&msg->list, &msg_list); 145438c8a9a5SSteve French desc_buf += desc_buf_len; 145538c8a9a5SSteve French } 145638c8a9a5SSteve French 145738c8a9a5SSteve French /* concatenate work requests of rdma_rw_ctxs */ 145838c8a9a5SSteve French first_wr = NULL; 145938c8a9a5SSteve French list_for_each_entry_reverse(msg, &msg_list, list) { 146038c8a9a5SSteve French first_wr = rdma_rw_ctx_wrs(&msg->rw_ctx, t->qp, t->qp->port, 146138c8a9a5SSteve French &msg->cqe, first_wr); 146238c8a9a5SSteve French } 146338c8a9a5SSteve French 146438c8a9a5SSteve French ret = ib_post_send(t->qp, first_wr, NULL); 146538c8a9a5SSteve French if (ret) { 146638c8a9a5SSteve French pr_err("failed to post send wr for RDMA R/W: %d\n", ret); 146738c8a9a5SSteve French goto out; 146838c8a9a5SSteve French } 146938c8a9a5SSteve French 147038c8a9a5SSteve French msg = list_last_entry(&msg_list, struct smb_direct_rdma_rw_msg, list); 147138c8a9a5SSteve French wait_for_completion(&completion); 147238c8a9a5SSteve French ret = msg->status; 147338c8a9a5SSteve French out: 147438c8a9a5SSteve French list_for_each_entry_safe(msg, next_msg, &msg_list, list) { 147538c8a9a5SSteve French list_del(&msg->list); 147638c8a9a5SSteve French smb_direct_free_rdma_rw_msg(t, msg, 147738c8a9a5SSteve French is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE); 147838c8a9a5SSteve French } 147938c8a9a5SSteve French atomic_add(credits_needed, &t->rw_credits); 148038c8a9a5SSteve French wake_up(&t->wait_rw_credits); 148138c8a9a5SSteve French return ret; 148238c8a9a5SSteve French } 148338c8a9a5SSteve French 148438c8a9a5SSteve French static int smb_direct_rdma_write(struct ksmbd_transport *t, 148538c8a9a5SSteve French void *buf, unsigned int buflen, 148638c8a9a5SSteve French struct smb2_buffer_desc_v1 *desc, 148738c8a9a5SSteve French unsigned int desc_len) 148838c8a9a5SSteve French { 148938c8a9a5SSteve French return smb_direct_rdma_xmit(smb_trans_direct_transfort(t), buf, buflen, 149038c8a9a5SSteve French desc, desc_len, false); 149138c8a9a5SSteve French } 149238c8a9a5SSteve French 149338c8a9a5SSteve French static int smb_direct_rdma_read(struct ksmbd_transport *t, 149438c8a9a5SSteve French void *buf, unsigned int buflen, 149538c8a9a5SSteve French struct smb2_buffer_desc_v1 *desc, 149638c8a9a5SSteve French unsigned int desc_len) 149738c8a9a5SSteve French { 149838c8a9a5SSteve French return smb_direct_rdma_xmit(smb_trans_direct_transfort(t), buf, buflen, 149938c8a9a5SSteve French desc, desc_len, true); 150038c8a9a5SSteve French } 150138c8a9a5SSteve French 150238c8a9a5SSteve French static void smb_direct_disconnect(struct ksmbd_transport *t) 150338c8a9a5SSteve French { 150438c8a9a5SSteve French struct smb_direct_transport *st = smb_trans_direct_transfort(t); 150538c8a9a5SSteve French 150638c8a9a5SSteve French ksmbd_debug(RDMA, "Disconnecting cm_id=%p\n", st->cm_id); 150738c8a9a5SSteve French 150838c8a9a5SSteve French smb_direct_disconnect_rdma_work(&st->disconnect_work); 150938c8a9a5SSteve French wait_event_interruptible(st->wait_status, 151038c8a9a5SSteve French st->status == SMB_DIRECT_CS_DISCONNECTED); 151138c8a9a5SSteve French free_transport(st); 151238c8a9a5SSteve French } 151338c8a9a5SSteve French 151438c8a9a5SSteve French static void smb_direct_shutdown(struct ksmbd_transport *t) 151538c8a9a5SSteve French { 151638c8a9a5SSteve French struct smb_direct_transport *st = smb_trans_direct_transfort(t); 151738c8a9a5SSteve French 151838c8a9a5SSteve French ksmbd_debug(RDMA, "smb-direct shutdown cm_id=%p\n", st->cm_id); 151938c8a9a5SSteve French 152038c8a9a5SSteve French smb_direct_disconnect_rdma_work(&st->disconnect_work); 152138c8a9a5SSteve French } 152238c8a9a5SSteve French 152338c8a9a5SSteve French static int smb_direct_cm_handler(struct rdma_cm_id *cm_id, 152438c8a9a5SSteve French struct rdma_cm_event *event) 152538c8a9a5SSteve French { 152638c8a9a5SSteve French struct smb_direct_transport *t = cm_id->context; 152738c8a9a5SSteve French 152838c8a9a5SSteve French ksmbd_debug(RDMA, "RDMA CM event. cm_id=%p event=%s (%d)\n", 152938c8a9a5SSteve French cm_id, rdma_event_msg(event->event), event->event); 153038c8a9a5SSteve French 153138c8a9a5SSteve French switch (event->event) { 153238c8a9a5SSteve French case RDMA_CM_EVENT_ESTABLISHED: { 153338c8a9a5SSteve French t->status = SMB_DIRECT_CS_CONNECTED; 153438c8a9a5SSteve French wake_up_interruptible(&t->wait_status); 153538c8a9a5SSteve French break; 153638c8a9a5SSteve French } 153738c8a9a5SSteve French case RDMA_CM_EVENT_DEVICE_REMOVAL: 153838c8a9a5SSteve French case RDMA_CM_EVENT_DISCONNECTED: { 153938c8a9a5SSteve French ib_drain_qp(t->qp); 154038c8a9a5SSteve French 154138c8a9a5SSteve French t->status = SMB_DIRECT_CS_DISCONNECTED; 154238c8a9a5SSteve French wake_up_interruptible(&t->wait_status); 154338c8a9a5SSteve French wake_up_interruptible(&t->wait_reassembly_queue); 154438c8a9a5SSteve French wake_up(&t->wait_send_credits); 154538c8a9a5SSteve French break; 154638c8a9a5SSteve French } 154738c8a9a5SSteve French case RDMA_CM_EVENT_CONNECT_ERROR: { 154838c8a9a5SSteve French t->status = SMB_DIRECT_CS_DISCONNECTED; 154938c8a9a5SSteve French wake_up_interruptible(&t->wait_status); 155038c8a9a5SSteve French break; 155138c8a9a5SSteve French } 155238c8a9a5SSteve French default: 155338c8a9a5SSteve French pr_err("Unexpected RDMA CM event. cm_id=%p, event=%s (%d)\n", 155438c8a9a5SSteve French cm_id, rdma_event_msg(event->event), 155538c8a9a5SSteve French event->event); 155638c8a9a5SSteve French break; 155738c8a9a5SSteve French } 155838c8a9a5SSteve French return 0; 155938c8a9a5SSteve French } 156038c8a9a5SSteve French 156138c8a9a5SSteve French static void smb_direct_qpair_handler(struct ib_event *event, void *context) 156238c8a9a5SSteve French { 156338c8a9a5SSteve French struct smb_direct_transport *t = context; 156438c8a9a5SSteve French 156538c8a9a5SSteve French ksmbd_debug(RDMA, "Received QP event. cm_id=%p, event=%s (%d)\n", 156638c8a9a5SSteve French t->cm_id, ib_event_msg(event->event), event->event); 156738c8a9a5SSteve French 156838c8a9a5SSteve French switch (event->event) { 156938c8a9a5SSteve French case IB_EVENT_CQ_ERR: 157038c8a9a5SSteve French case IB_EVENT_QP_FATAL: 157138c8a9a5SSteve French smb_direct_disconnect_rdma_connection(t); 157238c8a9a5SSteve French break; 157338c8a9a5SSteve French default: 157438c8a9a5SSteve French break; 157538c8a9a5SSteve French } 157638c8a9a5SSteve French } 157738c8a9a5SSteve French 157838c8a9a5SSteve French static int smb_direct_send_negotiate_response(struct smb_direct_transport *t, 157938c8a9a5SSteve French int failed) 158038c8a9a5SSteve French { 158138c8a9a5SSteve French struct smb_direct_sendmsg *sendmsg; 158238c8a9a5SSteve French struct smb_direct_negotiate_resp *resp; 158338c8a9a5SSteve French int ret; 158438c8a9a5SSteve French 158538c8a9a5SSteve French sendmsg = smb_direct_alloc_sendmsg(t); 158638c8a9a5SSteve French if (IS_ERR(sendmsg)) 158738c8a9a5SSteve French return -ENOMEM; 158838c8a9a5SSteve French 158938c8a9a5SSteve French resp = (struct smb_direct_negotiate_resp *)sendmsg->packet; 159038c8a9a5SSteve French if (failed) { 159138c8a9a5SSteve French memset(resp, 0, sizeof(*resp)); 159238c8a9a5SSteve French resp->min_version = cpu_to_le16(0x0100); 159338c8a9a5SSteve French resp->max_version = cpu_to_le16(0x0100); 159438c8a9a5SSteve French resp->status = STATUS_NOT_SUPPORTED; 159538c8a9a5SSteve French } else { 159638c8a9a5SSteve French resp->status = STATUS_SUCCESS; 159738c8a9a5SSteve French resp->min_version = SMB_DIRECT_VERSION_LE; 159838c8a9a5SSteve French resp->max_version = SMB_DIRECT_VERSION_LE; 159938c8a9a5SSteve French resp->negotiated_version = SMB_DIRECT_VERSION_LE; 160038c8a9a5SSteve French resp->reserved = 0; 160138c8a9a5SSteve French resp->credits_requested = 160238c8a9a5SSteve French cpu_to_le16(t->send_credit_target); 160338c8a9a5SSteve French resp->credits_granted = cpu_to_le16(manage_credits_prior_sending(t)); 160438c8a9a5SSteve French resp->max_readwrite_size = cpu_to_le32(t->max_rdma_rw_size); 160538c8a9a5SSteve French resp->preferred_send_size = cpu_to_le32(t->max_send_size); 160638c8a9a5SSteve French resp->max_receive_size = cpu_to_le32(t->max_recv_size); 160738c8a9a5SSteve French resp->max_fragmented_size = 160838c8a9a5SSteve French cpu_to_le32(t->max_fragmented_recv_size); 160938c8a9a5SSteve French } 161038c8a9a5SSteve French 161138c8a9a5SSteve French sendmsg->sge[0].addr = ib_dma_map_single(t->cm_id->device, 161238c8a9a5SSteve French (void *)resp, sizeof(*resp), 161338c8a9a5SSteve French DMA_TO_DEVICE); 161438c8a9a5SSteve French ret = ib_dma_mapping_error(t->cm_id->device, sendmsg->sge[0].addr); 161538c8a9a5SSteve French if (ret) { 161638c8a9a5SSteve French smb_direct_free_sendmsg(t, sendmsg); 161738c8a9a5SSteve French return ret; 161838c8a9a5SSteve French } 161938c8a9a5SSteve French 162038c8a9a5SSteve French sendmsg->num_sge = 1; 162138c8a9a5SSteve French sendmsg->sge[0].length = sizeof(*resp); 162238c8a9a5SSteve French sendmsg->sge[0].lkey = t->pd->local_dma_lkey; 162338c8a9a5SSteve French 162438c8a9a5SSteve French ret = post_sendmsg(t, NULL, sendmsg); 162538c8a9a5SSteve French if (ret) { 162638c8a9a5SSteve French smb_direct_free_sendmsg(t, sendmsg); 162738c8a9a5SSteve French return ret; 162838c8a9a5SSteve French } 162938c8a9a5SSteve French 163038c8a9a5SSteve French wait_event(t->wait_send_pending, 163138c8a9a5SSteve French atomic_read(&t->send_pending) == 0); 163238c8a9a5SSteve French return 0; 163338c8a9a5SSteve French } 163438c8a9a5SSteve French 163538c8a9a5SSteve French static int smb_direct_accept_client(struct smb_direct_transport *t) 163638c8a9a5SSteve French { 163738c8a9a5SSteve French struct rdma_conn_param conn_param; 163838c8a9a5SSteve French struct ib_port_immutable port_immutable; 163938c8a9a5SSteve French u32 ird_ord_hdr[2]; 164038c8a9a5SSteve French int ret; 164138c8a9a5SSteve French 164238c8a9a5SSteve French memset(&conn_param, 0, sizeof(conn_param)); 164338c8a9a5SSteve French conn_param.initiator_depth = min_t(u8, t->cm_id->device->attrs.max_qp_rd_atom, 164438c8a9a5SSteve French SMB_DIRECT_CM_INITIATOR_DEPTH); 164538c8a9a5SSteve French conn_param.responder_resources = 0; 164638c8a9a5SSteve French 164738c8a9a5SSteve French t->cm_id->device->ops.get_port_immutable(t->cm_id->device, 164838c8a9a5SSteve French t->cm_id->port_num, 164938c8a9a5SSteve French &port_immutable); 165038c8a9a5SSteve French if (port_immutable.core_cap_flags & RDMA_CORE_PORT_IWARP) { 165138c8a9a5SSteve French ird_ord_hdr[0] = conn_param.responder_resources; 165238c8a9a5SSteve French ird_ord_hdr[1] = 1; 165338c8a9a5SSteve French conn_param.private_data = ird_ord_hdr; 165438c8a9a5SSteve French conn_param.private_data_len = sizeof(ird_ord_hdr); 165538c8a9a5SSteve French } else { 165638c8a9a5SSteve French conn_param.private_data = NULL; 165738c8a9a5SSteve French conn_param.private_data_len = 0; 165838c8a9a5SSteve French } 165938c8a9a5SSteve French conn_param.retry_count = SMB_DIRECT_CM_RETRY; 166038c8a9a5SSteve French conn_param.rnr_retry_count = SMB_DIRECT_CM_RNR_RETRY; 166138c8a9a5SSteve French conn_param.flow_control = 0; 166238c8a9a5SSteve French 166338c8a9a5SSteve French ret = rdma_accept(t->cm_id, &conn_param); 166438c8a9a5SSteve French if (ret) { 166538c8a9a5SSteve French pr_err("error at rdma_accept: %d\n", ret); 166638c8a9a5SSteve French return ret; 166738c8a9a5SSteve French } 166838c8a9a5SSteve French return 0; 166938c8a9a5SSteve French } 167038c8a9a5SSteve French 167138c8a9a5SSteve French static int smb_direct_prepare_negotiation(struct smb_direct_transport *t) 167238c8a9a5SSteve French { 167338c8a9a5SSteve French int ret; 167438c8a9a5SSteve French struct smb_direct_recvmsg *recvmsg; 167538c8a9a5SSteve French 167638c8a9a5SSteve French recvmsg = get_free_recvmsg(t); 167738c8a9a5SSteve French if (!recvmsg) 167838c8a9a5SSteve French return -ENOMEM; 167938c8a9a5SSteve French recvmsg->type = SMB_DIRECT_MSG_NEGOTIATE_REQ; 168038c8a9a5SSteve French 168138c8a9a5SSteve French ret = smb_direct_post_recv(t, recvmsg); 168238c8a9a5SSteve French if (ret) { 168338c8a9a5SSteve French pr_err("Can't post recv: %d\n", ret); 168438c8a9a5SSteve French goto out_err; 168538c8a9a5SSteve French } 168638c8a9a5SSteve French 168738c8a9a5SSteve French t->negotiation_requested = false; 168838c8a9a5SSteve French ret = smb_direct_accept_client(t); 168938c8a9a5SSteve French if (ret) { 169038c8a9a5SSteve French pr_err("Can't accept client\n"); 169138c8a9a5SSteve French goto out_err; 169238c8a9a5SSteve French } 169338c8a9a5SSteve French 169438c8a9a5SSteve French smb_direct_post_recv_credits(&t->post_recv_credits_work.work); 169538c8a9a5SSteve French return 0; 169638c8a9a5SSteve French out_err: 169738c8a9a5SSteve French put_recvmsg(t, recvmsg); 169838c8a9a5SSteve French return ret; 169938c8a9a5SSteve French } 170038c8a9a5SSteve French 170138c8a9a5SSteve French static unsigned int smb_direct_get_max_fr_pages(struct smb_direct_transport *t) 170238c8a9a5SSteve French { 170338c8a9a5SSteve French return min_t(unsigned int, 170438c8a9a5SSteve French t->cm_id->device->attrs.max_fast_reg_page_list_len, 170538c8a9a5SSteve French 256); 170638c8a9a5SSteve French } 170738c8a9a5SSteve French 170838c8a9a5SSteve French static int smb_direct_init_params(struct smb_direct_transport *t, 170938c8a9a5SSteve French struct ib_qp_cap *cap) 171038c8a9a5SSteve French { 171138c8a9a5SSteve French struct ib_device *device = t->cm_id->device; 171238c8a9a5SSteve French int max_send_sges, max_rw_wrs, max_send_wrs; 171338c8a9a5SSteve French unsigned int max_sge_per_wr, wrs_per_credit; 171438c8a9a5SSteve French 171538c8a9a5SSteve French /* need 3 more sge. because a SMB_DIRECT header, SMB2 header, 171638c8a9a5SSteve French * SMB2 response could be mapped. 171738c8a9a5SSteve French */ 171838c8a9a5SSteve French t->max_send_size = smb_direct_max_send_size; 171938c8a9a5SSteve French max_send_sges = DIV_ROUND_UP(t->max_send_size, PAGE_SIZE) + 3; 172038c8a9a5SSteve French if (max_send_sges > SMB_DIRECT_MAX_SEND_SGES) { 172138c8a9a5SSteve French pr_err("max_send_size %d is too large\n", t->max_send_size); 172238c8a9a5SSteve French return -EINVAL; 172338c8a9a5SSteve French } 172438c8a9a5SSteve French 172538c8a9a5SSteve French /* Calculate the number of work requests for RDMA R/W. 172638c8a9a5SSteve French * The maximum number of pages which can be registered 172738c8a9a5SSteve French * with one Memory region can be transferred with one 172838c8a9a5SSteve French * R/W credit. And at least 4 work requests for each credit 172938c8a9a5SSteve French * are needed for MR registration, RDMA R/W, local & remote 173038c8a9a5SSteve French * MR invalidation. 173138c8a9a5SSteve French */ 173238c8a9a5SSteve French t->max_rdma_rw_size = smb_direct_max_read_write_size; 173338c8a9a5SSteve French t->pages_per_rw_credit = smb_direct_get_max_fr_pages(t); 173438c8a9a5SSteve French t->max_rw_credits = DIV_ROUND_UP(t->max_rdma_rw_size, 173538c8a9a5SSteve French (t->pages_per_rw_credit - 1) * 173638c8a9a5SSteve French PAGE_SIZE); 173738c8a9a5SSteve French 173838c8a9a5SSteve French max_sge_per_wr = min_t(unsigned int, device->attrs.max_send_sge, 173938c8a9a5SSteve French device->attrs.max_sge_rd); 174038c8a9a5SSteve French max_sge_per_wr = max_t(unsigned int, max_sge_per_wr, 174138c8a9a5SSteve French max_send_sges); 174238c8a9a5SSteve French wrs_per_credit = max_t(unsigned int, 4, 174338c8a9a5SSteve French DIV_ROUND_UP(t->pages_per_rw_credit, 174438c8a9a5SSteve French max_sge_per_wr) + 1); 174538c8a9a5SSteve French max_rw_wrs = t->max_rw_credits * wrs_per_credit; 174638c8a9a5SSteve French 174738c8a9a5SSteve French max_send_wrs = smb_direct_send_credit_target + max_rw_wrs; 174838c8a9a5SSteve French if (max_send_wrs > device->attrs.max_cqe || 174938c8a9a5SSteve French max_send_wrs > device->attrs.max_qp_wr) { 175038c8a9a5SSteve French pr_err("consider lowering send_credit_target = %d\n", 175138c8a9a5SSteve French smb_direct_send_credit_target); 175238c8a9a5SSteve French pr_err("Possible CQE overrun, device reporting max_cqe %d max_qp_wr %d\n", 175338c8a9a5SSteve French device->attrs.max_cqe, device->attrs.max_qp_wr); 175438c8a9a5SSteve French return -EINVAL; 175538c8a9a5SSteve French } 175638c8a9a5SSteve French 175738c8a9a5SSteve French if (smb_direct_receive_credit_max > device->attrs.max_cqe || 175838c8a9a5SSteve French smb_direct_receive_credit_max > device->attrs.max_qp_wr) { 175938c8a9a5SSteve French pr_err("consider lowering receive_credit_max = %d\n", 176038c8a9a5SSteve French smb_direct_receive_credit_max); 176138c8a9a5SSteve French pr_err("Possible CQE overrun, device reporting max_cpe %d max_qp_wr %d\n", 176238c8a9a5SSteve French device->attrs.max_cqe, device->attrs.max_qp_wr); 176338c8a9a5SSteve French return -EINVAL; 176438c8a9a5SSteve French } 176538c8a9a5SSteve French 176638c8a9a5SSteve French if (device->attrs.max_recv_sge < SMB_DIRECT_MAX_RECV_SGES) { 176738c8a9a5SSteve French pr_err("warning: device max_recv_sge = %d too small\n", 176838c8a9a5SSteve French device->attrs.max_recv_sge); 176938c8a9a5SSteve French return -EINVAL; 177038c8a9a5SSteve French } 177138c8a9a5SSteve French 177238c8a9a5SSteve French t->recv_credits = 0; 177338c8a9a5SSteve French t->count_avail_recvmsg = 0; 177438c8a9a5SSteve French 177538c8a9a5SSteve French t->recv_credit_max = smb_direct_receive_credit_max; 177638c8a9a5SSteve French t->recv_credit_target = 10; 177738c8a9a5SSteve French t->new_recv_credits = 0; 177838c8a9a5SSteve French 177938c8a9a5SSteve French t->send_credit_target = smb_direct_send_credit_target; 178038c8a9a5SSteve French atomic_set(&t->send_credits, 0); 178138c8a9a5SSteve French atomic_set(&t->rw_credits, t->max_rw_credits); 178238c8a9a5SSteve French 178338c8a9a5SSteve French t->max_send_size = smb_direct_max_send_size; 178438c8a9a5SSteve French t->max_recv_size = smb_direct_max_receive_size; 178538c8a9a5SSteve French t->max_fragmented_recv_size = smb_direct_max_fragmented_recv_size; 178638c8a9a5SSteve French 178738c8a9a5SSteve French cap->max_send_wr = max_send_wrs; 178838c8a9a5SSteve French cap->max_recv_wr = t->recv_credit_max; 178938c8a9a5SSteve French cap->max_send_sge = max_sge_per_wr; 179038c8a9a5SSteve French cap->max_recv_sge = SMB_DIRECT_MAX_RECV_SGES; 179138c8a9a5SSteve French cap->max_inline_data = 0; 179238c8a9a5SSteve French cap->max_rdma_ctxs = t->max_rw_credits; 179338c8a9a5SSteve French return 0; 179438c8a9a5SSteve French } 179538c8a9a5SSteve French 179638c8a9a5SSteve French static void smb_direct_destroy_pools(struct smb_direct_transport *t) 179738c8a9a5SSteve French { 179838c8a9a5SSteve French struct smb_direct_recvmsg *recvmsg; 179938c8a9a5SSteve French 180038c8a9a5SSteve French while ((recvmsg = get_free_recvmsg(t))) 180138c8a9a5SSteve French mempool_free(recvmsg, t->recvmsg_mempool); 180238c8a9a5SSteve French while ((recvmsg = get_empty_recvmsg(t))) 180338c8a9a5SSteve French mempool_free(recvmsg, t->recvmsg_mempool); 180438c8a9a5SSteve French 180538c8a9a5SSteve French mempool_destroy(t->recvmsg_mempool); 180638c8a9a5SSteve French t->recvmsg_mempool = NULL; 180738c8a9a5SSteve French 180838c8a9a5SSteve French kmem_cache_destroy(t->recvmsg_cache); 180938c8a9a5SSteve French t->recvmsg_cache = NULL; 181038c8a9a5SSteve French 181138c8a9a5SSteve French mempool_destroy(t->sendmsg_mempool); 181238c8a9a5SSteve French t->sendmsg_mempool = NULL; 181338c8a9a5SSteve French 181438c8a9a5SSteve French kmem_cache_destroy(t->sendmsg_cache); 181538c8a9a5SSteve French t->sendmsg_cache = NULL; 181638c8a9a5SSteve French } 181738c8a9a5SSteve French 181838c8a9a5SSteve French static int smb_direct_create_pools(struct smb_direct_transport *t) 181938c8a9a5SSteve French { 182038c8a9a5SSteve French char name[80]; 182138c8a9a5SSteve French int i; 182238c8a9a5SSteve French struct smb_direct_recvmsg *recvmsg; 182338c8a9a5SSteve French 182438c8a9a5SSteve French snprintf(name, sizeof(name), "smb_direct_rqst_pool_%p", t); 182538c8a9a5SSteve French t->sendmsg_cache = kmem_cache_create(name, 182638c8a9a5SSteve French sizeof(struct smb_direct_sendmsg) + 182738c8a9a5SSteve French sizeof(struct smb_direct_negotiate_resp), 182838c8a9a5SSteve French 0, SLAB_HWCACHE_ALIGN, NULL); 182938c8a9a5SSteve French if (!t->sendmsg_cache) 183038c8a9a5SSteve French return -ENOMEM; 183138c8a9a5SSteve French 183238c8a9a5SSteve French t->sendmsg_mempool = mempool_create(t->send_credit_target, 183338c8a9a5SSteve French mempool_alloc_slab, mempool_free_slab, 183438c8a9a5SSteve French t->sendmsg_cache); 183538c8a9a5SSteve French if (!t->sendmsg_mempool) 183638c8a9a5SSteve French goto err; 183738c8a9a5SSteve French 183838c8a9a5SSteve French snprintf(name, sizeof(name), "smb_direct_resp_%p", t); 183938c8a9a5SSteve French t->recvmsg_cache = kmem_cache_create(name, 184038c8a9a5SSteve French sizeof(struct smb_direct_recvmsg) + 184138c8a9a5SSteve French t->max_recv_size, 184238c8a9a5SSteve French 0, SLAB_HWCACHE_ALIGN, NULL); 184338c8a9a5SSteve French if (!t->recvmsg_cache) 184438c8a9a5SSteve French goto err; 184538c8a9a5SSteve French 184638c8a9a5SSteve French t->recvmsg_mempool = 184738c8a9a5SSteve French mempool_create(t->recv_credit_max, mempool_alloc_slab, 184838c8a9a5SSteve French mempool_free_slab, t->recvmsg_cache); 184938c8a9a5SSteve French if (!t->recvmsg_mempool) 185038c8a9a5SSteve French goto err; 185138c8a9a5SSteve French 185238c8a9a5SSteve French INIT_LIST_HEAD(&t->recvmsg_queue); 185338c8a9a5SSteve French 185438c8a9a5SSteve French for (i = 0; i < t->recv_credit_max; i++) { 185538c8a9a5SSteve French recvmsg = mempool_alloc(t->recvmsg_mempool, GFP_KERNEL); 185638c8a9a5SSteve French if (!recvmsg) 185738c8a9a5SSteve French goto err; 185838c8a9a5SSteve French recvmsg->transport = t; 185938c8a9a5SSteve French list_add(&recvmsg->list, &t->recvmsg_queue); 186038c8a9a5SSteve French } 186138c8a9a5SSteve French t->count_avail_recvmsg = t->recv_credit_max; 186238c8a9a5SSteve French 186338c8a9a5SSteve French return 0; 186438c8a9a5SSteve French err: 186538c8a9a5SSteve French smb_direct_destroy_pools(t); 186638c8a9a5SSteve French return -ENOMEM; 186738c8a9a5SSteve French } 186838c8a9a5SSteve French 186938c8a9a5SSteve French static int smb_direct_create_qpair(struct smb_direct_transport *t, 187038c8a9a5SSteve French struct ib_qp_cap *cap) 187138c8a9a5SSteve French { 187238c8a9a5SSteve French int ret; 187338c8a9a5SSteve French struct ib_qp_init_attr qp_attr; 187438c8a9a5SSteve French int pages_per_rw; 187538c8a9a5SSteve French 187638c8a9a5SSteve French t->pd = ib_alloc_pd(t->cm_id->device, 0); 187738c8a9a5SSteve French if (IS_ERR(t->pd)) { 187838c8a9a5SSteve French pr_err("Can't create RDMA PD\n"); 187938c8a9a5SSteve French ret = PTR_ERR(t->pd); 188038c8a9a5SSteve French t->pd = NULL; 188138c8a9a5SSteve French return ret; 188238c8a9a5SSteve French } 188338c8a9a5SSteve French 188438c8a9a5SSteve French t->send_cq = ib_alloc_cq(t->cm_id->device, t, 188538c8a9a5SSteve French smb_direct_send_credit_target + cap->max_rdma_ctxs, 188638c8a9a5SSteve French 0, IB_POLL_WORKQUEUE); 188738c8a9a5SSteve French if (IS_ERR(t->send_cq)) { 188838c8a9a5SSteve French pr_err("Can't create RDMA send CQ\n"); 188938c8a9a5SSteve French ret = PTR_ERR(t->send_cq); 189038c8a9a5SSteve French t->send_cq = NULL; 189138c8a9a5SSteve French goto err; 189238c8a9a5SSteve French } 189338c8a9a5SSteve French 189438c8a9a5SSteve French t->recv_cq = ib_alloc_cq(t->cm_id->device, t, 189538c8a9a5SSteve French t->recv_credit_max, 0, IB_POLL_WORKQUEUE); 189638c8a9a5SSteve French if (IS_ERR(t->recv_cq)) { 189738c8a9a5SSteve French pr_err("Can't create RDMA recv CQ\n"); 189838c8a9a5SSteve French ret = PTR_ERR(t->recv_cq); 189938c8a9a5SSteve French t->recv_cq = NULL; 190038c8a9a5SSteve French goto err; 190138c8a9a5SSteve French } 190238c8a9a5SSteve French 190338c8a9a5SSteve French memset(&qp_attr, 0, sizeof(qp_attr)); 190438c8a9a5SSteve French qp_attr.event_handler = smb_direct_qpair_handler; 190538c8a9a5SSteve French qp_attr.qp_context = t; 190638c8a9a5SSteve French qp_attr.cap = *cap; 190738c8a9a5SSteve French qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR; 190838c8a9a5SSteve French qp_attr.qp_type = IB_QPT_RC; 190938c8a9a5SSteve French qp_attr.send_cq = t->send_cq; 191038c8a9a5SSteve French qp_attr.recv_cq = t->recv_cq; 191138c8a9a5SSteve French qp_attr.port_num = ~0; 191238c8a9a5SSteve French 191338c8a9a5SSteve French ret = rdma_create_qp(t->cm_id, t->pd, &qp_attr); 191438c8a9a5SSteve French if (ret) { 191538c8a9a5SSteve French pr_err("Can't create RDMA QP: %d\n", ret); 191638c8a9a5SSteve French goto err; 191738c8a9a5SSteve French } 191838c8a9a5SSteve French 191938c8a9a5SSteve French t->qp = t->cm_id->qp; 192038c8a9a5SSteve French t->cm_id->event_handler = smb_direct_cm_handler; 192138c8a9a5SSteve French 192238c8a9a5SSteve French pages_per_rw = DIV_ROUND_UP(t->max_rdma_rw_size, PAGE_SIZE) + 1; 192338c8a9a5SSteve French if (pages_per_rw > t->cm_id->device->attrs.max_sgl_rd) { 192438c8a9a5SSteve French ret = ib_mr_pool_init(t->qp, &t->qp->rdma_mrs, 192538c8a9a5SSteve French t->max_rw_credits, IB_MR_TYPE_MEM_REG, 192638c8a9a5SSteve French t->pages_per_rw_credit, 0); 192738c8a9a5SSteve French if (ret) { 192838c8a9a5SSteve French pr_err("failed to init mr pool count %d pages %d\n", 192938c8a9a5SSteve French t->max_rw_credits, t->pages_per_rw_credit); 193038c8a9a5SSteve French goto err; 193138c8a9a5SSteve French } 193238c8a9a5SSteve French } 193338c8a9a5SSteve French 193438c8a9a5SSteve French return 0; 193538c8a9a5SSteve French err: 193638c8a9a5SSteve French if (t->qp) { 193738c8a9a5SSteve French ib_destroy_qp(t->qp); 193838c8a9a5SSteve French t->qp = NULL; 193938c8a9a5SSteve French } 194038c8a9a5SSteve French if (t->recv_cq) { 194138c8a9a5SSteve French ib_destroy_cq(t->recv_cq); 194238c8a9a5SSteve French t->recv_cq = NULL; 194338c8a9a5SSteve French } 194438c8a9a5SSteve French if (t->send_cq) { 194538c8a9a5SSteve French ib_destroy_cq(t->send_cq); 194638c8a9a5SSteve French t->send_cq = NULL; 194738c8a9a5SSteve French } 194838c8a9a5SSteve French if (t->pd) { 194938c8a9a5SSteve French ib_dealloc_pd(t->pd); 195038c8a9a5SSteve French t->pd = NULL; 195138c8a9a5SSteve French } 195238c8a9a5SSteve French return ret; 195338c8a9a5SSteve French } 195438c8a9a5SSteve French 195538c8a9a5SSteve French static int smb_direct_prepare(struct ksmbd_transport *t) 195638c8a9a5SSteve French { 195738c8a9a5SSteve French struct smb_direct_transport *st = smb_trans_direct_transfort(t); 195838c8a9a5SSteve French struct smb_direct_recvmsg *recvmsg; 195938c8a9a5SSteve French struct smb_direct_negotiate_req *req; 196038c8a9a5SSteve French int ret; 196138c8a9a5SSteve French 196238c8a9a5SSteve French ksmbd_debug(RDMA, "Waiting for SMB_DIRECT negotiate request\n"); 196338c8a9a5SSteve French ret = wait_event_interruptible_timeout(st->wait_status, 196438c8a9a5SSteve French st->negotiation_requested || 196538c8a9a5SSteve French st->status == SMB_DIRECT_CS_DISCONNECTED, 196638c8a9a5SSteve French SMB_DIRECT_NEGOTIATE_TIMEOUT * HZ); 196738c8a9a5SSteve French if (ret <= 0 || st->status == SMB_DIRECT_CS_DISCONNECTED) 196838c8a9a5SSteve French return ret < 0 ? ret : -ETIMEDOUT; 196938c8a9a5SSteve French 197038c8a9a5SSteve French recvmsg = get_first_reassembly(st); 197138c8a9a5SSteve French if (!recvmsg) 197238c8a9a5SSteve French return -ECONNABORTED; 197338c8a9a5SSteve French 197438c8a9a5SSteve French ret = smb_direct_check_recvmsg(recvmsg); 197538c8a9a5SSteve French if (ret == -ECONNABORTED) 197638c8a9a5SSteve French goto out; 197738c8a9a5SSteve French 197838c8a9a5SSteve French req = (struct smb_direct_negotiate_req *)recvmsg->packet; 197938c8a9a5SSteve French st->max_recv_size = min_t(int, st->max_recv_size, 198038c8a9a5SSteve French le32_to_cpu(req->preferred_send_size)); 198138c8a9a5SSteve French st->max_send_size = min_t(int, st->max_send_size, 198238c8a9a5SSteve French le32_to_cpu(req->max_receive_size)); 198338c8a9a5SSteve French st->max_fragmented_send_size = 198438c8a9a5SSteve French le32_to_cpu(req->max_fragmented_size); 198538c8a9a5SSteve French st->max_fragmented_recv_size = 198638c8a9a5SSteve French (st->recv_credit_max * st->max_recv_size) / 2; 198738c8a9a5SSteve French 198838c8a9a5SSteve French ret = smb_direct_send_negotiate_response(st, ret); 198938c8a9a5SSteve French out: 199038c8a9a5SSteve French spin_lock_irq(&st->reassembly_queue_lock); 199138c8a9a5SSteve French st->reassembly_queue_length--; 199238c8a9a5SSteve French list_del(&recvmsg->list); 199338c8a9a5SSteve French spin_unlock_irq(&st->reassembly_queue_lock); 199438c8a9a5SSteve French put_recvmsg(st, recvmsg); 199538c8a9a5SSteve French 199638c8a9a5SSteve French return ret; 199738c8a9a5SSteve French } 199838c8a9a5SSteve French 199938c8a9a5SSteve French static int smb_direct_connect(struct smb_direct_transport *st) 200038c8a9a5SSteve French { 200138c8a9a5SSteve French int ret; 200238c8a9a5SSteve French struct ib_qp_cap qp_cap; 200338c8a9a5SSteve French 200438c8a9a5SSteve French ret = smb_direct_init_params(st, &qp_cap); 200538c8a9a5SSteve French if (ret) { 200638c8a9a5SSteve French pr_err("Can't configure RDMA parameters\n"); 200738c8a9a5SSteve French return ret; 200838c8a9a5SSteve French } 200938c8a9a5SSteve French 201038c8a9a5SSteve French ret = smb_direct_create_pools(st); 201138c8a9a5SSteve French if (ret) { 201238c8a9a5SSteve French pr_err("Can't init RDMA pool: %d\n", ret); 201338c8a9a5SSteve French return ret; 201438c8a9a5SSteve French } 201538c8a9a5SSteve French 201638c8a9a5SSteve French ret = smb_direct_create_qpair(st, &qp_cap); 201738c8a9a5SSteve French if (ret) { 201838c8a9a5SSteve French pr_err("Can't accept RDMA client: %d\n", ret); 201938c8a9a5SSteve French return ret; 202038c8a9a5SSteve French } 202138c8a9a5SSteve French 202238c8a9a5SSteve French ret = smb_direct_prepare_negotiation(st); 202338c8a9a5SSteve French if (ret) { 202438c8a9a5SSteve French pr_err("Can't negotiate: %d\n", ret); 202538c8a9a5SSteve French return ret; 202638c8a9a5SSteve French } 202738c8a9a5SSteve French return 0; 202838c8a9a5SSteve French } 202938c8a9a5SSteve French 203038c8a9a5SSteve French static bool rdma_frwr_is_supported(struct ib_device_attr *attrs) 203138c8a9a5SSteve French { 203238c8a9a5SSteve French if (!(attrs->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS)) 203338c8a9a5SSteve French return false; 203438c8a9a5SSteve French if (attrs->max_fast_reg_page_list_len == 0) 203538c8a9a5SSteve French return false; 203638c8a9a5SSteve French return true; 203738c8a9a5SSteve French } 203838c8a9a5SSteve French 203938c8a9a5SSteve French static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id) 204038c8a9a5SSteve French { 204138c8a9a5SSteve French struct smb_direct_transport *t; 204238c8a9a5SSteve French int ret; 204338c8a9a5SSteve French 204438c8a9a5SSteve French if (!rdma_frwr_is_supported(&new_cm_id->device->attrs)) { 204538c8a9a5SSteve French ksmbd_debug(RDMA, 204638c8a9a5SSteve French "Fast Registration Work Requests is not supported. device capabilities=%llx\n", 204738c8a9a5SSteve French new_cm_id->device->attrs.device_cap_flags); 204838c8a9a5SSteve French return -EPROTONOSUPPORT; 204938c8a9a5SSteve French } 205038c8a9a5SSteve French 205138c8a9a5SSteve French t = alloc_transport(new_cm_id); 205238c8a9a5SSteve French if (!t) 205338c8a9a5SSteve French return -ENOMEM; 205438c8a9a5SSteve French 205538c8a9a5SSteve French ret = smb_direct_connect(t); 205638c8a9a5SSteve French if (ret) 205738c8a9a5SSteve French goto out_err; 205838c8a9a5SSteve French 205938c8a9a5SSteve French KSMBD_TRANS(t)->handler = kthread_run(ksmbd_conn_handler_loop, 206038c8a9a5SSteve French KSMBD_TRANS(t)->conn, "ksmbd:r%u", 206138c8a9a5SSteve French smb_direct_port); 206238c8a9a5SSteve French if (IS_ERR(KSMBD_TRANS(t)->handler)) { 206338c8a9a5SSteve French ret = PTR_ERR(KSMBD_TRANS(t)->handler); 206438c8a9a5SSteve French pr_err("Can't start thread\n"); 206538c8a9a5SSteve French goto out_err; 206638c8a9a5SSteve French } 206738c8a9a5SSteve French 206838c8a9a5SSteve French return 0; 206938c8a9a5SSteve French out_err: 207038c8a9a5SSteve French free_transport(t); 207138c8a9a5SSteve French return ret; 207238c8a9a5SSteve French } 207338c8a9a5SSteve French 207438c8a9a5SSteve French static int smb_direct_listen_handler(struct rdma_cm_id *cm_id, 207538c8a9a5SSteve French struct rdma_cm_event *event) 207638c8a9a5SSteve French { 207738c8a9a5SSteve French switch (event->event) { 207838c8a9a5SSteve French case RDMA_CM_EVENT_CONNECT_REQUEST: { 207938c8a9a5SSteve French int ret = smb_direct_handle_connect_request(cm_id); 208038c8a9a5SSteve French 208138c8a9a5SSteve French if (ret) { 208238c8a9a5SSteve French pr_err("Can't create transport: %d\n", ret); 208338c8a9a5SSteve French return ret; 208438c8a9a5SSteve French } 208538c8a9a5SSteve French 208638c8a9a5SSteve French ksmbd_debug(RDMA, "Received connection request. cm_id=%p\n", 208738c8a9a5SSteve French cm_id); 208838c8a9a5SSteve French break; 208938c8a9a5SSteve French } 209038c8a9a5SSteve French default: 209138c8a9a5SSteve French pr_err("Unexpected listen event. cm_id=%p, event=%s (%d)\n", 209238c8a9a5SSteve French cm_id, rdma_event_msg(event->event), event->event); 209338c8a9a5SSteve French break; 209438c8a9a5SSteve French } 209538c8a9a5SSteve French return 0; 209638c8a9a5SSteve French } 209738c8a9a5SSteve French 209838c8a9a5SSteve French static int smb_direct_listen(int port) 209938c8a9a5SSteve French { 210038c8a9a5SSteve French int ret; 210138c8a9a5SSteve French struct rdma_cm_id *cm_id; 210238c8a9a5SSteve French struct sockaddr_in sin = { 210338c8a9a5SSteve French .sin_family = AF_INET, 210438c8a9a5SSteve French .sin_addr.s_addr = htonl(INADDR_ANY), 210538c8a9a5SSteve French .sin_port = htons(port), 210638c8a9a5SSteve French }; 210738c8a9a5SSteve French 210838c8a9a5SSteve French cm_id = rdma_create_id(&init_net, smb_direct_listen_handler, 210938c8a9a5SSteve French &smb_direct_listener, RDMA_PS_TCP, IB_QPT_RC); 211038c8a9a5SSteve French if (IS_ERR(cm_id)) { 211138c8a9a5SSteve French pr_err("Can't create cm id: %ld\n", PTR_ERR(cm_id)); 211238c8a9a5SSteve French return PTR_ERR(cm_id); 211338c8a9a5SSteve French } 211438c8a9a5SSteve French 211538c8a9a5SSteve French ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin); 211638c8a9a5SSteve French if (ret) { 211738c8a9a5SSteve French pr_err("Can't bind: %d\n", ret); 211838c8a9a5SSteve French goto err; 211938c8a9a5SSteve French } 212038c8a9a5SSteve French 212138c8a9a5SSteve French smb_direct_listener.cm_id = cm_id; 212238c8a9a5SSteve French 212338c8a9a5SSteve French ret = rdma_listen(cm_id, 10); 212438c8a9a5SSteve French if (ret) { 212538c8a9a5SSteve French pr_err("Can't listen: %d\n", ret); 212638c8a9a5SSteve French goto err; 212738c8a9a5SSteve French } 212838c8a9a5SSteve French return 0; 212938c8a9a5SSteve French err: 213038c8a9a5SSteve French smb_direct_listener.cm_id = NULL; 213138c8a9a5SSteve French rdma_destroy_id(cm_id); 213238c8a9a5SSteve French return ret; 213338c8a9a5SSteve French } 213438c8a9a5SSteve French 213538c8a9a5SSteve French static int smb_direct_ib_client_add(struct ib_device *ib_dev) 213638c8a9a5SSteve French { 213738c8a9a5SSteve French struct smb_direct_device *smb_dev; 213838c8a9a5SSteve French 213938c8a9a5SSteve French /* Set 5445 port if device type is iWARP(No IB) */ 214038c8a9a5SSteve French if (ib_dev->node_type != RDMA_NODE_IB_CA) 214138c8a9a5SSteve French smb_direct_port = SMB_DIRECT_PORT_IWARP; 214238c8a9a5SSteve French 214338c8a9a5SSteve French if (!ib_dev->ops.get_netdev || 214438c8a9a5SSteve French !rdma_frwr_is_supported(&ib_dev->attrs)) 214538c8a9a5SSteve French return 0; 214638c8a9a5SSteve French 214738c8a9a5SSteve French smb_dev = kzalloc(sizeof(*smb_dev), GFP_KERNEL); 214838c8a9a5SSteve French if (!smb_dev) 214938c8a9a5SSteve French return -ENOMEM; 215038c8a9a5SSteve French smb_dev->ib_dev = ib_dev; 215138c8a9a5SSteve French 215238c8a9a5SSteve French write_lock(&smb_direct_device_lock); 215338c8a9a5SSteve French list_add(&smb_dev->list, &smb_direct_device_list); 215438c8a9a5SSteve French write_unlock(&smb_direct_device_lock); 215538c8a9a5SSteve French 215638c8a9a5SSteve French ksmbd_debug(RDMA, "ib device added: name %s\n", ib_dev->name); 215738c8a9a5SSteve French return 0; 215838c8a9a5SSteve French } 215938c8a9a5SSteve French 216038c8a9a5SSteve French static void smb_direct_ib_client_remove(struct ib_device *ib_dev, 216138c8a9a5SSteve French void *client_data) 216238c8a9a5SSteve French { 216338c8a9a5SSteve French struct smb_direct_device *smb_dev, *tmp; 216438c8a9a5SSteve French 216538c8a9a5SSteve French write_lock(&smb_direct_device_lock); 216638c8a9a5SSteve French list_for_each_entry_safe(smb_dev, tmp, &smb_direct_device_list, list) { 216738c8a9a5SSteve French if (smb_dev->ib_dev == ib_dev) { 216838c8a9a5SSteve French list_del(&smb_dev->list); 216938c8a9a5SSteve French kfree(smb_dev); 217038c8a9a5SSteve French break; 217138c8a9a5SSteve French } 217238c8a9a5SSteve French } 217338c8a9a5SSteve French write_unlock(&smb_direct_device_lock); 217438c8a9a5SSteve French } 217538c8a9a5SSteve French 217638c8a9a5SSteve French static struct ib_client smb_direct_ib_client = { 217738c8a9a5SSteve French .name = "ksmbd_smb_direct_ib", 217838c8a9a5SSteve French .add = smb_direct_ib_client_add, 217938c8a9a5SSteve French .remove = smb_direct_ib_client_remove, 218038c8a9a5SSteve French }; 218138c8a9a5SSteve French 218238c8a9a5SSteve French int ksmbd_rdma_init(void) 218338c8a9a5SSteve French { 218438c8a9a5SSteve French int ret; 218538c8a9a5SSteve French 218638c8a9a5SSteve French smb_direct_listener.cm_id = NULL; 218738c8a9a5SSteve French 218838c8a9a5SSteve French ret = ib_register_client(&smb_direct_ib_client); 218938c8a9a5SSteve French if (ret) { 219038c8a9a5SSteve French pr_err("failed to ib_register_client\n"); 219138c8a9a5SSteve French return ret; 219238c8a9a5SSteve French } 219338c8a9a5SSteve French 219438c8a9a5SSteve French /* When a client is running out of send credits, the credits are 219538c8a9a5SSteve French * granted by the server's sending a packet using this queue. 219638c8a9a5SSteve French * This avoids the situation that a clients cannot send packets 219738c8a9a5SSteve French * for lack of credits 219838c8a9a5SSteve French */ 219938c8a9a5SSteve French smb_direct_wq = alloc_workqueue("ksmbd-smb_direct-wq", 220038c8a9a5SSteve French WQ_HIGHPRI | WQ_MEM_RECLAIM, 0); 220138c8a9a5SSteve French if (!smb_direct_wq) 220238c8a9a5SSteve French return -ENOMEM; 220338c8a9a5SSteve French 220438c8a9a5SSteve French ret = smb_direct_listen(smb_direct_port); 220538c8a9a5SSteve French if (ret) { 220638c8a9a5SSteve French destroy_workqueue(smb_direct_wq); 220738c8a9a5SSteve French smb_direct_wq = NULL; 220838c8a9a5SSteve French pr_err("Can't listen: %d\n", ret); 220938c8a9a5SSteve French return ret; 221038c8a9a5SSteve French } 221138c8a9a5SSteve French 221238c8a9a5SSteve French ksmbd_debug(RDMA, "init RDMA listener. cm_id=%p\n", 221338c8a9a5SSteve French smb_direct_listener.cm_id); 221438c8a9a5SSteve French return 0; 221538c8a9a5SSteve French } 221638c8a9a5SSteve French 221738c8a9a5SSteve French void ksmbd_rdma_destroy(void) 221838c8a9a5SSteve French { 221938c8a9a5SSteve French if (!smb_direct_listener.cm_id) 222038c8a9a5SSteve French return; 222138c8a9a5SSteve French 222238c8a9a5SSteve French ib_unregister_client(&smb_direct_ib_client); 222338c8a9a5SSteve French rdma_destroy_id(smb_direct_listener.cm_id); 222438c8a9a5SSteve French 222538c8a9a5SSteve French smb_direct_listener.cm_id = NULL; 222638c8a9a5SSteve French 222738c8a9a5SSteve French if (smb_direct_wq) { 222838c8a9a5SSteve French destroy_workqueue(smb_direct_wq); 222938c8a9a5SSteve French smb_direct_wq = NULL; 223038c8a9a5SSteve French } 223138c8a9a5SSteve French } 223238c8a9a5SSteve French 223338c8a9a5SSteve French bool ksmbd_rdma_capable_netdev(struct net_device *netdev) 223438c8a9a5SSteve French { 223538c8a9a5SSteve French struct smb_direct_device *smb_dev; 223638c8a9a5SSteve French int i; 223738c8a9a5SSteve French bool rdma_capable = false; 223838c8a9a5SSteve French 223938c8a9a5SSteve French read_lock(&smb_direct_device_lock); 224038c8a9a5SSteve French list_for_each_entry(smb_dev, &smb_direct_device_list, list) { 224138c8a9a5SSteve French for (i = 0; i < smb_dev->ib_dev->phys_port_cnt; i++) { 224238c8a9a5SSteve French struct net_device *ndev; 224338c8a9a5SSteve French 224438c8a9a5SSteve French ndev = smb_dev->ib_dev->ops.get_netdev(smb_dev->ib_dev, 224538c8a9a5SSteve French i + 1); 224638c8a9a5SSteve French if (!ndev) 224738c8a9a5SSteve French continue; 224838c8a9a5SSteve French 224938c8a9a5SSteve French if (ndev == netdev) { 225038c8a9a5SSteve French dev_put(ndev); 225138c8a9a5SSteve French rdma_capable = true; 225238c8a9a5SSteve French goto out; 225338c8a9a5SSteve French } 225438c8a9a5SSteve French dev_put(ndev); 225538c8a9a5SSteve French } 225638c8a9a5SSteve French } 225738c8a9a5SSteve French out: 225838c8a9a5SSteve French read_unlock(&smb_direct_device_lock); 225938c8a9a5SSteve French 226038c8a9a5SSteve French if (rdma_capable == false) { 226138c8a9a5SSteve French struct ib_device *ibdev; 226238c8a9a5SSteve French 226338c8a9a5SSteve French ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_UNKNOWN); 226438c8a9a5SSteve French if (ibdev) { 226538c8a9a5SSteve French if (rdma_frwr_is_supported(&ibdev->attrs)) 226638c8a9a5SSteve French rdma_capable = true; 226738c8a9a5SSteve French ib_device_put(ibdev); 226838c8a9a5SSteve French } 226938c8a9a5SSteve French } 227038c8a9a5SSteve French 227138c8a9a5SSteve French return rdma_capable; 227238c8a9a5SSteve French } 227338c8a9a5SSteve French 227438c8a9a5SSteve French static struct ksmbd_transport_ops ksmbd_smb_direct_transport_ops = { 227538c8a9a5SSteve French .prepare = smb_direct_prepare, 227638c8a9a5SSteve French .disconnect = smb_direct_disconnect, 227738c8a9a5SSteve French .shutdown = smb_direct_shutdown, 227838c8a9a5SSteve French .writev = smb_direct_writev, 227938c8a9a5SSteve French .read = smb_direct_read, 228038c8a9a5SSteve French .rdma_read = smb_direct_rdma_read, 228138c8a9a5SSteve French .rdma_write = smb_direct_rdma_write, 228238c8a9a5SSteve French }; 2283