11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved. 31da177e4SLinus Torvalds * Copyright (c) 2004 Infinicon Corporation. All rights reserved. 41da177e4SLinus Torvalds * Copyright (c) 2004 Intel Corporation. All rights reserved. 51da177e4SLinus Torvalds * Copyright (c) 2004 Topspin Corporation. All rights reserved. 61da177e4SLinus Torvalds * Copyright (c) 2004 Voltaire Corporation. All rights reserved. 72a1d9b7fSRoland Dreier * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 833b9b3eeSRoland Dreier * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * This software is available to you under a choice of one of two 111da177e4SLinus Torvalds * licenses. You may choose to be licensed under the terms of the GNU 121da177e4SLinus Torvalds * General Public License (GPL) Version 2, available from the file 131da177e4SLinus Torvalds * COPYING in the main directory of this source tree, or the 141da177e4SLinus Torvalds * OpenIB.org BSD license below: 151da177e4SLinus Torvalds * 161da177e4SLinus Torvalds * Redistribution and use in source and binary forms, with or 171da177e4SLinus Torvalds * without modification, are permitted provided that the following 181da177e4SLinus Torvalds * conditions are met: 191da177e4SLinus Torvalds * 201da177e4SLinus Torvalds * - Redistributions of source code must retain the above 211da177e4SLinus Torvalds * copyright notice, this list of conditions and the following 221da177e4SLinus Torvalds * disclaimer. 231da177e4SLinus Torvalds * 241da177e4SLinus Torvalds * - Redistributions in binary form must reproduce the above 251da177e4SLinus Torvalds * copyright notice, this list of conditions and the following 261da177e4SLinus Torvalds * disclaimer in the documentation and/or other materials 271da177e4SLinus Torvalds * provided with the distribution. 281da177e4SLinus Torvalds * 291da177e4SLinus Torvalds * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 301da177e4SLinus Torvalds * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 311da177e4SLinus Torvalds * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 321da177e4SLinus Torvalds * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 331da177e4SLinus Torvalds * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 341da177e4SLinus Torvalds * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 351da177e4SLinus Torvalds * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 361da177e4SLinus Torvalds * SOFTWARE. 371da177e4SLinus Torvalds */ 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds #include <linux/errno.h> 401da177e4SLinus Torvalds #include <linux/err.h> 41b108d976SPaul Gortmaker #include <linux/export.h> 428c65b4a6STim Schmielau #include <linux/string.h> 430e0ec7e0SSean Hefty #include <linux/slab.h> 441da177e4SLinus Torvalds 45a4d61e84SRoland Dreier #include <rdma/ib_verbs.h> 46a4d61e84SRoland Dreier #include <rdma/ib_cache.h> 471da177e4SLinus Torvalds 48bf6a9e31SJack Morgenstein int ib_rate_to_mult(enum ib_rate rate) 49bf6a9e31SJack Morgenstein { 50bf6a9e31SJack Morgenstein switch (rate) { 51bf6a9e31SJack Morgenstein case IB_RATE_2_5_GBPS: return 1; 52bf6a9e31SJack Morgenstein case IB_RATE_5_GBPS: return 2; 53bf6a9e31SJack Morgenstein case IB_RATE_10_GBPS: return 4; 54bf6a9e31SJack Morgenstein case IB_RATE_20_GBPS: return 8; 55bf6a9e31SJack Morgenstein case IB_RATE_30_GBPS: return 12; 56bf6a9e31SJack Morgenstein case IB_RATE_40_GBPS: return 16; 57bf6a9e31SJack Morgenstein case IB_RATE_60_GBPS: return 24; 58bf6a9e31SJack Morgenstein case IB_RATE_80_GBPS: return 32; 59bf6a9e31SJack Morgenstein case IB_RATE_120_GBPS: return 48; 60bf6a9e31SJack Morgenstein default: return -1; 61bf6a9e31SJack Morgenstein } 62bf6a9e31SJack Morgenstein } 63bf6a9e31SJack Morgenstein EXPORT_SYMBOL(ib_rate_to_mult); 64bf6a9e31SJack Morgenstein 65bf6a9e31SJack Morgenstein enum ib_rate mult_to_ib_rate(int mult) 66bf6a9e31SJack Morgenstein { 67bf6a9e31SJack Morgenstein switch (mult) { 68bf6a9e31SJack Morgenstein case 1: return IB_RATE_2_5_GBPS; 69bf6a9e31SJack Morgenstein case 2: return IB_RATE_5_GBPS; 70bf6a9e31SJack Morgenstein case 4: return IB_RATE_10_GBPS; 71bf6a9e31SJack Morgenstein case 8: return IB_RATE_20_GBPS; 72bf6a9e31SJack Morgenstein case 12: return IB_RATE_30_GBPS; 73bf6a9e31SJack Morgenstein case 16: return IB_RATE_40_GBPS; 74bf6a9e31SJack Morgenstein case 24: return IB_RATE_60_GBPS; 75bf6a9e31SJack Morgenstein case 32: return IB_RATE_80_GBPS; 76bf6a9e31SJack Morgenstein case 48: return IB_RATE_120_GBPS; 77bf6a9e31SJack Morgenstein default: return IB_RATE_PORT_CURRENT; 78bf6a9e31SJack Morgenstein } 79bf6a9e31SJack Morgenstein } 80bf6a9e31SJack Morgenstein EXPORT_SYMBOL(mult_to_ib_rate); 81bf6a9e31SJack Morgenstein 8271eeba16SMarcel Apfelbaum int ib_rate_to_mbps(enum ib_rate rate) 8371eeba16SMarcel Apfelbaum { 8471eeba16SMarcel Apfelbaum switch (rate) { 8571eeba16SMarcel Apfelbaum case IB_RATE_2_5_GBPS: return 2500; 8671eeba16SMarcel Apfelbaum case IB_RATE_5_GBPS: return 5000; 8771eeba16SMarcel Apfelbaum case IB_RATE_10_GBPS: return 10000; 8871eeba16SMarcel Apfelbaum case IB_RATE_20_GBPS: return 20000; 8971eeba16SMarcel Apfelbaum case IB_RATE_30_GBPS: return 30000; 9071eeba16SMarcel Apfelbaum case IB_RATE_40_GBPS: return 40000; 9171eeba16SMarcel Apfelbaum case IB_RATE_60_GBPS: return 60000; 9271eeba16SMarcel Apfelbaum case IB_RATE_80_GBPS: return 80000; 9371eeba16SMarcel Apfelbaum case IB_RATE_120_GBPS: return 120000; 9471eeba16SMarcel Apfelbaum case IB_RATE_14_GBPS: return 14062; 9571eeba16SMarcel Apfelbaum case IB_RATE_56_GBPS: return 56250; 9671eeba16SMarcel Apfelbaum case IB_RATE_112_GBPS: return 112500; 9771eeba16SMarcel Apfelbaum case IB_RATE_168_GBPS: return 168750; 9871eeba16SMarcel Apfelbaum case IB_RATE_25_GBPS: return 25781; 9971eeba16SMarcel Apfelbaum case IB_RATE_100_GBPS: return 103125; 10071eeba16SMarcel Apfelbaum case IB_RATE_200_GBPS: return 206250; 10171eeba16SMarcel Apfelbaum case IB_RATE_300_GBPS: return 309375; 10271eeba16SMarcel Apfelbaum default: return -1; 10371eeba16SMarcel Apfelbaum } 10471eeba16SMarcel Apfelbaum } 10571eeba16SMarcel Apfelbaum EXPORT_SYMBOL(ib_rate_to_mbps); 10671eeba16SMarcel Apfelbaum 10707ebafbaSTom Tucker enum rdma_transport_type 10807ebafbaSTom Tucker rdma_node_get_transport(enum rdma_node_type node_type) 10907ebafbaSTom Tucker { 11007ebafbaSTom Tucker switch (node_type) { 11107ebafbaSTom Tucker case RDMA_NODE_IB_CA: 11207ebafbaSTom Tucker case RDMA_NODE_IB_SWITCH: 11307ebafbaSTom Tucker case RDMA_NODE_IB_ROUTER: 11407ebafbaSTom Tucker return RDMA_TRANSPORT_IB; 11507ebafbaSTom Tucker case RDMA_NODE_RNIC: 11607ebafbaSTom Tucker return RDMA_TRANSPORT_IWARP; 11707ebafbaSTom Tucker default: 11807ebafbaSTom Tucker BUG(); 11907ebafbaSTom Tucker return 0; 12007ebafbaSTom Tucker } 12107ebafbaSTom Tucker } 12207ebafbaSTom Tucker EXPORT_SYMBOL(rdma_node_get_transport); 12307ebafbaSTom Tucker 124a3f5adafSEli Cohen enum rdma_link_layer rdma_port_get_link_layer(struct ib_device *device, u8 port_num) 125a3f5adafSEli Cohen { 126a3f5adafSEli Cohen if (device->get_link_layer) 127a3f5adafSEli Cohen return device->get_link_layer(device, port_num); 128a3f5adafSEli Cohen 129a3f5adafSEli Cohen switch (rdma_node_get_transport(device->node_type)) { 130a3f5adafSEli Cohen case RDMA_TRANSPORT_IB: 131a3f5adafSEli Cohen return IB_LINK_LAYER_INFINIBAND; 132a3f5adafSEli Cohen case RDMA_TRANSPORT_IWARP: 133a3f5adafSEli Cohen return IB_LINK_LAYER_ETHERNET; 134a3f5adafSEli Cohen default: 135a3f5adafSEli Cohen return IB_LINK_LAYER_UNSPECIFIED; 136a3f5adafSEli Cohen } 137a3f5adafSEli Cohen } 138a3f5adafSEli Cohen EXPORT_SYMBOL(rdma_port_get_link_layer); 139a3f5adafSEli Cohen 1401da177e4SLinus Torvalds /* Protection domains */ 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds struct ib_pd *ib_alloc_pd(struct ib_device *device) 1431da177e4SLinus Torvalds { 1441da177e4SLinus Torvalds struct ib_pd *pd; 1451da177e4SLinus Torvalds 146b5e81bf5SRoland Dreier pd = device->alloc_pd(device, NULL, NULL); 1471da177e4SLinus Torvalds 1481da177e4SLinus Torvalds if (!IS_ERR(pd)) { 1491da177e4SLinus Torvalds pd->device = device; 150b5e81bf5SRoland Dreier pd->uobject = NULL; 1511da177e4SLinus Torvalds atomic_set(&pd->usecnt, 0); 1521da177e4SLinus Torvalds } 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds return pd; 1551da177e4SLinus Torvalds } 1561da177e4SLinus Torvalds EXPORT_SYMBOL(ib_alloc_pd); 1571da177e4SLinus Torvalds 1581da177e4SLinus Torvalds int ib_dealloc_pd(struct ib_pd *pd) 1591da177e4SLinus Torvalds { 1601da177e4SLinus Torvalds if (atomic_read(&pd->usecnt)) 1611da177e4SLinus Torvalds return -EBUSY; 1621da177e4SLinus Torvalds 1631da177e4SLinus Torvalds return pd->device->dealloc_pd(pd); 1641da177e4SLinus Torvalds } 1651da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dealloc_pd); 1661da177e4SLinus Torvalds 1671da177e4SLinus Torvalds /* Address handles */ 1681da177e4SLinus Torvalds 1691da177e4SLinus Torvalds struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) 1701da177e4SLinus Torvalds { 1711da177e4SLinus Torvalds struct ib_ah *ah; 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds ah = pd->device->create_ah(pd, ah_attr); 1741da177e4SLinus Torvalds 1751da177e4SLinus Torvalds if (!IS_ERR(ah)) { 1761da177e4SLinus Torvalds ah->device = pd->device; 1771da177e4SLinus Torvalds ah->pd = pd; 178b5e81bf5SRoland Dreier ah->uobject = NULL; 1791da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 1801da177e4SLinus Torvalds } 1811da177e4SLinus Torvalds 1821da177e4SLinus Torvalds return ah; 1831da177e4SLinus Torvalds } 1841da177e4SLinus Torvalds EXPORT_SYMBOL(ib_create_ah); 1851da177e4SLinus Torvalds 1864e00d694SSean Hefty int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc, 1874e00d694SSean Hefty struct ib_grh *grh, struct ib_ah_attr *ah_attr) 188513789edSHal Rosenstock { 189513789edSHal Rosenstock u32 flow_class; 190513789edSHal Rosenstock u16 gid_index; 191513789edSHal Rosenstock int ret; 192513789edSHal Rosenstock 1934e00d694SSean Hefty memset(ah_attr, 0, sizeof *ah_attr); 1944e00d694SSean Hefty ah_attr->dlid = wc->slid; 1954e00d694SSean Hefty ah_attr->sl = wc->sl; 1964e00d694SSean Hefty ah_attr->src_path_bits = wc->dlid_path_bits; 1974e00d694SSean Hefty ah_attr->port_num = port_num; 198513789edSHal Rosenstock 199513789edSHal Rosenstock if (wc->wc_flags & IB_WC_GRH) { 2004e00d694SSean Hefty ah_attr->ah_flags = IB_AH_GRH; 2014e00d694SSean Hefty ah_attr->grh.dgid = grh->sgid; 202513789edSHal Rosenstock 2034e00d694SSean Hefty ret = ib_find_cached_gid(device, &grh->dgid, &port_num, 204513789edSHal Rosenstock &gid_index); 205513789edSHal Rosenstock if (ret) 2064e00d694SSean Hefty return ret; 207513789edSHal Rosenstock 2084e00d694SSean Hefty ah_attr->grh.sgid_index = (u8) gid_index; 209497677abSHal Rosenstock flow_class = be32_to_cpu(grh->version_tclass_flow); 2104e00d694SSean Hefty ah_attr->grh.flow_label = flow_class & 0xFFFFF; 21147645d8dSSean Hefty ah_attr->grh.hop_limit = 0xFF; 2124e00d694SSean Hefty ah_attr->grh.traffic_class = (flow_class >> 20) & 0xFF; 213513789edSHal Rosenstock } 2144e00d694SSean Hefty return 0; 2154e00d694SSean Hefty } 2164e00d694SSean Hefty EXPORT_SYMBOL(ib_init_ah_from_wc); 2174e00d694SSean Hefty 2184e00d694SSean Hefty struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc, 2194e00d694SSean Hefty struct ib_grh *grh, u8 port_num) 2204e00d694SSean Hefty { 2214e00d694SSean Hefty struct ib_ah_attr ah_attr; 2224e00d694SSean Hefty int ret; 2234e00d694SSean Hefty 2244e00d694SSean Hefty ret = ib_init_ah_from_wc(pd->device, port_num, wc, grh, &ah_attr); 2254e00d694SSean Hefty if (ret) 2264e00d694SSean Hefty return ERR_PTR(ret); 227513789edSHal Rosenstock 228513789edSHal Rosenstock return ib_create_ah(pd, &ah_attr); 229513789edSHal Rosenstock } 230513789edSHal Rosenstock EXPORT_SYMBOL(ib_create_ah_from_wc); 231513789edSHal Rosenstock 2321da177e4SLinus Torvalds int ib_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) 2331da177e4SLinus Torvalds { 2341da177e4SLinus Torvalds return ah->device->modify_ah ? 2351da177e4SLinus Torvalds ah->device->modify_ah(ah, ah_attr) : 2361da177e4SLinus Torvalds -ENOSYS; 2371da177e4SLinus Torvalds } 2381da177e4SLinus Torvalds EXPORT_SYMBOL(ib_modify_ah); 2391da177e4SLinus Torvalds 2401da177e4SLinus Torvalds int ib_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) 2411da177e4SLinus Torvalds { 2421da177e4SLinus Torvalds return ah->device->query_ah ? 2431da177e4SLinus Torvalds ah->device->query_ah(ah, ah_attr) : 2441da177e4SLinus Torvalds -ENOSYS; 2451da177e4SLinus Torvalds } 2461da177e4SLinus Torvalds EXPORT_SYMBOL(ib_query_ah); 2471da177e4SLinus Torvalds 2481da177e4SLinus Torvalds int ib_destroy_ah(struct ib_ah *ah) 2491da177e4SLinus Torvalds { 2501da177e4SLinus Torvalds struct ib_pd *pd; 2511da177e4SLinus Torvalds int ret; 2521da177e4SLinus Torvalds 2531da177e4SLinus Torvalds pd = ah->pd; 2541da177e4SLinus Torvalds ret = ah->device->destroy_ah(ah); 2551da177e4SLinus Torvalds if (!ret) 2561da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 2571da177e4SLinus Torvalds 2581da177e4SLinus Torvalds return ret; 2591da177e4SLinus Torvalds } 2601da177e4SLinus Torvalds EXPORT_SYMBOL(ib_destroy_ah); 2611da177e4SLinus Torvalds 262d41fcc67SRoland Dreier /* Shared receive queues */ 263d41fcc67SRoland Dreier 264d41fcc67SRoland Dreier struct ib_srq *ib_create_srq(struct ib_pd *pd, 265d41fcc67SRoland Dreier struct ib_srq_init_attr *srq_init_attr) 266d41fcc67SRoland Dreier { 267d41fcc67SRoland Dreier struct ib_srq *srq; 268d41fcc67SRoland Dreier 269d41fcc67SRoland Dreier if (!pd->device->create_srq) 270d41fcc67SRoland Dreier return ERR_PTR(-ENOSYS); 271d41fcc67SRoland Dreier 272d41fcc67SRoland Dreier srq = pd->device->create_srq(pd, srq_init_attr, NULL); 273d41fcc67SRoland Dreier 274d41fcc67SRoland Dreier if (!IS_ERR(srq)) { 275d41fcc67SRoland Dreier srq->device = pd->device; 276d41fcc67SRoland Dreier srq->pd = pd; 277d41fcc67SRoland Dreier srq->uobject = NULL; 278d41fcc67SRoland Dreier srq->event_handler = srq_init_attr->event_handler; 279d41fcc67SRoland Dreier srq->srq_context = srq_init_attr->srq_context; 28096104edaSSean Hefty srq->srq_type = srq_init_attr->srq_type; 281418d5130SSean Hefty if (srq->srq_type == IB_SRQT_XRC) { 282418d5130SSean Hefty srq->ext.xrc.xrcd = srq_init_attr->ext.xrc.xrcd; 283418d5130SSean Hefty srq->ext.xrc.cq = srq_init_attr->ext.xrc.cq; 284418d5130SSean Hefty atomic_inc(&srq->ext.xrc.xrcd->usecnt); 285418d5130SSean Hefty atomic_inc(&srq->ext.xrc.cq->usecnt); 286418d5130SSean Hefty } 287d41fcc67SRoland Dreier atomic_inc(&pd->usecnt); 288d41fcc67SRoland Dreier atomic_set(&srq->usecnt, 0); 289d41fcc67SRoland Dreier } 290d41fcc67SRoland Dreier 291d41fcc67SRoland Dreier return srq; 292d41fcc67SRoland Dreier } 293d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_create_srq); 294d41fcc67SRoland Dreier 295d41fcc67SRoland Dreier int ib_modify_srq(struct ib_srq *srq, 296d41fcc67SRoland Dreier struct ib_srq_attr *srq_attr, 297d41fcc67SRoland Dreier enum ib_srq_attr_mask srq_attr_mask) 298d41fcc67SRoland Dreier { 2997ce5eacbSDotan Barak return srq->device->modify_srq ? 3007ce5eacbSDotan Barak srq->device->modify_srq(srq, srq_attr, srq_attr_mask, NULL) : 3017ce5eacbSDotan Barak -ENOSYS; 302d41fcc67SRoland Dreier } 303d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_modify_srq); 304d41fcc67SRoland Dreier 305d41fcc67SRoland Dreier int ib_query_srq(struct ib_srq *srq, 306d41fcc67SRoland Dreier struct ib_srq_attr *srq_attr) 307d41fcc67SRoland Dreier { 308d41fcc67SRoland Dreier return srq->device->query_srq ? 309d41fcc67SRoland Dreier srq->device->query_srq(srq, srq_attr) : -ENOSYS; 310d41fcc67SRoland Dreier } 311d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_query_srq); 312d41fcc67SRoland Dreier 313d41fcc67SRoland Dreier int ib_destroy_srq(struct ib_srq *srq) 314d41fcc67SRoland Dreier { 315d41fcc67SRoland Dreier struct ib_pd *pd; 316418d5130SSean Hefty enum ib_srq_type srq_type; 317418d5130SSean Hefty struct ib_xrcd *uninitialized_var(xrcd); 318418d5130SSean Hefty struct ib_cq *uninitialized_var(cq); 319d41fcc67SRoland Dreier int ret; 320d41fcc67SRoland Dreier 321d41fcc67SRoland Dreier if (atomic_read(&srq->usecnt)) 322d41fcc67SRoland Dreier return -EBUSY; 323d41fcc67SRoland Dreier 324d41fcc67SRoland Dreier pd = srq->pd; 325418d5130SSean Hefty srq_type = srq->srq_type; 326418d5130SSean Hefty if (srq_type == IB_SRQT_XRC) { 327418d5130SSean Hefty xrcd = srq->ext.xrc.xrcd; 328418d5130SSean Hefty cq = srq->ext.xrc.cq; 329418d5130SSean Hefty } 330d41fcc67SRoland Dreier 331d41fcc67SRoland Dreier ret = srq->device->destroy_srq(srq); 332418d5130SSean Hefty if (!ret) { 333d41fcc67SRoland Dreier atomic_dec(&pd->usecnt); 334418d5130SSean Hefty if (srq_type == IB_SRQT_XRC) { 335418d5130SSean Hefty atomic_dec(&xrcd->usecnt); 336418d5130SSean Hefty atomic_dec(&cq->usecnt); 337418d5130SSean Hefty } 338418d5130SSean Hefty } 339d41fcc67SRoland Dreier 340d41fcc67SRoland Dreier return ret; 341d41fcc67SRoland Dreier } 342d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_destroy_srq); 343d41fcc67SRoland Dreier 3441da177e4SLinus Torvalds /* Queue pairs */ 3451da177e4SLinus Torvalds 3460e0ec7e0SSean Hefty static void __ib_shared_qp_event_handler(struct ib_event *event, void *context) 3470e0ec7e0SSean Hefty { 3480e0ec7e0SSean Hefty struct ib_qp *qp = context; 3490e0ec7e0SSean Hefty 3500e0ec7e0SSean Hefty list_for_each_entry(event->element.qp, &qp->open_list, open_list) 3510e0ec7e0SSean Hefty event->element.qp->event_handler(event, event->element.qp->qp_context); 3520e0ec7e0SSean Hefty } 3530e0ec7e0SSean Hefty 354d3d72d90SSean Hefty static void __ib_insert_xrcd_qp(struct ib_xrcd *xrcd, struct ib_qp *qp) 355d3d72d90SSean Hefty { 356d3d72d90SSean Hefty mutex_lock(&xrcd->tgt_qp_mutex); 357d3d72d90SSean Hefty list_add(&qp->xrcd_list, &xrcd->tgt_qp_list); 358d3d72d90SSean Hefty mutex_unlock(&xrcd->tgt_qp_mutex); 359d3d72d90SSean Hefty } 360d3d72d90SSean Hefty 3610e0ec7e0SSean Hefty static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp, 3620e0ec7e0SSean Hefty void (*event_handler)(struct ib_event *, void *), 3630e0ec7e0SSean Hefty void *qp_context) 364d3d72d90SSean Hefty { 3650e0ec7e0SSean Hefty struct ib_qp *qp; 3660e0ec7e0SSean Hefty unsigned long flags; 3670e0ec7e0SSean Hefty 3680e0ec7e0SSean Hefty qp = kzalloc(sizeof *qp, GFP_KERNEL); 3690e0ec7e0SSean Hefty if (!qp) 3700e0ec7e0SSean Hefty return ERR_PTR(-ENOMEM); 3710e0ec7e0SSean Hefty 3720e0ec7e0SSean Hefty qp->real_qp = real_qp; 3730e0ec7e0SSean Hefty atomic_inc(&real_qp->usecnt); 3740e0ec7e0SSean Hefty qp->device = real_qp->device; 3750e0ec7e0SSean Hefty qp->event_handler = event_handler; 3760e0ec7e0SSean Hefty qp->qp_context = qp_context; 3770e0ec7e0SSean Hefty qp->qp_num = real_qp->qp_num; 3780e0ec7e0SSean Hefty qp->qp_type = real_qp->qp_type; 3790e0ec7e0SSean Hefty 3800e0ec7e0SSean Hefty spin_lock_irqsave(&real_qp->device->event_handler_lock, flags); 3810e0ec7e0SSean Hefty list_add(&qp->open_list, &real_qp->open_list); 3820e0ec7e0SSean Hefty spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags); 3830e0ec7e0SSean Hefty 3840e0ec7e0SSean Hefty return qp; 385d3d72d90SSean Hefty } 386d3d72d90SSean Hefty 3870e0ec7e0SSean Hefty struct ib_qp *ib_open_qp(struct ib_xrcd *xrcd, 3880e0ec7e0SSean Hefty struct ib_qp_open_attr *qp_open_attr) 3890e0ec7e0SSean Hefty { 3900e0ec7e0SSean Hefty struct ib_qp *qp, *real_qp; 3910e0ec7e0SSean Hefty 3920e0ec7e0SSean Hefty if (qp_open_attr->qp_type != IB_QPT_XRC_TGT) 3930e0ec7e0SSean Hefty return ERR_PTR(-EINVAL); 3940e0ec7e0SSean Hefty 3950e0ec7e0SSean Hefty qp = ERR_PTR(-EINVAL); 3960e0ec7e0SSean Hefty mutex_lock(&xrcd->tgt_qp_mutex); 3970e0ec7e0SSean Hefty list_for_each_entry(real_qp, &xrcd->tgt_qp_list, xrcd_list) { 3980e0ec7e0SSean Hefty if (real_qp->qp_num == qp_open_attr->qp_num) { 3990e0ec7e0SSean Hefty qp = __ib_open_qp(real_qp, qp_open_attr->event_handler, 4000e0ec7e0SSean Hefty qp_open_attr->qp_context); 4010e0ec7e0SSean Hefty break; 4020e0ec7e0SSean Hefty } 4030e0ec7e0SSean Hefty } 4040e0ec7e0SSean Hefty mutex_unlock(&xrcd->tgt_qp_mutex); 4050e0ec7e0SSean Hefty return qp; 4060e0ec7e0SSean Hefty } 4070e0ec7e0SSean Hefty EXPORT_SYMBOL(ib_open_qp); 4080e0ec7e0SSean Hefty 4091da177e4SLinus Torvalds struct ib_qp *ib_create_qp(struct ib_pd *pd, 4101da177e4SLinus Torvalds struct ib_qp_init_attr *qp_init_attr) 4111da177e4SLinus Torvalds { 4120e0ec7e0SSean Hefty struct ib_qp *qp, *real_qp; 413b42b63cfSSean Hefty struct ib_device *device; 4141da177e4SLinus Torvalds 415b42b63cfSSean Hefty device = pd ? pd->device : qp_init_attr->xrcd->device; 416b42b63cfSSean Hefty qp = device->create_qp(pd, qp_init_attr, NULL); 4171da177e4SLinus Torvalds 4181da177e4SLinus Torvalds if (!IS_ERR(qp)) { 419b42b63cfSSean Hefty qp->device = device; 4200e0ec7e0SSean Hefty qp->real_qp = qp; 421b5e81bf5SRoland Dreier qp->uobject = NULL; 4220e0ec7e0SSean Hefty qp->qp_type = qp_init_attr->qp_type; 423b42b63cfSSean Hefty 424e47e321aSBernd Schubert atomic_set(&qp->usecnt, 0); 425b42b63cfSSean Hefty if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) { 4260e0ec7e0SSean Hefty qp->event_handler = __ib_shared_qp_event_handler; 4270e0ec7e0SSean Hefty qp->qp_context = qp; 428b42b63cfSSean Hefty qp->pd = NULL; 429b42b63cfSSean Hefty qp->send_cq = qp->recv_cq = NULL; 430b42b63cfSSean Hefty qp->srq = NULL; 431b42b63cfSSean Hefty qp->xrcd = qp_init_attr->xrcd; 432b42b63cfSSean Hefty atomic_inc(&qp_init_attr->xrcd->usecnt); 4330e0ec7e0SSean Hefty INIT_LIST_HEAD(&qp->open_list); 4340e0ec7e0SSean Hefty 4350e0ec7e0SSean Hefty real_qp = qp; 4360e0ec7e0SSean Hefty qp = __ib_open_qp(real_qp, qp_init_attr->event_handler, 4370e0ec7e0SSean Hefty qp_init_attr->qp_context); 4380e0ec7e0SSean Hefty if (!IS_ERR(qp)) 4390e0ec7e0SSean Hefty __ib_insert_xrcd_qp(qp_init_attr->xrcd, real_qp); 4400e0ec7e0SSean Hefty else 4410e0ec7e0SSean Hefty real_qp->device->destroy_qp(real_qp); 442b42b63cfSSean Hefty } else { 4431da177e4SLinus Torvalds qp->event_handler = qp_init_attr->event_handler; 4441da177e4SLinus Torvalds qp->qp_context = qp_init_attr->qp_context; 445b42b63cfSSean Hefty if (qp_init_attr->qp_type == IB_QPT_XRC_INI) { 446b42b63cfSSean Hefty qp->recv_cq = NULL; 447b42b63cfSSean Hefty qp->srq = NULL; 448b42b63cfSSean Hefty } else { 449b42b63cfSSean Hefty qp->recv_cq = qp_init_attr->recv_cq; 450b42b63cfSSean Hefty atomic_inc(&qp_init_attr->recv_cq->usecnt); 451b42b63cfSSean Hefty qp->srq = qp_init_attr->srq; 452b42b63cfSSean Hefty if (qp->srq) 453b42b63cfSSean Hefty atomic_inc(&qp_init_attr->srq->usecnt); 454b42b63cfSSean Hefty } 455b42b63cfSSean Hefty 4561da177e4SLinus Torvalds qp->pd = pd; 4571da177e4SLinus Torvalds qp->send_cq = qp_init_attr->send_cq; 458b42b63cfSSean Hefty qp->xrcd = NULL; 459b42b63cfSSean Hefty 4601da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 4611da177e4SLinus Torvalds atomic_inc(&qp_init_attr->send_cq->usecnt); 462b42b63cfSSean Hefty } 4631da177e4SLinus Torvalds } 4641da177e4SLinus Torvalds 4651da177e4SLinus Torvalds return qp; 4661da177e4SLinus Torvalds } 4671da177e4SLinus Torvalds EXPORT_SYMBOL(ib_create_qp); 4681da177e4SLinus Torvalds 4698a51866fSRoland Dreier static const struct { 4708a51866fSRoland Dreier int valid; 471b42b63cfSSean Hefty enum ib_qp_attr_mask req_param[IB_QPT_MAX]; 472b42b63cfSSean Hefty enum ib_qp_attr_mask opt_param[IB_QPT_MAX]; 4738a51866fSRoland Dreier } qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = { 4748a51866fSRoland Dreier [IB_QPS_RESET] = { 4758a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 4768a51866fSRoland Dreier [IB_QPS_INIT] = { 4778a51866fSRoland Dreier .valid = 1, 4788a51866fSRoland Dreier .req_param = { 4798a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 4808a51866fSRoland Dreier IB_QP_PORT | 4818a51866fSRoland Dreier IB_QP_QKEY), 482c938a616SOr Gerlitz [IB_QPT_RAW_PACKET] = IB_QP_PORT, 4838a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_PKEY_INDEX | 4848a51866fSRoland Dreier IB_QP_PORT | 4858a51866fSRoland Dreier IB_QP_ACCESS_FLAGS), 4868a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_PKEY_INDEX | 4878a51866fSRoland Dreier IB_QP_PORT | 4888a51866fSRoland Dreier IB_QP_ACCESS_FLAGS), 489b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX | 490b42b63cfSSean Hefty IB_QP_PORT | 491b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS), 492b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX | 493b42b63cfSSean Hefty IB_QP_PORT | 494b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS), 4958a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 4968a51866fSRoland Dreier IB_QP_QKEY), 4978a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 4988a51866fSRoland Dreier IB_QP_QKEY), 4998a51866fSRoland Dreier } 5008a51866fSRoland Dreier }, 5018a51866fSRoland Dreier }, 5028a51866fSRoland Dreier [IB_QPS_INIT] = { 5038a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 5048a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 }, 5058a51866fSRoland Dreier [IB_QPS_INIT] = { 5068a51866fSRoland Dreier .valid = 1, 5078a51866fSRoland Dreier .opt_param = { 5088a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 5098a51866fSRoland Dreier IB_QP_PORT | 5108a51866fSRoland Dreier IB_QP_QKEY), 5118a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_PKEY_INDEX | 5128a51866fSRoland Dreier IB_QP_PORT | 5138a51866fSRoland Dreier IB_QP_ACCESS_FLAGS), 5148a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_PKEY_INDEX | 5158a51866fSRoland Dreier IB_QP_PORT | 5168a51866fSRoland Dreier IB_QP_ACCESS_FLAGS), 517b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX | 518b42b63cfSSean Hefty IB_QP_PORT | 519b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS), 520b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX | 521b42b63cfSSean Hefty IB_QP_PORT | 522b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS), 5238a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 5248a51866fSRoland Dreier IB_QP_QKEY), 5258a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 5268a51866fSRoland Dreier IB_QP_QKEY), 5278a51866fSRoland Dreier } 5288a51866fSRoland Dreier }, 5298a51866fSRoland Dreier [IB_QPS_RTR] = { 5308a51866fSRoland Dreier .valid = 1, 5318a51866fSRoland Dreier .req_param = { 5328a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_AV | 5338a51866fSRoland Dreier IB_QP_PATH_MTU | 5348a51866fSRoland Dreier IB_QP_DEST_QPN | 5358a51866fSRoland Dreier IB_QP_RQ_PSN), 5368a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_AV | 5378a51866fSRoland Dreier IB_QP_PATH_MTU | 5388a51866fSRoland Dreier IB_QP_DEST_QPN | 5398a51866fSRoland Dreier IB_QP_RQ_PSN | 5408a51866fSRoland Dreier IB_QP_MAX_DEST_RD_ATOMIC | 5418a51866fSRoland Dreier IB_QP_MIN_RNR_TIMER), 542b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_AV | 543b42b63cfSSean Hefty IB_QP_PATH_MTU | 544b42b63cfSSean Hefty IB_QP_DEST_QPN | 545b42b63cfSSean Hefty IB_QP_RQ_PSN), 546b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_AV | 547b42b63cfSSean Hefty IB_QP_PATH_MTU | 548b42b63cfSSean Hefty IB_QP_DEST_QPN | 549b42b63cfSSean Hefty IB_QP_RQ_PSN | 550b42b63cfSSean Hefty IB_QP_MAX_DEST_RD_ATOMIC | 551b42b63cfSSean Hefty IB_QP_MIN_RNR_TIMER), 5528a51866fSRoland Dreier }, 5538a51866fSRoland Dreier .opt_param = { 5548a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 5558a51866fSRoland Dreier IB_QP_QKEY), 5568a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_ALT_PATH | 5578a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 5588a51866fSRoland Dreier IB_QP_PKEY_INDEX), 5598a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_ALT_PATH | 5608a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 5618a51866fSRoland Dreier IB_QP_PKEY_INDEX), 562b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_ALT_PATH | 563b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 564b42b63cfSSean Hefty IB_QP_PKEY_INDEX), 565b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_ALT_PATH | 566b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 567b42b63cfSSean Hefty IB_QP_PKEY_INDEX), 5688a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 5698a51866fSRoland Dreier IB_QP_QKEY), 5708a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 5718a51866fSRoland Dreier IB_QP_QKEY), 5728a51866fSRoland Dreier } 5738a51866fSRoland Dreier } 5748a51866fSRoland Dreier }, 5758a51866fSRoland Dreier [IB_QPS_RTR] = { 5768a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 5778a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 }, 5788a51866fSRoland Dreier [IB_QPS_RTS] = { 5798a51866fSRoland Dreier .valid = 1, 5808a51866fSRoland Dreier .req_param = { 5818a51866fSRoland Dreier [IB_QPT_UD] = IB_QP_SQ_PSN, 5828a51866fSRoland Dreier [IB_QPT_UC] = IB_QP_SQ_PSN, 5838a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_TIMEOUT | 5848a51866fSRoland Dreier IB_QP_RETRY_CNT | 5858a51866fSRoland Dreier IB_QP_RNR_RETRY | 5868a51866fSRoland Dreier IB_QP_SQ_PSN | 5878a51866fSRoland Dreier IB_QP_MAX_QP_RD_ATOMIC), 588b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_TIMEOUT | 589b42b63cfSSean Hefty IB_QP_RETRY_CNT | 590b42b63cfSSean Hefty IB_QP_RNR_RETRY | 591b42b63cfSSean Hefty IB_QP_SQ_PSN | 592b42b63cfSSean Hefty IB_QP_MAX_QP_RD_ATOMIC), 593b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_TIMEOUT | 594b42b63cfSSean Hefty IB_QP_SQ_PSN), 5958a51866fSRoland Dreier [IB_QPT_SMI] = IB_QP_SQ_PSN, 5968a51866fSRoland Dreier [IB_QPT_GSI] = IB_QP_SQ_PSN, 5978a51866fSRoland Dreier }, 5988a51866fSRoland Dreier .opt_param = { 5998a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_CUR_STATE | 6008a51866fSRoland Dreier IB_QP_QKEY), 6018a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_CUR_STATE | 6028a51866fSRoland Dreier IB_QP_ALT_PATH | 6038a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 6048a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 6058a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_CUR_STATE | 6068a51866fSRoland Dreier IB_QP_ALT_PATH | 6078a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 6088a51866fSRoland Dreier IB_QP_MIN_RNR_TIMER | 6098a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 610b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE | 611b42b63cfSSean Hefty IB_QP_ALT_PATH | 612b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 613b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 614b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE | 615b42b63cfSSean Hefty IB_QP_ALT_PATH | 616b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 617b42b63cfSSean Hefty IB_QP_MIN_RNR_TIMER | 618b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 6198a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_CUR_STATE | 6208a51866fSRoland Dreier IB_QP_QKEY), 6218a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_CUR_STATE | 6228a51866fSRoland Dreier IB_QP_QKEY), 6238a51866fSRoland Dreier } 6248a51866fSRoland Dreier } 6258a51866fSRoland Dreier }, 6268a51866fSRoland Dreier [IB_QPS_RTS] = { 6278a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 6288a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 }, 6298a51866fSRoland Dreier [IB_QPS_RTS] = { 6308a51866fSRoland Dreier .valid = 1, 6318a51866fSRoland Dreier .opt_param = { 6328a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_CUR_STATE | 6338a51866fSRoland Dreier IB_QP_QKEY), 6344546d31dSDotan Barak [IB_QPT_UC] = (IB_QP_CUR_STATE | 6354546d31dSDotan Barak IB_QP_ACCESS_FLAGS | 6368a51866fSRoland Dreier IB_QP_ALT_PATH | 6378a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 6384546d31dSDotan Barak [IB_QPT_RC] = (IB_QP_CUR_STATE | 6394546d31dSDotan Barak IB_QP_ACCESS_FLAGS | 6408a51866fSRoland Dreier IB_QP_ALT_PATH | 6418a51866fSRoland Dreier IB_QP_PATH_MIG_STATE | 6428a51866fSRoland Dreier IB_QP_MIN_RNR_TIMER), 643b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE | 644b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 645b42b63cfSSean Hefty IB_QP_ALT_PATH | 646b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 647b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE | 648b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 649b42b63cfSSean Hefty IB_QP_ALT_PATH | 650b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE | 651b42b63cfSSean Hefty IB_QP_MIN_RNR_TIMER), 6528a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_CUR_STATE | 6538a51866fSRoland Dreier IB_QP_QKEY), 6548a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_CUR_STATE | 6558a51866fSRoland Dreier IB_QP_QKEY), 6568a51866fSRoland Dreier } 6578a51866fSRoland Dreier }, 6588a51866fSRoland Dreier [IB_QPS_SQD] = { 6598a51866fSRoland Dreier .valid = 1, 6608a51866fSRoland Dreier .opt_param = { 6618a51866fSRoland Dreier [IB_QPT_UD] = IB_QP_EN_SQD_ASYNC_NOTIFY, 6628a51866fSRoland Dreier [IB_QPT_UC] = IB_QP_EN_SQD_ASYNC_NOTIFY, 6638a51866fSRoland Dreier [IB_QPT_RC] = IB_QP_EN_SQD_ASYNC_NOTIFY, 664b42b63cfSSean Hefty [IB_QPT_XRC_INI] = IB_QP_EN_SQD_ASYNC_NOTIFY, 665b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = IB_QP_EN_SQD_ASYNC_NOTIFY, /* ??? */ 6668a51866fSRoland Dreier [IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY, 6678a51866fSRoland Dreier [IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY 6688a51866fSRoland Dreier } 6698a51866fSRoland Dreier }, 6708a51866fSRoland Dreier }, 6718a51866fSRoland Dreier [IB_QPS_SQD] = { 6728a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 6738a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 }, 6748a51866fSRoland Dreier [IB_QPS_RTS] = { 6758a51866fSRoland Dreier .valid = 1, 6768a51866fSRoland Dreier .opt_param = { 6778a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_CUR_STATE | 6788a51866fSRoland Dreier IB_QP_QKEY), 6798a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_CUR_STATE | 6808a51866fSRoland Dreier IB_QP_ALT_PATH | 6818a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 6828a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 6838a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_CUR_STATE | 6848a51866fSRoland Dreier IB_QP_ALT_PATH | 6858a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 6868a51866fSRoland Dreier IB_QP_MIN_RNR_TIMER | 6878a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 688b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE | 689b42b63cfSSean Hefty IB_QP_ALT_PATH | 690b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 691b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 692b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE | 693b42b63cfSSean Hefty IB_QP_ALT_PATH | 694b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 695b42b63cfSSean Hefty IB_QP_MIN_RNR_TIMER | 696b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 6978a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_CUR_STATE | 6988a51866fSRoland Dreier IB_QP_QKEY), 6998a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_CUR_STATE | 7008a51866fSRoland Dreier IB_QP_QKEY), 7018a51866fSRoland Dreier } 7028a51866fSRoland Dreier }, 7038a51866fSRoland Dreier [IB_QPS_SQD] = { 7048a51866fSRoland Dreier .valid = 1, 7058a51866fSRoland Dreier .opt_param = { 7068a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 7078a51866fSRoland Dreier IB_QP_QKEY), 7088a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_AV | 7098a51866fSRoland Dreier IB_QP_ALT_PATH | 7108a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 7118a51866fSRoland Dreier IB_QP_PKEY_INDEX | 7128a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 7138a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_PORT | 7148a51866fSRoland Dreier IB_QP_AV | 7158a51866fSRoland Dreier IB_QP_TIMEOUT | 7168a51866fSRoland Dreier IB_QP_RETRY_CNT | 7178a51866fSRoland Dreier IB_QP_RNR_RETRY | 7188a51866fSRoland Dreier IB_QP_MAX_QP_RD_ATOMIC | 7198a51866fSRoland Dreier IB_QP_MAX_DEST_RD_ATOMIC | 7208a51866fSRoland Dreier IB_QP_ALT_PATH | 7218a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 7228a51866fSRoland Dreier IB_QP_PKEY_INDEX | 7238a51866fSRoland Dreier IB_QP_MIN_RNR_TIMER | 7248a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 725b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_PORT | 726b42b63cfSSean Hefty IB_QP_AV | 727b42b63cfSSean Hefty IB_QP_TIMEOUT | 728b42b63cfSSean Hefty IB_QP_RETRY_CNT | 729b42b63cfSSean Hefty IB_QP_RNR_RETRY | 730b42b63cfSSean Hefty IB_QP_MAX_QP_RD_ATOMIC | 731b42b63cfSSean Hefty IB_QP_ALT_PATH | 732b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 733b42b63cfSSean Hefty IB_QP_PKEY_INDEX | 734b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 735b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_PORT | 736b42b63cfSSean Hefty IB_QP_AV | 737b42b63cfSSean Hefty IB_QP_TIMEOUT | 738b42b63cfSSean Hefty IB_QP_MAX_DEST_RD_ATOMIC | 739b42b63cfSSean Hefty IB_QP_ALT_PATH | 740b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 741b42b63cfSSean Hefty IB_QP_PKEY_INDEX | 742b42b63cfSSean Hefty IB_QP_MIN_RNR_TIMER | 743b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 7448a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 7458a51866fSRoland Dreier IB_QP_QKEY), 7468a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 7478a51866fSRoland Dreier IB_QP_QKEY), 7488a51866fSRoland Dreier } 7498a51866fSRoland Dreier } 7508a51866fSRoland Dreier }, 7518a51866fSRoland Dreier [IB_QPS_SQE] = { 7528a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 7538a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 }, 7548a51866fSRoland Dreier [IB_QPS_RTS] = { 7558a51866fSRoland Dreier .valid = 1, 7568a51866fSRoland Dreier .opt_param = { 7578a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_CUR_STATE | 7588a51866fSRoland Dreier IB_QP_QKEY), 7598a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_CUR_STATE | 7608a51866fSRoland Dreier IB_QP_ACCESS_FLAGS), 7618a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_CUR_STATE | 7628a51866fSRoland Dreier IB_QP_QKEY), 7638a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_CUR_STATE | 7648a51866fSRoland Dreier IB_QP_QKEY), 7658a51866fSRoland Dreier } 7668a51866fSRoland Dreier } 7678a51866fSRoland Dreier }, 7688a51866fSRoland Dreier [IB_QPS_ERR] = { 7698a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 7708a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 } 7718a51866fSRoland Dreier } 7728a51866fSRoland Dreier }; 7738a51866fSRoland Dreier 7748a51866fSRoland Dreier int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state, 7758a51866fSRoland Dreier enum ib_qp_type type, enum ib_qp_attr_mask mask) 7768a51866fSRoland Dreier { 7778a51866fSRoland Dreier enum ib_qp_attr_mask req_param, opt_param; 7788a51866fSRoland Dreier 7798a51866fSRoland Dreier if (cur_state < 0 || cur_state > IB_QPS_ERR || 7808a51866fSRoland Dreier next_state < 0 || next_state > IB_QPS_ERR) 7818a51866fSRoland Dreier return 0; 7828a51866fSRoland Dreier 7838a51866fSRoland Dreier if (mask & IB_QP_CUR_STATE && 7848a51866fSRoland Dreier cur_state != IB_QPS_RTR && cur_state != IB_QPS_RTS && 7858a51866fSRoland Dreier cur_state != IB_QPS_SQD && cur_state != IB_QPS_SQE) 7868a51866fSRoland Dreier return 0; 7878a51866fSRoland Dreier 7888a51866fSRoland Dreier if (!qp_state_table[cur_state][next_state].valid) 7898a51866fSRoland Dreier return 0; 7908a51866fSRoland Dreier 7918a51866fSRoland Dreier req_param = qp_state_table[cur_state][next_state].req_param[type]; 7928a51866fSRoland Dreier opt_param = qp_state_table[cur_state][next_state].opt_param[type]; 7938a51866fSRoland Dreier 7948a51866fSRoland Dreier if ((mask & req_param) != req_param) 7958a51866fSRoland Dreier return 0; 7968a51866fSRoland Dreier 7978a51866fSRoland Dreier if (mask & ~(req_param | opt_param | IB_QP_STATE)) 7988a51866fSRoland Dreier return 0; 7998a51866fSRoland Dreier 8008a51866fSRoland Dreier return 1; 8018a51866fSRoland Dreier } 8028a51866fSRoland Dreier EXPORT_SYMBOL(ib_modify_qp_is_ok); 8038a51866fSRoland Dreier 8041da177e4SLinus Torvalds int ib_modify_qp(struct ib_qp *qp, 8051da177e4SLinus Torvalds struct ib_qp_attr *qp_attr, 8061da177e4SLinus Torvalds int qp_attr_mask) 8071da177e4SLinus Torvalds { 8080e0ec7e0SSean Hefty return qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL); 8091da177e4SLinus Torvalds } 8101da177e4SLinus Torvalds EXPORT_SYMBOL(ib_modify_qp); 8111da177e4SLinus Torvalds 8121da177e4SLinus Torvalds int ib_query_qp(struct ib_qp *qp, 8131da177e4SLinus Torvalds struct ib_qp_attr *qp_attr, 8141da177e4SLinus Torvalds int qp_attr_mask, 8151da177e4SLinus Torvalds struct ib_qp_init_attr *qp_init_attr) 8161da177e4SLinus Torvalds { 8171da177e4SLinus Torvalds return qp->device->query_qp ? 8180e0ec7e0SSean Hefty qp->device->query_qp(qp->real_qp, qp_attr, qp_attr_mask, qp_init_attr) : 8191da177e4SLinus Torvalds -ENOSYS; 8201da177e4SLinus Torvalds } 8211da177e4SLinus Torvalds EXPORT_SYMBOL(ib_query_qp); 8221da177e4SLinus Torvalds 8230e0ec7e0SSean Hefty int ib_close_qp(struct ib_qp *qp) 8240e0ec7e0SSean Hefty { 8250e0ec7e0SSean Hefty struct ib_qp *real_qp; 8260e0ec7e0SSean Hefty unsigned long flags; 8270e0ec7e0SSean Hefty 8280e0ec7e0SSean Hefty real_qp = qp->real_qp; 8290e0ec7e0SSean Hefty if (real_qp == qp) 8300e0ec7e0SSean Hefty return -EINVAL; 8310e0ec7e0SSean Hefty 8320e0ec7e0SSean Hefty spin_lock_irqsave(&real_qp->device->event_handler_lock, flags); 8330e0ec7e0SSean Hefty list_del(&qp->open_list); 8340e0ec7e0SSean Hefty spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags); 8350e0ec7e0SSean Hefty 8360e0ec7e0SSean Hefty atomic_dec(&real_qp->usecnt); 8370e0ec7e0SSean Hefty kfree(qp); 8380e0ec7e0SSean Hefty 8390e0ec7e0SSean Hefty return 0; 8400e0ec7e0SSean Hefty } 8410e0ec7e0SSean Hefty EXPORT_SYMBOL(ib_close_qp); 8420e0ec7e0SSean Hefty 8430e0ec7e0SSean Hefty static int __ib_destroy_shared_qp(struct ib_qp *qp) 8440e0ec7e0SSean Hefty { 8450e0ec7e0SSean Hefty struct ib_xrcd *xrcd; 8460e0ec7e0SSean Hefty struct ib_qp *real_qp; 8470e0ec7e0SSean Hefty int ret; 8480e0ec7e0SSean Hefty 8490e0ec7e0SSean Hefty real_qp = qp->real_qp; 8500e0ec7e0SSean Hefty xrcd = real_qp->xrcd; 8510e0ec7e0SSean Hefty 8520e0ec7e0SSean Hefty mutex_lock(&xrcd->tgt_qp_mutex); 8530e0ec7e0SSean Hefty ib_close_qp(qp); 8540e0ec7e0SSean Hefty if (atomic_read(&real_qp->usecnt) == 0) 8550e0ec7e0SSean Hefty list_del(&real_qp->xrcd_list); 8560e0ec7e0SSean Hefty else 8570e0ec7e0SSean Hefty real_qp = NULL; 8580e0ec7e0SSean Hefty mutex_unlock(&xrcd->tgt_qp_mutex); 8590e0ec7e0SSean Hefty 8600e0ec7e0SSean Hefty if (real_qp) { 8610e0ec7e0SSean Hefty ret = ib_destroy_qp(real_qp); 8620e0ec7e0SSean Hefty if (!ret) 8630e0ec7e0SSean Hefty atomic_dec(&xrcd->usecnt); 8640e0ec7e0SSean Hefty else 8650e0ec7e0SSean Hefty __ib_insert_xrcd_qp(xrcd, real_qp); 8660e0ec7e0SSean Hefty } 8670e0ec7e0SSean Hefty 8680e0ec7e0SSean Hefty return 0; 8690e0ec7e0SSean Hefty } 8700e0ec7e0SSean Hefty 8711da177e4SLinus Torvalds int ib_destroy_qp(struct ib_qp *qp) 8721da177e4SLinus Torvalds { 8731da177e4SLinus Torvalds struct ib_pd *pd; 8741da177e4SLinus Torvalds struct ib_cq *scq, *rcq; 8751da177e4SLinus Torvalds struct ib_srq *srq; 8761da177e4SLinus Torvalds int ret; 8771da177e4SLinus Torvalds 8780e0ec7e0SSean Hefty if (atomic_read(&qp->usecnt)) 8790e0ec7e0SSean Hefty return -EBUSY; 8800e0ec7e0SSean Hefty 8810e0ec7e0SSean Hefty if (qp->real_qp != qp) 8820e0ec7e0SSean Hefty return __ib_destroy_shared_qp(qp); 8830e0ec7e0SSean Hefty 8841da177e4SLinus Torvalds pd = qp->pd; 8851da177e4SLinus Torvalds scq = qp->send_cq; 8861da177e4SLinus Torvalds rcq = qp->recv_cq; 8871da177e4SLinus Torvalds srq = qp->srq; 8881da177e4SLinus Torvalds 8891da177e4SLinus Torvalds ret = qp->device->destroy_qp(qp); 8901da177e4SLinus Torvalds if (!ret) { 891b42b63cfSSean Hefty if (pd) 8921da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 893b42b63cfSSean Hefty if (scq) 8941da177e4SLinus Torvalds atomic_dec(&scq->usecnt); 895b42b63cfSSean Hefty if (rcq) 8961da177e4SLinus Torvalds atomic_dec(&rcq->usecnt); 8971da177e4SLinus Torvalds if (srq) 8981da177e4SLinus Torvalds atomic_dec(&srq->usecnt); 8991da177e4SLinus Torvalds } 9001da177e4SLinus Torvalds 9011da177e4SLinus Torvalds return ret; 9021da177e4SLinus Torvalds } 9031da177e4SLinus Torvalds EXPORT_SYMBOL(ib_destroy_qp); 9041da177e4SLinus Torvalds 9051da177e4SLinus Torvalds /* Completion queues */ 9061da177e4SLinus Torvalds 9071da177e4SLinus Torvalds struct ib_cq *ib_create_cq(struct ib_device *device, 9081da177e4SLinus Torvalds ib_comp_handler comp_handler, 9091da177e4SLinus Torvalds void (*event_handler)(struct ib_event *, void *), 910f4fd0b22SMichael S. Tsirkin void *cq_context, int cqe, int comp_vector) 9111da177e4SLinus Torvalds { 9121da177e4SLinus Torvalds struct ib_cq *cq; 9131da177e4SLinus Torvalds 914f4fd0b22SMichael S. Tsirkin cq = device->create_cq(device, cqe, comp_vector, NULL, NULL); 9151da177e4SLinus Torvalds 9161da177e4SLinus Torvalds if (!IS_ERR(cq)) { 9171da177e4SLinus Torvalds cq->device = device; 918b5e81bf5SRoland Dreier cq->uobject = NULL; 9191da177e4SLinus Torvalds cq->comp_handler = comp_handler; 9201da177e4SLinus Torvalds cq->event_handler = event_handler; 9211da177e4SLinus Torvalds cq->cq_context = cq_context; 9221da177e4SLinus Torvalds atomic_set(&cq->usecnt, 0); 9231da177e4SLinus Torvalds } 9241da177e4SLinus Torvalds 9251da177e4SLinus Torvalds return cq; 9261da177e4SLinus Torvalds } 9271da177e4SLinus Torvalds EXPORT_SYMBOL(ib_create_cq); 9281da177e4SLinus Torvalds 9292dd57162SEli Cohen int ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period) 9302dd57162SEli Cohen { 9312dd57162SEli Cohen return cq->device->modify_cq ? 9322dd57162SEli Cohen cq->device->modify_cq(cq, cq_count, cq_period) : -ENOSYS; 9332dd57162SEli Cohen } 9342dd57162SEli Cohen EXPORT_SYMBOL(ib_modify_cq); 9352dd57162SEli Cohen 9361da177e4SLinus Torvalds int ib_destroy_cq(struct ib_cq *cq) 9371da177e4SLinus Torvalds { 9381da177e4SLinus Torvalds if (atomic_read(&cq->usecnt)) 9391da177e4SLinus Torvalds return -EBUSY; 9401da177e4SLinus Torvalds 9411da177e4SLinus Torvalds return cq->device->destroy_cq(cq); 9421da177e4SLinus Torvalds } 9431da177e4SLinus Torvalds EXPORT_SYMBOL(ib_destroy_cq); 9441da177e4SLinus Torvalds 945a74cd4afSRoland Dreier int ib_resize_cq(struct ib_cq *cq, int cqe) 9461da177e4SLinus Torvalds { 94740de2e54SRoland Dreier return cq->device->resize_cq ? 94833b9b3eeSRoland Dreier cq->device->resize_cq(cq, cqe, NULL) : -ENOSYS; 9491da177e4SLinus Torvalds } 9501da177e4SLinus Torvalds EXPORT_SYMBOL(ib_resize_cq); 9511da177e4SLinus Torvalds 9521da177e4SLinus Torvalds /* Memory regions */ 9531da177e4SLinus Torvalds 9541da177e4SLinus Torvalds struct ib_mr *ib_get_dma_mr(struct ib_pd *pd, int mr_access_flags) 9551da177e4SLinus Torvalds { 9561da177e4SLinus Torvalds struct ib_mr *mr; 9571da177e4SLinus Torvalds 9581da177e4SLinus Torvalds mr = pd->device->get_dma_mr(pd, mr_access_flags); 9591da177e4SLinus Torvalds 9601da177e4SLinus Torvalds if (!IS_ERR(mr)) { 9611da177e4SLinus Torvalds mr->device = pd->device; 9621da177e4SLinus Torvalds mr->pd = pd; 963b5e81bf5SRoland Dreier mr->uobject = NULL; 9641da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 9651da177e4SLinus Torvalds atomic_set(&mr->usecnt, 0); 9661da177e4SLinus Torvalds } 9671da177e4SLinus Torvalds 9681da177e4SLinus Torvalds return mr; 9691da177e4SLinus Torvalds } 9701da177e4SLinus Torvalds EXPORT_SYMBOL(ib_get_dma_mr); 9711da177e4SLinus Torvalds 9721da177e4SLinus Torvalds struct ib_mr *ib_reg_phys_mr(struct ib_pd *pd, 9731da177e4SLinus Torvalds struct ib_phys_buf *phys_buf_array, 9741da177e4SLinus Torvalds int num_phys_buf, 9751da177e4SLinus Torvalds int mr_access_flags, 9761da177e4SLinus Torvalds u64 *iova_start) 9771da177e4SLinus Torvalds { 9781da177e4SLinus Torvalds struct ib_mr *mr; 9791da177e4SLinus Torvalds 9807ce5eacbSDotan Barak if (!pd->device->reg_phys_mr) 9817ce5eacbSDotan Barak return ERR_PTR(-ENOSYS); 9827ce5eacbSDotan Barak 9831da177e4SLinus Torvalds mr = pd->device->reg_phys_mr(pd, phys_buf_array, num_phys_buf, 9841da177e4SLinus Torvalds mr_access_flags, iova_start); 9851da177e4SLinus Torvalds 9861da177e4SLinus Torvalds if (!IS_ERR(mr)) { 9871da177e4SLinus Torvalds mr->device = pd->device; 9881da177e4SLinus Torvalds mr->pd = pd; 989b5e81bf5SRoland Dreier mr->uobject = NULL; 9901da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 9911da177e4SLinus Torvalds atomic_set(&mr->usecnt, 0); 9921da177e4SLinus Torvalds } 9931da177e4SLinus Torvalds 9941da177e4SLinus Torvalds return mr; 9951da177e4SLinus Torvalds } 9961da177e4SLinus Torvalds EXPORT_SYMBOL(ib_reg_phys_mr); 9971da177e4SLinus Torvalds 9981da177e4SLinus Torvalds int ib_rereg_phys_mr(struct ib_mr *mr, 9991da177e4SLinus Torvalds int mr_rereg_mask, 10001da177e4SLinus Torvalds struct ib_pd *pd, 10011da177e4SLinus Torvalds struct ib_phys_buf *phys_buf_array, 10021da177e4SLinus Torvalds int num_phys_buf, 10031da177e4SLinus Torvalds int mr_access_flags, 10041da177e4SLinus Torvalds u64 *iova_start) 10051da177e4SLinus Torvalds { 10061da177e4SLinus Torvalds struct ib_pd *old_pd; 10071da177e4SLinus Torvalds int ret; 10081da177e4SLinus Torvalds 10091da177e4SLinus Torvalds if (!mr->device->rereg_phys_mr) 10101da177e4SLinus Torvalds return -ENOSYS; 10111da177e4SLinus Torvalds 10121da177e4SLinus Torvalds if (atomic_read(&mr->usecnt)) 10131da177e4SLinus Torvalds return -EBUSY; 10141da177e4SLinus Torvalds 10151da177e4SLinus Torvalds old_pd = mr->pd; 10161da177e4SLinus Torvalds 10171da177e4SLinus Torvalds ret = mr->device->rereg_phys_mr(mr, mr_rereg_mask, pd, 10181da177e4SLinus Torvalds phys_buf_array, num_phys_buf, 10191da177e4SLinus Torvalds mr_access_flags, iova_start); 10201da177e4SLinus Torvalds 10211da177e4SLinus Torvalds if (!ret && (mr_rereg_mask & IB_MR_REREG_PD)) { 10221da177e4SLinus Torvalds atomic_dec(&old_pd->usecnt); 10231da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 10241da177e4SLinus Torvalds } 10251da177e4SLinus Torvalds 10261da177e4SLinus Torvalds return ret; 10271da177e4SLinus Torvalds } 10281da177e4SLinus Torvalds EXPORT_SYMBOL(ib_rereg_phys_mr); 10291da177e4SLinus Torvalds 10301da177e4SLinus Torvalds int ib_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr) 10311da177e4SLinus Torvalds { 10321da177e4SLinus Torvalds return mr->device->query_mr ? 10331da177e4SLinus Torvalds mr->device->query_mr(mr, mr_attr) : -ENOSYS; 10341da177e4SLinus Torvalds } 10351da177e4SLinus Torvalds EXPORT_SYMBOL(ib_query_mr); 10361da177e4SLinus Torvalds 10371da177e4SLinus Torvalds int ib_dereg_mr(struct ib_mr *mr) 10381da177e4SLinus Torvalds { 10391da177e4SLinus Torvalds struct ib_pd *pd; 10401da177e4SLinus Torvalds int ret; 10411da177e4SLinus Torvalds 10421da177e4SLinus Torvalds if (atomic_read(&mr->usecnt)) 10431da177e4SLinus Torvalds return -EBUSY; 10441da177e4SLinus Torvalds 10451da177e4SLinus Torvalds pd = mr->pd; 10461da177e4SLinus Torvalds ret = mr->device->dereg_mr(mr); 10471da177e4SLinus Torvalds if (!ret) 10481da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 10491da177e4SLinus Torvalds 10501da177e4SLinus Torvalds return ret; 10511da177e4SLinus Torvalds } 10521da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dereg_mr); 10531da177e4SLinus Torvalds 105400f7ec36SSteve Wise struct ib_mr *ib_alloc_fast_reg_mr(struct ib_pd *pd, int max_page_list_len) 105500f7ec36SSteve Wise { 105600f7ec36SSteve Wise struct ib_mr *mr; 105700f7ec36SSteve Wise 105800f7ec36SSteve Wise if (!pd->device->alloc_fast_reg_mr) 105900f7ec36SSteve Wise return ERR_PTR(-ENOSYS); 106000f7ec36SSteve Wise 106100f7ec36SSteve Wise mr = pd->device->alloc_fast_reg_mr(pd, max_page_list_len); 106200f7ec36SSteve Wise 106300f7ec36SSteve Wise if (!IS_ERR(mr)) { 106400f7ec36SSteve Wise mr->device = pd->device; 106500f7ec36SSteve Wise mr->pd = pd; 106600f7ec36SSteve Wise mr->uobject = NULL; 106700f7ec36SSteve Wise atomic_inc(&pd->usecnt); 106800f7ec36SSteve Wise atomic_set(&mr->usecnt, 0); 106900f7ec36SSteve Wise } 107000f7ec36SSteve Wise 107100f7ec36SSteve Wise return mr; 107200f7ec36SSteve Wise } 107300f7ec36SSteve Wise EXPORT_SYMBOL(ib_alloc_fast_reg_mr); 107400f7ec36SSteve Wise 107500f7ec36SSteve Wise struct ib_fast_reg_page_list *ib_alloc_fast_reg_page_list(struct ib_device *device, 107600f7ec36SSteve Wise int max_page_list_len) 107700f7ec36SSteve Wise { 107800f7ec36SSteve Wise struct ib_fast_reg_page_list *page_list; 107900f7ec36SSteve Wise 108000f7ec36SSteve Wise if (!device->alloc_fast_reg_page_list) 108100f7ec36SSteve Wise return ERR_PTR(-ENOSYS); 108200f7ec36SSteve Wise 108300f7ec36SSteve Wise page_list = device->alloc_fast_reg_page_list(device, max_page_list_len); 108400f7ec36SSteve Wise 108500f7ec36SSteve Wise if (!IS_ERR(page_list)) { 108600f7ec36SSteve Wise page_list->device = device; 108700f7ec36SSteve Wise page_list->max_page_list_len = max_page_list_len; 108800f7ec36SSteve Wise } 108900f7ec36SSteve Wise 109000f7ec36SSteve Wise return page_list; 109100f7ec36SSteve Wise } 109200f7ec36SSteve Wise EXPORT_SYMBOL(ib_alloc_fast_reg_page_list); 109300f7ec36SSteve Wise 109400f7ec36SSteve Wise void ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list) 109500f7ec36SSteve Wise { 109600f7ec36SSteve Wise page_list->device->free_fast_reg_page_list(page_list); 109700f7ec36SSteve Wise } 109800f7ec36SSteve Wise EXPORT_SYMBOL(ib_free_fast_reg_page_list); 109900f7ec36SSteve Wise 11001da177e4SLinus Torvalds /* Memory windows */ 11011da177e4SLinus Torvalds 11027083e42eSShani Michaeli struct ib_mw *ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type) 11031da177e4SLinus Torvalds { 11041da177e4SLinus Torvalds struct ib_mw *mw; 11051da177e4SLinus Torvalds 11061da177e4SLinus Torvalds if (!pd->device->alloc_mw) 11071da177e4SLinus Torvalds return ERR_PTR(-ENOSYS); 11081da177e4SLinus Torvalds 11097083e42eSShani Michaeli mw = pd->device->alloc_mw(pd, type); 11101da177e4SLinus Torvalds if (!IS_ERR(mw)) { 11111da177e4SLinus Torvalds mw->device = pd->device; 11121da177e4SLinus Torvalds mw->pd = pd; 1113b5e81bf5SRoland Dreier mw->uobject = NULL; 11147083e42eSShani Michaeli mw->type = type; 11151da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 11161da177e4SLinus Torvalds } 11171da177e4SLinus Torvalds 11181da177e4SLinus Torvalds return mw; 11191da177e4SLinus Torvalds } 11201da177e4SLinus Torvalds EXPORT_SYMBOL(ib_alloc_mw); 11211da177e4SLinus Torvalds 11221da177e4SLinus Torvalds int ib_dealloc_mw(struct ib_mw *mw) 11231da177e4SLinus Torvalds { 11241da177e4SLinus Torvalds struct ib_pd *pd; 11251da177e4SLinus Torvalds int ret; 11261da177e4SLinus Torvalds 11271da177e4SLinus Torvalds pd = mw->pd; 11281da177e4SLinus Torvalds ret = mw->device->dealloc_mw(mw); 11291da177e4SLinus Torvalds if (!ret) 11301da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 11311da177e4SLinus Torvalds 11321da177e4SLinus Torvalds return ret; 11331da177e4SLinus Torvalds } 11341da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dealloc_mw); 11351da177e4SLinus Torvalds 11361da177e4SLinus Torvalds /* "Fast" memory regions */ 11371da177e4SLinus Torvalds 11381da177e4SLinus Torvalds struct ib_fmr *ib_alloc_fmr(struct ib_pd *pd, 11391da177e4SLinus Torvalds int mr_access_flags, 11401da177e4SLinus Torvalds struct ib_fmr_attr *fmr_attr) 11411da177e4SLinus Torvalds { 11421da177e4SLinus Torvalds struct ib_fmr *fmr; 11431da177e4SLinus Torvalds 11441da177e4SLinus Torvalds if (!pd->device->alloc_fmr) 11451da177e4SLinus Torvalds return ERR_PTR(-ENOSYS); 11461da177e4SLinus Torvalds 11471da177e4SLinus Torvalds fmr = pd->device->alloc_fmr(pd, mr_access_flags, fmr_attr); 11481da177e4SLinus Torvalds if (!IS_ERR(fmr)) { 11491da177e4SLinus Torvalds fmr->device = pd->device; 11501da177e4SLinus Torvalds fmr->pd = pd; 11511da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 11521da177e4SLinus Torvalds } 11531da177e4SLinus Torvalds 11541da177e4SLinus Torvalds return fmr; 11551da177e4SLinus Torvalds } 11561da177e4SLinus Torvalds EXPORT_SYMBOL(ib_alloc_fmr); 11571da177e4SLinus Torvalds 11581da177e4SLinus Torvalds int ib_unmap_fmr(struct list_head *fmr_list) 11591da177e4SLinus Torvalds { 11601da177e4SLinus Torvalds struct ib_fmr *fmr; 11611da177e4SLinus Torvalds 11621da177e4SLinus Torvalds if (list_empty(fmr_list)) 11631da177e4SLinus Torvalds return 0; 11641da177e4SLinus Torvalds 11651da177e4SLinus Torvalds fmr = list_entry(fmr_list->next, struct ib_fmr, list); 11661da177e4SLinus Torvalds return fmr->device->unmap_fmr(fmr_list); 11671da177e4SLinus Torvalds } 11681da177e4SLinus Torvalds EXPORT_SYMBOL(ib_unmap_fmr); 11691da177e4SLinus Torvalds 11701da177e4SLinus Torvalds int ib_dealloc_fmr(struct ib_fmr *fmr) 11711da177e4SLinus Torvalds { 11721da177e4SLinus Torvalds struct ib_pd *pd; 11731da177e4SLinus Torvalds int ret; 11741da177e4SLinus Torvalds 11751da177e4SLinus Torvalds pd = fmr->pd; 11761da177e4SLinus Torvalds ret = fmr->device->dealloc_fmr(fmr); 11771da177e4SLinus Torvalds if (!ret) 11781da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 11791da177e4SLinus Torvalds 11801da177e4SLinus Torvalds return ret; 11811da177e4SLinus Torvalds } 11821da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dealloc_fmr); 11831da177e4SLinus Torvalds 11841da177e4SLinus Torvalds /* Multicast groups */ 11851da177e4SLinus Torvalds 11861da177e4SLinus Torvalds int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid) 11871da177e4SLinus Torvalds { 1188c3bccbfbSOr Gerlitz int ret; 1189c3bccbfbSOr Gerlitz 11900c33aeedSJack Morgenstein if (!qp->device->attach_mcast) 11910c33aeedSJack Morgenstein return -ENOSYS; 11920c33aeedSJack Morgenstein if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD) 11930c33aeedSJack Morgenstein return -EINVAL; 11940c33aeedSJack Morgenstein 1195c3bccbfbSOr Gerlitz ret = qp->device->attach_mcast(qp, gid, lid); 1196c3bccbfbSOr Gerlitz if (!ret) 1197c3bccbfbSOr Gerlitz atomic_inc(&qp->usecnt); 1198c3bccbfbSOr Gerlitz return ret; 11991da177e4SLinus Torvalds } 12001da177e4SLinus Torvalds EXPORT_SYMBOL(ib_attach_mcast); 12011da177e4SLinus Torvalds 12021da177e4SLinus Torvalds int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid) 12031da177e4SLinus Torvalds { 1204c3bccbfbSOr Gerlitz int ret; 1205c3bccbfbSOr Gerlitz 12060c33aeedSJack Morgenstein if (!qp->device->detach_mcast) 12070c33aeedSJack Morgenstein return -ENOSYS; 12080c33aeedSJack Morgenstein if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD) 12090c33aeedSJack Morgenstein return -EINVAL; 12100c33aeedSJack Morgenstein 1211c3bccbfbSOr Gerlitz ret = qp->device->detach_mcast(qp, gid, lid); 1212c3bccbfbSOr Gerlitz if (!ret) 1213c3bccbfbSOr Gerlitz atomic_dec(&qp->usecnt); 1214c3bccbfbSOr Gerlitz return ret; 12151da177e4SLinus Torvalds } 12161da177e4SLinus Torvalds EXPORT_SYMBOL(ib_detach_mcast); 121759991f94SSean Hefty 121859991f94SSean Hefty struct ib_xrcd *ib_alloc_xrcd(struct ib_device *device) 121959991f94SSean Hefty { 122059991f94SSean Hefty struct ib_xrcd *xrcd; 122159991f94SSean Hefty 122259991f94SSean Hefty if (!device->alloc_xrcd) 122359991f94SSean Hefty return ERR_PTR(-ENOSYS); 122459991f94SSean Hefty 122559991f94SSean Hefty xrcd = device->alloc_xrcd(device, NULL, NULL); 122659991f94SSean Hefty if (!IS_ERR(xrcd)) { 122759991f94SSean Hefty xrcd->device = device; 122853d0bd1eSSean Hefty xrcd->inode = NULL; 122959991f94SSean Hefty atomic_set(&xrcd->usecnt, 0); 1230d3d72d90SSean Hefty mutex_init(&xrcd->tgt_qp_mutex); 1231d3d72d90SSean Hefty INIT_LIST_HEAD(&xrcd->tgt_qp_list); 123259991f94SSean Hefty } 123359991f94SSean Hefty 123459991f94SSean Hefty return xrcd; 123559991f94SSean Hefty } 123659991f94SSean Hefty EXPORT_SYMBOL(ib_alloc_xrcd); 123759991f94SSean Hefty 123859991f94SSean Hefty int ib_dealloc_xrcd(struct ib_xrcd *xrcd) 123959991f94SSean Hefty { 1240d3d72d90SSean Hefty struct ib_qp *qp; 1241d3d72d90SSean Hefty int ret; 1242d3d72d90SSean Hefty 124359991f94SSean Hefty if (atomic_read(&xrcd->usecnt)) 124459991f94SSean Hefty return -EBUSY; 124559991f94SSean Hefty 1246d3d72d90SSean Hefty while (!list_empty(&xrcd->tgt_qp_list)) { 1247d3d72d90SSean Hefty qp = list_entry(xrcd->tgt_qp_list.next, struct ib_qp, xrcd_list); 1248d3d72d90SSean Hefty ret = ib_destroy_qp(qp); 1249d3d72d90SSean Hefty if (ret) 1250d3d72d90SSean Hefty return ret; 1251d3d72d90SSean Hefty } 1252d3d72d90SSean Hefty 125359991f94SSean Hefty return xrcd->device->dealloc_xrcd(xrcd); 125459991f94SSean Hefty } 125559991f94SSean Hefty EXPORT_SYMBOL(ib_dealloc_xrcd); 1256