1ec16227eSAndy Grover /* 2ec16227eSAndy Grover * Copyright (c) 2006 Oracle. All rights reserved. 3ec16227eSAndy Grover * 4ec16227eSAndy Grover * This software is available to you under a choice of one of two 5ec16227eSAndy Grover * licenses. You may choose to be licensed under the terms of the GNU 6ec16227eSAndy Grover * General Public License (GPL) Version 2, available from the file 7ec16227eSAndy Grover * COPYING in the main directory of this source tree, or the 8ec16227eSAndy Grover * OpenIB.org BSD license below: 9ec16227eSAndy Grover * 10ec16227eSAndy Grover * Redistribution and use in source and binary forms, with or 11ec16227eSAndy Grover * without modification, are permitted provided that the following 12ec16227eSAndy Grover * conditions are met: 13ec16227eSAndy Grover * 14ec16227eSAndy Grover * - Redistributions of source code must retain the above 15ec16227eSAndy Grover * copyright notice, this list of conditions and the following 16ec16227eSAndy Grover * disclaimer. 17ec16227eSAndy Grover * 18ec16227eSAndy Grover * - Redistributions in binary form must reproduce the above 19ec16227eSAndy Grover * copyright notice, this list of conditions and the following 20ec16227eSAndy Grover * disclaimer in the documentation and/or other materials 21ec16227eSAndy Grover * provided with the distribution. 22ec16227eSAndy Grover * 23ec16227eSAndy Grover * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24ec16227eSAndy Grover * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25ec16227eSAndy Grover * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26ec16227eSAndy Grover * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27ec16227eSAndy Grover * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28ec16227eSAndy Grover * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29ec16227eSAndy Grover * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30ec16227eSAndy Grover * SOFTWARE. 31ec16227eSAndy Grover * 32ec16227eSAndy Grover */ 33ec16227eSAndy Grover #include <linux/kernel.h> 34ec16227eSAndy Grover #include <linux/in.h> 35ec16227eSAndy Grover #include <linux/if.h> 36ec16227eSAndy Grover #include <linux/netdevice.h> 37ec16227eSAndy Grover #include <linux/inetdevice.h> 38ec16227eSAndy Grover #include <linux/if_arp.h> 39ec16227eSAndy Grover #include <linux/delay.h> 405a0e3ad6STejun Heo #include <linux/slab.h> 413a9a231dSPaul Gortmaker #include <linux/module.h> 42ec16227eSAndy Grover 430cb43965SSowmini Varadhan #include "rds_single_path.h" 44ec16227eSAndy Grover #include "rds.h" 45ec16227eSAndy Grover #include "ib.h" 46f6df683fSsantosh.shilimkar@oracle.com #include "ib_mr.h" 47ec16227eSAndy Grover 48f6df683fSsantosh.shilimkar@oracle.com unsigned int rds_ib_mr_1m_pool_size = RDS_MR_1M_POOL_SIZE; 49f6df683fSsantosh.shilimkar@oracle.com unsigned int rds_ib_mr_8k_pool_size = RDS_MR_8K_POOL_SIZE; 503ba23adeSAndy Grover unsigned int rds_ib_retry_count = RDS_IB_DEFAULT_RETRY_COUNT; 51ec16227eSAndy Grover 52f6df683fSsantosh.shilimkar@oracle.com module_param(rds_ib_mr_1m_pool_size, int, 0444); 53f6df683fSsantosh.shilimkar@oracle.com MODULE_PARM_DESC(rds_ib_mr_1m_pool_size, " Max number of 1M mr per HCA"); 54f6df683fSsantosh.shilimkar@oracle.com module_param(rds_ib_mr_8k_pool_size, int, 0444); 55f6df683fSsantosh.shilimkar@oracle.com MODULE_PARM_DESC(rds_ib_mr_8k_pool_size, " Max number of 8K mr per HCA"); 563ba23adeSAndy Grover module_param(rds_ib_retry_count, int, 0444); 573ba23adeSAndy Grover MODULE_PARM_DESC(rds_ib_retry_count, " Number of hw retries before reporting an error"); 58ec16227eSAndy Grover 59ea819867SZach Brown /* 60ea819867SZach Brown * we have a clumsy combination of RCU and a rwsem protecting this list 61ea819867SZach Brown * because it is used both in the get_mr fast path and while blocking in 62ea819867SZach Brown * the FMR flushing path. 63ea819867SZach Brown */ 64ea819867SZach Brown DECLARE_RWSEM(rds_ib_devices_lock); 65ec16227eSAndy Grover struct list_head rds_ib_devices; 66ec16227eSAndy Grover 67745cbccaSAndy Grover /* NOTE: if also grabbing ibdev lock, grab this first */ 68ec16227eSAndy Grover DEFINE_SPINLOCK(ib_nodev_conns_lock); 69ec16227eSAndy Grover LIST_HEAD(ib_nodev_conns); 70ec16227eSAndy Grover 71ff51bf84Sstephen hemminger static void rds_ib_nodev_connect(void) 72fc19de38SZach Brown { 73fc19de38SZach Brown struct rds_ib_connection *ic; 74fc19de38SZach Brown 75fc19de38SZach Brown spin_lock(&ib_nodev_conns_lock); 76fc19de38SZach Brown list_for_each_entry(ic, &ib_nodev_conns, ib_node) 77fc19de38SZach Brown rds_conn_connect_if_down(ic->conn); 78fc19de38SZach Brown spin_unlock(&ib_nodev_conns_lock); 79fc19de38SZach Brown } 80fc19de38SZach Brown 81ff51bf84Sstephen hemminger static void rds_ib_dev_shutdown(struct rds_ib_device *rds_ibdev) 82fc19de38SZach Brown { 83fc19de38SZach Brown struct rds_ib_connection *ic; 84fc19de38SZach Brown unsigned long flags; 85fc19de38SZach Brown 86fc19de38SZach Brown spin_lock_irqsave(&rds_ibdev->spinlock, flags); 87fc19de38SZach Brown list_for_each_entry(ic, &rds_ibdev->conn_list, ib_node) 88fc19de38SZach Brown rds_conn_drop(ic->conn); 89fc19de38SZach Brown spin_unlock_irqrestore(&rds_ibdev->spinlock, flags); 90fc19de38SZach Brown } 91fc19de38SZach Brown 923e0249f9SZach Brown /* 933e0249f9SZach Brown * rds_ib_destroy_mr_pool() blocks on a few things and mrs drop references 943e0249f9SZach Brown * from interrupt context so we push freing off into a work struct in krdsd. 953e0249f9SZach Brown */ 963e0249f9SZach Brown static void rds_ib_dev_free(struct work_struct *work) 973e0249f9SZach Brown { 983e0249f9SZach Brown struct rds_ib_ipaddr *i_ipaddr, *i_next; 993e0249f9SZach Brown struct rds_ib_device *rds_ibdev = container_of(work, 1003e0249f9SZach Brown struct rds_ib_device, free_work); 1013e0249f9SZach Brown 10206766513SSantosh Shilimkar if (rds_ibdev->mr_8k_pool) 10306766513SSantosh Shilimkar rds_ib_destroy_mr_pool(rds_ibdev->mr_8k_pool); 10406766513SSantosh Shilimkar if (rds_ibdev->mr_1m_pool) 10506766513SSantosh Shilimkar rds_ib_destroy_mr_pool(rds_ibdev->mr_1m_pool); 1063e0249f9SZach Brown if (rds_ibdev->pd) 1073e0249f9SZach Brown ib_dealloc_pd(rds_ibdev->pd); 1083e0249f9SZach Brown 1093e0249f9SZach Brown list_for_each_entry_safe(i_ipaddr, i_next, &rds_ibdev->ipaddr_list, list) { 1103e0249f9SZach Brown list_del(&i_ipaddr->list); 1113e0249f9SZach Brown kfree(i_ipaddr); 1123e0249f9SZach Brown } 1133e0249f9SZach Brown 1143e0249f9SZach Brown kfree(rds_ibdev); 1153e0249f9SZach Brown } 1163e0249f9SZach Brown 1173e0249f9SZach Brown void rds_ib_dev_put(struct rds_ib_device *rds_ibdev) 1183e0249f9SZach Brown { 1193e0249f9SZach Brown BUG_ON(atomic_read(&rds_ibdev->refcount) <= 0); 1203e0249f9SZach Brown if (atomic_dec_and_test(&rds_ibdev->refcount)) 1213e0249f9SZach Brown queue_work(rds_wq, &rds_ibdev->free_work); 1223e0249f9SZach Brown } 1233e0249f9SZach Brown 124ff51bf84Sstephen hemminger static void rds_ib_add_one(struct ib_device *device) 125ec16227eSAndy Grover { 126ec16227eSAndy Grover struct rds_ib_device *rds_ibdev; 127ec16227eSAndy Grover 128ec16227eSAndy Grover /* Only handle IB (no iWARP) devices */ 129ec16227eSAndy Grover if (device->node_type != RDMA_NODE_IB_CA) 130ec16227eSAndy Grover return; 131ec16227eSAndy Grover 1323e0249f9SZach Brown rds_ibdev = kzalloc_node(sizeof(struct rds_ib_device), GFP_KERNEL, 1333e0249f9SZach Brown ibdev_to_node(device)); 134ec16227eSAndy Grover if (!rds_ibdev) 1350353261cSOr Gerlitz return; 136ec16227eSAndy Grover 137ec16227eSAndy Grover spin_lock_init(&rds_ibdev->spinlock); 1383e0249f9SZach Brown atomic_set(&rds_ibdev->refcount, 1); 1393e0249f9SZach Brown INIT_WORK(&rds_ibdev->free_work, rds_ib_dev_free); 140ec16227eSAndy Grover 1410353261cSOr Gerlitz rds_ibdev->max_wrs = device->attrs.max_qp_wr; 1420353261cSOr Gerlitz rds_ibdev->max_sge = min(device->attrs.max_sge, RDS_IB_MAX_SGE); 143ec16227eSAndy Grover 1442cb2912dSsantosh.shilimkar@oracle.com rds_ibdev->has_fr = (device->attrs.device_cap_flags & 1452cb2912dSsantosh.shilimkar@oracle.com IB_DEVICE_MEM_MGT_EXTENSIONS); 1462cb2912dSsantosh.shilimkar@oracle.com rds_ibdev->has_fmr = (device->alloc_fmr && device->dealloc_fmr && 1472cb2912dSsantosh.shilimkar@oracle.com device->map_phys_fmr && device->unmap_fmr); 1482cb2912dSsantosh.shilimkar@oracle.com rds_ibdev->use_fastreg = (rds_ibdev->has_fr && !rds_ibdev->has_fmr); 1492cb2912dSsantosh.shilimkar@oracle.com 1500353261cSOr Gerlitz rds_ibdev->fmr_max_remaps = device->attrs.max_map_per_fmr?: 32; 151f6df683fSsantosh.shilimkar@oracle.com rds_ibdev->max_1m_mrs = device->attrs.max_mr ? 1520353261cSOr Gerlitz min_t(unsigned int, (device->attrs.max_mr / 2), 153f6df683fSsantosh.shilimkar@oracle.com rds_ib_mr_1m_pool_size) : rds_ib_mr_1m_pool_size; 15406766513SSantosh Shilimkar 155f6df683fSsantosh.shilimkar@oracle.com rds_ibdev->max_8k_mrs = device->attrs.max_mr ? 1560353261cSOr Gerlitz min_t(unsigned int, ((device->attrs.max_mr / 2) * RDS_MR_8K_SCALE), 157f6df683fSsantosh.shilimkar@oracle.com rds_ib_mr_8k_pool_size) : rds_ib_mr_8k_pool_size; 158ec16227eSAndy Grover 1590353261cSOr Gerlitz rds_ibdev->max_initiator_depth = device->attrs.max_qp_init_rd_atom; 1600353261cSOr Gerlitz rds_ibdev->max_responder_resources = device->attrs.max_qp_rd_atom; 16140589e74SAndy Grover 162ec16227eSAndy Grover rds_ibdev->dev = device; 163ec16227eSAndy Grover rds_ibdev->pd = ib_alloc_pd(device); 1643e0249f9SZach Brown if (IS_ERR(rds_ibdev->pd)) { 1653e0249f9SZach Brown rds_ibdev->pd = NULL; 1663e0249f9SZach Brown goto put_dev; 1673e0249f9SZach Brown } 168ec16227eSAndy Grover 16906766513SSantosh Shilimkar rds_ibdev->mr_1m_pool = 17006766513SSantosh Shilimkar rds_ib_create_mr_pool(rds_ibdev, RDS_IB_MR_1M_POOL); 17106766513SSantosh Shilimkar if (IS_ERR(rds_ibdev->mr_1m_pool)) { 17206766513SSantosh Shilimkar rds_ibdev->mr_1m_pool = NULL; 1733e0249f9SZach Brown goto put_dev; 174ec16227eSAndy Grover } 175ec16227eSAndy Grover 17606766513SSantosh Shilimkar rds_ibdev->mr_8k_pool = 17706766513SSantosh Shilimkar rds_ib_create_mr_pool(rds_ibdev, RDS_IB_MR_8K_POOL); 17806766513SSantosh Shilimkar if (IS_ERR(rds_ibdev->mr_8k_pool)) { 17906766513SSantosh Shilimkar rds_ibdev->mr_8k_pool = NULL; 18006766513SSantosh Shilimkar goto put_dev; 18106766513SSantosh Shilimkar } 18206766513SSantosh Shilimkar 183f6df683fSsantosh.shilimkar@oracle.com rdsdebug("RDS/IB: max_mr = %d, max_wrs = %d, max_sge = %d, fmr_max_remaps = %d, max_1m_mrs = %d, max_8k_mrs = %d\n", 1840353261cSOr Gerlitz device->attrs.max_fmr, rds_ibdev->max_wrs, rds_ibdev->max_sge, 185f6df683fSsantosh.shilimkar@oracle.com rds_ibdev->fmr_max_remaps, rds_ibdev->max_1m_mrs, 186f6df683fSsantosh.shilimkar@oracle.com rds_ibdev->max_8k_mrs); 18706766513SSantosh Shilimkar 1882cb2912dSsantosh.shilimkar@oracle.com pr_info("RDS/IB: %s: %s supported and preferred\n", 1892cb2912dSsantosh.shilimkar@oracle.com device->name, 1902cb2912dSsantosh.shilimkar@oracle.com rds_ibdev->use_fastreg ? "FRMR" : "FMR"); 1912cb2912dSsantosh.shilimkar@oracle.com 192ec16227eSAndy Grover INIT_LIST_HEAD(&rds_ibdev->ipaddr_list); 193ec16227eSAndy Grover INIT_LIST_HEAD(&rds_ibdev->conn_list); 194ea819867SZach Brown 195ea819867SZach Brown down_write(&rds_ib_devices_lock); 196ea819867SZach Brown list_add_tail_rcu(&rds_ibdev->list, &rds_ib_devices); 197ea819867SZach Brown up_write(&rds_ib_devices_lock); 1983e0249f9SZach Brown atomic_inc(&rds_ibdev->refcount); 199ec16227eSAndy Grover 200ec16227eSAndy Grover ib_set_client_data(device, &rds_ib_client, rds_ibdev); 2013e0249f9SZach Brown atomic_inc(&rds_ibdev->refcount); 202ec16227eSAndy Grover 203fc19de38SZach Brown rds_ib_nodev_connect(); 204fc19de38SZach Brown 2053e0249f9SZach Brown put_dev: 2063e0249f9SZach Brown rds_ib_dev_put(rds_ibdev); 207ec16227eSAndy Grover } 208ec16227eSAndy Grover 2093e0249f9SZach Brown /* 2103e0249f9SZach Brown * New connections use this to find the device to associate with the 2113e0249f9SZach Brown * connection. It's not in the fast path so we're not concerned about the 2123e0249f9SZach Brown * performance of the IB call. (As of this writing, it uses an interrupt 2133e0249f9SZach Brown * blocking spinlock to serialize walking a per-device list of all registered 2143e0249f9SZach Brown * clients.) 2153e0249f9SZach Brown * 2163e0249f9SZach Brown * RCU is used to handle incoming connections racing with device teardown. 2173e0249f9SZach Brown * Rather than use a lock to serialize removal from the client_data and 2183e0249f9SZach Brown * getting a new reference, we use an RCU grace period. The destruction 2193e0249f9SZach Brown * path removes the device from client_data and then waits for all RCU 2203e0249f9SZach Brown * readers to finish. 2213e0249f9SZach Brown * 2223e0249f9SZach Brown * A new connection can get NULL from this if its arriving on a 2233e0249f9SZach Brown * device that is in the process of being removed. 2243e0249f9SZach Brown */ 2253e0249f9SZach Brown struct rds_ib_device *rds_ib_get_client_data(struct ib_device *device) 2263e0249f9SZach Brown { 2273e0249f9SZach Brown struct rds_ib_device *rds_ibdev; 2283e0249f9SZach Brown 2293e0249f9SZach Brown rcu_read_lock(); 2303e0249f9SZach Brown rds_ibdev = ib_get_client_data(device, &rds_ib_client); 2313e0249f9SZach Brown if (rds_ibdev) 2323e0249f9SZach Brown atomic_inc(&rds_ibdev->refcount); 2333e0249f9SZach Brown rcu_read_unlock(); 2343e0249f9SZach Brown return rds_ibdev; 2353e0249f9SZach Brown } 2363e0249f9SZach Brown 2373e0249f9SZach Brown /* 2383e0249f9SZach Brown * The IB stack is letting us know that a device is going away. This can 2393e0249f9SZach Brown * happen if the underlying HCA driver is removed or if PCI hotplug is removing 2403e0249f9SZach Brown * the pci function, for example. 2413e0249f9SZach Brown * 2423e0249f9SZach Brown * This can be called at any time and can be racing with any other RDS path. 2433e0249f9SZach Brown */ 2447c1eb45aSHaggai Eran static void rds_ib_remove_one(struct ib_device *device, void *client_data) 245ec16227eSAndy Grover { 2467c1eb45aSHaggai Eran struct rds_ib_device *rds_ibdev = client_data; 247ec16227eSAndy Grover 248ec16227eSAndy Grover if (!rds_ibdev) 249ec16227eSAndy Grover return; 250ec16227eSAndy Grover 251fc19de38SZach Brown rds_ib_dev_shutdown(rds_ibdev); 252ec16227eSAndy Grover 253ea819867SZach Brown /* stop connection attempts from getting a reference to this device. */ 2543e0249f9SZach Brown ib_set_client_data(device, &rds_ib_client, NULL); 255ea819867SZach Brown 256ea819867SZach Brown down_write(&rds_ib_devices_lock); 257ea819867SZach Brown list_del_rcu(&rds_ibdev->list); 258ea819867SZach Brown up_write(&rds_ib_devices_lock); 259ea819867SZach Brown 260ea819867SZach Brown /* 261ea819867SZach Brown * This synchronize rcu is waiting for readers of both the ib 262ea819867SZach Brown * client data and the devices list to finish before we drop 263ea819867SZach Brown * both of those references. 264ea819867SZach Brown */ 2653e0249f9SZach Brown synchronize_rcu(); 2663e0249f9SZach Brown rds_ib_dev_put(rds_ibdev); 2673e0249f9SZach Brown rds_ib_dev_put(rds_ibdev); 268ec16227eSAndy Grover } 269ec16227eSAndy Grover 270ec16227eSAndy Grover struct ib_client rds_ib_client = { 271ec16227eSAndy Grover .name = "rds_ib", 272ec16227eSAndy Grover .add = rds_ib_add_one, 273ec16227eSAndy Grover .remove = rds_ib_remove_one 274ec16227eSAndy Grover }; 275ec16227eSAndy Grover 276ec16227eSAndy Grover static int rds_ib_conn_info_visitor(struct rds_connection *conn, 277ec16227eSAndy Grover void *buffer) 278ec16227eSAndy Grover { 279ec16227eSAndy Grover struct rds_info_rdma_connection *iinfo = buffer; 280ec16227eSAndy Grover struct rds_ib_connection *ic; 281ec16227eSAndy Grover 282ec16227eSAndy Grover /* We will only ever look at IB transports */ 283ec16227eSAndy Grover if (conn->c_trans != &rds_ib_transport) 284ec16227eSAndy Grover return 0; 285ec16227eSAndy Grover 286ec16227eSAndy Grover iinfo->src_addr = conn->c_laddr; 287ec16227eSAndy Grover iinfo->dst_addr = conn->c_faddr; 288ec16227eSAndy Grover 289ec16227eSAndy Grover memset(&iinfo->src_gid, 0, sizeof(iinfo->src_gid)); 290ec16227eSAndy Grover memset(&iinfo->dst_gid, 0, sizeof(iinfo->dst_gid)); 291ec16227eSAndy Grover if (rds_conn_state(conn) == RDS_CONN_UP) { 292ec16227eSAndy Grover struct rds_ib_device *rds_ibdev; 293ec16227eSAndy Grover struct rdma_dev_addr *dev_addr; 294ec16227eSAndy Grover 295ec16227eSAndy Grover ic = conn->c_transport_data; 296ec16227eSAndy Grover dev_addr = &ic->i_cm_id->route.addr.dev_addr; 297ec16227eSAndy Grover 2986f8372b6SSean Hefty rdma_addr_get_sgid(dev_addr, (union ib_gid *) &iinfo->src_gid); 2996f8372b6SSean Hefty rdma_addr_get_dgid(dev_addr, (union ib_gid *) &iinfo->dst_gid); 300ec16227eSAndy Grover 3013e0249f9SZach Brown rds_ibdev = ic->rds_ibdev; 302ec16227eSAndy Grover iinfo->max_send_wr = ic->i_send_ring.w_nr; 303ec16227eSAndy Grover iinfo->max_recv_wr = ic->i_recv_ring.w_nr; 304ec16227eSAndy Grover iinfo->max_send_sge = rds_ibdev->max_sge; 305ec16227eSAndy Grover rds_ib_get_mr_info(rds_ibdev, iinfo); 306ec16227eSAndy Grover } 307ec16227eSAndy Grover return 1; 308ec16227eSAndy Grover } 309ec16227eSAndy Grover 310ec16227eSAndy Grover static void rds_ib_ic_info(struct socket *sock, unsigned int len, 311ec16227eSAndy Grover struct rds_info_iterator *iter, 312ec16227eSAndy Grover struct rds_info_lengths *lens) 313ec16227eSAndy Grover { 314ec16227eSAndy Grover rds_for_each_conn_info(sock, len, iter, lens, 315ec16227eSAndy Grover rds_ib_conn_info_visitor, 316ec16227eSAndy Grover sizeof(struct rds_info_rdma_connection)); 317ec16227eSAndy Grover } 318ec16227eSAndy Grover 319ec16227eSAndy Grover 320ec16227eSAndy Grover /* 321ec16227eSAndy Grover * Early RDS/IB was built to only bind to an address if there is an IPoIB 322ec16227eSAndy Grover * device with that address set. 323ec16227eSAndy Grover * 324ec16227eSAndy Grover * If it were me, I'd advocate for something more flexible. Sending and 325ec16227eSAndy Grover * receiving should be device-agnostic. Transports would try and maintain 326ec16227eSAndy Grover * connections between peers who have messages queued. Userspace would be 327ec16227eSAndy Grover * allowed to influence which paths have priority. We could call userspace 328ec16227eSAndy Grover * asserting this policy "routing". 329ec16227eSAndy Grover */ 330d5a8ac28SSowmini Varadhan static int rds_ib_laddr_check(struct net *net, __be32 addr) 331ec16227eSAndy Grover { 332ec16227eSAndy Grover int ret; 333ec16227eSAndy Grover struct rdma_cm_id *cm_id; 334ec16227eSAndy Grover struct sockaddr_in sin; 335ec16227eSAndy Grover 336ec16227eSAndy Grover /* Create a CMA ID and try to bind it. This catches both 337ec16227eSAndy Grover * IB and iWARP capable NICs. 338ec16227eSAndy Grover */ 339fa20105eSGuy Shapiro cm_id = rdma_create_id(&init_net, NULL, NULL, RDMA_PS_TCP, IB_QPT_RC); 34094713babSDan Carpenter if (IS_ERR(cm_id)) 34194713babSDan Carpenter return PTR_ERR(cm_id); 342ec16227eSAndy Grover 343ec16227eSAndy Grover memset(&sin, 0, sizeof(sin)); 344ec16227eSAndy Grover sin.sin_family = AF_INET; 345ec16227eSAndy Grover sin.sin_addr.s_addr = addr; 346ec16227eSAndy Grover 347ec16227eSAndy Grover /* rdma_bind_addr will only succeed for IB & iWARP devices */ 348ec16227eSAndy Grover ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin); 349ec16227eSAndy Grover /* due to this, we will claim to support iWARP devices unless we 350ec16227eSAndy Grover check node_type. */ 351c2349758SSasha Levin if (ret || !cm_id->device || 352c2349758SSasha Levin cm_id->device->node_type != RDMA_NODE_IB_CA) 353ec16227eSAndy Grover ret = -EADDRNOTAVAIL; 354ec16227eSAndy Grover 355ec16227eSAndy Grover rdsdebug("addr %pI4 ret %d node type %d\n", 356ec16227eSAndy Grover &addr, ret, 357ec16227eSAndy Grover cm_id->device ? cm_id->device->node_type : -1); 358ec16227eSAndy Grover 359ec16227eSAndy Grover rdma_destroy_id(cm_id); 360ec16227eSAndy Grover 361ec16227eSAndy Grover return ret; 362ec16227eSAndy Grover } 363ec16227eSAndy Grover 36424fa163aSZach Brown static void rds_ib_unregister_client(void) 36524fa163aSZach Brown { 36624fa163aSZach Brown ib_unregister_client(&rds_ib_client); 36724fa163aSZach Brown /* wait for rds_ib_dev_free() to complete */ 36824fa163aSZach Brown flush_workqueue(rds_wq); 36924fa163aSZach Brown } 37024fa163aSZach Brown 371ec16227eSAndy Grover void rds_ib_exit(void) 372ec16227eSAndy Grover { 373ec16227eSAndy Grover rds_info_deregister_func(RDS_INFO_IB_CONNECTIONS, rds_ib_ic_info); 37424fa163aSZach Brown rds_ib_unregister_client(); 3758aeb1ba6SZach Brown rds_ib_destroy_nodev_conns(); 376ec16227eSAndy Grover rds_ib_sysctl_exit(); 377ec16227eSAndy Grover rds_ib_recv_exit(); 378ec16227eSAndy Grover rds_trans_unregister(&rds_ib_transport); 379f6df683fSsantosh.shilimkar@oracle.com rds_ib_mr_exit(); 380ec16227eSAndy Grover } 381ec16227eSAndy Grover 382ec16227eSAndy Grover struct rds_transport rds_ib_transport = { 383ec16227eSAndy Grover .laddr_check = rds_ib_laddr_check, 384*226f7a7dSSowmini Varadhan .xmit_path_complete = rds_ib_xmit_path_complete, 385ec16227eSAndy Grover .xmit = rds_ib_xmit, 386ec16227eSAndy Grover .xmit_rdma = rds_ib_xmit_rdma, 38715133f6eSAndy Grover .xmit_atomic = rds_ib_xmit_atomic, 388ec16227eSAndy Grover .recv = rds_ib_recv, 389ec16227eSAndy Grover .conn_alloc = rds_ib_conn_alloc, 390ec16227eSAndy Grover .conn_free = rds_ib_conn_free, 391ec16227eSAndy Grover .conn_connect = rds_ib_conn_connect, 392*226f7a7dSSowmini Varadhan .conn_path_shutdown = rds_ib_conn_path_shutdown, 393ec16227eSAndy Grover .inc_copy_to_user = rds_ib_inc_copy_to_user, 394ec16227eSAndy Grover .inc_free = rds_ib_inc_free, 395ec16227eSAndy Grover .cm_initiate_connect = rds_ib_cm_initiate_connect, 396ec16227eSAndy Grover .cm_handle_connect = rds_ib_cm_handle_connect, 397ec16227eSAndy Grover .cm_connect_complete = rds_ib_cm_connect_complete, 398ec16227eSAndy Grover .stats_info_copy = rds_ib_stats_info_copy, 399ec16227eSAndy Grover .exit = rds_ib_exit, 400ec16227eSAndy Grover .get_mr = rds_ib_get_mr, 401ec16227eSAndy Grover .sync_mr = rds_ib_sync_mr, 402ec16227eSAndy Grover .free_mr = rds_ib_free_mr, 403ec16227eSAndy Grover .flush_mrs = rds_ib_flush_mrs, 404ec16227eSAndy Grover .t_owner = THIS_MODULE, 405ec16227eSAndy Grover .t_name = "infiniband", 406335776bdSAndy Grover .t_type = RDS_TRANS_IB 407ec16227eSAndy Grover }; 408ec16227eSAndy Grover 409ef87b7eaSZach Brown int rds_ib_init(void) 410ec16227eSAndy Grover { 411ec16227eSAndy Grover int ret; 412ec16227eSAndy Grover 413ec16227eSAndy Grover INIT_LIST_HEAD(&rds_ib_devices); 414ec16227eSAndy Grover 415f6df683fSsantosh.shilimkar@oracle.com ret = rds_ib_mr_init(); 416515e079dSZach Brown if (ret) 417c534a107STejun Heo goto out; 418515e079dSZach Brown 419ad1d7dc0Ssantosh.shilimkar@oracle.com ret = ib_register_client(&rds_ib_client); 420ad1d7dc0Ssantosh.shilimkar@oracle.com if (ret) 421f6df683fSsantosh.shilimkar@oracle.com goto out_mr_exit; 422ad1d7dc0Ssantosh.shilimkar@oracle.com 423ec16227eSAndy Grover ret = rds_ib_sysctl_init(); 424ec16227eSAndy Grover if (ret) 425ec16227eSAndy Grover goto out_ibreg; 426ec16227eSAndy Grover 427ec16227eSAndy Grover ret = rds_ib_recv_init(); 428ec16227eSAndy Grover if (ret) 429ec16227eSAndy Grover goto out_sysctl; 430ec16227eSAndy Grover 431ec16227eSAndy Grover ret = rds_trans_register(&rds_ib_transport); 432ec16227eSAndy Grover if (ret) 433ec16227eSAndy Grover goto out_recv; 434ec16227eSAndy Grover 435ec16227eSAndy Grover rds_info_register_func(RDS_INFO_IB_CONNECTIONS, rds_ib_ic_info); 436ec16227eSAndy Grover 437ec16227eSAndy Grover goto out; 438ec16227eSAndy Grover 439ec16227eSAndy Grover out_recv: 440ec16227eSAndy Grover rds_ib_recv_exit(); 441ec16227eSAndy Grover out_sysctl: 442ec16227eSAndy Grover rds_ib_sysctl_exit(); 443ec16227eSAndy Grover out_ibreg: 44424fa163aSZach Brown rds_ib_unregister_client(); 445f6df683fSsantosh.shilimkar@oracle.com out_mr_exit: 446f6df683fSsantosh.shilimkar@oracle.com rds_ib_mr_exit(); 447ec16227eSAndy Grover out: 448ec16227eSAndy Grover return ret; 449ec16227eSAndy Grover } 450ec16227eSAndy Grover 451ec16227eSAndy Grover MODULE_LICENSE("GPL"); 452ec16227eSAndy Grover 453