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> 47dd5f03beSMatan Barak #include <rdma/ib_addr.h> 481da177e4SLinus Torvalds 49ed4c54e5SOr Gerlitz #include "core_priv.h" 501da177e4SLinus Torvalds 518385fd84SRoland Dreier __attribute_const__ int ib_rate_to_mult(enum ib_rate rate) 52bf6a9e31SJack Morgenstein { 53bf6a9e31SJack Morgenstein switch (rate) { 54bf6a9e31SJack Morgenstein case IB_RATE_2_5_GBPS: return 1; 55bf6a9e31SJack Morgenstein case IB_RATE_5_GBPS: return 2; 56bf6a9e31SJack Morgenstein case IB_RATE_10_GBPS: return 4; 57bf6a9e31SJack Morgenstein case IB_RATE_20_GBPS: return 8; 58bf6a9e31SJack Morgenstein case IB_RATE_30_GBPS: return 12; 59bf6a9e31SJack Morgenstein case IB_RATE_40_GBPS: return 16; 60bf6a9e31SJack Morgenstein case IB_RATE_60_GBPS: return 24; 61bf6a9e31SJack Morgenstein case IB_RATE_80_GBPS: return 32; 62bf6a9e31SJack Morgenstein case IB_RATE_120_GBPS: return 48; 63bf6a9e31SJack Morgenstein default: return -1; 64bf6a9e31SJack Morgenstein } 65bf6a9e31SJack Morgenstein } 66bf6a9e31SJack Morgenstein EXPORT_SYMBOL(ib_rate_to_mult); 67bf6a9e31SJack Morgenstein 688385fd84SRoland Dreier __attribute_const__ enum ib_rate mult_to_ib_rate(int mult) 69bf6a9e31SJack Morgenstein { 70bf6a9e31SJack Morgenstein switch (mult) { 71bf6a9e31SJack Morgenstein case 1: return IB_RATE_2_5_GBPS; 72bf6a9e31SJack Morgenstein case 2: return IB_RATE_5_GBPS; 73bf6a9e31SJack Morgenstein case 4: return IB_RATE_10_GBPS; 74bf6a9e31SJack Morgenstein case 8: return IB_RATE_20_GBPS; 75bf6a9e31SJack Morgenstein case 12: return IB_RATE_30_GBPS; 76bf6a9e31SJack Morgenstein case 16: return IB_RATE_40_GBPS; 77bf6a9e31SJack Morgenstein case 24: return IB_RATE_60_GBPS; 78bf6a9e31SJack Morgenstein case 32: return IB_RATE_80_GBPS; 79bf6a9e31SJack Morgenstein case 48: return IB_RATE_120_GBPS; 80bf6a9e31SJack Morgenstein default: return IB_RATE_PORT_CURRENT; 81bf6a9e31SJack Morgenstein } 82bf6a9e31SJack Morgenstein } 83bf6a9e31SJack Morgenstein EXPORT_SYMBOL(mult_to_ib_rate); 84bf6a9e31SJack Morgenstein 858385fd84SRoland Dreier __attribute_const__ int ib_rate_to_mbps(enum ib_rate rate) 8671eeba16SMarcel Apfelbaum { 8771eeba16SMarcel Apfelbaum switch (rate) { 8871eeba16SMarcel Apfelbaum case IB_RATE_2_5_GBPS: return 2500; 8971eeba16SMarcel Apfelbaum case IB_RATE_5_GBPS: return 5000; 9071eeba16SMarcel Apfelbaum case IB_RATE_10_GBPS: return 10000; 9171eeba16SMarcel Apfelbaum case IB_RATE_20_GBPS: return 20000; 9271eeba16SMarcel Apfelbaum case IB_RATE_30_GBPS: return 30000; 9371eeba16SMarcel Apfelbaum case IB_RATE_40_GBPS: return 40000; 9471eeba16SMarcel Apfelbaum case IB_RATE_60_GBPS: return 60000; 9571eeba16SMarcel Apfelbaum case IB_RATE_80_GBPS: return 80000; 9671eeba16SMarcel Apfelbaum case IB_RATE_120_GBPS: return 120000; 9771eeba16SMarcel Apfelbaum case IB_RATE_14_GBPS: return 14062; 9871eeba16SMarcel Apfelbaum case IB_RATE_56_GBPS: return 56250; 9971eeba16SMarcel Apfelbaum case IB_RATE_112_GBPS: return 112500; 10071eeba16SMarcel Apfelbaum case IB_RATE_168_GBPS: return 168750; 10171eeba16SMarcel Apfelbaum case IB_RATE_25_GBPS: return 25781; 10271eeba16SMarcel Apfelbaum case IB_RATE_100_GBPS: return 103125; 10371eeba16SMarcel Apfelbaum case IB_RATE_200_GBPS: return 206250; 10471eeba16SMarcel Apfelbaum case IB_RATE_300_GBPS: return 309375; 10571eeba16SMarcel Apfelbaum default: return -1; 10671eeba16SMarcel Apfelbaum } 10771eeba16SMarcel Apfelbaum } 10871eeba16SMarcel Apfelbaum EXPORT_SYMBOL(ib_rate_to_mbps); 10971eeba16SMarcel Apfelbaum 1108385fd84SRoland Dreier __attribute_const__ enum rdma_transport_type 11107ebafbaSTom Tucker rdma_node_get_transport(enum rdma_node_type node_type) 11207ebafbaSTom Tucker { 11307ebafbaSTom Tucker switch (node_type) { 11407ebafbaSTom Tucker case RDMA_NODE_IB_CA: 11507ebafbaSTom Tucker case RDMA_NODE_IB_SWITCH: 11607ebafbaSTom Tucker case RDMA_NODE_IB_ROUTER: 11707ebafbaSTom Tucker return RDMA_TRANSPORT_IB; 11807ebafbaSTom Tucker case RDMA_NODE_RNIC: 11907ebafbaSTom Tucker return RDMA_TRANSPORT_IWARP; 120180771a3SUpinder Malhi \(umalhi\) case RDMA_NODE_USNIC: 1215db5765eSUpinder Malhi return RDMA_TRANSPORT_USNIC; 1225db5765eSUpinder Malhi case RDMA_NODE_USNIC_UDP: 123248567f7SUpinder Malhi return RDMA_TRANSPORT_USNIC_UDP; 12407ebafbaSTom Tucker default: 12507ebafbaSTom Tucker BUG(); 12607ebafbaSTom Tucker return 0; 12707ebafbaSTom Tucker } 12807ebafbaSTom Tucker } 12907ebafbaSTom Tucker EXPORT_SYMBOL(rdma_node_get_transport); 13007ebafbaSTom Tucker 131a3f5adafSEli Cohen enum rdma_link_layer rdma_port_get_link_layer(struct ib_device *device, u8 port_num) 132a3f5adafSEli Cohen { 133a3f5adafSEli Cohen if (device->get_link_layer) 134a3f5adafSEli Cohen return device->get_link_layer(device, port_num); 135a3f5adafSEli Cohen 136a3f5adafSEli Cohen switch (rdma_node_get_transport(device->node_type)) { 137a3f5adafSEli Cohen case RDMA_TRANSPORT_IB: 138a3f5adafSEli Cohen return IB_LINK_LAYER_INFINIBAND; 139a3f5adafSEli Cohen case RDMA_TRANSPORT_IWARP: 140180771a3SUpinder Malhi \(umalhi\) case RDMA_TRANSPORT_USNIC: 141248567f7SUpinder Malhi case RDMA_TRANSPORT_USNIC_UDP: 142a3f5adafSEli Cohen return IB_LINK_LAYER_ETHERNET; 143a3f5adafSEli Cohen default: 144a3f5adafSEli Cohen return IB_LINK_LAYER_UNSPECIFIED; 145a3f5adafSEli Cohen } 146a3f5adafSEli Cohen } 147a3f5adafSEli Cohen EXPORT_SYMBOL(rdma_port_get_link_layer); 148a3f5adafSEli Cohen 1491da177e4SLinus Torvalds /* Protection domains */ 1501da177e4SLinus Torvalds 1511da177e4SLinus Torvalds struct ib_pd *ib_alloc_pd(struct ib_device *device) 1521da177e4SLinus Torvalds { 1531da177e4SLinus Torvalds struct ib_pd *pd; 1541da177e4SLinus Torvalds 155b5e81bf5SRoland Dreier pd = device->alloc_pd(device, NULL, NULL); 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds if (!IS_ERR(pd)) { 1581da177e4SLinus Torvalds pd->device = device; 159b5e81bf5SRoland Dreier pd->uobject = NULL; 1601da177e4SLinus Torvalds atomic_set(&pd->usecnt, 0); 1611da177e4SLinus Torvalds } 1621da177e4SLinus Torvalds 1631da177e4SLinus Torvalds return pd; 1641da177e4SLinus Torvalds } 1651da177e4SLinus Torvalds EXPORT_SYMBOL(ib_alloc_pd); 1661da177e4SLinus Torvalds 1671da177e4SLinus Torvalds int ib_dealloc_pd(struct ib_pd *pd) 1681da177e4SLinus Torvalds { 1691da177e4SLinus Torvalds if (atomic_read(&pd->usecnt)) 1701da177e4SLinus Torvalds return -EBUSY; 1711da177e4SLinus Torvalds 1721da177e4SLinus Torvalds return pd->device->dealloc_pd(pd); 1731da177e4SLinus Torvalds } 1741da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dealloc_pd); 1751da177e4SLinus Torvalds 1761da177e4SLinus Torvalds /* Address handles */ 1771da177e4SLinus Torvalds 1781da177e4SLinus Torvalds struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) 1791da177e4SLinus Torvalds { 1801da177e4SLinus Torvalds struct ib_ah *ah; 1811da177e4SLinus Torvalds 1821da177e4SLinus Torvalds ah = pd->device->create_ah(pd, ah_attr); 1831da177e4SLinus Torvalds 1841da177e4SLinus Torvalds if (!IS_ERR(ah)) { 1851da177e4SLinus Torvalds ah->device = pd->device; 1861da177e4SLinus Torvalds ah->pd = pd; 187b5e81bf5SRoland Dreier ah->uobject = NULL; 1881da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 1891da177e4SLinus Torvalds } 1901da177e4SLinus Torvalds 1911da177e4SLinus Torvalds return ah; 1921da177e4SLinus Torvalds } 1931da177e4SLinus Torvalds EXPORT_SYMBOL(ib_create_ah); 1941da177e4SLinus Torvalds 1954e00d694SSean Hefty int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc, 1964e00d694SSean Hefty struct ib_grh *grh, struct ib_ah_attr *ah_attr) 197513789edSHal Rosenstock { 198513789edSHal Rosenstock u32 flow_class; 199513789edSHal Rosenstock u16 gid_index; 200513789edSHal Rosenstock int ret; 201dd5f03beSMatan Barak int is_eth = (rdma_port_get_link_layer(device, port_num) == 202dd5f03beSMatan Barak IB_LINK_LAYER_ETHERNET); 203513789edSHal Rosenstock 2044e00d694SSean Hefty memset(ah_attr, 0, sizeof *ah_attr); 205dd5f03beSMatan Barak if (is_eth) { 206dd5f03beSMatan Barak if (!(wc->wc_flags & IB_WC_GRH)) 207dd5f03beSMatan Barak return -EPROTOTYPE; 208dd5f03beSMatan Barak 209dd5f03beSMatan Barak if (wc->wc_flags & IB_WC_WITH_SMAC && 210dd5f03beSMatan Barak wc->wc_flags & IB_WC_WITH_VLAN) { 211dd5f03beSMatan Barak memcpy(ah_attr->dmac, wc->smac, ETH_ALEN); 212dd5f03beSMatan Barak ah_attr->vlan_id = wc->vlan_id; 213dd5f03beSMatan Barak } else { 214dd5f03beSMatan Barak ret = rdma_addr_find_dmac_by_grh(&grh->dgid, &grh->sgid, 215dd5f03beSMatan Barak ah_attr->dmac, &ah_attr->vlan_id); 216dd5f03beSMatan Barak if (ret) 217dd5f03beSMatan Barak return ret; 218dd5f03beSMatan Barak } 219dd5f03beSMatan Barak } else { 220dd5f03beSMatan Barak ah_attr->vlan_id = 0xffff; 221dd5f03beSMatan Barak } 222dd5f03beSMatan Barak 2234e00d694SSean Hefty ah_attr->dlid = wc->slid; 2244e00d694SSean Hefty ah_attr->sl = wc->sl; 2254e00d694SSean Hefty ah_attr->src_path_bits = wc->dlid_path_bits; 2264e00d694SSean Hefty ah_attr->port_num = port_num; 227513789edSHal Rosenstock 228513789edSHal Rosenstock if (wc->wc_flags & IB_WC_GRH) { 2294e00d694SSean Hefty ah_attr->ah_flags = IB_AH_GRH; 2304e00d694SSean Hefty ah_attr->grh.dgid = grh->sgid; 231513789edSHal Rosenstock 2324e00d694SSean Hefty ret = ib_find_cached_gid(device, &grh->dgid, &port_num, 233513789edSHal Rosenstock &gid_index); 234513789edSHal Rosenstock if (ret) 2354e00d694SSean Hefty return ret; 236513789edSHal Rosenstock 2374e00d694SSean Hefty ah_attr->grh.sgid_index = (u8) gid_index; 238497677abSHal Rosenstock flow_class = be32_to_cpu(grh->version_tclass_flow); 2394e00d694SSean Hefty ah_attr->grh.flow_label = flow_class & 0xFFFFF; 24047645d8dSSean Hefty ah_attr->grh.hop_limit = 0xFF; 2414e00d694SSean Hefty ah_attr->grh.traffic_class = (flow_class >> 20) & 0xFF; 242513789edSHal Rosenstock } 2434e00d694SSean Hefty return 0; 2444e00d694SSean Hefty } 2454e00d694SSean Hefty EXPORT_SYMBOL(ib_init_ah_from_wc); 2464e00d694SSean Hefty 2474e00d694SSean Hefty struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc, 2484e00d694SSean Hefty struct ib_grh *grh, u8 port_num) 2494e00d694SSean Hefty { 2504e00d694SSean Hefty struct ib_ah_attr ah_attr; 2514e00d694SSean Hefty int ret; 2524e00d694SSean Hefty 2534e00d694SSean Hefty ret = ib_init_ah_from_wc(pd->device, port_num, wc, grh, &ah_attr); 2544e00d694SSean Hefty if (ret) 2554e00d694SSean Hefty return ERR_PTR(ret); 256513789edSHal Rosenstock 257513789edSHal Rosenstock return ib_create_ah(pd, &ah_attr); 258513789edSHal Rosenstock } 259513789edSHal Rosenstock EXPORT_SYMBOL(ib_create_ah_from_wc); 260513789edSHal Rosenstock 2611da177e4SLinus Torvalds int ib_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) 2621da177e4SLinus Torvalds { 2631da177e4SLinus Torvalds return ah->device->modify_ah ? 2641da177e4SLinus Torvalds ah->device->modify_ah(ah, ah_attr) : 2651da177e4SLinus Torvalds -ENOSYS; 2661da177e4SLinus Torvalds } 2671da177e4SLinus Torvalds EXPORT_SYMBOL(ib_modify_ah); 2681da177e4SLinus Torvalds 2691da177e4SLinus Torvalds int ib_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) 2701da177e4SLinus Torvalds { 2711da177e4SLinus Torvalds return ah->device->query_ah ? 2721da177e4SLinus Torvalds ah->device->query_ah(ah, ah_attr) : 2731da177e4SLinus Torvalds -ENOSYS; 2741da177e4SLinus Torvalds } 2751da177e4SLinus Torvalds EXPORT_SYMBOL(ib_query_ah); 2761da177e4SLinus Torvalds 2771da177e4SLinus Torvalds int ib_destroy_ah(struct ib_ah *ah) 2781da177e4SLinus Torvalds { 2791da177e4SLinus Torvalds struct ib_pd *pd; 2801da177e4SLinus Torvalds int ret; 2811da177e4SLinus Torvalds 2821da177e4SLinus Torvalds pd = ah->pd; 2831da177e4SLinus Torvalds ret = ah->device->destroy_ah(ah); 2841da177e4SLinus Torvalds if (!ret) 2851da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 2861da177e4SLinus Torvalds 2871da177e4SLinus Torvalds return ret; 2881da177e4SLinus Torvalds } 2891da177e4SLinus Torvalds EXPORT_SYMBOL(ib_destroy_ah); 2901da177e4SLinus Torvalds 291d41fcc67SRoland Dreier /* Shared receive queues */ 292d41fcc67SRoland Dreier 293d41fcc67SRoland Dreier struct ib_srq *ib_create_srq(struct ib_pd *pd, 294d41fcc67SRoland Dreier struct ib_srq_init_attr *srq_init_attr) 295d41fcc67SRoland Dreier { 296d41fcc67SRoland Dreier struct ib_srq *srq; 297d41fcc67SRoland Dreier 298d41fcc67SRoland Dreier if (!pd->device->create_srq) 299d41fcc67SRoland Dreier return ERR_PTR(-ENOSYS); 300d41fcc67SRoland Dreier 301d41fcc67SRoland Dreier srq = pd->device->create_srq(pd, srq_init_attr, NULL); 302d41fcc67SRoland Dreier 303d41fcc67SRoland Dreier if (!IS_ERR(srq)) { 304d41fcc67SRoland Dreier srq->device = pd->device; 305d41fcc67SRoland Dreier srq->pd = pd; 306d41fcc67SRoland Dreier srq->uobject = NULL; 307d41fcc67SRoland Dreier srq->event_handler = srq_init_attr->event_handler; 308d41fcc67SRoland Dreier srq->srq_context = srq_init_attr->srq_context; 30996104edaSSean Hefty srq->srq_type = srq_init_attr->srq_type; 310418d5130SSean Hefty if (srq->srq_type == IB_SRQT_XRC) { 311418d5130SSean Hefty srq->ext.xrc.xrcd = srq_init_attr->ext.xrc.xrcd; 312418d5130SSean Hefty srq->ext.xrc.cq = srq_init_attr->ext.xrc.cq; 313418d5130SSean Hefty atomic_inc(&srq->ext.xrc.xrcd->usecnt); 314418d5130SSean Hefty atomic_inc(&srq->ext.xrc.cq->usecnt); 315418d5130SSean Hefty } 316d41fcc67SRoland Dreier atomic_inc(&pd->usecnt); 317d41fcc67SRoland Dreier atomic_set(&srq->usecnt, 0); 318d41fcc67SRoland Dreier } 319d41fcc67SRoland Dreier 320d41fcc67SRoland Dreier return srq; 321d41fcc67SRoland Dreier } 322d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_create_srq); 323d41fcc67SRoland Dreier 324d41fcc67SRoland Dreier int ib_modify_srq(struct ib_srq *srq, 325d41fcc67SRoland Dreier struct ib_srq_attr *srq_attr, 326d41fcc67SRoland Dreier enum ib_srq_attr_mask srq_attr_mask) 327d41fcc67SRoland Dreier { 3287ce5eacbSDotan Barak return srq->device->modify_srq ? 3297ce5eacbSDotan Barak srq->device->modify_srq(srq, srq_attr, srq_attr_mask, NULL) : 3307ce5eacbSDotan Barak -ENOSYS; 331d41fcc67SRoland Dreier } 332d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_modify_srq); 333d41fcc67SRoland Dreier 334d41fcc67SRoland Dreier int ib_query_srq(struct ib_srq *srq, 335d41fcc67SRoland Dreier struct ib_srq_attr *srq_attr) 336d41fcc67SRoland Dreier { 337d41fcc67SRoland Dreier return srq->device->query_srq ? 338d41fcc67SRoland Dreier srq->device->query_srq(srq, srq_attr) : -ENOSYS; 339d41fcc67SRoland Dreier } 340d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_query_srq); 341d41fcc67SRoland Dreier 342d41fcc67SRoland Dreier int ib_destroy_srq(struct ib_srq *srq) 343d41fcc67SRoland Dreier { 344d41fcc67SRoland Dreier struct ib_pd *pd; 345418d5130SSean Hefty enum ib_srq_type srq_type; 346418d5130SSean Hefty struct ib_xrcd *uninitialized_var(xrcd); 347418d5130SSean Hefty struct ib_cq *uninitialized_var(cq); 348d41fcc67SRoland Dreier int ret; 349d41fcc67SRoland Dreier 350d41fcc67SRoland Dreier if (atomic_read(&srq->usecnt)) 351d41fcc67SRoland Dreier return -EBUSY; 352d41fcc67SRoland Dreier 353d41fcc67SRoland Dreier pd = srq->pd; 354418d5130SSean Hefty srq_type = srq->srq_type; 355418d5130SSean Hefty if (srq_type == IB_SRQT_XRC) { 356418d5130SSean Hefty xrcd = srq->ext.xrc.xrcd; 357418d5130SSean Hefty cq = srq->ext.xrc.cq; 358418d5130SSean Hefty } 359d41fcc67SRoland Dreier 360d41fcc67SRoland Dreier ret = srq->device->destroy_srq(srq); 361418d5130SSean Hefty if (!ret) { 362d41fcc67SRoland Dreier atomic_dec(&pd->usecnt); 363418d5130SSean Hefty if (srq_type == IB_SRQT_XRC) { 364418d5130SSean Hefty atomic_dec(&xrcd->usecnt); 365418d5130SSean Hefty atomic_dec(&cq->usecnt); 366418d5130SSean Hefty } 367418d5130SSean Hefty } 368d41fcc67SRoland Dreier 369d41fcc67SRoland Dreier return ret; 370d41fcc67SRoland Dreier } 371d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_destroy_srq); 372d41fcc67SRoland Dreier 3731da177e4SLinus Torvalds /* Queue pairs */ 3741da177e4SLinus Torvalds 3750e0ec7e0SSean Hefty static void __ib_shared_qp_event_handler(struct ib_event *event, void *context) 3760e0ec7e0SSean Hefty { 3770e0ec7e0SSean Hefty struct ib_qp *qp = context; 37873c40c61SYishai Hadas unsigned long flags; 3790e0ec7e0SSean Hefty 38073c40c61SYishai Hadas spin_lock_irqsave(&qp->device->event_handler_lock, flags); 3810e0ec7e0SSean Hefty list_for_each_entry(event->element.qp, &qp->open_list, open_list) 382eec9e29fSShlomo Pongratz if (event->element.qp->event_handler) 3830e0ec7e0SSean Hefty event->element.qp->event_handler(event, event->element.qp->qp_context); 38473c40c61SYishai Hadas spin_unlock_irqrestore(&qp->device->event_handler_lock, flags); 3850e0ec7e0SSean Hefty } 3860e0ec7e0SSean Hefty 387d3d72d90SSean Hefty static void __ib_insert_xrcd_qp(struct ib_xrcd *xrcd, struct ib_qp *qp) 388d3d72d90SSean Hefty { 389d3d72d90SSean Hefty mutex_lock(&xrcd->tgt_qp_mutex); 390d3d72d90SSean Hefty list_add(&qp->xrcd_list, &xrcd->tgt_qp_list); 391d3d72d90SSean Hefty mutex_unlock(&xrcd->tgt_qp_mutex); 392d3d72d90SSean Hefty } 393d3d72d90SSean Hefty 3940e0ec7e0SSean Hefty static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp, 3950e0ec7e0SSean Hefty void (*event_handler)(struct ib_event *, void *), 3960e0ec7e0SSean Hefty void *qp_context) 397d3d72d90SSean Hefty { 3980e0ec7e0SSean Hefty struct ib_qp *qp; 3990e0ec7e0SSean Hefty unsigned long flags; 4000e0ec7e0SSean Hefty 4010e0ec7e0SSean Hefty qp = kzalloc(sizeof *qp, GFP_KERNEL); 4020e0ec7e0SSean Hefty if (!qp) 4030e0ec7e0SSean Hefty return ERR_PTR(-ENOMEM); 4040e0ec7e0SSean Hefty 4050e0ec7e0SSean Hefty qp->real_qp = real_qp; 4060e0ec7e0SSean Hefty atomic_inc(&real_qp->usecnt); 4070e0ec7e0SSean Hefty qp->device = real_qp->device; 4080e0ec7e0SSean Hefty qp->event_handler = event_handler; 4090e0ec7e0SSean Hefty qp->qp_context = qp_context; 4100e0ec7e0SSean Hefty qp->qp_num = real_qp->qp_num; 4110e0ec7e0SSean Hefty qp->qp_type = real_qp->qp_type; 4120e0ec7e0SSean Hefty 4130e0ec7e0SSean Hefty spin_lock_irqsave(&real_qp->device->event_handler_lock, flags); 4140e0ec7e0SSean Hefty list_add(&qp->open_list, &real_qp->open_list); 4150e0ec7e0SSean Hefty spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags); 4160e0ec7e0SSean Hefty 4170e0ec7e0SSean Hefty return qp; 418d3d72d90SSean Hefty } 419d3d72d90SSean Hefty 4200e0ec7e0SSean Hefty struct ib_qp *ib_open_qp(struct ib_xrcd *xrcd, 4210e0ec7e0SSean Hefty struct ib_qp_open_attr *qp_open_attr) 4220e0ec7e0SSean Hefty { 4230e0ec7e0SSean Hefty struct ib_qp *qp, *real_qp; 4240e0ec7e0SSean Hefty 4250e0ec7e0SSean Hefty if (qp_open_attr->qp_type != IB_QPT_XRC_TGT) 4260e0ec7e0SSean Hefty return ERR_PTR(-EINVAL); 4270e0ec7e0SSean Hefty 4280e0ec7e0SSean Hefty qp = ERR_PTR(-EINVAL); 4290e0ec7e0SSean Hefty mutex_lock(&xrcd->tgt_qp_mutex); 4300e0ec7e0SSean Hefty list_for_each_entry(real_qp, &xrcd->tgt_qp_list, xrcd_list) { 4310e0ec7e0SSean Hefty if (real_qp->qp_num == qp_open_attr->qp_num) { 4320e0ec7e0SSean Hefty qp = __ib_open_qp(real_qp, qp_open_attr->event_handler, 4330e0ec7e0SSean Hefty qp_open_attr->qp_context); 4340e0ec7e0SSean Hefty break; 4350e0ec7e0SSean Hefty } 4360e0ec7e0SSean Hefty } 4370e0ec7e0SSean Hefty mutex_unlock(&xrcd->tgt_qp_mutex); 4380e0ec7e0SSean Hefty return qp; 4390e0ec7e0SSean Hefty } 4400e0ec7e0SSean Hefty EXPORT_SYMBOL(ib_open_qp); 4410e0ec7e0SSean Hefty 4421da177e4SLinus Torvalds struct ib_qp *ib_create_qp(struct ib_pd *pd, 4431da177e4SLinus Torvalds struct ib_qp_init_attr *qp_init_attr) 4441da177e4SLinus Torvalds { 4450e0ec7e0SSean Hefty struct ib_qp *qp, *real_qp; 446b42b63cfSSean Hefty struct ib_device *device; 4471da177e4SLinus Torvalds 448b42b63cfSSean Hefty device = pd ? pd->device : qp_init_attr->xrcd->device; 449b42b63cfSSean Hefty qp = device->create_qp(pd, qp_init_attr, NULL); 4501da177e4SLinus Torvalds 4511da177e4SLinus Torvalds if (!IS_ERR(qp)) { 452b42b63cfSSean Hefty qp->device = device; 4530e0ec7e0SSean Hefty qp->real_qp = qp; 454b5e81bf5SRoland Dreier qp->uobject = NULL; 4550e0ec7e0SSean Hefty qp->qp_type = qp_init_attr->qp_type; 456b42b63cfSSean Hefty 457e47e321aSBernd Schubert atomic_set(&qp->usecnt, 0); 458b42b63cfSSean Hefty if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) { 4590e0ec7e0SSean Hefty qp->event_handler = __ib_shared_qp_event_handler; 4600e0ec7e0SSean Hefty qp->qp_context = qp; 461b42b63cfSSean Hefty qp->pd = NULL; 462b42b63cfSSean Hefty qp->send_cq = qp->recv_cq = NULL; 463b42b63cfSSean Hefty qp->srq = NULL; 464b42b63cfSSean Hefty qp->xrcd = qp_init_attr->xrcd; 465b42b63cfSSean Hefty atomic_inc(&qp_init_attr->xrcd->usecnt); 4660e0ec7e0SSean Hefty INIT_LIST_HEAD(&qp->open_list); 4670e0ec7e0SSean Hefty 4680e0ec7e0SSean Hefty real_qp = qp; 4690e0ec7e0SSean Hefty qp = __ib_open_qp(real_qp, qp_init_attr->event_handler, 4700e0ec7e0SSean Hefty qp_init_attr->qp_context); 4710e0ec7e0SSean Hefty if (!IS_ERR(qp)) 4720e0ec7e0SSean Hefty __ib_insert_xrcd_qp(qp_init_attr->xrcd, real_qp); 4730e0ec7e0SSean Hefty else 4740e0ec7e0SSean Hefty real_qp->device->destroy_qp(real_qp); 475b42b63cfSSean Hefty } else { 4761da177e4SLinus Torvalds qp->event_handler = qp_init_attr->event_handler; 4771da177e4SLinus Torvalds qp->qp_context = qp_init_attr->qp_context; 478b42b63cfSSean Hefty if (qp_init_attr->qp_type == IB_QPT_XRC_INI) { 479b42b63cfSSean Hefty qp->recv_cq = NULL; 480b42b63cfSSean Hefty qp->srq = NULL; 481b42b63cfSSean Hefty } else { 482b42b63cfSSean Hefty qp->recv_cq = qp_init_attr->recv_cq; 483b42b63cfSSean Hefty atomic_inc(&qp_init_attr->recv_cq->usecnt); 484b42b63cfSSean Hefty qp->srq = qp_init_attr->srq; 485b42b63cfSSean Hefty if (qp->srq) 486b42b63cfSSean Hefty atomic_inc(&qp_init_attr->srq->usecnt); 487b42b63cfSSean Hefty } 488b42b63cfSSean Hefty 4891da177e4SLinus Torvalds qp->pd = pd; 4901da177e4SLinus Torvalds qp->send_cq = qp_init_attr->send_cq; 491b42b63cfSSean Hefty qp->xrcd = NULL; 492b42b63cfSSean Hefty 4931da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 4941da177e4SLinus Torvalds atomic_inc(&qp_init_attr->send_cq->usecnt); 495b42b63cfSSean Hefty } 4961da177e4SLinus Torvalds } 4971da177e4SLinus Torvalds 4981da177e4SLinus Torvalds return qp; 4991da177e4SLinus Torvalds } 5001da177e4SLinus Torvalds EXPORT_SYMBOL(ib_create_qp); 5011da177e4SLinus Torvalds 5028a51866fSRoland Dreier static const struct { 5038a51866fSRoland Dreier int valid; 504b42b63cfSSean Hefty enum ib_qp_attr_mask req_param[IB_QPT_MAX]; 505dd5f03beSMatan Barak enum ib_qp_attr_mask req_param_add_eth[IB_QPT_MAX]; 506b42b63cfSSean Hefty enum ib_qp_attr_mask opt_param[IB_QPT_MAX]; 507dd5f03beSMatan Barak enum ib_qp_attr_mask opt_param_add_eth[IB_QPT_MAX]; 5088a51866fSRoland Dreier } qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = { 5098a51866fSRoland Dreier [IB_QPS_RESET] = { 5108a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 5118a51866fSRoland Dreier [IB_QPS_INIT] = { 5128a51866fSRoland Dreier .valid = 1, 5138a51866fSRoland Dreier .req_param = { 5148a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 5158a51866fSRoland Dreier IB_QP_PORT | 5168a51866fSRoland Dreier IB_QP_QKEY), 517c938a616SOr Gerlitz [IB_QPT_RAW_PACKET] = IB_QP_PORT, 5188a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_PKEY_INDEX | 5198a51866fSRoland Dreier IB_QP_PORT | 5208a51866fSRoland Dreier IB_QP_ACCESS_FLAGS), 5218a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_PKEY_INDEX | 5228a51866fSRoland Dreier IB_QP_PORT | 5238a51866fSRoland Dreier IB_QP_ACCESS_FLAGS), 524b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX | 525b42b63cfSSean Hefty IB_QP_PORT | 526b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS), 527b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX | 528b42b63cfSSean Hefty IB_QP_PORT | 529b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS), 5308a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 5318a51866fSRoland Dreier IB_QP_QKEY), 5328a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 5338a51866fSRoland Dreier IB_QP_QKEY), 5348a51866fSRoland Dreier } 5358a51866fSRoland Dreier }, 5368a51866fSRoland Dreier }, 5378a51866fSRoland Dreier [IB_QPS_INIT] = { 5388a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 5398a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 }, 5408a51866fSRoland Dreier [IB_QPS_INIT] = { 5418a51866fSRoland Dreier .valid = 1, 5428a51866fSRoland Dreier .opt_param = { 5438a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 5448a51866fSRoland Dreier IB_QP_PORT | 5458a51866fSRoland Dreier IB_QP_QKEY), 5468a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_PKEY_INDEX | 5478a51866fSRoland Dreier IB_QP_PORT | 5488a51866fSRoland Dreier IB_QP_ACCESS_FLAGS), 5498a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_PKEY_INDEX | 5508a51866fSRoland Dreier IB_QP_PORT | 5518a51866fSRoland Dreier IB_QP_ACCESS_FLAGS), 552b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX | 553b42b63cfSSean Hefty IB_QP_PORT | 554b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS), 555b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX | 556b42b63cfSSean Hefty IB_QP_PORT | 557b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS), 5588a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 5598a51866fSRoland Dreier IB_QP_QKEY), 5608a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 5618a51866fSRoland Dreier IB_QP_QKEY), 5628a51866fSRoland Dreier } 5638a51866fSRoland Dreier }, 5648a51866fSRoland Dreier [IB_QPS_RTR] = { 5658a51866fSRoland Dreier .valid = 1, 5668a51866fSRoland Dreier .req_param = { 5678a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_AV | 5688a51866fSRoland Dreier IB_QP_PATH_MTU | 5698a51866fSRoland Dreier IB_QP_DEST_QPN | 5708a51866fSRoland Dreier IB_QP_RQ_PSN), 5718a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_AV | 5728a51866fSRoland Dreier IB_QP_PATH_MTU | 5738a51866fSRoland Dreier IB_QP_DEST_QPN | 5748a51866fSRoland Dreier IB_QP_RQ_PSN | 5758a51866fSRoland Dreier IB_QP_MAX_DEST_RD_ATOMIC | 5768a51866fSRoland Dreier IB_QP_MIN_RNR_TIMER), 577b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_AV | 578b42b63cfSSean Hefty IB_QP_PATH_MTU | 579b42b63cfSSean Hefty IB_QP_DEST_QPN | 580b42b63cfSSean Hefty IB_QP_RQ_PSN), 581b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_AV | 582b42b63cfSSean Hefty IB_QP_PATH_MTU | 583b42b63cfSSean Hefty IB_QP_DEST_QPN | 584b42b63cfSSean Hefty IB_QP_RQ_PSN | 585b42b63cfSSean Hefty IB_QP_MAX_DEST_RD_ATOMIC | 586b42b63cfSSean Hefty IB_QP_MIN_RNR_TIMER), 5878a51866fSRoland Dreier }, 588dd5f03beSMatan Barak .req_param_add_eth = { 589dd5f03beSMatan Barak [IB_QPT_RC] = (IB_QP_SMAC), 590dd5f03beSMatan Barak [IB_QPT_UC] = (IB_QP_SMAC), 591dd5f03beSMatan Barak [IB_QPT_XRC_INI] = (IB_QP_SMAC), 592dd5f03beSMatan Barak [IB_QPT_XRC_TGT] = (IB_QP_SMAC) 593dd5f03beSMatan Barak }, 5948a51866fSRoland Dreier .opt_param = { 5958a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 5968a51866fSRoland Dreier IB_QP_QKEY), 5978a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_ALT_PATH | 5988a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 5998a51866fSRoland Dreier IB_QP_PKEY_INDEX), 6008a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_ALT_PATH | 6018a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 6028a51866fSRoland Dreier IB_QP_PKEY_INDEX), 603b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_ALT_PATH | 604b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 605b42b63cfSSean Hefty IB_QP_PKEY_INDEX), 606b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_ALT_PATH | 607b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 608b42b63cfSSean Hefty IB_QP_PKEY_INDEX), 6098a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 6108a51866fSRoland Dreier IB_QP_QKEY), 6118a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 6128a51866fSRoland Dreier IB_QP_QKEY), 613dd5f03beSMatan Barak }, 614dd5f03beSMatan Barak .opt_param_add_eth = { 615dd5f03beSMatan Barak [IB_QPT_RC] = (IB_QP_ALT_SMAC | 616dd5f03beSMatan Barak IB_QP_VID | 617dd5f03beSMatan Barak IB_QP_ALT_VID), 618dd5f03beSMatan Barak [IB_QPT_UC] = (IB_QP_ALT_SMAC | 619dd5f03beSMatan Barak IB_QP_VID | 620dd5f03beSMatan Barak IB_QP_ALT_VID), 621dd5f03beSMatan Barak [IB_QPT_XRC_INI] = (IB_QP_ALT_SMAC | 622dd5f03beSMatan Barak IB_QP_VID | 623dd5f03beSMatan Barak IB_QP_ALT_VID), 624dd5f03beSMatan Barak [IB_QPT_XRC_TGT] = (IB_QP_ALT_SMAC | 625dd5f03beSMatan Barak IB_QP_VID | 626dd5f03beSMatan Barak IB_QP_ALT_VID) 6278a51866fSRoland Dreier } 6288a51866fSRoland Dreier } 6298a51866fSRoland Dreier }, 6308a51866fSRoland Dreier [IB_QPS_RTR] = { 6318a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 6328a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 }, 6338a51866fSRoland Dreier [IB_QPS_RTS] = { 6348a51866fSRoland Dreier .valid = 1, 6358a51866fSRoland Dreier .req_param = { 6368a51866fSRoland Dreier [IB_QPT_UD] = IB_QP_SQ_PSN, 6378a51866fSRoland Dreier [IB_QPT_UC] = IB_QP_SQ_PSN, 6388a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_TIMEOUT | 6398a51866fSRoland Dreier IB_QP_RETRY_CNT | 6408a51866fSRoland Dreier IB_QP_RNR_RETRY | 6418a51866fSRoland Dreier IB_QP_SQ_PSN | 6428a51866fSRoland Dreier IB_QP_MAX_QP_RD_ATOMIC), 643b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_TIMEOUT | 644b42b63cfSSean Hefty IB_QP_RETRY_CNT | 645b42b63cfSSean Hefty IB_QP_RNR_RETRY | 646b42b63cfSSean Hefty IB_QP_SQ_PSN | 647b42b63cfSSean Hefty IB_QP_MAX_QP_RD_ATOMIC), 648b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_TIMEOUT | 649b42b63cfSSean Hefty IB_QP_SQ_PSN), 6508a51866fSRoland Dreier [IB_QPT_SMI] = IB_QP_SQ_PSN, 6518a51866fSRoland Dreier [IB_QPT_GSI] = IB_QP_SQ_PSN, 6528a51866fSRoland Dreier }, 6538a51866fSRoland Dreier .opt_param = { 6548a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_CUR_STATE | 6558a51866fSRoland Dreier IB_QP_QKEY), 6568a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_CUR_STATE | 6578a51866fSRoland Dreier IB_QP_ALT_PATH | 6588a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 6598a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 6608a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_CUR_STATE | 6618a51866fSRoland Dreier IB_QP_ALT_PATH | 6628a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 6638a51866fSRoland Dreier IB_QP_MIN_RNR_TIMER | 6648a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 665b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE | 666b42b63cfSSean Hefty IB_QP_ALT_PATH | 667b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 668b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 669b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE | 670b42b63cfSSean Hefty IB_QP_ALT_PATH | 671b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 672b42b63cfSSean Hefty IB_QP_MIN_RNR_TIMER | 673b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 6748a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_CUR_STATE | 6758a51866fSRoland Dreier IB_QP_QKEY), 6768a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_CUR_STATE | 6778a51866fSRoland Dreier IB_QP_QKEY), 6788a51866fSRoland Dreier } 6798a51866fSRoland Dreier } 6808a51866fSRoland Dreier }, 6818a51866fSRoland Dreier [IB_QPS_RTS] = { 6828a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 6838a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 }, 6848a51866fSRoland Dreier [IB_QPS_RTS] = { 6858a51866fSRoland Dreier .valid = 1, 6868a51866fSRoland Dreier .opt_param = { 6878a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_CUR_STATE | 6888a51866fSRoland Dreier IB_QP_QKEY), 6894546d31dSDotan Barak [IB_QPT_UC] = (IB_QP_CUR_STATE | 6904546d31dSDotan Barak IB_QP_ACCESS_FLAGS | 6918a51866fSRoland Dreier IB_QP_ALT_PATH | 6928a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 6934546d31dSDotan Barak [IB_QPT_RC] = (IB_QP_CUR_STATE | 6944546d31dSDotan Barak IB_QP_ACCESS_FLAGS | 6958a51866fSRoland Dreier IB_QP_ALT_PATH | 6968a51866fSRoland Dreier IB_QP_PATH_MIG_STATE | 6978a51866fSRoland Dreier IB_QP_MIN_RNR_TIMER), 698b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE | 699b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 700b42b63cfSSean Hefty IB_QP_ALT_PATH | 701b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 702b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE | 703b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 704b42b63cfSSean Hefty IB_QP_ALT_PATH | 705b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE | 706b42b63cfSSean Hefty IB_QP_MIN_RNR_TIMER), 7078a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_CUR_STATE | 7088a51866fSRoland Dreier IB_QP_QKEY), 7098a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_CUR_STATE | 7108a51866fSRoland Dreier IB_QP_QKEY), 7118a51866fSRoland Dreier } 7128a51866fSRoland Dreier }, 7138a51866fSRoland Dreier [IB_QPS_SQD] = { 7148a51866fSRoland Dreier .valid = 1, 7158a51866fSRoland Dreier .opt_param = { 7168a51866fSRoland Dreier [IB_QPT_UD] = IB_QP_EN_SQD_ASYNC_NOTIFY, 7178a51866fSRoland Dreier [IB_QPT_UC] = IB_QP_EN_SQD_ASYNC_NOTIFY, 7188a51866fSRoland Dreier [IB_QPT_RC] = IB_QP_EN_SQD_ASYNC_NOTIFY, 719b42b63cfSSean Hefty [IB_QPT_XRC_INI] = IB_QP_EN_SQD_ASYNC_NOTIFY, 720b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = IB_QP_EN_SQD_ASYNC_NOTIFY, /* ??? */ 7218a51866fSRoland Dreier [IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY, 7228a51866fSRoland Dreier [IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY 7238a51866fSRoland Dreier } 7248a51866fSRoland Dreier }, 7258a51866fSRoland Dreier }, 7268a51866fSRoland Dreier [IB_QPS_SQD] = { 7278a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 7288a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 }, 7298a51866fSRoland Dreier [IB_QPS_RTS] = { 7308a51866fSRoland Dreier .valid = 1, 7318a51866fSRoland Dreier .opt_param = { 7328a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_CUR_STATE | 7338a51866fSRoland Dreier IB_QP_QKEY), 7348a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_CUR_STATE | 7358a51866fSRoland Dreier IB_QP_ALT_PATH | 7368a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 7378a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 7388a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_CUR_STATE | 7398a51866fSRoland Dreier IB_QP_ALT_PATH | 7408a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 7418a51866fSRoland Dreier IB_QP_MIN_RNR_TIMER | 7428a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 743b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE | 744b42b63cfSSean Hefty IB_QP_ALT_PATH | 745b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 746b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 747b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE | 748b42b63cfSSean Hefty IB_QP_ALT_PATH | 749b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 750b42b63cfSSean Hefty IB_QP_MIN_RNR_TIMER | 751b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 7528a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_CUR_STATE | 7538a51866fSRoland Dreier IB_QP_QKEY), 7548a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_CUR_STATE | 7558a51866fSRoland Dreier IB_QP_QKEY), 7568a51866fSRoland Dreier } 7578a51866fSRoland Dreier }, 7588a51866fSRoland Dreier [IB_QPS_SQD] = { 7598a51866fSRoland Dreier .valid = 1, 7608a51866fSRoland Dreier .opt_param = { 7618a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 7628a51866fSRoland Dreier IB_QP_QKEY), 7638a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_AV | 7648a51866fSRoland Dreier IB_QP_ALT_PATH | 7658a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 7668a51866fSRoland Dreier IB_QP_PKEY_INDEX | 7678a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 7688a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_PORT | 7698a51866fSRoland Dreier IB_QP_AV | 7708a51866fSRoland Dreier IB_QP_TIMEOUT | 7718a51866fSRoland Dreier IB_QP_RETRY_CNT | 7728a51866fSRoland Dreier IB_QP_RNR_RETRY | 7738a51866fSRoland Dreier IB_QP_MAX_QP_RD_ATOMIC | 7748a51866fSRoland Dreier IB_QP_MAX_DEST_RD_ATOMIC | 7758a51866fSRoland Dreier IB_QP_ALT_PATH | 7768a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 7778a51866fSRoland Dreier IB_QP_PKEY_INDEX | 7788a51866fSRoland Dreier IB_QP_MIN_RNR_TIMER | 7798a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 780b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_PORT | 781b42b63cfSSean Hefty IB_QP_AV | 782b42b63cfSSean Hefty IB_QP_TIMEOUT | 783b42b63cfSSean Hefty IB_QP_RETRY_CNT | 784b42b63cfSSean Hefty IB_QP_RNR_RETRY | 785b42b63cfSSean Hefty IB_QP_MAX_QP_RD_ATOMIC | 786b42b63cfSSean Hefty IB_QP_ALT_PATH | 787b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 788b42b63cfSSean Hefty IB_QP_PKEY_INDEX | 789b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 790b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_PORT | 791b42b63cfSSean Hefty IB_QP_AV | 792b42b63cfSSean Hefty IB_QP_TIMEOUT | 793b42b63cfSSean Hefty IB_QP_MAX_DEST_RD_ATOMIC | 794b42b63cfSSean Hefty IB_QP_ALT_PATH | 795b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 796b42b63cfSSean Hefty IB_QP_PKEY_INDEX | 797b42b63cfSSean Hefty IB_QP_MIN_RNR_TIMER | 798b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 7998a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 8008a51866fSRoland Dreier IB_QP_QKEY), 8018a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 8028a51866fSRoland Dreier IB_QP_QKEY), 8038a51866fSRoland Dreier } 8048a51866fSRoland Dreier } 8058a51866fSRoland Dreier }, 8068a51866fSRoland Dreier [IB_QPS_SQE] = { 8078a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 8088a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 }, 8098a51866fSRoland Dreier [IB_QPS_RTS] = { 8108a51866fSRoland Dreier .valid = 1, 8118a51866fSRoland Dreier .opt_param = { 8128a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_CUR_STATE | 8138a51866fSRoland Dreier IB_QP_QKEY), 8148a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_CUR_STATE | 8158a51866fSRoland Dreier IB_QP_ACCESS_FLAGS), 8168a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_CUR_STATE | 8178a51866fSRoland Dreier IB_QP_QKEY), 8188a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_CUR_STATE | 8198a51866fSRoland Dreier IB_QP_QKEY), 8208a51866fSRoland Dreier } 8218a51866fSRoland Dreier } 8228a51866fSRoland Dreier }, 8238a51866fSRoland Dreier [IB_QPS_ERR] = { 8248a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 8258a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 } 8268a51866fSRoland Dreier } 8278a51866fSRoland Dreier }; 8288a51866fSRoland Dreier 8298a51866fSRoland Dreier int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state, 830dd5f03beSMatan Barak enum ib_qp_type type, enum ib_qp_attr_mask mask, 831dd5f03beSMatan Barak enum rdma_link_layer ll) 8328a51866fSRoland Dreier { 8338a51866fSRoland Dreier enum ib_qp_attr_mask req_param, opt_param; 8348a51866fSRoland Dreier 8358a51866fSRoland Dreier if (cur_state < 0 || cur_state > IB_QPS_ERR || 8368a51866fSRoland Dreier next_state < 0 || next_state > IB_QPS_ERR) 8378a51866fSRoland Dreier return 0; 8388a51866fSRoland Dreier 8398a51866fSRoland Dreier if (mask & IB_QP_CUR_STATE && 8408a51866fSRoland Dreier cur_state != IB_QPS_RTR && cur_state != IB_QPS_RTS && 8418a51866fSRoland Dreier cur_state != IB_QPS_SQD && cur_state != IB_QPS_SQE) 8428a51866fSRoland Dreier return 0; 8438a51866fSRoland Dreier 8448a51866fSRoland Dreier if (!qp_state_table[cur_state][next_state].valid) 8458a51866fSRoland Dreier return 0; 8468a51866fSRoland Dreier 8478a51866fSRoland Dreier req_param = qp_state_table[cur_state][next_state].req_param[type]; 8488a51866fSRoland Dreier opt_param = qp_state_table[cur_state][next_state].opt_param[type]; 8498a51866fSRoland Dreier 850dd5f03beSMatan Barak if (ll == IB_LINK_LAYER_ETHERNET) { 851dd5f03beSMatan Barak req_param |= qp_state_table[cur_state][next_state]. 852dd5f03beSMatan Barak req_param_add_eth[type]; 853dd5f03beSMatan Barak opt_param |= qp_state_table[cur_state][next_state]. 854dd5f03beSMatan Barak opt_param_add_eth[type]; 855dd5f03beSMatan Barak } 856dd5f03beSMatan Barak 8578a51866fSRoland Dreier if ((mask & req_param) != req_param) 8588a51866fSRoland Dreier return 0; 8598a51866fSRoland Dreier 8608a51866fSRoland Dreier if (mask & ~(req_param | opt_param | IB_QP_STATE)) 8618a51866fSRoland Dreier return 0; 8628a51866fSRoland Dreier 8638a51866fSRoland Dreier return 1; 8648a51866fSRoland Dreier } 8658a51866fSRoland Dreier EXPORT_SYMBOL(ib_modify_qp_is_ok); 8668a51866fSRoland Dreier 867ed4c54e5SOr Gerlitz int ib_resolve_eth_l2_attrs(struct ib_qp *qp, 868ed4c54e5SOr Gerlitz struct ib_qp_attr *qp_attr, int *qp_attr_mask) 869ed4c54e5SOr Gerlitz { 870ed4c54e5SOr Gerlitz int ret = 0; 871ed4c54e5SOr Gerlitz union ib_gid sgid; 872ed4c54e5SOr Gerlitz 873ed4c54e5SOr Gerlitz if ((*qp_attr_mask & IB_QP_AV) && 874ed4c54e5SOr Gerlitz (rdma_port_get_link_layer(qp->device, qp_attr->ah_attr.port_num) == IB_LINK_LAYER_ETHERNET)) { 875ed4c54e5SOr Gerlitz ret = ib_query_gid(qp->device, qp_attr->ah_attr.port_num, 876ed4c54e5SOr Gerlitz qp_attr->ah_attr.grh.sgid_index, &sgid); 877ed4c54e5SOr Gerlitz if (ret) 878ed4c54e5SOr Gerlitz goto out; 879ed4c54e5SOr Gerlitz if (rdma_link_local_addr((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw)) { 880ed4c54e5SOr Gerlitz rdma_get_ll_mac((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw, qp_attr->ah_attr.dmac); 881ed4c54e5SOr Gerlitz rdma_get_ll_mac((struct in6_addr *)sgid.raw, qp_attr->smac); 882c1bd6cdeSMoni Shoua if (!(*qp_attr_mask & IB_QP_VID)) 883ed4c54e5SOr Gerlitz qp_attr->vlan_id = rdma_get_vlan_id(&sgid); 884ed4c54e5SOr Gerlitz } else { 885ed4c54e5SOr Gerlitz ret = rdma_addr_find_dmac_by_grh(&sgid, &qp_attr->ah_attr.grh.dgid, 886ed4c54e5SOr Gerlitz qp_attr->ah_attr.dmac, &qp_attr->vlan_id); 887ed4c54e5SOr Gerlitz if (ret) 888ed4c54e5SOr Gerlitz goto out; 889ed4c54e5SOr Gerlitz ret = rdma_addr_find_smac_by_sgid(&sgid, qp_attr->smac, NULL); 890ed4c54e5SOr Gerlitz if (ret) 891ed4c54e5SOr Gerlitz goto out; 892ed4c54e5SOr Gerlitz } 893ed4c54e5SOr Gerlitz *qp_attr_mask |= IB_QP_SMAC; 894ed4c54e5SOr Gerlitz if (qp_attr->vlan_id < 0xFFFF) 895ed4c54e5SOr Gerlitz *qp_attr_mask |= IB_QP_VID; 896ed4c54e5SOr Gerlitz } 897ed4c54e5SOr Gerlitz out: 898ed4c54e5SOr Gerlitz return ret; 899ed4c54e5SOr Gerlitz } 900ed4c54e5SOr Gerlitz EXPORT_SYMBOL(ib_resolve_eth_l2_attrs); 901ed4c54e5SOr Gerlitz 902ed4c54e5SOr Gerlitz 9031da177e4SLinus Torvalds int ib_modify_qp(struct ib_qp *qp, 9041da177e4SLinus Torvalds struct ib_qp_attr *qp_attr, 9051da177e4SLinus Torvalds int qp_attr_mask) 9061da177e4SLinus Torvalds { 907ed4c54e5SOr Gerlitz int ret; 908ed4c54e5SOr Gerlitz 909ed4c54e5SOr Gerlitz ret = ib_resolve_eth_l2_attrs(qp, qp_attr, &qp_attr_mask); 910ed4c54e5SOr Gerlitz if (ret) 911ed4c54e5SOr Gerlitz return ret; 912ed4c54e5SOr Gerlitz 9130e0ec7e0SSean Hefty return qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL); 9141da177e4SLinus Torvalds } 9151da177e4SLinus Torvalds EXPORT_SYMBOL(ib_modify_qp); 9161da177e4SLinus Torvalds 9171da177e4SLinus Torvalds int ib_query_qp(struct ib_qp *qp, 9181da177e4SLinus Torvalds struct ib_qp_attr *qp_attr, 9191da177e4SLinus Torvalds int qp_attr_mask, 9201da177e4SLinus Torvalds struct ib_qp_init_attr *qp_init_attr) 9211da177e4SLinus Torvalds { 9221da177e4SLinus Torvalds return qp->device->query_qp ? 9230e0ec7e0SSean Hefty qp->device->query_qp(qp->real_qp, qp_attr, qp_attr_mask, qp_init_attr) : 9241da177e4SLinus Torvalds -ENOSYS; 9251da177e4SLinus Torvalds } 9261da177e4SLinus Torvalds EXPORT_SYMBOL(ib_query_qp); 9271da177e4SLinus Torvalds 9280e0ec7e0SSean Hefty int ib_close_qp(struct ib_qp *qp) 9290e0ec7e0SSean Hefty { 9300e0ec7e0SSean Hefty struct ib_qp *real_qp; 9310e0ec7e0SSean Hefty unsigned long flags; 9320e0ec7e0SSean Hefty 9330e0ec7e0SSean Hefty real_qp = qp->real_qp; 9340e0ec7e0SSean Hefty if (real_qp == qp) 9350e0ec7e0SSean Hefty return -EINVAL; 9360e0ec7e0SSean Hefty 9370e0ec7e0SSean Hefty spin_lock_irqsave(&real_qp->device->event_handler_lock, flags); 9380e0ec7e0SSean Hefty list_del(&qp->open_list); 9390e0ec7e0SSean Hefty spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags); 9400e0ec7e0SSean Hefty 9410e0ec7e0SSean Hefty atomic_dec(&real_qp->usecnt); 9420e0ec7e0SSean Hefty kfree(qp); 9430e0ec7e0SSean Hefty 9440e0ec7e0SSean Hefty return 0; 9450e0ec7e0SSean Hefty } 9460e0ec7e0SSean Hefty EXPORT_SYMBOL(ib_close_qp); 9470e0ec7e0SSean Hefty 9480e0ec7e0SSean Hefty static int __ib_destroy_shared_qp(struct ib_qp *qp) 9490e0ec7e0SSean Hefty { 9500e0ec7e0SSean Hefty struct ib_xrcd *xrcd; 9510e0ec7e0SSean Hefty struct ib_qp *real_qp; 9520e0ec7e0SSean Hefty int ret; 9530e0ec7e0SSean Hefty 9540e0ec7e0SSean Hefty real_qp = qp->real_qp; 9550e0ec7e0SSean Hefty xrcd = real_qp->xrcd; 9560e0ec7e0SSean Hefty 9570e0ec7e0SSean Hefty mutex_lock(&xrcd->tgt_qp_mutex); 9580e0ec7e0SSean Hefty ib_close_qp(qp); 9590e0ec7e0SSean Hefty if (atomic_read(&real_qp->usecnt) == 0) 9600e0ec7e0SSean Hefty list_del(&real_qp->xrcd_list); 9610e0ec7e0SSean Hefty else 9620e0ec7e0SSean Hefty real_qp = NULL; 9630e0ec7e0SSean Hefty mutex_unlock(&xrcd->tgt_qp_mutex); 9640e0ec7e0SSean Hefty 9650e0ec7e0SSean Hefty if (real_qp) { 9660e0ec7e0SSean Hefty ret = ib_destroy_qp(real_qp); 9670e0ec7e0SSean Hefty if (!ret) 9680e0ec7e0SSean Hefty atomic_dec(&xrcd->usecnt); 9690e0ec7e0SSean Hefty else 9700e0ec7e0SSean Hefty __ib_insert_xrcd_qp(xrcd, real_qp); 9710e0ec7e0SSean Hefty } 9720e0ec7e0SSean Hefty 9730e0ec7e0SSean Hefty return 0; 9740e0ec7e0SSean Hefty } 9750e0ec7e0SSean Hefty 9761da177e4SLinus Torvalds int ib_destroy_qp(struct ib_qp *qp) 9771da177e4SLinus Torvalds { 9781da177e4SLinus Torvalds struct ib_pd *pd; 9791da177e4SLinus Torvalds struct ib_cq *scq, *rcq; 9801da177e4SLinus Torvalds struct ib_srq *srq; 9811da177e4SLinus Torvalds int ret; 9821da177e4SLinus Torvalds 9830e0ec7e0SSean Hefty if (atomic_read(&qp->usecnt)) 9840e0ec7e0SSean Hefty return -EBUSY; 9850e0ec7e0SSean Hefty 9860e0ec7e0SSean Hefty if (qp->real_qp != qp) 9870e0ec7e0SSean Hefty return __ib_destroy_shared_qp(qp); 9880e0ec7e0SSean Hefty 9891da177e4SLinus Torvalds pd = qp->pd; 9901da177e4SLinus Torvalds scq = qp->send_cq; 9911da177e4SLinus Torvalds rcq = qp->recv_cq; 9921da177e4SLinus Torvalds srq = qp->srq; 9931da177e4SLinus Torvalds 9941da177e4SLinus Torvalds ret = qp->device->destroy_qp(qp); 9951da177e4SLinus Torvalds if (!ret) { 996b42b63cfSSean Hefty if (pd) 9971da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 998b42b63cfSSean Hefty if (scq) 9991da177e4SLinus Torvalds atomic_dec(&scq->usecnt); 1000b42b63cfSSean Hefty if (rcq) 10011da177e4SLinus Torvalds atomic_dec(&rcq->usecnt); 10021da177e4SLinus Torvalds if (srq) 10031da177e4SLinus Torvalds atomic_dec(&srq->usecnt); 10041da177e4SLinus Torvalds } 10051da177e4SLinus Torvalds 10061da177e4SLinus Torvalds return ret; 10071da177e4SLinus Torvalds } 10081da177e4SLinus Torvalds EXPORT_SYMBOL(ib_destroy_qp); 10091da177e4SLinus Torvalds 10101da177e4SLinus Torvalds /* Completion queues */ 10111da177e4SLinus Torvalds 10121da177e4SLinus Torvalds struct ib_cq *ib_create_cq(struct ib_device *device, 10131da177e4SLinus Torvalds ib_comp_handler comp_handler, 10141da177e4SLinus Torvalds void (*event_handler)(struct ib_event *, void *), 1015f4fd0b22SMichael S. Tsirkin void *cq_context, int cqe, int comp_vector) 10161da177e4SLinus Torvalds { 10171da177e4SLinus Torvalds struct ib_cq *cq; 10181da177e4SLinus Torvalds 1019f4fd0b22SMichael S. Tsirkin cq = device->create_cq(device, cqe, comp_vector, NULL, NULL); 10201da177e4SLinus Torvalds 10211da177e4SLinus Torvalds if (!IS_ERR(cq)) { 10221da177e4SLinus Torvalds cq->device = device; 1023b5e81bf5SRoland Dreier cq->uobject = NULL; 10241da177e4SLinus Torvalds cq->comp_handler = comp_handler; 10251da177e4SLinus Torvalds cq->event_handler = event_handler; 10261da177e4SLinus Torvalds cq->cq_context = cq_context; 10271da177e4SLinus Torvalds atomic_set(&cq->usecnt, 0); 10281da177e4SLinus Torvalds } 10291da177e4SLinus Torvalds 10301da177e4SLinus Torvalds return cq; 10311da177e4SLinus Torvalds } 10321da177e4SLinus Torvalds EXPORT_SYMBOL(ib_create_cq); 10331da177e4SLinus Torvalds 10342dd57162SEli Cohen int ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period) 10352dd57162SEli Cohen { 10362dd57162SEli Cohen return cq->device->modify_cq ? 10372dd57162SEli Cohen cq->device->modify_cq(cq, cq_count, cq_period) : -ENOSYS; 10382dd57162SEli Cohen } 10392dd57162SEli Cohen EXPORT_SYMBOL(ib_modify_cq); 10402dd57162SEli Cohen 10411da177e4SLinus Torvalds int ib_destroy_cq(struct ib_cq *cq) 10421da177e4SLinus Torvalds { 10431da177e4SLinus Torvalds if (atomic_read(&cq->usecnt)) 10441da177e4SLinus Torvalds return -EBUSY; 10451da177e4SLinus Torvalds 10461da177e4SLinus Torvalds return cq->device->destroy_cq(cq); 10471da177e4SLinus Torvalds } 10481da177e4SLinus Torvalds EXPORT_SYMBOL(ib_destroy_cq); 10491da177e4SLinus Torvalds 1050a74cd4afSRoland Dreier int ib_resize_cq(struct ib_cq *cq, int cqe) 10511da177e4SLinus Torvalds { 105240de2e54SRoland Dreier return cq->device->resize_cq ? 105333b9b3eeSRoland Dreier cq->device->resize_cq(cq, cqe, NULL) : -ENOSYS; 10541da177e4SLinus Torvalds } 10551da177e4SLinus Torvalds EXPORT_SYMBOL(ib_resize_cq); 10561da177e4SLinus Torvalds 10571da177e4SLinus Torvalds /* Memory regions */ 10581da177e4SLinus Torvalds 10591da177e4SLinus Torvalds struct ib_mr *ib_get_dma_mr(struct ib_pd *pd, int mr_access_flags) 10601da177e4SLinus Torvalds { 10611da177e4SLinus Torvalds struct ib_mr *mr; 10621c636f80SEli Cohen int err; 10631c636f80SEli Cohen 10641c636f80SEli Cohen err = ib_check_mr_access(mr_access_flags); 10651c636f80SEli Cohen if (err) 10661c636f80SEli Cohen return ERR_PTR(err); 10671da177e4SLinus Torvalds 10681da177e4SLinus Torvalds mr = pd->device->get_dma_mr(pd, mr_access_flags); 10691da177e4SLinus Torvalds 10701da177e4SLinus Torvalds if (!IS_ERR(mr)) { 10711da177e4SLinus Torvalds mr->device = pd->device; 10721da177e4SLinus Torvalds mr->pd = pd; 1073b5e81bf5SRoland Dreier mr->uobject = NULL; 10741da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 10751da177e4SLinus Torvalds atomic_set(&mr->usecnt, 0); 10761da177e4SLinus Torvalds } 10771da177e4SLinus Torvalds 10781da177e4SLinus Torvalds return mr; 10791da177e4SLinus Torvalds } 10801da177e4SLinus Torvalds EXPORT_SYMBOL(ib_get_dma_mr); 10811da177e4SLinus Torvalds 10821da177e4SLinus Torvalds struct ib_mr *ib_reg_phys_mr(struct ib_pd *pd, 10831da177e4SLinus Torvalds struct ib_phys_buf *phys_buf_array, 10841da177e4SLinus Torvalds int num_phys_buf, 10851da177e4SLinus Torvalds int mr_access_flags, 10861da177e4SLinus Torvalds u64 *iova_start) 10871da177e4SLinus Torvalds { 10881da177e4SLinus Torvalds struct ib_mr *mr; 10891c636f80SEli Cohen int err; 10901c636f80SEli Cohen 10911c636f80SEli Cohen err = ib_check_mr_access(mr_access_flags); 10921c636f80SEli Cohen if (err) 10931c636f80SEli Cohen return ERR_PTR(err); 10941da177e4SLinus Torvalds 10957ce5eacbSDotan Barak if (!pd->device->reg_phys_mr) 10967ce5eacbSDotan Barak return ERR_PTR(-ENOSYS); 10977ce5eacbSDotan Barak 10981da177e4SLinus Torvalds mr = pd->device->reg_phys_mr(pd, phys_buf_array, num_phys_buf, 10991da177e4SLinus Torvalds mr_access_flags, iova_start); 11001da177e4SLinus Torvalds 11011da177e4SLinus Torvalds if (!IS_ERR(mr)) { 11021da177e4SLinus Torvalds mr->device = pd->device; 11031da177e4SLinus Torvalds mr->pd = pd; 1104b5e81bf5SRoland Dreier mr->uobject = NULL; 11051da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 11061da177e4SLinus Torvalds atomic_set(&mr->usecnt, 0); 11071da177e4SLinus Torvalds } 11081da177e4SLinus Torvalds 11091da177e4SLinus Torvalds return mr; 11101da177e4SLinus Torvalds } 11111da177e4SLinus Torvalds EXPORT_SYMBOL(ib_reg_phys_mr); 11121da177e4SLinus Torvalds 11131da177e4SLinus Torvalds int ib_rereg_phys_mr(struct ib_mr *mr, 11141da177e4SLinus Torvalds int mr_rereg_mask, 11151da177e4SLinus Torvalds struct ib_pd *pd, 11161da177e4SLinus Torvalds struct ib_phys_buf *phys_buf_array, 11171da177e4SLinus Torvalds int num_phys_buf, 11181da177e4SLinus Torvalds int mr_access_flags, 11191da177e4SLinus Torvalds u64 *iova_start) 11201da177e4SLinus Torvalds { 11211da177e4SLinus Torvalds struct ib_pd *old_pd; 11221da177e4SLinus Torvalds int ret; 11231da177e4SLinus Torvalds 11241c636f80SEli Cohen ret = ib_check_mr_access(mr_access_flags); 11251c636f80SEli Cohen if (ret) 11261c636f80SEli Cohen return ret; 11271c636f80SEli Cohen 11281da177e4SLinus Torvalds if (!mr->device->rereg_phys_mr) 11291da177e4SLinus Torvalds return -ENOSYS; 11301da177e4SLinus Torvalds 11311da177e4SLinus Torvalds if (atomic_read(&mr->usecnt)) 11321da177e4SLinus Torvalds return -EBUSY; 11331da177e4SLinus Torvalds 11341da177e4SLinus Torvalds old_pd = mr->pd; 11351da177e4SLinus Torvalds 11361da177e4SLinus Torvalds ret = mr->device->rereg_phys_mr(mr, mr_rereg_mask, pd, 11371da177e4SLinus Torvalds phys_buf_array, num_phys_buf, 11381da177e4SLinus Torvalds mr_access_flags, iova_start); 11391da177e4SLinus Torvalds 11401da177e4SLinus Torvalds if (!ret && (mr_rereg_mask & IB_MR_REREG_PD)) { 11411da177e4SLinus Torvalds atomic_dec(&old_pd->usecnt); 11421da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 11431da177e4SLinus Torvalds } 11441da177e4SLinus Torvalds 11451da177e4SLinus Torvalds return ret; 11461da177e4SLinus Torvalds } 11471da177e4SLinus Torvalds EXPORT_SYMBOL(ib_rereg_phys_mr); 11481da177e4SLinus Torvalds 11491da177e4SLinus Torvalds int ib_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr) 11501da177e4SLinus Torvalds { 11511da177e4SLinus Torvalds return mr->device->query_mr ? 11521da177e4SLinus Torvalds mr->device->query_mr(mr, mr_attr) : -ENOSYS; 11531da177e4SLinus Torvalds } 11541da177e4SLinus Torvalds EXPORT_SYMBOL(ib_query_mr); 11551da177e4SLinus Torvalds 11561da177e4SLinus Torvalds int ib_dereg_mr(struct ib_mr *mr) 11571da177e4SLinus Torvalds { 11581da177e4SLinus Torvalds struct ib_pd *pd; 11591da177e4SLinus Torvalds int ret; 11601da177e4SLinus Torvalds 11611da177e4SLinus Torvalds if (atomic_read(&mr->usecnt)) 11621da177e4SLinus Torvalds return -EBUSY; 11631da177e4SLinus Torvalds 11641da177e4SLinus Torvalds pd = mr->pd; 11651da177e4SLinus Torvalds ret = mr->device->dereg_mr(mr); 11661da177e4SLinus Torvalds if (!ret) 11671da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 11681da177e4SLinus Torvalds 11691da177e4SLinus Torvalds return ret; 11701da177e4SLinus Torvalds } 11711da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dereg_mr); 11721da177e4SLinus Torvalds 117317cd3a2dSSagi Grimberg struct ib_mr *ib_create_mr(struct ib_pd *pd, 117417cd3a2dSSagi Grimberg struct ib_mr_init_attr *mr_init_attr) 117517cd3a2dSSagi Grimberg { 117617cd3a2dSSagi Grimberg struct ib_mr *mr; 117717cd3a2dSSagi Grimberg 117817cd3a2dSSagi Grimberg if (!pd->device->create_mr) 117917cd3a2dSSagi Grimberg return ERR_PTR(-ENOSYS); 118017cd3a2dSSagi Grimberg 118117cd3a2dSSagi Grimberg mr = pd->device->create_mr(pd, mr_init_attr); 118217cd3a2dSSagi Grimberg 118317cd3a2dSSagi Grimberg if (!IS_ERR(mr)) { 118417cd3a2dSSagi Grimberg mr->device = pd->device; 118517cd3a2dSSagi Grimberg mr->pd = pd; 118617cd3a2dSSagi Grimberg mr->uobject = NULL; 118717cd3a2dSSagi Grimberg atomic_inc(&pd->usecnt); 118817cd3a2dSSagi Grimberg atomic_set(&mr->usecnt, 0); 118917cd3a2dSSagi Grimberg } 119017cd3a2dSSagi Grimberg 119117cd3a2dSSagi Grimberg return mr; 119217cd3a2dSSagi Grimberg } 119317cd3a2dSSagi Grimberg EXPORT_SYMBOL(ib_create_mr); 119417cd3a2dSSagi Grimberg 119517cd3a2dSSagi Grimberg int ib_destroy_mr(struct ib_mr *mr) 119617cd3a2dSSagi Grimberg { 119717cd3a2dSSagi Grimberg struct ib_pd *pd; 119817cd3a2dSSagi Grimberg int ret; 119917cd3a2dSSagi Grimberg 120017cd3a2dSSagi Grimberg if (atomic_read(&mr->usecnt)) 120117cd3a2dSSagi Grimberg return -EBUSY; 120217cd3a2dSSagi Grimberg 120317cd3a2dSSagi Grimberg pd = mr->pd; 120417cd3a2dSSagi Grimberg ret = mr->device->destroy_mr(mr); 120517cd3a2dSSagi Grimberg if (!ret) 120617cd3a2dSSagi Grimberg atomic_dec(&pd->usecnt); 120717cd3a2dSSagi Grimberg 120817cd3a2dSSagi Grimberg return ret; 120917cd3a2dSSagi Grimberg } 121017cd3a2dSSagi Grimberg EXPORT_SYMBOL(ib_destroy_mr); 121117cd3a2dSSagi Grimberg 121200f7ec36SSteve Wise struct ib_mr *ib_alloc_fast_reg_mr(struct ib_pd *pd, int max_page_list_len) 121300f7ec36SSteve Wise { 121400f7ec36SSteve Wise struct ib_mr *mr; 121500f7ec36SSteve Wise 121600f7ec36SSteve Wise if (!pd->device->alloc_fast_reg_mr) 121700f7ec36SSteve Wise return ERR_PTR(-ENOSYS); 121800f7ec36SSteve Wise 121900f7ec36SSteve Wise mr = pd->device->alloc_fast_reg_mr(pd, max_page_list_len); 122000f7ec36SSteve Wise 122100f7ec36SSteve Wise if (!IS_ERR(mr)) { 122200f7ec36SSteve Wise mr->device = pd->device; 122300f7ec36SSteve Wise mr->pd = pd; 122400f7ec36SSteve Wise mr->uobject = NULL; 122500f7ec36SSteve Wise atomic_inc(&pd->usecnt); 122600f7ec36SSteve Wise atomic_set(&mr->usecnt, 0); 122700f7ec36SSteve Wise } 122800f7ec36SSteve Wise 122900f7ec36SSteve Wise return mr; 123000f7ec36SSteve Wise } 123100f7ec36SSteve Wise EXPORT_SYMBOL(ib_alloc_fast_reg_mr); 123200f7ec36SSteve Wise 123300f7ec36SSteve Wise struct ib_fast_reg_page_list *ib_alloc_fast_reg_page_list(struct ib_device *device, 123400f7ec36SSteve Wise int max_page_list_len) 123500f7ec36SSteve Wise { 123600f7ec36SSteve Wise struct ib_fast_reg_page_list *page_list; 123700f7ec36SSteve Wise 123800f7ec36SSteve Wise if (!device->alloc_fast_reg_page_list) 123900f7ec36SSteve Wise return ERR_PTR(-ENOSYS); 124000f7ec36SSteve Wise 124100f7ec36SSteve Wise page_list = device->alloc_fast_reg_page_list(device, max_page_list_len); 124200f7ec36SSteve Wise 124300f7ec36SSteve Wise if (!IS_ERR(page_list)) { 124400f7ec36SSteve Wise page_list->device = device; 124500f7ec36SSteve Wise page_list->max_page_list_len = max_page_list_len; 124600f7ec36SSteve Wise } 124700f7ec36SSteve Wise 124800f7ec36SSteve Wise return page_list; 124900f7ec36SSteve Wise } 125000f7ec36SSteve Wise EXPORT_SYMBOL(ib_alloc_fast_reg_page_list); 125100f7ec36SSteve Wise 125200f7ec36SSteve Wise void ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list) 125300f7ec36SSteve Wise { 125400f7ec36SSteve Wise page_list->device->free_fast_reg_page_list(page_list); 125500f7ec36SSteve Wise } 125600f7ec36SSteve Wise EXPORT_SYMBOL(ib_free_fast_reg_page_list); 125700f7ec36SSteve Wise 12581da177e4SLinus Torvalds /* Memory windows */ 12591da177e4SLinus Torvalds 12607083e42eSShani Michaeli struct ib_mw *ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type) 12611da177e4SLinus Torvalds { 12621da177e4SLinus Torvalds struct ib_mw *mw; 12631da177e4SLinus Torvalds 12641da177e4SLinus Torvalds if (!pd->device->alloc_mw) 12651da177e4SLinus Torvalds return ERR_PTR(-ENOSYS); 12661da177e4SLinus Torvalds 12677083e42eSShani Michaeli mw = pd->device->alloc_mw(pd, type); 12681da177e4SLinus Torvalds if (!IS_ERR(mw)) { 12691da177e4SLinus Torvalds mw->device = pd->device; 12701da177e4SLinus Torvalds mw->pd = pd; 1271b5e81bf5SRoland Dreier mw->uobject = NULL; 12727083e42eSShani Michaeli mw->type = type; 12731da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 12741da177e4SLinus Torvalds } 12751da177e4SLinus Torvalds 12761da177e4SLinus Torvalds return mw; 12771da177e4SLinus Torvalds } 12781da177e4SLinus Torvalds EXPORT_SYMBOL(ib_alloc_mw); 12791da177e4SLinus Torvalds 12801da177e4SLinus Torvalds int ib_dealloc_mw(struct ib_mw *mw) 12811da177e4SLinus Torvalds { 12821da177e4SLinus Torvalds struct ib_pd *pd; 12831da177e4SLinus Torvalds int ret; 12841da177e4SLinus Torvalds 12851da177e4SLinus Torvalds pd = mw->pd; 12861da177e4SLinus Torvalds ret = mw->device->dealloc_mw(mw); 12871da177e4SLinus Torvalds if (!ret) 12881da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 12891da177e4SLinus Torvalds 12901da177e4SLinus Torvalds return ret; 12911da177e4SLinus Torvalds } 12921da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dealloc_mw); 12931da177e4SLinus Torvalds 12941da177e4SLinus Torvalds /* "Fast" memory regions */ 12951da177e4SLinus Torvalds 12961da177e4SLinus Torvalds struct ib_fmr *ib_alloc_fmr(struct ib_pd *pd, 12971da177e4SLinus Torvalds int mr_access_flags, 12981da177e4SLinus Torvalds struct ib_fmr_attr *fmr_attr) 12991da177e4SLinus Torvalds { 13001da177e4SLinus Torvalds struct ib_fmr *fmr; 13011da177e4SLinus Torvalds 13021da177e4SLinus Torvalds if (!pd->device->alloc_fmr) 13031da177e4SLinus Torvalds return ERR_PTR(-ENOSYS); 13041da177e4SLinus Torvalds 13051da177e4SLinus Torvalds fmr = pd->device->alloc_fmr(pd, mr_access_flags, fmr_attr); 13061da177e4SLinus Torvalds if (!IS_ERR(fmr)) { 13071da177e4SLinus Torvalds fmr->device = pd->device; 13081da177e4SLinus Torvalds fmr->pd = pd; 13091da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 13101da177e4SLinus Torvalds } 13111da177e4SLinus Torvalds 13121da177e4SLinus Torvalds return fmr; 13131da177e4SLinus Torvalds } 13141da177e4SLinus Torvalds EXPORT_SYMBOL(ib_alloc_fmr); 13151da177e4SLinus Torvalds 13161da177e4SLinus Torvalds int ib_unmap_fmr(struct list_head *fmr_list) 13171da177e4SLinus Torvalds { 13181da177e4SLinus Torvalds struct ib_fmr *fmr; 13191da177e4SLinus Torvalds 13201da177e4SLinus Torvalds if (list_empty(fmr_list)) 13211da177e4SLinus Torvalds return 0; 13221da177e4SLinus Torvalds 13231da177e4SLinus Torvalds fmr = list_entry(fmr_list->next, struct ib_fmr, list); 13241da177e4SLinus Torvalds return fmr->device->unmap_fmr(fmr_list); 13251da177e4SLinus Torvalds } 13261da177e4SLinus Torvalds EXPORT_SYMBOL(ib_unmap_fmr); 13271da177e4SLinus Torvalds 13281da177e4SLinus Torvalds int ib_dealloc_fmr(struct ib_fmr *fmr) 13291da177e4SLinus Torvalds { 13301da177e4SLinus Torvalds struct ib_pd *pd; 13311da177e4SLinus Torvalds int ret; 13321da177e4SLinus Torvalds 13331da177e4SLinus Torvalds pd = fmr->pd; 13341da177e4SLinus Torvalds ret = fmr->device->dealloc_fmr(fmr); 13351da177e4SLinus Torvalds if (!ret) 13361da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 13371da177e4SLinus Torvalds 13381da177e4SLinus Torvalds return ret; 13391da177e4SLinus Torvalds } 13401da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dealloc_fmr); 13411da177e4SLinus Torvalds 13421da177e4SLinus Torvalds /* Multicast groups */ 13431da177e4SLinus Torvalds 13441da177e4SLinus Torvalds int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid) 13451da177e4SLinus Torvalds { 1346c3bccbfbSOr Gerlitz int ret; 1347c3bccbfbSOr Gerlitz 13480c33aeedSJack Morgenstein if (!qp->device->attach_mcast) 13490c33aeedSJack Morgenstein return -ENOSYS; 13500c33aeedSJack Morgenstein if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD) 13510c33aeedSJack Morgenstein return -EINVAL; 13520c33aeedSJack Morgenstein 1353c3bccbfbSOr Gerlitz ret = qp->device->attach_mcast(qp, gid, lid); 1354c3bccbfbSOr Gerlitz if (!ret) 1355c3bccbfbSOr Gerlitz atomic_inc(&qp->usecnt); 1356c3bccbfbSOr Gerlitz return ret; 13571da177e4SLinus Torvalds } 13581da177e4SLinus Torvalds EXPORT_SYMBOL(ib_attach_mcast); 13591da177e4SLinus Torvalds 13601da177e4SLinus Torvalds int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid) 13611da177e4SLinus Torvalds { 1362c3bccbfbSOr Gerlitz int ret; 1363c3bccbfbSOr Gerlitz 13640c33aeedSJack Morgenstein if (!qp->device->detach_mcast) 13650c33aeedSJack Morgenstein return -ENOSYS; 13660c33aeedSJack Morgenstein if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD) 13670c33aeedSJack Morgenstein return -EINVAL; 13680c33aeedSJack Morgenstein 1369c3bccbfbSOr Gerlitz ret = qp->device->detach_mcast(qp, gid, lid); 1370c3bccbfbSOr Gerlitz if (!ret) 1371c3bccbfbSOr Gerlitz atomic_dec(&qp->usecnt); 1372c3bccbfbSOr Gerlitz return ret; 13731da177e4SLinus Torvalds } 13741da177e4SLinus Torvalds EXPORT_SYMBOL(ib_detach_mcast); 137559991f94SSean Hefty 137659991f94SSean Hefty struct ib_xrcd *ib_alloc_xrcd(struct ib_device *device) 137759991f94SSean Hefty { 137859991f94SSean Hefty struct ib_xrcd *xrcd; 137959991f94SSean Hefty 138059991f94SSean Hefty if (!device->alloc_xrcd) 138159991f94SSean Hefty return ERR_PTR(-ENOSYS); 138259991f94SSean Hefty 138359991f94SSean Hefty xrcd = device->alloc_xrcd(device, NULL, NULL); 138459991f94SSean Hefty if (!IS_ERR(xrcd)) { 138559991f94SSean Hefty xrcd->device = device; 138653d0bd1eSSean Hefty xrcd->inode = NULL; 138759991f94SSean Hefty atomic_set(&xrcd->usecnt, 0); 1388d3d72d90SSean Hefty mutex_init(&xrcd->tgt_qp_mutex); 1389d3d72d90SSean Hefty INIT_LIST_HEAD(&xrcd->tgt_qp_list); 139059991f94SSean Hefty } 139159991f94SSean Hefty 139259991f94SSean Hefty return xrcd; 139359991f94SSean Hefty } 139459991f94SSean Hefty EXPORT_SYMBOL(ib_alloc_xrcd); 139559991f94SSean Hefty 139659991f94SSean Hefty int ib_dealloc_xrcd(struct ib_xrcd *xrcd) 139759991f94SSean Hefty { 1398d3d72d90SSean Hefty struct ib_qp *qp; 1399d3d72d90SSean Hefty int ret; 1400d3d72d90SSean Hefty 140159991f94SSean Hefty if (atomic_read(&xrcd->usecnt)) 140259991f94SSean Hefty return -EBUSY; 140359991f94SSean Hefty 1404d3d72d90SSean Hefty while (!list_empty(&xrcd->tgt_qp_list)) { 1405d3d72d90SSean Hefty qp = list_entry(xrcd->tgt_qp_list.next, struct ib_qp, xrcd_list); 1406d3d72d90SSean Hefty ret = ib_destroy_qp(qp); 1407d3d72d90SSean Hefty if (ret) 1408d3d72d90SSean Hefty return ret; 1409d3d72d90SSean Hefty } 1410d3d72d90SSean Hefty 141159991f94SSean Hefty return xrcd->device->dealloc_xrcd(xrcd); 141259991f94SSean Hefty } 141359991f94SSean Hefty EXPORT_SYMBOL(ib_dealloc_xrcd); 1414319a441dSHadar Hen Zion 1415319a441dSHadar Hen Zion struct ib_flow *ib_create_flow(struct ib_qp *qp, 1416319a441dSHadar Hen Zion struct ib_flow_attr *flow_attr, 1417319a441dSHadar Hen Zion int domain) 1418319a441dSHadar Hen Zion { 1419319a441dSHadar Hen Zion struct ib_flow *flow_id; 1420319a441dSHadar Hen Zion if (!qp->device->create_flow) 1421319a441dSHadar Hen Zion return ERR_PTR(-ENOSYS); 1422319a441dSHadar Hen Zion 1423319a441dSHadar Hen Zion flow_id = qp->device->create_flow(qp, flow_attr, domain); 1424319a441dSHadar Hen Zion if (!IS_ERR(flow_id)) 1425319a441dSHadar Hen Zion atomic_inc(&qp->usecnt); 1426319a441dSHadar Hen Zion return flow_id; 1427319a441dSHadar Hen Zion } 1428319a441dSHadar Hen Zion EXPORT_SYMBOL(ib_create_flow); 1429319a441dSHadar Hen Zion 1430319a441dSHadar Hen Zion int ib_destroy_flow(struct ib_flow *flow_id) 1431319a441dSHadar Hen Zion { 1432319a441dSHadar Hen Zion int err; 1433319a441dSHadar Hen Zion struct ib_qp *qp = flow_id->qp; 1434319a441dSHadar Hen Zion 1435319a441dSHadar Hen Zion err = qp->device->destroy_flow(flow_id); 1436319a441dSHadar Hen Zion if (!err) 1437319a441dSHadar Hen Zion atomic_dec(&qp->usecnt); 1438319a441dSHadar Hen Zion return err; 1439319a441dSHadar Hen Zion } 1440319a441dSHadar Hen Zion EXPORT_SYMBOL(ib_destroy_flow); 14411b01d335SSagi Grimberg 14421b01d335SSagi Grimberg int ib_check_mr_status(struct ib_mr *mr, u32 check_mask, 14431b01d335SSagi Grimberg struct ib_mr_status *mr_status) 14441b01d335SSagi Grimberg { 14451b01d335SSagi Grimberg return mr->device->check_mr_status ? 14461b01d335SSagi Grimberg mr->device->check_mr_status(mr, check_mask, mr_status) : -ENOSYS; 14471b01d335SSagi Grimberg } 14481b01d335SSagi Grimberg EXPORT_SYMBOL(ib_check_mr_status); 1449