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/* 4362306a36Sopenharmony_ci * transport.c 4462306a36Sopenharmony_ci * 4562306a36Sopenharmony_ci * This file contains the top-level implementation of an RPC RDMA 4662306a36Sopenharmony_ci * transport. 4762306a36Sopenharmony_ci * 4862306a36Sopenharmony_ci * Naming convention: functions beginning with xprt_ are part of the 4962306a36Sopenharmony_ci * transport switch. All others are RPC RDMA internal. 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#include <linux/module.h> 5362306a36Sopenharmony_ci#include <linux/slab.h> 5462306a36Sopenharmony_ci#include <linux/seq_file.h> 5562306a36Sopenharmony_ci#include <linux/smp.h> 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#include <linux/sunrpc/addr.h> 5862306a36Sopenharmony_ci#include <linux/sunrpc/svc_rdma.h> 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#include "xprt_rdma.h" 6162306a36Sopenharmony_ci#include <trace/events/rpcrdma.h> 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/* 6462306a36Sopenharmony_ci * tunables 6562306a36Sopenharmony_ci */ 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic unsigned int xprt_rdma_slot_table_entries = RPCRDMA_DEF_SLOT_TABLE; 6862306a36Sopenharmony_ciunsigned int xprt_rdma_max_inline_read = RPCRDMA_DEF_INLINE; 6962306a36Sopenharmony_ciunsigned int xprt_rdma_max_inline_write = RPCRDMA_DEF_INLINE; 7062306a36Sopenharmony_ciunsigned int xprt_rdma_memreg_strategy = RPCRDMA_FRWR; 7162306a36Sopenharmony_ciint xprt_rdma_pad_optimize; 7262306a36Sopenharmony_cistatic struct xprt_class xprt_rdma; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_SUNRPC_DEBUG) 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic unsigned int min_slot_table_size = RPCRDMA_MIN_SLOT_TABLE; 7762306a36Sopenharmony_cistatic unsigned int max_slot_table_size = RPCRDMA_MAX_SLOT_TABLE; 7862306a36Sopenharmony_cistatic unsigned int min_inline_size = RPCRDMA_MIN_INLINE; 7962306a36Sopenharmony_cistatic unsigned int max_inline_size = RPCRDMA_MAX_INLINE; 8062306a36Sopenharmony_cistatic unsigned int max_padding = PAGE_SIZE; 8162306a36Sopenharmony_cistatic unsigned int min_memreg = RPCRDMA_BOUNCEBUFFERS; 8262306a36Sopenharmony_cistatic unsigned int max_memreg = RPCRDMA_LAST - 1; 8362306a36Sopenharmony_cistatic unsigned int dummy; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic struct ctl_table_header *sunrpc_table_header; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic struct ctl_table xr_tunables_table[] = { 8862306a36Sopenharmony_ci { 8962306a36Sopenharmony_ci .procname = "rdma_slot_table_entries", 9062306a36Sopenharmony_ci .data = &xprt_rdma_slot_table_entries, 9162306a36Sopenharmony_ci .maxlen = sizeof(unsigned int), 9262306a36Sopenharmony_ci .mode = 0644, 9362306a36Sopenharmony_ci .proc_handler = proc_dointvec_minmax, 9462306a36Sopenharmony_ci .extra1 = &min_slot_table_size, 9562306a36Sopenharmony_ci .extra2 = &max_slot_table_size 9662306a36Sopenharmony_ci }, 9762306a36Sopenharmony_ci { 9862306a36Sopenharmony_ci .procname = "rdma_max_inline_read", 9962306a36Sopenharmony_ci .data = &xprt_rdma_max_inline_read, 10062306a36Sopenharmony_ci .maxlen = sizeof(unsigned int), 10162306a36Sopenharmony_ci .mode = 0644, 10262306a36Sopenharmony_ci .proc_handler = proc_dointvec_minmax, 10362306a36Sopenharmony_ci .extra1 = &min_inline_size, 10462306a36Sopenharmony_ci .extra2 = &max_inline_size, 10562306a36Sopenharmony_ci }, 10662306a36Sopenharmony_ci { 10762306a36Sopenharmony_ci .procname = "rdma_max_inline_write", 10862306a36Sopenharmony_ci .data = &xprt_rdma_max_inline_write, 10962306a36Sopenharmony_ci .maxlen = sizeof(unsigned int), 11062306a36Sopenharmony_ci .mode = 0644, 11162306a36Sopenharmony_ci .proc_handler = proc_dointvec_minmax, 11262306a36Sopenharmony_ci .extra1 = &min_inline_size, 11362306a36Sopenharmony_ci .extra2 = &max_inline_size, 11462306a36Sopenharmony_ci }, 11562306a36Sopenharmony_ci { 11662306a36Sopenharmony_ci .procname = "rdma_inline_write_padding", 11762306a36Sopenharmony_ci .data = &dummy, 11862306a36Sopenharmony_ci .maxlen = sizeof(unsigned int), 11962306a36Sopenharmony_ci .mode = 0644, 12062306a36Sopenharmony_ci .proc_handler = proc_dointvec_minmax, 12162306a36Sopenharmony_ci .extra1 = SYSCTL_ZERO, 12262306a36Sopenharmony_ci .extra2 = &max_padding, 12362306a36Sopenharmony_ci }, 12462306a36Sopenharmony_ci { 12562306a36Sopenharmony_ci .procname = "rdma_memreg_strategy", 12662306a36Sopenharmony_ci .data = &xprt_rdma_memreg_strategy, 12762306a36Sopenharmony_ci .maxlen = sizeof(unsigned int), 12862306a36Sopenharmony_ci .mode = 0644, 12962306a36Sopenharmony_ci .proc_handler = proc_dointvec_minmax, 13062306a36Sopenharmony_ci .extra1 = &min_memreg, 13162306a36Sopenharmony_ci .extra2 = &max_memreg, 13262306a36Sopenharmony_ci }, 13362306a36Sopenharmony_ci { 13462306a36Sopenharmony_ci .procname = "rdma_pad_optimize", 13562306a36Sopenharmony_ci .data = &xprt_rdma_pad_optimize, 13662306a36Sopenharmony_ci .maxlen = sizeof(unsigned int), 13762306a36Sopenharmony_ci .mode = 0644, 13862306a36Sopenharmony_ci .proc_handler = proc_dointvec, 13962306a36Sopenharmony_ci }, 14062306a36Sopenharmony_ci { }, 14162306a36Sopenharmony_ci}; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci#endif 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cistatic const struct rpc_xprt_ops xprt_rdma_procs; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic void 14862306a36Sopenharmony_cixprt_rdma_format_addresses4(struct rpc_xprt *xprt, struct sockaddr *sap) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci struct sockaddr_in *sin = (struct sockaddr_in *)sap; 15162306a36Sopenharmony_ci char buf[20]; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "%08x", ntohl(sin->sin_addr.s_addr)); 15462306a36Sopenharmony_ci xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = kstrdup(buf, GFP_KERNEL); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci xprt->address_strings[RPC_DISPLAY_NETID] = RPCBIND_NETID_RDMA; 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic void 16062306a36Sopenharmony_cixprt_rdma_format_addresses6(struct rpc_xprt *xprt, struct sockaddr *sap) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; 16362306a36Sopenharmony_ci char buf[40]; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "%pi6", &sin6->sin6_addr); 16662306a36Sopenharmony_ci xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = kstrdup(buf, GFP_KERNEL); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci xprt->address_strings[RPC_DISPLAY_NETID] = RPCBIND_NETID_RDMA6; 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_civoid 17262306a36Sopenharmony_cixprt_rdma_format_addresses(struct rpc_xprt *xprt, struct sockaddr *sap) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci char buf[128]; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci switch (sap->sa_family) { 17762306a36Sopenharmony_ci case AF_INET: 17862306a36Sopenharmony_ci xprt_rdma_format_addresses4(xprt, sap); 17962306a36Sopenharmony_ci break; 18062306a36Sopenharmony_ci case AF_INET6: 18162306a36Sopenharmony_ci xprt_rdma_format_addresses6(xprt, sap); 18262306a36Sopenharmony_ci break; 18362306a36Sopenharmony_ci default: 18462306a36Sopenharmony_ci pr_err("rpcrdma: Unrecognized address family\n"); 18562306a36Sopenharmony_ci return; 18662306a36Sopenharmony_ci } 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci (void)rpc_ntop(sap, buf, sizeof(buf)); 18962306a36Sopenharmony_ci xprt->address_strings[RPC_DISPLAY_ADDR] = kstrdup(buf, GFP_KERNEL); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "%u", rpc_get_port(sap)); 19262306a36Sopenharmony_ci xprt->address_strings[RPC_DISPLAY_PORT] = kstrdup(buf, GFP_KERNEL); 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "%4hx", rpc_get_port(sap)); 19562306a36Sopenharmony_ci xprt->address_strings[RPC_DISPLAY_HEX_PORT] = kstrdup(buf, GFP_KERNEL); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci xprt->address_strings[RPC_DISPLAY_PROTO] = "rdma"; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_civoid 20162306a36Sopenharmony_cixprt_rdma_free_addresses(struct rpc_xprt *xprt) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci unsigned int i; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci for (i = 0; i < RPC_DISPLAY_MAX; i++) 20662306a36Sopenharmony_ci switch (i) { 20762306a36Sopenharmony_ci case RPC_DISPLAY_PROTO: 20862306a36Sopenharmony_ci case RPC_DISPLAY_NETID: 20962306a36Sopenharmony_ci continue; 21062306a36Sopenharmony_ci default: 21162306a36Sopenharmony_ci kfree(xprt->address_strings[i]); 21262306a36Sopenharmony_ci } 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci/** 21662306a36Sopenharmony_ci * xprt_rdma_connect_worker - establish connection in the background 21762306a36Sopenharmony_ci * @work: worker thread context 21862306a36Sopenharmony_ci * 21962306a36Sopenharmony_ci * Requester holds the xprt's send lock to prevent activity on this 22062306a36Sopenharmony_ci * transport while a fresh connection is being established. RPC tasks 22162306a36Sopenharmony_ci * sleep on the xprt's pending queue waiting for connect to complete. 22262306a36Sopenharmony_ci */ 22362306a36Sopenharmony_cistatic void 22462306a36Sopenharmony_cixprt_rdma_connect_worker(struct work_struct *work) 22562306a36Sopenharmony_ci{ 22662306a36Sopenharmony_ci struct rpcrdma_xprt *r_xprt = container_of(work, struct rpcrdma_xprt, 22762306a36Sopenharmony_ci rx_connect_worker.work); 22862306a36Sopenharmony_ci struct rpc_xprt *xprt = &r_xprt->rx_xprt; 22962306a36Sopenharmony_ci unsigned int pflags = current->flags; 23062306a36Sopenharmony_ci int rc; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci if (atomic_read(&xprt->swapper)) 23362306a36Sopenharmony_ci current->flags |= PF_MEMALLOC; 23462306a36Sopenharmony_ci rc = rpcrdma_xprt_connect(r_xprt); 23562306a36Sopenharmony_ci xprt_clear_connecting(xprt); 23662306a36Sopenharmony_ci if (!rc) { 23762306a36Sopenharmony_ci xprt->connect_cookie++; 23862306a36Sopenharmony_ci xprt->stat.connect_count++; 23962306a36Sopenharmony_ci xprt->stat.connect_time += (long)jiffies - 24062306a36Sopenharmony_ci xprt->stat.connect_start; 24162306a36Sopenharmony_ci xprt_set_connected(xprt); 24262306a36Sopenharmony_ci rc = -EAGAIN; 24362306a36Sopenharmony_ci } else 24462306a36Sopenharmony_ci rpcrdma_xprt_disconnect(r_xprt); 24562306a36Sopenharmony_ci xprt_unlock_connect(xprt, r_xprt); 24662306a36Sopenharmony_ci xprt_wake_pending_tasks(xprt, rc); 24762306a36Sopenharmony_ci current_restore_flags(pflags, PF_MEMALLOC); 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci/** 25162306a36Sopenharmony_ci * xprt_rdma_inject_disconnect - inject a connection fault 25262306a36Sopenharmony_ci * @xprt: transport context 25362306a36Sopenharmony_ci * 25462306a36Sopenharmony_ci * If @xprt is connected, disconnect it to simulate spurious 25562306a36Sopenharmony_ci * connection loss. Caller must hold @xprt's send lock to 25662306a36Sopenharmony_ci * ensure that data structures and hardware resources are 25762306a36Sopenharmony_ci * stable during the rdma_disconnect() call. 25862306a36Sopenharmony_ci */ 25962306a36Sopenharmony_cistatic void 26062306a36Sopenharmony_cixprt_rdma_inject_disconnect(struct rpc_xprt *xprt) 26162306a36Sopenharmony_ci{ 26262306a36Sopenharmony_ci struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci trace_xprtrdma_op_inject_dsc(r_xprt); 26562306a36Sopenharmony_ci rdma_disconnect(r_xprt->rx_ep->re_id); 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci/** 26962306a36Sopenharmony_ci * xprt_rdma_destroy - Full tear down of transport 27062306a36Sopenharmony_ci * @xprt: doomed transport context 27162306a36Sopenharmony_ci * 27262306a36Sopenharmony_ci * Caller guarantees there will be no more calls to us with 27362306a36Sopenharmony_ci * this @xprt. 27462306a36Sopenharmony_ci */ 27562306a36Sopenharmony_cistatic void 27662306a36Sopenharmony_cixprt_rdma_destroy(struct rpc_xprt *xprt) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci cancel_delayed_work_sync(&r_xprt->rx_connect_worker); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci rpcrdma_xprt_disconnect(r_xprt); 28362306a36Sopenharmony_ci rpcrdma_buffer_destroy(&r_xprt->rx_buf); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci xprt_rdma_free_addresses(xprt); 28662306a36Sopenharmony_ci xprt_free(xprt); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci module_put(THIS_MODULE); 28962306a36Sopenharmony_ci} 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci/* 60 second timeout, no retries */ 29262306a36Sopenharmony_cistatic const struct rpc_timeout xprt_rdma_default_timeout = { 29362306a36Sopenharmony_ci .to_initval = 60 * HZ, 29462306a36Sopenharmony_ci .to_maxval = 60 * HZ, 29562306a36Sopenharmony_ci}; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci/** 29862306a36Sopenharmony_ci * xprt_setup_rdma - Set up transport to use RDMA 29962306a36Sopenharmony_ci * 30062306a36Sopenharmony_ci * @args: rpc transport arguments 30162306a36Sopenharmony_ci */ 30262306a36Sopenharmony_cistatic struct rpc_xprt * 30362306a36Sopenharmony_cixprt_setup_rdma(struct xprt_create *args) 30462306a36Sopenharmony_ci{ 30562306a36Sopenharmony_ci struct rpc_xprt *xprt; 30662306a36Sopenharmony_ci struct rpcrdma_xprt *new_xprt; 30762306a36Sopenharmony_ci struct sockaddr *sap; 30862306a36Sopenharmony_ci int rc; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci if (args->addrlen > sizeof(xprt->addr)) 31162306a36Sopenharmony_ci return ERR_PTR(-EBADF); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci if (!try_module_get(THIS_MODULE)) 31462306a36Sopenharmony_ci return ERR_PTR(-EIO); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci xprt = xprt_alloc(args->net, sizeof(struct rpcrdma_xprt), 0, 31762306a36Sopenharmony_ci xprt_rdma_slot_table_entries); 31862306a36Sopenharmony_ci if (!xprt) { 31962306a36Sopenharmony_ci module_put(THIS_MODULE); 32062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 32162306a36Sopenharmony_ci } 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci xprt->timeout = &xprt_rdma_default_timeout; 32462306a36Sopenharmony_ci xprt->connect_timeout = xprt->timeout->to_initval; 32562306a36Sopenharmony_ci xprt->max_reconnect_timeout = xprt->timeout->to_maxval; 32662306a36Sopenharmony_ci xprt->bind_timeout = RPCRDMA_BIND_TO; 32762306a36Sopenharmony_ci xprt->reestablish_timeout = RPCRDMA_INIT_REEST_TO; 32862306a36Sopenharmony_ci xprt->idle_timeout = RPCRDMA_IDLE_DISC_TO; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci xprt->resvport = 0; /* privileged port not needed */ 33162306a36Sopenharmony_ci xprt->ops = &xprt_rdma_procs; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci /* 33462306a36Sopenharmony_ci * Set up RDMA-specific connect data. 33562306a36Sopenharmony_ci */ 33662306a36Sopenharmony_ci sap = args->dstaddr; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci /* Ensure xprt->addr holds valid server TCP (not RDMA) 33962306a36Sopenharmony_ci * address, for any side protocols which peek at it */ 34062306a36Sopenharmony_ci xprt->prot = IPPROTO_TCP; 34162306a36Sopenharmony_ci xprt->xprt_class = &xprt_rdma; 34262306a36Sopenharmony_ci xprt->addrlen = args->addrlen; 34362306a36Sopenharmony_ci memcpy(&xprt->addr, sap, xprt->addrlen); 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci if (rpc_get_port(sap)) 34662306a36Sopenharmony_ci xprt_set_bound(xprt); 34762306a36Sopenharmony_ci xprt_rdma_format_addresses(xprt, sap); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci new_xprt = rpcx_to_rdmax(xprt); 35062306a36Sopenharmony_ci rc = rpcrdma_buffer_create(new_xprt); 35162306a36Sopenharmony_ci if (rc) { 35262306a36Sopenharmony_ci xprt_rdma_free_addresses(xprt); 35362306a36Sopenharmony_ci xprt_free(xprt); 35462306a36Sopenharmony_ci module_put(THIS_MODULE); 35562306a36Sopenharmony_ci return ERR_PTR(rc); 35662306a36Sopenharmony_ci } 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci INIT_DELAYED_WORK(&new_xprt->rx_connect_worker, 35962306a36Sopenharmony_ci xprt_rdma_connect_worker); 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci xprt->max_payload = RPCRDMA_MAX_DATA_SEGS << PAGE_SHIFT; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci return xprt; 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci/** 36762306a36Sopenharmony_ci * xprt_rdma_close - close a transport connection 36862306a36Sopenharmony_ci * @xprt: transport context 36962306a36Sopenharmony_ci * 37062306a36Sopenharmony_ci * Called during autoclose or device removal. 37162306a36Sopenharmony_ci * 37262306a36Sopenharmony_ci * Caller holds @xprt's send lock to prevent activity on this 37362306a36Sopenharmony_ci * transport while the connection is torn down. 37462306a36Sopenharmony_ci */ 37562306a36Sopenharmony_civoid xprt_rdma_close(struct rpc_xprt *xprt) 37662306a36Sopenharmony_ci{ 37762306a36Sopenharmony_ci struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci rpcrdma_xprt_disconnect(r_xprt); 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci xprt->reestablish_timeout = 0; 38262306a36Sopenharmony_ci ++xprt->connect_cookie; 38362306a36Sopenharmony_ci xprt_disconnect_done(xprt); 38462306a36Sopenharmony_ci} 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci/** 38762306a36Sopenharmony_ci * xprt_rdma_set_port - update server port with rpcbind result 38862306a36Sopenharmony_ci * @xprt: controlling RPC transport 38962306a36Sopenharmony_ci * @port: new port value 39062306a36Sopenharmony_ci * 39162306a36Sopenharmony_ci * Transport connect status is unchanged. 39262306a36Sopenharmony_ci */ 39362306a36Sopenharmony_cistatic void 39462306a36Sopenharmony_cixprt_rdma_set_port(struct rpc_xprt *xprt, u16 port) 39562306a36Sopenharmony_ci{ 39662306a36Sopenharmony_ci struct sockaddr *sap = (struct sockaddr *)&xprt->addr; 39762306a36Sopenharmony_ci char buf[8]; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci rpc_set_port(sap, port); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci kfree(xprt->address_strings[RPC_DISPLAY_PORT]); 40262306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "%u", port); 40362306a36Sopenharmony_ci xprt->address_strings[RPC_DISPLAY_PORT] = kstrdup(buf, GFP_KERNEL); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci kfree(xprt->address_strings[RPC_DISPLAY_HEX_PORT]); 40662306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "%4hx", port); 40762306a36Sopenharmony_ci xprt->address_strings[RPC_DISPLAY_HEX_PORT] = kstrdup(buf, GFP_KERNEL); 40862306a36Sopenharmony_ci} 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci/** 41162306a36Sopenharmony_ci * xprt_rdma_timer - invoked when an RPC times out 41262306a36Sopenharmony_ci * @xprt: controlling RPC transport 41362306a36Sopenharmony_ci * @task: RPC task that timed out 41462306a36Sopenharmony_ci * 41562306a36Sopenharmony_ci * Invoked when the transport is still connected, but an RPC 41662306a36Sopenharmony_ci * retransmit timeout occurs. 41762306a36Sopenharmony_ci * 41862306a36Sopenharmony_ci * Since RDMA connections don't have a keep-alive, forcibly 41962306a36Sopenharmony_ci * disconnect and retry to connect. This drives full 42062306a36Sopenharmony_ci * detection of the network path, and retransmissions of 42162306a36Sopenharmony_ci * all pending RPCs. 42262306a36Sopenharmony_ci */ 42362306a36Sopenharmony_cistatic void 42462306a36Sopenharmony_cixprt_rdma_timer(struct rpc_xprt *xprt, struct rpc_task *task) 42562306a36Sopenharmony_ci{ 42662306a36Sopenharmony_ci xprt_force_disconnect(xprt); 42762306a36Sopenharmony_ci} 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci/** 43062306a36Sopenharmony_ci * xprt_rdma_set_connect_timeout - set timeouts for establishing a connection 43162306a36Sopenharmony_ci * @xprt: controlling transport instance 43262306a36Sopenharmony_ci * @connect_timeout: reconnect timeout after client disconnects 43362306a36Sopenharmony_ci * @reconnect_timeout: reconnect timeout after server disconnects 43462306a36Sopenharmony_ci * 43562306a36Sopenharmony_ci */ 43662306a36Sopenharmony_cistatic void xprt_rdma_set_connect_timeout(struct rpc_xprt *xprt, 43762306a36Sopenharmony_ci unsigned long connect_timeout, 43862306a36Sopenharmony_ci unsigned long reconnect_timeout) 43962306a36Sopenharmony_ci{ 44062306a36Sopenharmony_ci struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci trace_xprtrdma_op_set_cto(r_xprt, connect_timeout, reconnect_timeout); 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci spin_lock(&xprt->transport_lock); 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci if (connect_timeout < xprt->connect_timeout) { 44762306a36Sopenharmony_ci struct rpc_timeout to; 44862306a36Sopenharmony_ci unsigned long initval; 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci to = *xprt->timeout; 45162306a36Sopenharmony_ci initval = connect_timeout; 45262306a36Sopenharmony_ci if (initval < RPCRDMA_INIT_REEST_TO << 1) 45362306a36Sopenharmony_ci initval = RPCRDMA_INIT_REEST_TO << 1; 45462306a36Sopenharmony_ci to.to_initval = initval; 45562306a36Sopenharmony_ci to.to_maxval = initval; 45662306a36Sopenharmony_ci r_xprt->rx_timeout = to; 45762306a36Sopenharmony_ci xprt->timeout = &r_xprt->rx_timeout; 45862306a36Sopenharmony_ci xprt->connect_timeout = connect_timeout; 45962306a36Sopenharmony_ci } 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci if (reconnect_timeout < xprt->max_reconnect_timeout) 46262306a36Sopenharmony_ci xprt->max_reconnect_timeout = reconnect_timeout; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci spin_unlock(&xprt->transport_lock); 46562306a36Sopenharmony_ci} 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci/** 46862306a36Sopenharmony_ci * xprt_rdma_connect - schedule an attempt to reconnect 46962306a36Sopenharmony_ci * @xprt: transport state 47062306a36Sopenharmony_ci * @task: RPC scheduler context (unused) 47162306a36Sopenharmony_ci * 47262306a36Sopenharmony_ci */ 47362306a36Sopenharmony_cistatic void 47462306a36Sopenharmony_cixprt_rdma_connect(struct rpc_xprt *xprt, struct rpc_task *task) 47562306a36Sopenharmony_ci{ 47662306a36Sopenharmony_ci struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); 47762306a36Sopenharmony_ci struct rpcrdma_ep *ep = r_xprt->rx_ep; 47862306a36Sopenharmony_ci unsigned long delay; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci WARN_ON_ONCE(!xprt_lock_connect(xprt, task, r_xprt)); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci delay = 0; 48362306a36Sopenharmony_ci if (ep && ep->re_connect_status != 0) { 48462306a36Sopenharmony_ci delay = xprt_reconnect_delay(xprt); 48562306a36Sopenharmony_ci xprt_reconnect_backoff(xprt, RPCRDMA_INIT_REEST_TO); 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci trace_xprtrdma_op_connect(r_xprt, delay); 48862306a36Sopenharmony_ci queue_delayed_work(system_long_wq, &r_xprt->rx_connect_worker, delay); 48962306a36Sopenharmony_ci} 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci/** 49262306a36Sopenharmony_ci * xprt_rdma_alloc_slot - allocate an rpc_rqst 49362306a36Sopenharmony_ci * @xprt: controlling RPC transport 49462306a36Sopenharmony_ci * @task: RPC task requesting a fresh rpc_rqst 49562306a36Sopenharmony_ci * 49662306a36Sopenharmony_ci * tk_status values: 49762306a36Sopenharmony_ci * %0 if task->tk_rqstp points to a fresh rpc_rqst 49862306a36Sopenharmony_ci * %-EAGAIN if no rpc_rqst is available; queued on backlog 49962306a36Sopenharmony_ci */ 50062306a36Sopenharmony_cistatic void 50162306a36Sopenharmony_cixprt_rdma_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) 50262306a36Sopenharmony_ci{ 50362306a36Sopenharmony_ci struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); 50462306a36Sopenharmony_ci struct rpcrdma_req *req; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci req = rpcrdma_buffer_get(&r_xprt->rx_buf); 50762306a36Sopenharmony_ci if (!req) 50862306a36Sopenharmony_ci goto out_sleep; 50962306a36Sopenharmony_ci task->tk_rqstp = &req->rl_slot; 51062306a36Sopenharmony_ci task->tk_status = 0; 51162306a36Sopenharmony_ci return; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ciout_sleep: 51462306a36Sopenharmony_ci task->tk_status = -ENOMEM; 51562306a36Sopenharmony_ci xprt_add_backlog(xprt, task); 51662306a36Sopenharmony_ci} 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci/** 51962306a36Sopenharmony_ci * xprt_rdma_free_slot - release an rpc_rqst 52062306a36Sopenharmony_ci * @xprt: controlling RPC transport 52162306a36Sopenharmony_ci * @rqst: rpc_rqst to release 52262306a36Sopenharmony_ci * 52362306a36Sopenharmony_ci */ 52462306a36Sopenharmony_cistatic void 52562306a36Sopenharmony_cixprt_rdma_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *rqst) 52662306a36Sopenharmony_ci{ 52762306a36Sopenharmony_ci struct rpcrdma_xprt *r_xprt = 52862306a36Sopenharmony_ci container_of(xprt, struct rpcrdma_xprt, rx_xprt); 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci rpcrdma_reply_put(&r_xprt->rx_buf, rpcr_to_rdmar(rqst)); 53162306a36Sopenharmony_ci if (!xprt_wake_up_backlog(xprt, rqst)) { 53262306a36Sopenharmony_ci memset(rqst, 0, sizeof(*rqst)); 53362306a36Sopenharmony_ci rpcrdma_buffer_put(&r_xprt->rx_buf, rpcr_to_rdmar(rqst)); 53462306a36Sopenharmony_ci } 53562306a36Sopenharmony_ci} 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_cistatic bool rpcrdma_check_regbuf(struct rpcrdma_xprt *r_xprt, 53862306a36Sopenharmony_ci struct rpcrdma_regbuf *rb, size_t size, 53962306a36Sopenharmony_ci gfp_t flags) 54062306a36Sopenharmony_ci{ 54162306a36Sopenharmony_ci if (unlikely(rdmab_length(rb) < size)) { 54262306a36Sopenharmony_ci if (!rpcrdma_regbuf_realloc(rb, size, flags)) 54362306a36Sopenharmony_ci return false; 54462306a36Sopenharmony_ci r_xprt->rx_stats.hardway_register_count += size; 54562306a36Sopenharmony_ci } 54662306a36Sopenharmony_ci return true; 54762306a36Sopenharmony_ci} 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci/** 55062306a36Sopenharmony_ci * xprt_rdma_allocate - allocate transport resources for an RPC 55162306a36Sopenharmony_ci * @task: RPC task 55262306a36Sopenharmony_ci * 55362306a36Sopenharmony_ci * Return values: 55462306a36Sopenharmony_ci * 0: Success; rq_buffer points to RPC buffer to use 55562306a36Sopenharmony_ci * ENOMEM: Out of memory, call again later 55662306a36Sopenharmony_ci * EIO: A permanent error occurred, do not retry 55762306a36Sopenharmony_ci */ 55862306a36Sopenharmony_cistatic int 55962306a36Sopenharmony_cixprt_rdma_allocate(struct rpc_task *task) 56062306a36Sopenharmony_ci{ 56162306a36Sopenharmony_ci struct rpc_rqst *rqst = task->tk_rqstp; 56262306a36Sopenharmony_ci struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(rqst->rq_xprt); 56362306a36Sopenharmony_ci struct rpcrdma_req *req = rpcr_to_rdmar(rqst); 56462306a36Sopenharmony_ci gfp_t flags = rpc_task_gfp_mask(); 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci if (!rpcrdma_check_regbuf(r_xprt, req->rl_sendbuf, rqst->rq_callsize, 56762306a36Sopenharmony_ci flags)) 56862306a36Sopenharmony_ci goto out_fail; 56962306a36Sopenharmony_ci if (!rpcrdma_check_regbuf(r_xprt, req->rl_recvbuf, rqst->rq_rcvsize, 57062306a36Sopenharmony_ci flags)) 57162306a36Sopenharmony_ci goto out_fail; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci rqst->rq_buffer = rdmab_data(req->rl_sendbuf); 57462306a36Sopenharmony_ci rqst->rq_rbuffer = rdmab_data(req->rl_recvbuf); 57562306a36Sopenharmony_ci return 0; 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ciout_fail: 57862306a36Sopenharmony_ci return -ENOMEM; 57962306a36Sopenharmony_ci} 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci/** 58262306a36Sopenharmony_ci * xprt_rdma_free - release resources allocated by xprt_rdma_allocate 58362306a36Sopenharmony_ci * @task: RPC task 58462306a36Sopenharmony_ci * 58562306a36Sopenharmony_ci * Caller guarantees rqst->rq_buffer is non-NULL. 58662306a36Sopenharmony_ci */ 58762306a36Sopenharmony_cistatic void 58862306a36Sopenharmony_cixprt_rdma_free(struct rpc_task *task) 58962306a36Sopenharmony_ci{ 59062306a36Sopenharmony_ci struct rpc_rqst *rqst = task->tk_rqstp; 59162306a36Sopenharmony_ci struct rpcrdma_req *req = rpcr_to_rdmar(rqst); 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci if (unlikely(!list_empty(&req->rl_registered))) { 59462306a36Sopenharmony_ci trace_xprtrdma_mrs_zap(task); 59562306a36Sopenharmony_ci frwr_unmap_sync(rpcx_to_rdmax(rqst->rq_xprt), req); 59662306a36Sopenharmony_ci } 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci /* XXX: If the RPC is completing because of a signal and 59962306a36Sopenharmony_ci * not because a reply was received, we ought to ensure 60062306a36Sopenharmony_ci * that the Send completion has fired, so that memory 60162306a36Sopenharmony_ci * involved with the Send is not still visible to the NIC. 60262306a36Sopenharmony_ci */ 60362306a36Sopenharmony_ci} 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci/** 60662306a36Sopenharmony_ci * xprt_rdma_send_request - marshal and send an RPC request 60762306a36Sopenharmony_ci * @rqst: RPC message in rq_snd_buf 60862306a36Sopenharmony_ci * 60962306a36Sopenharmony_ci * Caller holds the transport's write lock. 61062306a36Sopenharmony_ci * 61162306a36Sopenharmony_ci * Returns: 61262306a36Sopenharmony_ci * %0 if the RPC message has been sent 61362306a36Sopenharmony_ci * %-ENOTCONN if the caller should reconnect and call again 61462306a36Sopenharmony_ci * %-EAGAIN if the caller should call again 61562306a36Sopenharmony_ci * %-ENOBUFS if the caller should call again after a delay 61662306a36Sopenharmony_ci * %-EMSGSIZE if encoding ran out of buffer space. The request 61762306a36Sopenharmony_ci * was not sent. Do not try to send this message again. 61862306a36Sopenharmony_ci * %-EIO if an I/O error occurred. The request was not sent. 61962306a36Sopenharmony_ci * Do not try to send this message again. 62062306a36Sopenharmony_ci */ 62162306a36Sopenharmony_cistatic int 62262306a36Sopenharmony_cixprt_rdma_send_request(struct rpc_rqst *rqst) 62362306a36Sopenharmony_ci{ 62462306a36Sopenharmony_ci struct rpc_xprt *xprt = rqst->rq_xprt; 62562306a36Sopenharmony_ci struct rpcrdma_req *req = rpcr_to_rdmar(rqst); 62662306a36Sopenharmony_ci struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); 62762306a36Sopenharmony_ci int rc = 0; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci#if defined(CONFIG_SUNRPC_BACKCHANNEL) 63062306a36Sopenharmony_ci if (unlikely(!rqst->rq_buffer)) 63162306a36Sopenharmony_ci return xprt_rdma_bc_send_reply(rqst); 63262306a36Sopenharmony_ci#endif /* CONFIG_SUNRPC_BACKCHANNEL */ 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci if (!xprt_connected(xprt)) 63562306a36Sopenharmony_ci return -ENOTCONN; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci if (!xprt_request_get_cong(xprt, rqst)) 63862306a36Sopenharmony_ci return -EBADSLT; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci rc = rpcrdma_marshal_req(r_xprt, rqst); 64162306a36Sopenharmony_ci if (rc < 0) 64262306a36Sopenharmony_ci goto failed_marshal; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci /* Must suppress retransmit to maintain credits */ 64562306a36Sopenharmony_ci if (rqst->rq_connect_cookie == xprt->connect_cookie) 64662306a36Sopenharmony_ci goto drop_connection; 64762306a36Sopenharmony_ci rqst->rq_xtime = ktime_get(); 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci if (frwr_send(r_xprt, req)) 65062306a36Sopenharmony_ci goto drop_connection; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci rqst->rq_xmit_bytes_sent += rqst->rq_snd_buf.len; 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci /* An RPC with no reply will throw off credit accounting, 65562306a36Sopenharmony_ci * so drop the connection to reset the credit grant. 65662306a36Sopenharmony_ci */ 65762306a36Sopenharmony_ci if (!rpc_reply_expected(rqst->rq_task)) 65862306a36Sopenharmony_ci goto drop_connection; 65962306a36Sopenharmony_ci return 0; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_cifailed_marshal: 66262306a36Sopenharmony_ci if (rc != -ENOTCONN) 66362306a36Sopenharmony_ci return rc; 66462306a36Sopenharmony_cidrop_connection: 66562306a36Sopenharmony_ci xprt_rdma_close(xprt); 66662306a36Sopenharmony_ci return -ENOTCONN; 66762306a36Sopenharmony_ci} 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_civoid xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) 67062306a36Sopenharmony_ci{ 67162306a36Sopenharmony_ci struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); 67262306a36Sopenharmony_ci long idle_time = 0; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci if (xprt_connected(xprt)) 67562306a36Sopenharmony_ci idle_time = (long)(jiffies - xprt->last_used) / HZ; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci seq_puts(seq, "\txprt:\trdma "); 67862306a36Sopenharmony_ci seq_printf(seq, "%u %lu %lu %lu %ld %lu %lu %lu %llu %llu ", 67962306a36Sopenharmony_ci 0, /* need a local port? */ 68062306a36Sopenharmony_ci xprt->stat.bind_count, 68162306a36Sopenharmony_ci xprt->stat.connect_count, 68262306a36Sopenharmony_ci xprt->stat.connect_time / HZ, 68362306a36Sopenharmony_ci idle_time, 68462306a36Sopenharmony_ci xprt->stat.sends, 68562306a36Sopenharmony_ci xprt->stat.recvs, 68662306a36Sopenharmony_ci xprt->stat.bad_xids, 68762306a36Sopenharmony_ci xprt->stat.req_u, 68862306a36Sopenharmony_ci xprt->stat.bklog_u); 68962306a36Sopenharmony_ci seq_printf(seq, "%lu %lu %lu %llu %llu %llu %llu %lu %lu %lu %lu ", 69062306a36Sopenharmony_ci r_xprt->rx_stats.read_chunk_count, 69162306a36Sopenharmony_ci r_xprt->rx_stats.write_chunk_count, 69262306a36Sopenharmony_ci r_xprt->rx_stats.reply_chunk_count, 69362306a36Sopenharmony_ci r_xprt->rx_stats.total_rdma_request, 69462306a36Sopenharmony_ci r_xprt->rx_stats.total_rdma_reply, 69562306a36Sopenharmony_ci r_xprt->rx_stats.pullup_copy_count, 69662306a36Sopenharmony_ci r_xprt->rx_stats.fixup_copy_count, 69762306a36Sopenharmony_ci r_xprt->rx_stats.hardway_register_count, 69862306a36Sopenharmony_ci r_xprt->rx_stats.failed_marshal_count, 69962306a36Sopenharmony_ci r_xprt->rx_stats.bad_reply_count, 70062306a36Sopenharmony_ci r_xprt->rx_stats.nomsg_call_count); 70162306a36Sopenharmony_ci seq_printf(seq, "%lu %lu %lu %lu %lu %lu\n", 70262306a36Sopenharmony_ci r_xprt->rx_stats.mrs_recycled, 70362306a36Sopenharmony_ci r_xprt->rx_stats.mrs_orphaned, 70462306a36Sopenharmony_ci r_xprt->rx_stats.mrs_allocated, 70562306a36Sopenharmony_ci r_xprt->rx_stats.local_inv_needed, 70662306a36Sopenharmony_ci r_xprt->rx_stats.empty_sendctx_q, 70762306a36Sopenharmony_ci r_xprt->rx_stats.reply_waits_for_send); 70862306a36Sopenharmony_ci} 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_cistatic int 71162306a36Sopenharmony_cixprt_rdma_enable_swap(struct rpc_xprt *xprt) 71262306a36Sopenharmony_ci{ 71362306a36Sopenharmony_ci return 0; 71462306a36Sopenharmony_ci} 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_cistatic void 71762306a36Sopenharmony_cixprt_rdma_disable_swap(struct rpc_xprt *xprt) 71862306a36Sopenharmony_ci{ 71962306a36Sopenharmony_ci} 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci/* 72262306a36Sopenharmony_ci * Plumbing for rpc transport switch and kernel module 72362306a36Sopenharmony_ci */ 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_cistatic const struct rpc_xprt_ops xprt_rdma_procs = { 72662306a36Sopenharmony_ci .reserve_xprt = xprt_reserve_xprt_cong, 72762306a36Sopenharmony_ci .release_xprt = xprt_release_xprt_cong, /* sunrpc/xprt.c */ 72862306a36Sopenharmony_ci .alloc_slot = xprt_rdma_alloc_slot, 72962306a36Sopenharmony_ci .free_slot = xprt_rdma_free_slot, 73062306a36Sopenharmony_ci .release_request = xprt_release_rqst_cong, /* ditto */ 73162306a36Sopenharmony_ci .wait_for_reply_request = xprt_wait_for_reply_request_def, /* ditto */ 73262306a36Sopenharmony_ci .timer = xprt_rdma_timer, 73362306a36Sopenharmony_ci .rpcbind = rpcb_getport_async, /* sunrpc/rpcb_clnt.c */ 73462306a36Sopenharmony_ci .set_port = xprt_rdma_set_port, 73562306a36Sopenharmony_ci .connect = xprt_rdma_connect, 73662306a36Sopenharmony_ci .buf_alloc = xprt_rdma_allocate, 73762306a36Sopenharmony_ci .buf_free = xprt_rdma_free, 73862306a36Sopenharmony_ci .send_request = xprt_rdma_send_request, 73962306a36Sopenharmony_ci .close = xprt_rdma_close, 74062306a36Sopenharmony_ci .destroy = xprt_rdma_destroy, 74162306a36Sopenharmony_ci .set_connect_timeout = xprt_rdma_set_connect_timeout, 74262306a36Sopenharmony_ci .print_stats = xprt_rdma_print_stats, 74362306a36Sopenharmony_ci .enable_swap = xprt_rdma_enable_swap, 74462306a36Sopenharmony_ci .disable_swap = xprt_rdma_disable_swap, 74562306a36Sopenharmony_ci .inject_disconnect = xprt_rdma_inject_disconnect, 74662306a36Sopenharmony_ci#if defined(CONFIG_SUNRPC_BACKCHANNEL) 74762306a36Sopenharmony_ci .bc_setup = xprt_rdma_bc_setup, 74862306a36Sopenharmony_ci .bc_maxpayload = xprt_rdma_bc_maxpayload, 74962306a36Sopenharmony_ci .bc_num_slots = xprt_rdma_bc_max_slots, 75062306a36Sopenharmony_ci .bc_free_rqst = xprt_rdma_bc_free_rqst, 75162306a36Sopenharmony_ci .bc_destroy = xprt_rdma_bc_destroy, 75262306a36Sopenharmony_ci#endif 75362306a36Sopenharmony_ci}; 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_cistatic struct xprt_class xprt_rdma = { 75662306a36Sopenharmony_ci .list = LIST_HEAD_INIT(xprt_rdma.list), 75762306a36Sopenharmony_ci .name = "rdma", 75862306a36Sopenharmony_ci .owner = THIS_MODULE, 75962306a36Sopenharmony_ci .ident = XPRT_TRANSPORT_RDMA, 76062306a36Sopenharmony_ci .setup = xprt_setup_rdma, 76162306a36Sopenharmony_ci .netid = { "rdma", "rdma6", "" }, 76262306a36Sopenharmony_ci}; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_civoid xprt_rdma_cleanup(void) 76562306a36Sopenharmony_ci{ 76662306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_SUNRPC_DEBUG) 76762306a36Sopenharmony_ci if (sunrpc_table_header) { 76862306a36Sopenharmony_ci unregister_sysctl_table(sunrpc_table_header); 76962306a36Sopenharmony_ci sunrpc_table_header = NULL; 77062306a36Sopenharmony_ci } 77162306a36Sopenharmony_ci#endif 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci xprt_unregister_transport(&xprt_rdma); 77462306a36Sopenharmony_ci xprt_unregister_transport(&xprt_rdma_bc); 77562306a36Sopenharmony_ci} 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ciint xprt_rdma_init(void) 77862306a36Sopenharmony_ci{ 77962306a36Sopenharmony_ci int rc; 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci rc = xprt_register_transport(&xprt_rdma); 78262306a36Sopenharmony_ci if (rc) 78362306a36Sopenharmony_ci return rc; 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci rc = xprt_register_transport(&xprt_rdma_bc); 78662306a36Sopenharmony_ci if (rc) { 78762306a36Sopenharmony_ci xprt_unregister_transport(&xprt_rdma); 78862306a36Sopenharmony_ci return rc; 78962306a36Sopenharmony_ci } 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_SUNRPC_DEBUG) 79262306a36Sopenharmony_ci if (!sunrpc_table_header) 79362306a36Sopenharmony_ci sunrpc_table_header = register_sysctl("sunrpc", xr_tunables_table); 79462306a36Sopenharmony_ci#endif 79562306a36Sopenharmony_ci return 0; 79662306a36Sopenharmony_ci} 797