1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (c) 2015-2018 Oracle. All rights reserved. 4 * Copyright (c) 2005-2006 Network Appliance, Inc. All rights reserved. 5 * 6 * This software is available to you under a choice of one of two 7 * licenses. You may choose to be licensed under the terms of the GNU 8 * General Public License (GPL) Version 2, available from the file 9 * COPYING in the main directory of this source tree, or the BSD-type 10 * license below: 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 16 * Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 19 * Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials provided 22 * with the distribution. 23 * 24 * Neither the name of the Network Appliance, Inc. nor the names of 25 * its contributors may be used to endorse or promote products 26 * derived from this software without specific prior written 27 * permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Author: Tom Tucker <tom@opengridcomputing.com> 42 */ 43 44 #include <linux/slab.h> 45 #include <linux/fs.h> 46 #include <linux/sysctl.h> 47 #include <linux/workqueue.h> 48 #include <linux/sunrpc/clnt.h> 49 #include <linux/sunrpc/sched.h> 50 #include <linux/sunrpc/svc_rdma.h> 51 52 #define RPCDBG_FACILITY RPCDBG_SVCXPRT 53 54 /* RPC/RDMA parameters */ 55 unsigned int svcrdma_ord = 16; /* historical default */ 56 static unsigned int min_ord = 1; 57 static unsigned int max_ord = 255; 58 unsigned int svcrdma_max_requests = RPCRDMA_MAX_REQUESTS; 59 unsigned int svcrdma_max_bc_requests = RPCRDMA_MAX_BC_REQUESTS; 60 static unsigned int min_max_requests = 4; 61 static unsigned int max_max_requests = 16384; 62 unsigned int svcrdma_max_req_size = RPCRDMA_DEF_INLINE_THRESH; 63 static unsigned int min_max_inline = RPCRDMA_DEF_INLINE_THRESH; 64 static unsigned int max_max_inline = RPCRDMA_MAX_INLINE_THRESH; 65 66 atomic_t rdma_stat_recv; 67 atomic_t rdma_stat_read; 68 atomic_t rdma_stat_write; 69 atomic_t rdma_stat_sq_starve; 70 atomic_t rdma_stat_rq_starve; 71 atomic_t rdma_stat_rq_poll; 72 atomic_t rdma_stat_rq_prod; 73 atomic_t rdma_stat_sq_poll; 74 atomic_t rdma_stat_sq_prod; 75 76 struct workqueue_struct *svc_rdma_wq; 77 78 /* 79 * This function implements reading and resetting an atomic_t stat 80 * variable through read/write to a proc file. Any write to the file 81 * resets the associated statistic to zero. Any read returns it's 82 * current value. 83 */ 84 static int read_reset_stat(struct ctl_table *table, int write, 85 void __user *buffer, size_t *lenp, 86 loff_t *ppos) 87 { 88 atomic_t *stat = (atomic_t *)table->data; 89 90 if (!stat) 91 return -EINVAL; 92 93 if (write) 94 atomic_set(stat, 0); 95 else { 96 char str_buf[32]; 97 char *data; 98 int len = snprintf(str_buf, 32, "%d\n", atomic_read(stat)); 99 if (len >= 32) 100 return -EFAULT; 101 len = strlen(str_buf); 102 if (*ppos > len) { 103 *lenp = 0; 104 return 0; 105 } 106 data = &str_buf[*ppos]; 107 len -= *ppos; 108 if (len > *lenp) 109 len = *lenp; 110 if (len && copy_to_user(buffer, str_buf, len)) 111 return -EFAULT; 112 *lenp = len; 113 *ppos += len; 114 } 115 return 0; 116 } 117 118 static struct ctl_table_header *svcrdma_table_header; 119 static struct ctl_table svcrdma_parm_table[] = { 120 { 121 .procname = "max_requests", 122 .data = &svcrdma_max_requests, 123 .maxlen = sizeof(unsigned int), 124 .mode = 0644, 125 .proc_handler = proc_dointvec_minmax, 126 .extra1 = &min_max_requests, 127 .extra2 = &max_max_requests 128 }, 129 { 130 .procname = "max_req_size", 131 .data = &svcrdma_max_req_size, 132 .maxlen = sizeof(unsigned int), 133 .mode = 0644, 134 .proc_handler = proc_dointvec_minmax, 135 .extra1 = &min_max_inline, 136 .extra2 = &max_max_inline 137 }, 138 { 139 .procname = "max_outbound_read_requests", 140 .data = &svcrdma_ord, 141 .maxlen = sizeof(unsigned int), 142 .mode = 0644, 143 .proc_handler = proc_dointvec_minmax, 144 .extra1 = &min_ord, 145 .extra2 = &max_ord, 146 }, 147 148 { 149 .procname = "rdma_stat_read", 150 .data = &rdma_stat_read, 151 .maxlen = sizeof(atomic_t), 152 .mode = 0644, 153 .proc_handler = read_reset_stat, 154 }, 155 { 156 .procname = "rdma_stat_recv", 157 .data = &rdma_stat_recv, 158 .maxlen = sizeof(atomic_t), 159 .mode = 0644, 160 .proc_handler = read_reset_stat, 161 }, 162 { 163 .procname = "rdma_stat_write", 164 .data = &rdma_stat_write, 165 .maxlen = sizeof(atomic_t), 166 .mode = 0644, 167 .proc_handler = read_reset_stat, 168 }, 169 { 170 .procname = "rdma_stat_sq_starve", 171 .data = &rdma_stat_sq_starve, 172 .maxlen = sizeof(atomic_t), 173 .mode = 0644, 174 .proc_handler = read_reset_stat, 175 }, 176 { 177 .procname = "rdma_stat_rq_starve", 178 .data = &rdma_stat_rq_starve, 179 .maxlen = sizeof(atomic_t), 180 .mode = 0644, 181 .proc_handler = read_reset_stat, 182 }, 183 { 184 .procname = "rdma_stat_rq_poll", 185 .data = &rdma_stat_rq_poll, 186 .maxlen = sizeof(atomic_t), 187 .mode = 0644, 188 .proc_handler = read_reset_stat, 189 }, 190 { 191 .procname = "rdma_stat_rq_prod", 192 .data = &rdma_stat_rq_prod, 193 .maxlen = sizeof(atomic_t), 194 .mode = 0644, 195 .proc_handler = read_reset_stat, 196 }, 197 { 198 .procname = "rdma_stat_sq_poll", 199 .data = &rdma_stat_sq_poll, 200 .maxlen = sizeof(atomic_t), 201 .mode = 0644, 202 .proc_handler = read_reset_stat, 203 }, 204 { 205 .procname = "rdma_stat_sq_prod", 206 .data = &rdma_stat_sq_prod, 207 .maxlen = sizeof(atomic_t), 208 .mode = 0644, 209 .proc_handler = read_reset_stat, 210 }, 211 { }, 212 }; 213 214 static struct ctl_table svcrdma_table[] = { 215 { 216 .procname = "svc_rdma", 217 .mode = 0555, 218 .child = svcrdma_parm_table 219 }, 220 { }, 221 }; 222 223 static struct ctl_table svcrdma_root_table[] = { 224 { 225 .procname = "sunrpc", 226 .mode = 0555, 227 .child = svcrdma_table 228 }, 229 { }, 230 }; 231 232 void svc_rdma_cleanup(void) 233 { 234 dprintk("SVCRDMA Module Removed, deregister RPC RDMA transport\n"); 235 destroy_workqueue(svc_rdma_wq); 236 if (svcrdma_table_header) { 237 unregister_sysctl_table(svcrdma_table_header); 238 svcrdma_table_header = NULL; 239 } 240 #if defined(CONFIG_SUNRPC_BACKCHANNEL) 241 svc_unreg_xprt_class(&svc_rdma_bc_class); 242 #endif 243 svc_unreg_xprt_class(&svc_rdma_class); 244 } 245 246 int svc_rdma_init(void) 247 { 248 dprintk("SVCRDMA Module Init, register RPC RDMA transport\n"); 249 dprintk("\tsvcrdma_ord : %d\n", svcrdma_ord); 250 dprintk("\tmax_requests : %u\n", svcrdma_max_requests); 251 dprintk("\tmax_bc_requests : %u\n", svcrdma_max_bc_requests); 252 dprintk("\tmax_inline : %d\n", svcrdma_max_req_size); 253 254 svc_rdma_wq = alloc_workqueue("svc_rdma", 0, 0); 255 if (!svc_rdma_wq) 256 return -ENOMEM; 257 258 if (!svcrdma_table_header) 259 svcrdma_table_header = 260 register_sysctl_table(svcrdma_root_table); 261 262 /* Register RDMA with the SVC transport switch */ 263 svc_reg_xprt_class(&svc_rdma_class); 264 #if defined(CONFIG_SUNRPC_BACKCHANNEL) 265 svc_reg_xprt_class(&svc_rdma_bc_class); 266 #endif 267 return 0; 268 } 269