| /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ | 
| /* | 
|  * Copyright (c) 2014-2017 Oracle.  All rights reserved. | 
|  * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved. | 
|  * | 
|  * This software is available to you under a choice of one of two | 
|  * licenses.  You may choose to be licensed under the terms of the GNU | 
|  * General Public License (GPL) Version 2, available from the file | 
|  * COPYING in the main directory of this source tree, or the BSD-type | 
|  * license below: | 
|  * | 
|  * Redistribution and use in source and binary forms, with or without | 
|  * modification, are permitted provided that the following conditions | 
|  * are met: | 
|  * | 
|  *      Redistributions of source code must retain the above copyright | 
|  *      notice, this list of conditions and the following disclaimer. | 
|  * | 
|  *      Redistributions in binary form must reproduce the above | 
|  *      copyright notice, this list of conditions and the following | 
|  *      disclaimer in the documentation and/or other materials provided | 
|  *      with the distribution. | 
|  * | 
|  *      Neither the name of the Network Appliance, Inc. nor the names of | 
|  *      its contributors may be used to endorse or promote products | 
|  *      derived from this software without specific prior written | 
|  *      permission. | 
|  * | 
|  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
|  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
|  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
|  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
|  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
|  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
|  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
|  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
|  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
|  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  */ | 
|   | 
| #ifndef _LINUX_SUNRPC_XPRT_RDMA_H | 
| #define _LINUX_SUNRPC_XPRT_RDMA_H | 
|   | 
| #include <linux/wait.h>         /* wait_queue_head_t, etc */ | 
| #include <linux/spinlock.h>         /* spinlock_t, etc */ | 
| #include <linux/atomic.h>        /* atomic_t, etc */ | 
| #include <linux/kref.h>            /* struct kref */ | 
| #include <linux/workqueue.h>        /* struct work_struct */ | 
| #include <linux/llist.h> | 
|   | 
| #include <rdma/rdma_cm.h>        /* RDMA connection api */ | 
| #include <rdma/ib_verbs.h>        /* RDMA verbs api */ | 
|   | 
| #include <linux/sunrpc/clnt.h>         /* rpc_xprt */ | 
| #include <linux/sunrpc/rpc_rdma.h>     /* RPC/RDMA protocol */ | 
| #include <linux/sunrpc/xprtrdma.h>     /* xprt parameters */ | 
|   | 
| #define RDMA_RESOLVE_TIMEOUT    (5000)    /* 5 seconds */ | 
| #define RDMA_CONNECT_RETRY_MAX    (2)    /* retries if no listener backlog */ | 
|   | 
| #define RPCRDMA_BIND_TO        (60U * HZ) | 
| #define RPCRDMA_INIT_REEST_TO    (5U * HZ) | 
| #define RPCRDMA_MAX_REEST_TO    (30U * HZ) | 
| #define RPCRDMA_IDLE_DISC_TO    (5U * 60 * HZ) | 
|   | 
| /* | 
|  * RDMA Endpoint -- connection endpoint details | 
|  */ | 
| struct rpcrdma_ep { | 
|     struct kref        re_kref; | 
|     struct rdma_cm_id     *re_id; | 
|     struct ib_pd        *re_pd; | 
|     unsigned int        re_max_rdma_segs; | 
|     unsigned int        re_max_fr_depth; | 
|     bool            re_implicit_roundup; | 
|     enum ib_mr_type        re_mrtype; | 
|     struct completion    re_done; | 
|     unsigned int        re_send_count; | 
|     unsigned int        re_send_batch; | 
|     unsigned int        re_max_inline_send; | 
|     unsigned int        re_max_inline_recv; | 
|     int            re_async_rc; | 
|     int            re_connect_status; | 
|     atomic_t        re_force_disconnect; | 
|     struct ib_qp_init_attr    re_attr; | 
|     wait_queue_head_t       re_connect_wait; | 
|     struct rpc_xprt        *re_xprt; | 
|     struct rpcrdma_connect_private | 
|                 re_cm_private; | 
|     struct rdma_conn_param    re_remote_cma; | 
|     int            re_receive_count; | 
|     unsigned int        re_max_requests; /* depends on device */ | 
|     unsigned int        re_inline_send;    /* negotiated */ | 
|     unsigned int        re_inline_recv;    /* negotiated */ | 
| }; | 
|   | 
| /* Pre-allocate extra Work Requests for handling backward receives | 
|  * and sends. This is a fixed value because the Work Queues are | 
|  * allocated when the forward channel is set up, long before the | 
|  * backchannel is provisioned. This value is two times | 
|  * NFS4_DEF_CB_SLOT_TABLE_SIZE. | 
|  */ | 
| #if defined(CONFIG_SUNRPC_BACKCHANNEL) | 
| #define RPCRDMA_BACKWARD_WRS (32) | 
| #else | 
| #define RPCRDMA_BACKWARD_WRS (0) | 
| #endif | 
|   | 
| /* Registered buffer -- registered kmalloc'd memory for RDMA SEND/RECV | 
|  */ | 
|   | 
| struct rpcrdma_regbuf { | 
|     struct ib_sge        rg_iov; | 
|     struct ib_device    *rg_device; | 
|     enum dma_data_direction    rg_direction; | 
|     void            *rg_data; | 
| }; | 
|   | 
| static inline u64 rdmab_addr(struct rpcrdma_regbuf *rb) | 
| { | 
|     return rb->rg_iov.addr; | 
| } | 
|   | 
| static inline u32 rdmab_length(struct rpcrdma_regbuf *rb) | 
| { | 
|     return rb->rg_iov.length; | 
| } | 
|   | 
| static inline u32 rdmab_lkey(struct rpcrdma_regbuf *rb) | 
| { | 
|     return rb->rg_iov.lkey; | 
| } | 
|   | 
| static inline struct ib_device *rdmab_device(struct rpcrdma_regbuf *rb) | 
| { | 
|     return rb->rg_device; | 
| } | 
|   | 
| static inline void *rdmab_data(const struct rpcrdma_regbuf *rb) | 
| { | 
|     return rb->rg_data; | 
| } | 
|   | 
| #define RPCRDMA_DEF_GFP        (GFP_NOIO | __GFP_NOWARN) | 
|   | 
| /* To ensure a transport can always make forward progress, | 
|  * the number of RDMA segments allowed in header chunk lists | 
|  * is capped at 16. This prevents less-capable devices from | 
|  * overrunning the Send buffer while building chunk lists. | 
|  * | 
|  * Elements of the Read list take up more room than the | 
|  * Write list or Reply chunk. 16 read segments means the | 
|  * chunk lists cannot consume more than | 
|  * | 
|  * ((16 + 2) * read segment size) + 1 XDR words, | 
|  * | 
|  * or about 400 bytes. The fixed part of the header is | 
|  * another 24 bytes. Thus when the inline threshold is | 
|  * 1024 bytes, at least 600 bytes are available for RPC | 
|  * message bodies. | 
|  */ | 
| enum { | 
|     RPCRDMA_MAX_HDR_SEGS = 16, | 
| }; | 
|   | 
| /* | 
|  * struct rpcrdma_rep -- this structure encapsulates state required | 
|  * to receive and complete an RPC Reply, asychronously. It needs | 
|  * several pieces of state: | 
|  * | 
|  *   o receive buffer and ib_sge (donated to provider) | 
|  *   o status of receive (success or not, length, inv rkey) | 
|  *   o bookkeeping state to get run by reply handler (XDR stream) | 
|  * | 
|  * These structures are allocated during transport initialization. | 
|  * N of these are associated with a transport instance, managed by | 
|  * struct rpcrdma_buffer. N is the max number of outstanding RPCs. | 
|  */ | 
|   | 
| struct rpcrdma_rep { | 
|     struct ib_cqe        rr_cqe; | 
|     __be32            rr_xid; | 
|     __be32            rr_vers; | 
|     __be32            rr_proc; | 
|     int            rr_wc_flags; | 
|     u32            rr_inv_rkey; | 
|     bool            rr_temp; | 
|     struct rpcrdma_regbuf    *rr_rdmabuf; | 
|     struct rpcrdma_xprt    *rr_rxprt; | 
|     struct rpc_rqst        *rr_rqst; | 
|     struct xdr_buf        rr_hdrbuf; | 
|     struct xdr_stream    rr_stream; | 
|     struct llist_node    rr_node; | 
|     struct ib_recv_wr    rr_recv_wr; | 
|     struct list_head    rr_all; | 
| }; | 
|   | 
| /* To reduce the rate at which a transport invokes ib_post_recv | 
|  * (and thus the hardware doorbell rate), xprtrdma posts Receive | 
|  * WRs in batches. | 
|  * | 
|  * Setting this to zero disables Receive post batching. | 
|  */ | 
| enum { | 
|     RPCRDMA_MAX_RECV_BATCH = 7, | 
| }; | 
|   | 
| /* struct rpcrdma_sendctx - DMA mapped SGEs to unmap after Send completes | 
|  */ | 
| struct rpcrdma_req; | 
| struct rpcrdma_sendctx { | 
|     struct ib_cqe        sc_cqe; | 
|     struct rpcrdma_req    *sc_req; | 
|     unsigned int        sc_unmap_count; | 
|     struct ib_sge        sc_sges[]; | 
| }; | 
|   | 
| /* | 
|  * struct rpcrdma_mr - external memory region metadata | 
|  * | 
|  * An external memory region is any buffer or page that is registered | 
|  * on the fly (ie, not pre-registered). | 
|  */ | 
| struct rpcrdma_frwr { | 
|     struct ib_mr            *fr_mr; | 
|     struct ib_cqe            fr_cqe; | 
|     struct completion        fr_linv_done; | 
|     union { | 
|         struct ib_reg_wr    fr_regwr; | 
|         struct ib_send_wr    fr_invwr; | 
|     }; | 
| }; | 
|   | 
| struct rpcrdma_req; | 
| struct rpcrdma_mr { | 
|     struct list_head    mr_list; | 
|     struct rpcrdma_req    *mr_req; | 
|     struct scatterlist    *mr_sg; | 
|     int            mr_nents; | 
|     enum dma_data_direction    mr_dir; | 
|     struct rpcrdma_frwr    frwr; | 
|     struct rpcrdma_xprt    *mr_xprt; | 
|     u32            mr_handle; | 
|     u32            mr_length; | 
|     u64            mr_offset; | 
|     struct list_head    mr_all; | 
| }; | 
|   | 
| /* | 
|  * struct rpcrdma_req -- structure central to the request/reply sequence. | 
|  * | 
|  * N of these are associated with a transport instance, and stored in | 
|  * struct rpcrdma_buffer. N is the max number of outstanding requests. | 
|  * | 
|  * It includes pre-registered buffer memory for send AND recv. | 
|  * The recv buffer, however, is not owned by this structure, and | 
|  * is "donated" to the hardware when a recv is posted. When a | 
|  * reply is handled, the recv buffer used is given back to the | 
|  * struct rpcrdma_req associated with the request. | 
|  * | 
|  * In addition to the basic memory, this structure includes an array | 
|  * of iovs for send operations. The reason is that the iovs passed to | 
|  * ib_post_{send,recv} must not be modified until the work request | 
|  * completes. | 
|  */ | 
|   | 
| /* Maximum number of page-sized "segments" per chunk list to be | 
|  * registered or invalidated. Must handle a Reply chunk: | 
|  */ | 
| enum { | 
|     RPCRDMA_MAX_IOV_SEGS    = 3, | 
|     RPCRDMA_MAX_DATA_SEGS    = ((1 * 1024 * 1024) / PAGE_SIZE) + 1, | 
|     RPCRDMA_MAX_SEGS    = RPCRDMA_MAX_DATA_SEGS + | 
|                   RPCRDMA_MAX_IOV_SEGS, | 
| }; | 
|   | 
| struct rpcrdma_mr_seg {        /* chunk descriptors */ | 
|     u32        mr_len;        /* length of chunk or segment */ | 
|     struct page    *mr_page;    /* owning page, if any */ | 
|     char        *mr_offset;    /* kva if no page, else offset */ | 
| }; | 
|   | 
| /* The Send SGE array is provisioned to send a maximum size | 
|  * inline request: | 
|  * - RPC-over-RDMA header | 
|  * - xdr_buf head iovec | 
|  * - RPCRDMA_MAX_INLINE bytes, in pages | 
|  * - xdr_buf tail iovec | 
|  * | 
|  * The actual number of array elements consumed by each RPC | 
|  * depends on the device's max_sge limit. | 
|  */ | 
| enum { | 
|     RPCRDMA_MIN_SEND_SGES = 3, | 
|     RPCRDMA_MAX_PAGE_SGES = RPCRDMA_MAX_INLINE >> PAGE_SHIFT, | 
|     RPCRDMA_MAX_SEND_SGES = 1 + 1 + RPCRDMA_MAX_PAGE_SGES + 1, | 
| }; | 
|   | 
| struct rpcrdma_buffer; | 
| struct rpcrdma_req { | 
|     struct list_head    rl_list; | 
|     struct rpc_rqst        rl_slot; | 
|     struct rpcrdma_rep    *rl_reply; | 
|     struct xdr_stream    rl_stream; | 
|     struct xdr_buf        rl_hdrbuf; | 
|     struct ib_send_wr    rl_wr; | 
|     struct rpcrdma_sendctx    *rl_sendctx; | 
|     struct rpcrdma_regbuf    *rl_rdmabuf;    /* xprt header */ | 
|     struct rpcrdma_regbuf    *rl_sendbuf;    /* rq_snd_buf */ | 
|     struct rpcrdma_regbuf    *rl_recvbuf;    /* rq_rcv_buf */ | 
|   | 
|     struct list_head    rl_all; | 
|     struct kref        rl_kref; | 
|   | 
|     struct list_head    rl_free_mrs; | 
|     struct list_head    rl_registered; | 
|     struct rpcrdma_mr_seg    rl_segments[RPCRDMA_MAX_SEGS]; | 
| }; | 
|   | 
| static inline struct rpcrdma_req * | 
| rpcr_to_rdmar(const struct rpc_rqst *rqst) | 
| { | 
|     return container_of(rqst, struct rpcrdma_req, rl_slot); | 
| } | 
|   | 
| static inline void | 
| rpcrdma_mr_push(struct rpcrdma_mr *mr, struct list_head *list) | 
| { | 
|     list_add(&mr->mr_list, list); | 
| } | 
|   | 
| static inline struct rpcrdma_mr * | 
| rpcrdma_mr_pop(struct list_head *list) | 
| { | 
|     struct rpcrdma_mr *mr; | 
|   | 
|     mr = list_first_entry_or_null(list, struct rpcrdma_mr, mr_list); | 
|     if (mr) | 
|         list_del_init(&mr->mr_list); | 
|     return mr; | 
| } | 
|   | 
| /* | 
|  * struct rpcrdma_buffer -- holds list/queue of pre-registered memory for | 
|  * inline requests/replies, and client/server credits. | 
|  * | 
|  * One of these is associated with a transport instance | 
|  */ | 
| struct rpcrdma_buffer { | 
|     spinlock_t        rb_lock; | 
|     struct list_head    rb_send_bufs; | 
|     struct list_head    rb_mrs; | 
|   | 
|     unsigned long        rb_sc_head; | 
|     unsigned long        rb_sc_tail; | 
|     unsigned long        rb_sc_last; | 
|     struct rpcrdma_sendctx    **rb_sc_ctxs; | 
|   | 
|     struct list_head    rb_allreqs; | 
|     struct list_head    rb_all_mrs; | 
|     struct list_head    rb_all_reps; | 
|   | 
|     struct llist_head    rb_free_reps; | 
|   | 
|     __be32            rb_max_requests; | 
|     u32            rb_credits;    /* most recent credit grant */ | 
|   | 
|     u32            rb_bc_srv_max_requests; | 
|     u32            rb_bc_max_requests; | 
|   | 
|     struct work_struct    rb_refresh_worker; | 
| }; | 
|   | 
| /* | 
|  * Statistics for RPCRDMA | 
|  */ | 
| struct rpcrdma_stats { | 
|     /* accessed when sending a call */ | 
|     unsigned long        read_chunk_count; | 
|     unsigned long        write_chunk_count; | 
|     unsigned long        reply_chunk_count; | 
|     unsigned long long    total_rdma_request; | 
|   | 
|     /* rarely accessed error counters */ | 
|     unsigned long long    pullup_copy_count; | 
|     unsigned long        hardway_register_count; | 
|     unsigned long        failed_marshal_count; | 
|     unsigned long        bad_reply_count; | 
|     unsigned long        mrs_recycled; | 
|     unsigned long        mrs_orphaned; | 
|     unsigned long        mrs_allocated; | 
|     unsigned long        empty_sendctx_q; | 
|   | 
|     /* accessed when receiving a reply */ | 
|     unsigned long long    total_rdma_reply; | 
|     unsigned long long    fixup_copy_count; | 
|     unsigned long        reply_waits_for_send; | 
|     unsigned long        local_inv_needed; | 
|     unsigned long        nomsg_call_count; | 
|     unsigned long        bcall_count; | 
| }; | 
|   | 
| /* | 
|  * RPCRDMA transport -- encapsulates the structures above for | 
|  * integration with RPC. | 
|  * | 
|  * The contained structures are embedded, not pointers, | 
|  * for convenience. This structure need not be visible externally. | 
|  * | 
|  * It is allocated and initialized during mount, and released | 
|  * during unmount. | 
|  */ | 
| struct rpcrdma_xprt { | 
|     struct rpc_xprt        rx_xprt; | 
|     struct rpcrdma_ep    *rx_ep; | 
|     struct rpcrdma_buffer    rx_buf; | 
|     struct delayed_work    rx_connect_worker; | 
|     struct rpc_timeout    rx_timeout; | 
|     struct rpcrdma_stats    rx_stats; | 
| }; | 
|   | 
| #define rpcx_to_rdmax(x) container_of(x, struct rpcrdma_xprt, rx_xprt) | 
|   | 
| static inline const char * | 
| rpcrdma_addrstr(const struct rpcrdma_xprt *r_xprt) | 
| { | 
|     return r_xprt->rx_xprt.address_strings[RPC_DISPLAY_ADDR]; | 
| } | 
|   | 
| static inline const char * | 
| rpcrdma_portstr(const struct rpcrdma_xprt *r_xprt) | 
| { | 
|     return r_xprt->rx_xprt.address_strings[RPC_DISPLAY_PORT]; | 
| } | 
|   | 
| /* Setting this to 0 ensures interoperability with early servers. | 
|  * Setting this to 1 enhances certain unaligned read/write performance. | 
|  * Default is 0, see sysctl entry and rpc_rdma.c rpcrdma_convert_iovs() */ | 
| extern int xprt_rdma_pad_optimize; | 
|   | 
| /* This setting controls the hunt for a supported memory | 
|  * registration strategy. | 
|  */ | 
| extern unsigned int xprt_rdma_memreg_strategy; | 
|   | 
| /* | 
|  * Endpoint calls - xprtrdma/verbs.c | 
|  */ | 
| void rpcrdma_flush_disconnect(struct rpcrdma_xprt *r_xprt, struct ib_wc *wc); | 
| int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt); | 
| void rpcrdma_xprt_disconnect(struct rpcrdma_xprt *r_xprt); | 
|   | 
| int rpcrdma_post_sends(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req); | 
| void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, int needed, bool temp); | 
|   | 
| /* | 
|  * Buffer calls - xprtrdma/verbs.c | 
|  */ | 
| struct rpcrdma_req *rpcrdma_req_create(struct rpcrdma_xprt *r_xprt, size_t size, | 
|                        gfp_t flags); | 
| int rpcrdma_req_setup(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req); | 
| void rpcrdma_req_destroy(struct rpcrdma_req *req); | 
| int rpcrdma_buffer_create(struct rpcrdma_xprt *); | 
| void rpcrdma_buffer_destroy(struct rpcrdma_buffer *); | 
| struct rpcrdma_sendctx *rpcrdma_sendctx_get_locked(struct rpcrdma_xprt *r_xprt); | 
|   | 
| struct rpcrdma_mr *rpcrdma_mr_get(struct rpcrdma_xprt *r_xprt); | 
| void rpcrdma_mr_put(struct rpcrdma_mr *mr); | 
| void rpcrdma_mrs_refresh(struct rpcrdma_xprt *r_xprt); | 
|   | 
| struct rpcrdma_req *rpcrdma_buffer_get(struct rpcrdma_buffer *); | 
| void rpcrdma_buffer_put(struct rpcrdma_buffer *buffers, | 
|             struct rpcrdma_req *req); | 
| void rpcrdma_reply_put(struct rpcrdma_buffer *buffers, struct rpcrdma_req *req); | 
| void rpcrdma_recv_buffer_put(struct rpcrdma_rep *); | 
|   | 
| bool rpcrdma_regbuf_realloc(struct rpcrdma_regbuf *rb, size_t size, | 
|                 gfp_t flags); | 
| bool __rpcrdma_regbuf_dma_map(struct rpcrdma_xprt *r_xprt, | 
|                   struct rpcrdma_regbuf *rb); | 
|   | 
| /** | 
|  * rpcrdma_regbuf_is_mapped - check if buffer is DMA mapped | 
|  * | 
|  * Returns true if the buffer is now mapped to rb->rg_device. | 
|  */ | 
| static inline bool rpcrdma_regbuf_is_mapped(struct rpcrdma_regbuf *rb) | 
| { | 
|     return rb->rg_device != NULL; | 
| } | 
|   | 
| /** | 
|  * rpcrdma_regbuf_dma_map - DMA-map a regbuf | 
|  * @r_xprt: controlling transport instance | 
|  * @rb: regbuf to be mapped | 
|  * | 
|  * Returns true if the buffer is currently DMA mapped. | 
|  */ | 
| static inline bool rpcrdma_regbuf_dma_map(struct rpcrdma_xprt *r_xprt, | 
|                       struct rpcrdma_regbuf *rb) | 
| { | 
|     if (likely(rpcrdma_regbuf_is_mapped(rb))) | 
|         return true; | 
|     return __rpcrdma_regbuf_dma_map(r_xprt, rb); | 
| } | 
|   | 
| /* | 
|  * Wrappers for chunk registration, shared by read/write chunk code. | 
|  */ | 
|   | 
| static inline enum dma_data_direction | 
| rpcrdma_data_dir(bool writing) | 
| { | 
|     return writing ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | 
| } | 
|   | 
| /* Memory registration calls xprtrdma/frwr_ops.c | 
|  */ | 
| void frwr_reset(struct rpcrdma_req *req); | 
| int frwr_query_device(struct rpcrdma_ep *ep, const struct ib_device *device); | 
| int frwr_mr_init(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr *mr); | 
| void frwr_release_mr(struct rpcrdma_mr *mr); | 
| struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt, | 
|                 struct rpcrdma_mr_seg *seg, | 
|                 int nsegs, bool writing, __be32 xid, | 
|                 struct rpcrdma_mr *mr); | 
| int frwr_send(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req); | 
| void frwr_reminv(struct rpcrdma_rep *rep, struct list_head *mrs); | 
| void frwr_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req); | 
| void frwr_unmap_async(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req); | 
|   | 
| /* | 
|  * RPC/RDMA protocol calls - xprtrdma/rpc_rdma.c | 
|  */ | 
|   | 
| enum rpcrdma_chunktype { | 
|     rpcrdma_noch = 0, | 
|     rpcrdma_noch_pullup, | 
|     rpcrdma_noch_mapped, | 
|     rpcrdma_readch, | 
|     rpcrdma_areadch, | 
|     rpcrdma_writech, | 
|     rpcrdma_replych | 
| }; | 
|   | 
| int rpcrdma_prepare_send_sges(struct rpcrdma_xprt *r_xprt, | 
|                   struct rpcrdma_req *req, u32 hdrlen, | 
|                   struct xdr_buf *xdr, | 
|                   enum rpcrdma_chunktype rtype); | 
| void rpcrdma_sendctx_unmap(struct rpcrdma_sendctx *sc); | 
| int rpcrdma_marshal_req(struct rpcrdma_xprt *r_xprt, struct rpc_rqst *rqst); | 
| void rpcrdma_set_max_header_sizes(struct rpcrdma_ep *ep); | 
| void rpcrdma_reset_cwnd(struct rpcrdma_xprt *r_xprt); | 
| void rpcrdma_complete_rqst(struct rpcrdma_rep *rep); | 
| void rpcrdma_reply_handler(struct rpcrdma_rep *rep); | 
|   | 
| static inline void rpcrdma_set_xdrlen(struct xdr_buf *xdr, size_t len) | 
| { | 
|     xdr->head[0].iov_len = len; | 
|     xdr->len = len; | 
| } | 
|   | 
| /* RPC/RDMA module init - xprtrdma/transport.c | 
|  */ | 
| extern unsigned int xprt_rdma_max_inline_read; | 
| extern unsigned int xprt_rdma_max_inline_write; | 
| void xprt_rdma_format_addresses(struct rpc_xprt *xprt, struct sockaddr *sap); | 
| void xprt_rdma_free_addresses(struct rpc_xprt *xprt); | 
| void xprt_rdma_close(struct rpc_xprt *xprt); | 
| void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq); | 
| int xprt_rdma_init(void); | 
| void xprt_rdma_cleanup(void); | 
|   | 
| /* Backchannel calls - xprtrdma/backchannel.c | 
|  */ | 
| #if defined(CONFIG_SUNRPC_BACKCHANNEL) | 
| int xprt_rdma_bc_setup(struct rpc_xprt *, unsigned int); | 
| size_t xprt_rdma_bc_maxpayload(struct rpc_xprt *); | 
| unsigned int xprt_rdma_bc_max_slots(struct rpc_xprt *); | 
| int rpcrdma_bc_post_recv(struct rpcrdma_xprt *, unsigned int); | 
| void rpcrdma_bc_receive_call(struct rpcrdma_xprt *, struct rpcrdma_rep *); | 
| int xprt_rdma_bc_send_reply(struct rpc_rqst *rqst); | 
| void xprt_rdma_bc_free_rqst(struct rpc_rqst *); | 
| void xprt_rdma_bc_destroy(struct rpc_xprt *, unsigned int); | 
| #endif    /* CONFIG_SUNRPC_BACKCHANNEL */ | 
|   | 
| extern struct xprt_class xprt_rdma_bc; | 
|   | 
| #endif                /* _LINUX_SUNRPC_XPRT_RDMA_H */ |