162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2014-2017 Oracle. All rights reserved. 462306a36Sopenharmony_ci * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * This software is available to you under a choice of one of two 762306a36Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 862306a36Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 962306a36Sopenharmony_ci * COPYING in the main directory of this source tree, or the BSD-type 1062306a36Sopenharmony_ci * license below: 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 1362306a36Sopenharmony_ci * modification, are permitted provided that the following conditions 1462306a36Sopenharmony_ci * are met: 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * Redistributions of source code must retain the above copyright 1762306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * Redistributions in binary form must reproduce the above 2062306a36Sopenharmony_ci * copyright notice, this list of conditions and the following 2162306a36Sopenharmony_ci * disclaimer in the documentation and/or other materials provided 2262306a36Sopenharmony_ci * with the distribution. 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * Neither the name of the Network Appliance, Inc. nor the names of 2562306a36Sopenharmony_ci * its contributors may be used to endorse or promote products 2662306a36Sopenharmony_ci * derived from this software without specific prior written 2762306a36Sopenharmony_ci * permission. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3062306a36Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3162306a36Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3262306a36Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3362306a36Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3462306a36Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3562306a36Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3662306a36Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3762306a36Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3862306a36Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3962306a36Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#ifndef _LINUX_SUNRPC_XPRT_RDMA_H 4362306a36Sopenharmony_ci#define _LINUX_SUNRPC_XPRT_RDMA_H 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#include <linux/wait.h> /* wait_queue_head_t, etc */ 4662306a36Sopenharmony_ci#include <linux/spinlock.h> /* spinlock_t, etc */ 4762306a36Sopenharmony_ci#include <linux/atomic.h> /* atomic_t, etc */ 4862306a36Sopenharmony_ci#include <linux/kref.h> /* struct kref */ 4962306a36Sopenharmony_ci#include <linux/workqueue.h> /* struct work_struct */ 5062306a36Sopenharmony_ci#include <linux/llist.h> 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#include <rdma/rdma_cm.h> /* RDMA connection api */ 5362306a36Sopenharmony_ci#include <rdma/ib_verbs.h> /* RDMA verbs api */ 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#include <linux/sunrpc/clnt.h> /* rpc_xprt */ 5662306a36Sopenharmony_ci#include <linux/sunrpc/rpc_rdma_cid.h> /* completion IDs */ 5762306a36Sopenharmony_ci#include <linux/sunrpc/rpc_rdma.h> /* RPC/RDMA protocol */ 5862306a36Sopenharmony_ci#include <linux/sunrpc/xprtrdma.h> /* xprt parameters */ 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#define RDMA_RESOLVE_TIMEOUT (5000) /* 5 seconds */ 6162306a36Sopenharmony_ci#define RDMA_CONNECT_RETRY_MAX (2) /* retries if no listener backlog */ 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci#define RPCRDMA_BIND_TO (60U * HZ) 6462306a36Sopenharmony_ci#define RPCRDMA_INIT_REEST_TO (5U * HZ) 6562306a36Sopenharmony_ci#define RPCRDMA_MAX_REEST_TO (30U * HZ) 6662306a36Sopenharmony_ci#define RPCRDMA_IDLE_DISC_TO (5U * 60 * HZ) 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/* 6962306a36Sopenharmony_ci * RDMA Endpoint -- connection endpoint details 7062306a36Sopenharmony_ci */ 7162306a36Sopenharmony_cistruct rpcrdma_mr; 7262306a36Sopenharmony_cistruct rpcrdma_ep { 7362306a36Sopenharmony_ci struct kref re_kref; 7462306a36Sopenharmony_ci struct rdma_cm_id *re_id; 7562306a36Sopenharmony_ci struct ib_pd *re_pd; 7662306a36Sopenharmony_ci unsigned int re_max_rdma_segs; 7762306a36Sopenharmony_ci unsigned int re_max_fr_depth; 7862306a36Sopenharmony_ci struct rpcrdma_mr *re_write_pad_mr; 7962306a36Sopenharmony_ci enum ib_mr_type re_mrtype; 8062306a36Sopenharmony_ci struct completion re_done; 8162306a36Sopenharmony_ci unsigned int re_send_count; 8262306a36Sopenharmony_ci unsigned int re_send_batch; 8362306a36Sopenharmony_ci unsigned int re_max_inline_send; 8462306a36Sopenharmony_ci unsigned int re_max_inline_recv; 8562306a36Sopenharmony_ci int re_async_rc; 8662306a36Sopenharmony_ci int re_connect_status; 8762306a36Sopenharmony_ci atomic_t re_receiving; 8862306a36Sopenharmony_ci atomic_t re_force_disconnect; 8962306a36Sopenharmony_ci struct ib_qp_init_attr re_attr; 9062306a36Sopenharmony_ci wait_queue_head_t re_connect_wait; 9162306a36Sopenharmony_ci struct rpc_xprt *re_xprt; 9262306a36Sopenharmony_ci struct rpcrdma_connect_private 9362306a36Sopenharmony_ci re_cm_private; 9462306a36Sopenharmony_ci struct rdma_conn_param re_remote_cma; 9562306a36Sopenharmony_ci int re_receive_count; 9662306a36Sopenharmony_ci unsigned int re_max_requests; /* depends on device */ 9762306a36Sopenharmony_ci unsigned int re_inline_send; /* negotiated */ 9862306a36Sopenharmony_ci unsigned int re_inline_recv; /* negotiated */ 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci atomic_t re_completion_ids; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci char re_write_pad[XDR_UNIT]; 10362306a36Sopenharmony_ci}; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci/* Pre-allocate extra Work Requests for handling reverse-direction 10662306a36Sopenharmony_ci * Receives and Sends. This is a fixed value because the Work Queues 10762306a36Sopenharmony_ci * are allocated when the forward channel is set up, long before the 10862306a36Sopenharmony_ci * backchannel is provisioned. This value is two times 10962306a36Sopenharmony_ci * NFS4_DEF_CB_SLOT_TABLE_SIZE. 11062306a36Sopenharmony_ci */ 11162306a36Sopenharmony_ci#if defined(CONFIG_SUNRPC_BACKCHANNEL) 11262306a36Sopenharmony_ci#define RPCRDMA_BACKWARD_WRS (32) 11362306a36Sopenharmony_ci#else 11462306a36Sopenharmony_ci#define RPCRDMA_BACKWARD_WRS (0) 11562306a36Sopenharmony_ci#endif 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci/* Registered buffer -- registered kmalloc'd memory for RDMA SEND/RECV 11862306a36Sopenharmony_ci */ 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistruct rpcrdma_regbuf { 12162306a36Sopenharmony_ci struct ib_sge rg_iov; 12262306a36Sopenharmony_ci struct ib_device *rg_device; 12362306a36Sopenharmony_ci enum dma_data_direction rg_direction; 12462306a36Sopenharmony_ci void *rg_data; 12562306a36Sopenharmony_ci}; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic inline u64 rdmab_addr(struct rpcrdma_regbuf *rb) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci return rb->rg_iov.addr; 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic inline u32 rdmab_length(struct rpcrdma_regbuf *rb) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci return rb->rg_iov.length; 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic inline u32 rdmab_lkey(struct rpcrdma_regbuf *rb) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci return rb->rg_iov.lkey; 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic inline struct ib_device *rdmab_device(struct rpcrdma_regbuf *rb) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci return rb->rg_device; 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic inline void *rdmab_data(const struct rpcrdma_regbuf *rb) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci return rb->rg_data; 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci/* Do not use emergency memory reserves, and fail quickly if memory 15362306a36Sopenharmony_ci * cannot be allocated easily. These flags may be used wherever there 15462306a36Sopenharmony_ci * is robust logic to handle a failure to allocate. 15562306a36Sopenharmony_ci */ 15662306a36Sopenharmony_ci#define XPRTRDMA_GFP_FLAGS (__GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN) 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci/* To ensure a transport can always make forward progress, 15962306a36Sopenharmony_ci * the number of RDMA segments allowed in header chunk lists 16062306a36Sopenharmony_ci * is capped at 16. This prevents less-capable devices from 16162306a36Sopenharmony_ci * overrunning the Send buffer while building chunk lists. 16262306a36Sopenharmony_ci * 16362306a36Sopenharmony_ci * Elements of the Read list take up more room than the 16462306a36Sopenharmony_ci * Write list or Reply chunk. 16 read segments means the 16562306a36Sopenharmony_ci * chunk lists cannot consume more than 16662306a36Sopenharmony_ci * 16762306a36Sopenharmony_ci * ((16 + 2) * read segment size) + 1 XDR words, 16862306a36Sopenharmony_ci * 16962306a36Sopenharmony_ci * or about 400 bytes. The fixed part of the header is 17062306a36Sopenharmony_ci * another 24 bytes. Thus when the inline threshold is 17162306a36Sopenharmony_ci * 1024 bytes, at least 600 bytes are available for RPC 17262306a36Sopenharmony_ci * message bodies. 17362306a36Sopenharmony_ci */ 17462306a36Sopenharmony_cienum { 17562306a36Sopenharmony_ci RPCRDMA_MAX_HDR_SEGS = 16, 17662306a36Sopenharmony_ci}; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci/* 17962306a36Sopenharmony_ci * struct rpcrdma_rep -- this structure encapsulates state required 18062306a36Sopenharmony_ci * to receive and complete an RPC Reply, asychronously. It needs 18162306a36Sopenharmony_ci * several pieces of state: 18262306a36Sopenharmony_ci * 18362306a36Sopenharmony_ci * o receive buffer and ib_sge (donated to provider) 18462306a36Sopenharmony_ci * o status of receive (success or not, length, inv rkey) 18562306a36Sopenharmony_ci * o bookkeeping state to get run by reply handler (XDR stream) 18662306a36Sopenharmony_ci * 18762306a36Sopenharmony_ci * These structures are allocated during transport initialization. 18862306a36Sopenharmony_ci * N of these are associated with a transport instance, managed by 18962306a36Sopenharmony_ci * struct rpcrdma_buffer. N is the max number of outstanding RPCs. 19062306a36Sopenharmony_ci */ 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistruct rpcrdma_rep { 19362306a36Sopenharmony_ci struct ib_cqe rr_cqe; 19462306a36Sopenharmony_ci struct rpc_rdma_cid rr_cid; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci __be32 rr_xid; 19762306a36Sopenharmony_ci __be32 rr_vers; 19862306a36Sopenharmony_ci __be32 rr_proc; 19962306a36Sopenharmony_ci int rr_wc_flags; 20062306a36Sopenharmony_ci u32 rr_inv_rkey; 20162306a36Sopenharmony_ci bool rr_temp; 20262306a36Sopenharmony_ci struct rpcrdma_regbuf *rr_rdmabuf; 20362306a36Sopenharmony_ci struct rpcrdma_xprt *rr_rxprt; 20462306a36Sopenharmony_ci struct rpc_rqst *rr_rqst; 20562306a36Sopenharmony_ci struct xdr_buf rr_hdrbuf; 20662306a36Sopenharmony_ci struct xdr_stream rr_stream; 20762306a36Sopenharmony_ci struct llist_node rr_node; 20862306a36Sopenharmony_ci struct ib_recv_wr rr_recv_wr; 20962306a36Sopenharmony_ci struct list_head rr_all; 21062306a36Sopenharmony_ci}; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci/* To reduce the rate at which a transport invokes ib_post_recv 21362306a36Sopenharmony_ci * (and thus the hardware doorbell rate), xprtrdma posts Receive 21462306a36Sopenharmony_ci * WRs in batches. 21562306a36Sopenharmony_ci * 21662306a36Sopenharmony_ci * Setting this to zero disables Receive post batching. 21762306a36Sopenharmony_ci */ 21862306a36Sopenharmony_cienum { 21962306a36Sopenharmony_ci RPCRDMA_MAX_RECV_BATCH = 7, 22062306a36Sopenharmony_ci}; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci/* struct rpcrdma_sendctx - DMA mapped SGEs to unmap after Send completes 22362306a36Sopenharmony_ci */ 22462306a36Sopenharmony_cistruct rpcrdma_req; 22562306a36Sopenharmony_cistruct rpcrdma_sendctx { 22662306a36Sopenharmony_ci struct ib_cqe sc_cqe; 22762306a36Sopenharmony_ci struct rpc_rdma_cid sc_cid; 22862306a36Sopenharmony_ci struct rpcrdma_req *sc_req; 22962306a36Sopenharmony_ci unsigned int sc_unmap_count; 23062306a36Sopenharmony_ci struct ib_sge sc_sges[]; 23162306a36Sopenharmony_ci}; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci/* 23462306a36Sopenharmony_ci * struct rpcrdma_mr - external memory region metadata 23562306a36Sopenharmony_ci * 23662306a36Sopenharmony_ci * An external memory region is any buffer or page that is registered 23762306a36Sopenharmony_ci * on the fly (ie, not pre-registered). 23862306a36Sopenharmony_ci */ 23962306a36Sopenharmony_cistruct rpcrdma_req; 24062306a36Sopenharmony_cistruct rpcrdma_mr { 24162306a36Sopenharmony_ci struct list_head mr_list; 24262306a36Sopenharmony_ci struct rpcrdma_req *mr_req; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci struct ib_mr *mr_ibmr; 24562306a36Sopenharmony_ci struct ib_device *mr_device; 24662306a36Sopenharmony_ci struct scatterlist *mr_sg; 24762306a36Sopenharmony_ci int mr_nents; 24862306a36Sopenharmony_ci enum dma_data_direction mr_dir; 24962306a36Sopenharmony_ci struct ib_cqe mr_cqe; 25062306a36Sopenharmony_ci struct completion mr_linv_done; 25162306a36Sopenharmony_ci union { 25262306a36Sopenharmony_ci struct ib_reg_wr mr_regwr; 25362306a36Sopenharmony_ci struct ib_send_wr mr_invwr; 25462306a36Sopenharmony_ci }; 25562306a36Sopenharmony_ci struct rpcrdma_xprt *mr_xprt; 25662306a36Sopenharmony_ci u32 mr_handle; 25762306a36Sopenharmony_ci u32 mr_length; 25862306a36Sopenharmony_ci u64 mr_offset; 25962306a36Sopenharmony_ci struct list_head mr_all; 26062306a36Sopenharmony_ci struct rpc_rdma_cid mr_cid; 26162306a36Sopenharmony_ci}; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci/* 26462306a36Sopenharmony_ci * struct rpcrdma_req -- structure central to the request/reply sequence. 26562306a36Sopenharmony_ci * 26662306a36Sopenharmony_ci * N of these are associated with a transport instance, and stored in 26762306a36Sopenharmony_ci * struct rpcrdma_buffer. N is the max number of outstanding requests. 26862306a36Sopenharmony_ci * 26962306a36Sopenharmony_ci * It includes pre-registered buffer memory for send AND recv. 27062306a36Sopenharmony_ci * The recv buffer, however, is not owned by this structure, and 27162306a36Sopenharmony_ci * is "donated" to the hardware when a recv is posted. When a 27262306a36Sopenharmony_ci * reply is handled, the recv buffer used is given back to the 27362306a36Sopenharmony_ci * struct rpcrdma_req associated with the request. 27462306a36Sopenharmony_ci * 27562306a36Sopenharmony_ci * In addition to the basic memory, this structure includes an array 27662306a36Sopenharmony_ci * of iovs for send operations. The reason is that the iovs passed to 27762306a36Sopenharmony_ci * ib_post_{send,recv} must not be modified until the work request 27862306a36Sopenharmony_ci * completes. 27962306a36Sopenharmony_ci */ 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci/* Maximum number of page-sized "segments" per chunk list to be 28262306a36Sopenharmony_ci * registered or invalidated. Must handle a Reply chunk: 28362306a36Sopenharmony_ci */ 28462306a36Sopenharmony_cienum { 28562306a36Sopenharmony_ci RPCRDMA_MAX_IOV_SEGS = 3, 28662306a36Sopenharmony_ci RPCRDMA_MAX_DATA_SEGS = ((1 * 1024 * 1024) / PAGE_SIZE) + 1, 28762306a36Sopenharmony_ci RPCRDMA_MAX_SEGS = RPCRDMA_MAX_DATA_SEGS + 28862306a36Sopenharmony_ci RPCRDMA_MAX_IOV_SEGS, 28962306a36Sopenharmony_ci}; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci/* Arguments for DMA mapping and registration */ 29262306a36Sopenharmony_cistruct rpcrdma_mr_seg { 29362306a36Sopenharmony_ci u32 mr_len; /* length of segment */ 29462306a36Sopenharmony_ci struct page *mr_page; /* underlying struct page */ 29562306a36Sopenharmony_ci u64 mr_offset; /* IN: page offset, OUT: iova */ 29662306a36Sopenharmony_ci}; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci/* The Send SGE array is provisioned to send a maximum size 29962306a36Sopenharmony_ci * inline request: 30062306a36Sopenharmony_ci * - RPC-over-RDMA header 30162306a36Sopenharmony_ci * - xdr_buf head iovec 30262306a36Sopenharmony_ci * - RPCRDMA_MAX_INLINE bytes, in pages 30362306a36Sopenharmony_ci * - xdr_buf tail iovec 30462306a36Sopenharmony_ci * 30562306a36Sopenharmony_ci * The actual number of array elements consumed by each RPC 30662306a36Sopenharmony_ci * depends on the device's max_sge limit. 30762306a36Sopenharmony_ci */ 30862306a36Sopenharmony_cienum { 30962306a36Sopenharmony_ci RPCRDMA_MIN_SEND_SGES = 3, 31062306a36Sopenharmony_ci RPCRDMA_MAX_PAGE_SGES = RPCRDMA_MAX_INLINE >> PAGE_SHIFT, 31162306a36Sopenharmony_ci RPCRDMA_MAX_SEND_SGES = 1 + 1 + RPCRDMA_MAX_PAGE_SGES + 1, 31262306a36Sopenharmony_ci}; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cistruct rpcrdma_buffer; 31562306a36Sopenharmony_cistruct rpcrdma_req { 31662306a36Sopenharmony_ci struct list_head rl_list; 31762306a36Sopenharmony_ci struct rpc_rqst rl_slot; 31862306a36Sopenharmony_ci struct rpcrdma_rep *rl_reply; 31962306a36Sopenharmony_ci struct xdr_stream rl_stream; 32062306a36Sopenharmony_ci struct xdr_buf rl_hdrbuf; 32162306a36Sopenharmony_ci struct ib_send_wr rl_wr; 32262306a36Sopenharmony_ci struct rpcrdma_sendctx *rl_sendctx; 32362306a36Sopenharmony_ci struct rpcrdma_regbuf *rl_rdmabuf; /* xprt header */ 32462306a36Sopenharmony_ci struct rpcrdma_regbuf *rl_sendbuf; /* rq_snd_buf */ 32562306a36Sopenharmony_ci struct rpcrdma_regbuf *rl_recvbuf; /* rq_rcv_buf */ 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci struct list_head rl_all; 32862306a36Sopenharmony_ci struct kref rl_kref; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci struct list_head rl_free_mrs; 33162306a36Sopenharmony_ci struct list_head rl_registered; 33262306a36Sopenharmony_ci struct rpcrdma_mr_seg rl_segments[RPCRDMA_MAX_SEGS]; 33362306a36Sopenharmony_ci}; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_cistatic inline struct rpcrdma_req * 33662306a36Sopenharmony_cirpcr_to_rdmar(const struct rpc_rqst *rqst) 33762306a36Sopenharmony_ci{ 33862306a36Sopenharmony_ci return container_of(rqst, struct rpcrdma_req, rl_slot); 33962306a36Sopenharmony_ci} 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_cistatic inline void 34262306a36Sopenharmony_cirpcrdma_mr_push(struct rpcrdma_mr *mr, struct list_head *list) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci list_add(&mr->mr_list, list); 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_cistatic inline struct rpcrdma_mr * 34862306a36Sopenharmony_cirpcrdma_mr_pop(struct list_head *list) 34962306a36Sopenharmony_ci{ 35062306a36Sopenharmony_ci struct rpcrdma_mr *mr; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci mr = list_first_entry_or_null(list, struct rpcrdma_mr, mr_list); 35362306a36Sopenharmony_ci if (mr) 35462306a36Sopenharmony_ci list_del_init(&mr->mr_list); 35562306a36Sopenharmony_ci return mr; 35662306a36Sopenharmony_ci} 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci/* 35962306a36Sopenharmony_ci * struct rpcrdma_buffer -- holds list/queue of pre-registered memory for 36062306a36Sopenharmony_ci * inline requests/replies, and client/server credits. 36162306a36Sopenharmony_ci * 36262306a36Sopenharmony_ci * One of these is associated with a transport instance 36362306a36Sopenharmony_ci */ 36462306a36Sopenharmony_cistruct rpcrdma_buffer { 36562306a36Sopenharmony_ci spinlock_t rb_lock; 36662306a36Sopenharmony_ci struct list_head rb_send_bufs; 36762306a36Sopenharmony_ci struct list_head rb_mrs; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci unsigned long rb_sc_head; 37062306a36Sopenharmony_ci unsigned long rb_sc_tail; 37162306a36Sopenharmony_ci unsigned long rb_sc_last; 37262306a36Sopenharmony_ci struct rpcrdma_sendctx **rb_sc_ctxs; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci struct list_head rb_allreqs; 37562306a36Sopenharmony_ci struct list_head rb_all_mrs; 37662306a36Sopenharmony_ci struct list_head rb_all_reps; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci struct llist_head rb_free_reps; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci __be32 rb_max_requests; 38162306a36Sopenharmony_ci u32 rb_credits; /* most recent credit grant */ 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci u32 rb_bc_srv_max_requests; 38462306a36Sopenharmony_ci u32 rb_bc_max_requests; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci struct work_struct rb_refresh_worker; 38762306a36Sopenharmony_ci}; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci/* 39062306a36Sopenharmony_ci * Statistics for RPCRDMA 39162306a36Sopenharmony_ci */ 39262306a36Sopenharmony_cistruct rpcrdma_stats { 39362306a36Sopenharmony_ci /* accessed when sending a call */ 39462306a36Sopenharmony_ci unsigned long read_chunk_count; 39562306a36Sopenharmony_ci unsigned long write_chunk_count; 39662306a36Sopenharmony_ci unsigned long reply_chunk_count; 39762306a36Sopenharmony_ci unsigned long long total_rdma_request; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci /* rarely accessed error counters */ 40062306a36Sopenharmony_ci unsigned long long pullup_copy_count; 40162306a36Sopenharmony_ci unsigned long hardway_register_count; 40262306a36Sopenharmony_ci unsigned long failed_marshal_count; 40362306a36Sopenharmony_ci unsigned long bad_reply_count; 40462306a36Sopenharmony_ci unsigned long mrs_recycled; 40562306a36Sopenharmony_ci unsigned long mrs_orphaned; 40662306a36Sopenharmony_ci unsigned long mrs_allocated; 40762306a36Sopenharmony_ci unsigned long empty_sendctx_q; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci /* accessed when receiving a reply */ 41062306a36Sopenharmony_ci unsigned long long total_rdma_reply; 41162306a36Sopenharmony_ci unsigned long long fixup_copy_count; 41262306a36Sopenharmony_ci unsigned long reply_waits_for_send; 41362306a36Sopenharmony_ci unsigned long local_inv_needed; 41462306a36Sopenharmony_ci unsigned long nomsg_call_count; 41562306a36Sopenharmony_ci unsigned long bcall_count; 41662306a36Sopenharmony_ci}; 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci/* 41962306a36Sopenharmony_ci * RPCRDMA transport -- encapsulates the structures above for 42062306a36Sopenharmony_ci * integration with RPC. 42162306a36Sopenharmony_ci * 42262306a36Sopenharmony_ci * The contained structures are embedded, not pointers, 42362306a36Sopenharmony_ci * for convenience. This structure need not be visible externally. 42462306a36Sopenharmony_ci * 42562306a36Sopenharmony_ci * It is allocated and initialized during mount, and released 42662306a36Sopenharmony_ci * during unmount. 42762306a36Sopenharmony_ci */ 42862306a36Sopenharmony_cistruct rpcrdma_xprt { 42962306a36Sopenharmony_ci struct rpc_xprt rx_xprt; 43062306a36Sopenharmony_ci struct rpcrdma_ep *rx_ep; 43162306a36Sopenharmony_ci struct rpcrdma_buffer rx_buf; 43262306a36Sopenharmony_ci struct delayed_work rx_connect_worker; 43362306a36Sopenharmony_ci struct rpc_timeout rx_timeout; 43462306a36Sopenharmony_ci struct rpcrdma_stats rx_stats; 43562306a36Sopenharmony_ci}; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci#define rpcx_to_rdmax(x) container_of(x, struct rpcrdma_xprt, rx_xprt) 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cistatic inline const char * 44062306a36Sopenharmony_cirpcrdma_addrstr(const struct rpcrdma_xprt *r_xprt) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci return r_xprt->rx_xprt.address_strings[RPC_DISPLAY_ADDR]; 44362306a36Sopenharmony_ci} 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_cistatic inline const char * 44662306a36Sopenharmony_cirpcrdma_portstr(const struct rpcrdma_xprt *r_xprt) 44762306a36Sopenharmony_ci{ 44862306a36Sopenharmony_ci return r_xprt->rx_xprt.address_strings[RPC_DISPLAY_PORT]; 44962306a36Sopenharmony_ci} 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci/* Setting this to 0 ensures interoperability with early servers. 45262306a36Sopenharmony_ci * Setting this to 1 enhances certain unaligned read/write performance. 45362306a36Sopenharmony_ci * Default is 0, see sysctl entry and rpc_rdma.c rpcrdma_convert_iovs() */ 45462306a36Sopenharmony_ciextern int xprt_rdma_pad_optimize; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci/* This setting controls the hunt for a supported memory 45762306a36Sopenharmony_ci * registration strategy. 45862306a36Sopenharmony_ci */ 45962306a36Sopenharmony_ciextern unsigned int xprt_rdma_memreg_strategy; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci/* 46262306a36Sopenharmony_ci * Endpoint calls - xprtrdma/verbs.c 46362306a36Sopenharmony_ci */ 46462306a36Sopenharmony_civoid rpcrdma_force_disconnect(struct rpcrdma_ep *ep); 46562306a36Sopenharmony_civoid rpcrdma_flush_disconnect(struct rpcrdma_xprt *r_xprt, struct ib_wc *wc); 46662306a36Sopenharmony_ciint rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt); 46762306a36Sopenharmony_civoid rpcrdma_xprt_disconnect(struct rpcrdma_xprt *r_xprt); 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_civoid rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, int needed, bool temp); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci/* 47262306a36Sopenharmony_ci * Buffer calls - xprtrdma/verbs.c 47362306a36Sopenharmony_ci */ 47462306a36Sopenharmony_cistruct rpcrdma_req *rpcrdma_req_create(struct rpcrdma_xprt *r_xprt, 47562306a36Sopenharmony_ci size_t size); 47662306a36Sopenharmony_ciint rpcrdma_req_setup(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req); 47762306a36Sopenharmony_civoid rpcrdma_req_destroy(struct rpcrdma_req *req); 47862306a36Sopenharmony_ciint rpcrdma_buffer_create(struct rpcrdma_xprt *); 47962306a36Sopenharmony_civoid rpcrdma_buffer_destroy(struct rpcrdma_buffer *); 48062306a36Sopenharmony_cistruct rpcrdma_sendctx *rpcrdma_sendctx_get_locked(struct rpcrdma_xprt *r_xprt); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_cistruct rpcrdma_mr *rpcrdma_mr_get(struct rpcrdma_xprt *r_xprt); 48362306a36Sopenharmony_civoid rpcrdma_mrs_refresh(struct rpcrdma_xprt *r_xprt); 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_cistruct rpcrdma_req *rpcrdma_buffer_get(struct rpcrdma_buffer *); 48662306a36Sopenharmony_civoid rpcrdma_buffer_put(struct rpcrdma_buffer *buffers, 48762306a36Sopenharmony_ci struct rpcrdma_req *req); 48862306a36Sopenharmony_civoid rpcrdma_rep_put(struct rpcrdma_buffer *buf, struct rpcrdma_rep *rep); 48962306a36Sopenharmony_civoid rpcrdma_reply_put(struct rpcrdma_buffer *buffers, struct rpcrdma_req *req); 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_cibool rpcrdma_regbuf_realloc(struct rpcrdma_regbuf *rb, size_t size, 49262306a36Sopenharmony_ci gfp_t flags); 49362306a36Sopenharmony_cibool __rpcrdma_regbuf_dma_map(struct rpcrdma_xprt *r_xprt, 49462306a36Sopenharmony_ci struct rpcrdma_regbuf *rb); 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci/** 49762306a36Sopenharmony_ci * rpcrdma_regbuf_is_mapped - check if buffer is DMA mapped 49862306a36Sopenharmony_ci * 49962306a36Sopenharmony_ci * Returns true if the buffer is now mapped to rb->rg_device. 50062306a36Sopenharmony_ci */ 50162306a36Sopenharmony_cistatic inline bool rpcrdma_regbuf_is_mapped(struct rpcrdma_regbuf *rb) 50262306a36Sopenharmony_ci{ 50362306a36Sopenharmony_ci return rb->rg_device != NULL; 50462306a36Sopenharmony_ci} 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci/** 50762306a36Sopenharmony_ci * rpcrdma_regbuf_dma_map - DMA-map a regbuf 50862306a36Sopenharmony_ci * @r_xprt: controlling transport instance 50962306a36Sopenharmony_ci * @rb: regbuf to be mapped 51062306a36Sopenharmony_ci * 51162306a36Sopenharmony_ci * Returns true if the buffer is currently DMA mapped. 51262306a36Sopenharmony_ci */ 51362306a36Sopenharmony_cistatic inline bool rpcrdma_regbuf_dma_map(struct rpcrdma_xprt *r_xprt, 51462306a36Sopenharmony_ci struct rpcrdma_regbuf *rb) 51562306a36Sopenharmony_ci{ 51662306a36Sopenharmony_ci if (likely(rpcrdma_regbuf_is_mapped(rb))) 51762306a36Sopenharmony_ci return true; 51862306a36Sopenharmony_ci return __rpcrdma_regbuf_dma_map(r_xprt, rb); 51962306a36Sopenharmony_ci} 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci/* 52262306a36Sopenharmony_ci * Wrappers for chunk registration, shared by read/write chunk code. 52362306a36Sopenharmony_ci */ 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_cistatic inline enum dma_data_direction 52662306a36Sopenharmony_cirpcrdma_data_dir(bool writing) 52762306a36Sopenharmony_ci{ 52862306a36Sopenharmony_ci return writing ? DMA_FROM_DEVICE : DMA_TO_DEVICE; 52962306a36Sopenharmony_ci} 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci/* Memory registration calls xprtrdma/frwr_ops.c 53262306a36Sopenharmony_ci */ 53362306a36Sopenharmony_civoid frwr_reset(struct rpcrdma_req *req); 53462306a36Sopenharmony_ciint frwr_query_device(struct rpcrdma_ep *ep, const struct ib_device *device); 53562306a36Sopenharmony_ciint frwr_mr_init(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr *mr); 53662306a36Sopenharmony_civoid frwr_mr_release(struct rpcrdma_mr *mr); 53762306a36Sopenharmony_cistruct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt, 53862306a36Sopenharmony_ci struct rpcrdma_mr_seg *seg, 53962306a36Sopenharmony_ci int nsegs, bool writing, __be32 xid, 54062306a36Sopenharmony_ci struct rpcrdma_mr *mr); 54162306a36Sopenharmony_ciint frwr_send(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req); 54262306a36Sopenharmony_civoid frwr_reminv(struct rpcrdma_rep *rep, struct list_head *mrs); 54362306a36Sopenharmony_civoid frwr_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req); 54462306a36Sopenharmony_civoid frwr_unmap_async(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req); 54562306a36Sopenharmony_ciint frwr_wp_create(struct rpcrdma_xprt *r_xprt); 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci/* 54862306a36Sopenharmony_ci * RPC/RDMA protocol calls - xprtrdma/rpc_rdma.c 54962306a36Sopenharmony_ci */ 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_cienum rpcrdma_chunktype { 55262306a36Sopenharmony_ci rpcrdma_noch = 0, 55362306a36Sopenharmony_ci rpcrdma_noch_pullup, 55462306a36Sopenharmony_ci rpcrdma_noch_mapped, 55562306a36Sopenharmony_ci rpcrdma_readch, 55662306a36Sopenharmony_ci rpcrdma_areadch, 55762306a36Sopenharmony_ci rpcrdma_writech, 55862306a36Sopenharmony_ci rpcrdma_replych 55962306a36Sopenharmony_ci}; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ciint rpcrdma_prepare_send_sges(struct rpcrdma_xprt *r_xprt, 56262306a36Sopenharmony_ci struct rpcrdma_req *req, u32 hdrlen, 56362306a36Sopenharmony_ci struct xdr_buf *xdr, 56462306a36Sopenharmony_ci enum rpcrdma_chunktype rtype); 56562306a36Sopenharmony_civoid rpcrdma_sendctx_unmap(struct rpcrdma_sendctx *sc); 56662306a36Sopenharmony_ciint rpcrdma_marshal_req(struct rpcrdma_xprt *r_xprt, struct rpc_rqst *rqst); 56762306a36Sopenharmony_civoid rpcrdma_set_max_header_sizes(struct rpcrdma_ep *ep); 56862306a36Sopenharmony_civoid rpcrdma_reset_cwnd(struct rpcrdma_xprt *r_xprt); 56962306a36Sopenharmony_civoid rpcrdma_complete_rqst(struct rpcrdma_rep *rep); 57062306a36Sopenharmony_civoid rpcrdma_unpin_rqst(struct rpcrdma_rep *rep); 57162306a36Sopenharmony_civoid rpcrdma_reply_handler(struct rpcrdma_rep *rep); 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_cistatic inline void rpcrdma_set_xdrlen(struct xdr_buf *xdr, size_t len) 57462306a36Sopenharmony_ci{ 57562306a36Sopenharmony_ci xdr->head[0].iov_len = len; 57662306a36Sopenharmony_ci xdr->len = len; 57762306a36Sopenharmony_ci} 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci/* RPC/RDMA module init - xprtrdma/transport.c 58062306a36Sopenharmony_ci */ 58162306a36Sopenharmony_ciextern unsigned int xprt_rdma_max_inline_read; 58262306a36Sopenharmony_ciextern unsigned int xprt_rdma_max_inline_write; 58362306a36Sopenharmony_civoid xprt_rdma_format_addresses(struct rpc_xprt *xprt, struct sockaddr *sap); 58462306a36Sopenharmony_civoid xprt_rdma_free_addresses(struct rpc_xprt *xprt); 58562306a36Sopenharmony_civoid xprt_rdma_close(struct rpc_xprt *xprt); 58662306a36Sopenharmony_civoid xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq); 58762306a36Sopenharmony_ciint xprt_rdma_init(void); 58862306a36Sopenharmony_civoid xprt_rdma_cleanup(void); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci/* Backchannel calls - xprtrdma/backchannel.c 59162306a36Sopenharmony_ci */ 59262306a36Sopenharmony_ci#if defined(CONFIG_SUNRPC_BACKCHANNEL) 59362306a36Sopenharmony_ciint xprt_rdma_bc_setup(struct rpc_xprt *, unsigned int); 59462306a36Sopenharmony_cisize_t xprt_rdma_bc_maxpayload(struct rpc_xprt *); 59562306a36Sopenharmony_ciunsigned int xprt_rdma_bc_max_slots(struct rpc_xprt *); 59662306a36Sopenharmony_civoid rpcrdma_bc_receive_call(struct rpcrdma_xprt *, struct rpcrdma_rep *); 59762306a36Sopenharmony_ciint xprt_rdma_bc_send_reply(struct rpc_rqst *rqst); 59862306a36Sopenharmony_civoid xprt_rdma_bc_free_rqst(struct rpc_rqst *); 59962306a36Sopenharmony_civoid xprt_rdma_bc_destroy(struct rpc_xprt *, unsigned int); 60062306a36Sopenharmony_ci#endif /* CONFIG_SUNRPC_BACKCHANNEL */ 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ciextern struct xprt_class xprt_rdma_bc; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci#endif /* _LINUX_SUNRPC_XPRT_RDMA_H */ 605