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 512b1b5b60SSagi Grimberg static const char * const ib_events[] = { 522b1b5b60SSagi Grimberg [IB_EVENT_CQ_ERR] = "CQ error", 532b1b5b60SSagi Grimberg [IB_EVENT_QP_FATAL] = "QP fatal error", 542b1b5b60SSagi Grimberg [IB_EVENT_QP_REQ_ERR] = "QP request error", 552b1b5b60SSagi Grimberg [IB_EVENT_QP_ACCESS_ERR] = "QP access error", 562b1b5b60SSagi Grimberg [IB_EVENT_COMM_EST] = "communication established", 572b1b5b60SSagi Grimberg [IB_EVENT_SQ_DRAINED] = "send queue drained", 582b1b5b60SSagi Grimberg [IB_EVENT_PATH_MIG] = "path migration successful", 592b1b5b60SSagi Grimberg [IB_EVENT_PATH_MIG_ERR] = "path migration error", 602b1b5b60SSagi Grimberg [IB_EVENT_DEVICE_FATAL] = "device fatal error", 612b1b5b60SSagi Grimberg [IB_EVENT_PORT_ACTIVE] = "port active", 622b1b5b60SSagi Grimberg [IB_EVENT_PORT_ERR] = "port error", 632b1b5b60SSagi Grimberg [IB_EVENT_LID_CHANGE] = "LID change", 642b1b5b60SSagi Grimberg [IB_EVENT_PKEY_CHANGE] = "P_key change", 652b1b5b60SSagi Grimberg [IB_EVENT_SM_CHANGE] = "SM change", 662b1b5b60SSagi Grimberg [IB_EVENT_SRQ_ERR] = "SRQ error", 672b1b5b60SSagi Grimberg [IB_EVENT_SRQ_LIMIT_REACHED] = "SRQ limit reached", 682b1b5b60SSagi Grimberg [IB_EVENT_QP_LAST_WQE_REACHED] = "last WQE reached", 692b1b5b60SSagi Grimberg [IB_EVENT_CLIENT_REREGISTER] = "client reregister", 702b1b5b60SSagi Grimberg [IB_EVENT_GID_CHANGE] = "GID changed", 712b1b5b60SSagi Grimberg }; 722b1b5b60SSagi Grimberg 732b1b5b60SSagi Grimberg const char *ib_event_msg(enum ib_event_type event) 742b1b5b60SSagi Grimberg { 752b1b5b60SSagi Grimberg size_t index = event; 762b1b5b60SSagi Grimberg 772b1b5b60SSagi Grimberg return (index < ARRAY_SIZE(ib_events) && ib_events[index]) ? 782b1b5b60SSagi Grimberg ib_events[index] : "unrecognized event"; 792b1b5b60SSagi Grimberg } 802b1b5b60SSagi Grimberg EXPORT_SYMBOL(ib_event_msg); 812b1b5b60SSagi Grimberg 822b1b5b60SSagi Grimberg static const char * const wc_statuses[] = { 832b1b5b60SSagi Grimberg [IB_WC_SUCCESS] = "success", 842b1b5b60SSagi Grimberg [IB_WC_LOC_LEN_ERR] = "local length error", 852b1b5b60SSagi Grimberg [IB_WC_LOC_QP_OP_ERR] = "local QP operation error", 862b1b5b60SSagi Grimberg [IB_WC_LOC_EEC_OP_ERR] = "local EE context operation error", 872b1b5b60SSagi Grimberg [IB_WC_LOC_PROT_ERR] = "local protection error", 882b1b5b60SSagi Grimberg [IB_WC_WR_FLUSH_ERR] = "WR flushed", 892b1b5b60SSagi Grimberg [IB_WC_MW_BIND_ERR] = "memory management operation error", 902b1b5b60SSagi Grimberg [IB_WC_BAD_RESP_ERR] = "bad response error", 912b1b5b60SSagi Grimberg [IB_WC_LOC_ACCESS_ERR] = "local access error", 922b1b5b60SSagi Grimberg [IB_WC_REM_INV_REQ_ERR] = "invalid request error", 932b1b5b60SSagi Grimberg [IB_WC_REM_ACCESS_ERR] = "remote access error", 942b1b5b60SSagi Grimberg [IB_WC_REM_OP_ERR] = "remote operation error", 952b1b5b60SSagi Grimberg [IB_WC_RETRY_EXC_ERR] = "transport retry counter exceeded", 962b1b5b60SSagi Grimberg [IB_WC_RNR_RETRY_EXC_ERR] = "RNR retry counter exceeded", 972b1b5b60SSagi Grimberg [IB_WC_LOC_RDD_VIOL_ERR] = "local RDD violation error", 982b1b5b60SSagi Grimberg [IB_WC_REM_INV_RD_REQ_ERR] = "remote invalid RD request", 992b1b5b60SSagi Grimberg [IB_WC_REM_ABORT_ERR] = "operation aborted", 1002b1b5b60SSagi Grimberg [IB_WC_INV_EECN_ERR] = "invalid EE context number", 1012b1b5b60SSagi Grimberg [IB_WC_INV_EEC_STATE_ERR] = "invalid EE context state", 1022b1b5b60SSagi Grimberg [IB_WC_FATAL_ERR] = "fatal error", 1032b1b5b60SSagi Grimberg [IB_WC_RESP_TIMEOUT_ERR] = "response timeout error", 1042b1b5b60SSagi Grimberg [IB_WC_GENERAL_ERR] = "general error", 1052b1b5b60SSagi Grimberg }; 1062b1b5b60SSagi Grimberg 1072b1b5b60SSagi Grimberg const char *ib_wc_status_msg(enum ib_wc_status status) 1082b1b5b60SSagi Grimberg { 1092b1b5b60SSagi Grimberg size_t index = status; 1102b1b5b60SSagi Grimberg 1112b1b5b60SSagi Grimberg return (index < ARRAY_SIZE(wc_statuses) && wc_statuses[index]) ? 1122b1b5b60SSagi Grimberg wc_statuses[index] : "unrecognized status"; 1132b1b5b60SSagi Grimberg } 1142b1b5b60SSagi Grimberg EXPORT_SYMBOL(ib_wc_status_msg); 1152b1b5b60SSagi Grimberg 1168385fd84SRoland Dreier __attribute_const__ int ib_rate_to_mult(enum ib_rate rate) 117bf6a9e31SJack Morgenstein { 118bf6a9e31SJack Morgenstein switch (rate) { 119bf6a9e31SJack Morgenstein case IB_RATE_2_5_GBPS: return 1; 120bf6a9e31SJack Morgenstein case IB_RATE_5_GBPS: return 2; 121bf6a9e31SJack Morgenstein case IB_RATE_10_GBPS: return 4; 122bf6a9e31SJack Morgenstein case IB_RATE_20_GBPS: return 8; 123bf6a9e31SJack Morgenstein case IB_RATE_30_GBPS: return 12; 124bf6a9e31SJack Morgenstein case IB_RATE_40_GBPS: return 16; 125bf6a9e31SJack Morgenstein case IB_RATE_60_GBPS: return 24; 126bf6a9e31SJack Morgenstein case IB_RATE_80_GBPS: return 32; 127bf6a9e31SJack Morgenstein case IB_RATE_120_GBPS: return 48; 128bf6a9e31SJack Morgenstein default: return -1; 129bf6a9e31SJack Morgenstein } 130bf6a9e31SJack Morgenstein } 131bf6a9e31SJack Morgenstein EXPORT_SYMBOL(ib_rate_to_mult); 132bf6a9e31SJack Morgenstein 1338385fd84SRoland Dreier __attribute_const__ enum ib_rate mult_to_ib_rate(int mult) 134bf6a9e31SJack Morgenstein { 135bf6a9e31SJack Morgenstein switch (mult) { 136bf6a9e31SJack Morgenstein case 1: return IB_RATE_2_5_GBPS; 137bf6a9e31SJack Morgenstein case 2: return IB_RATE_5_GBPS; 138bf6a9e31SJack Morgenstein case 4: return IB_RATE_10_GBPS; 139bf6a9e31SJack Morgenstein case 8: return IB_RATE_20_GBPS; 140bf6a9e31SJack Morgenstein case 12: return IB_RATE_30_GBPS; 141bf6a9e31SJack Morgenstein case 16: return IB_RATE_40_GBPS; 142bf6a9e31SJack Morgenstein case 24: return IB_RATE_60_GBPS; 143bf6a9e31SJack Morgenstein case 32: return IB_RATE_80_GBPS; 144bf6a9e31SJack Morgenstein case 48: return IB_RATE_120_GBPS; 145bf6a9e31SJack Morgenstein default: return IB_RATE_PORT_CURRENT; 146bf6a9e31SJack Morgenstein } 147bf6a9e31SJack Morgenstein } 148bf6a9e31SJack Morgenstein EXPORT_SYMBOL(mult_to_ib_rate); 149bf6a9e31SJack Morgenstein 1508385fd84SRoland Dreier __attribute_const__ int ib_rate_to_mbps(enum ib_rate rate) 15171eeba16SMarcel Apfelbaum { 15271eeba16SMarcel Apfelbaum switch (rate) { 15371eeba16SMarcel Apfelbaum case IB_RATE_2_5_GBPS: return 2500; 15471eeba16SMarcel Apfelbaum case IB_RATE_5_GBPS: return 5000; 15571eeba16SMarcel Apfelbaum case IB_RATE_10_GBPS: return 10000; 15671eeba16SMarcel Apfelbaum case IB_RATE_20_GBPS: return 20000; 15771eeba16SMarcel Apfelbaum case IB_RATE_30_GBPS: return 30000; 15871eeba16SMarcel Apfelbaum case IB_RATE_40_GBPS: return 40000; 15971eeba16SMarcel Apfelbaum case IB_RATE_60_GBPS: return 60000; 16071eeba16SMarcel Apfelbaum case IB_RATE_80_GBPS: return 80000; 16171eeba16SMarcel Apfelbaum case IB_RATE_120_GBPS: return 120000; 16271eeba16SMarcel Apfelbaum case IB_RATE_14_GBPS: return 14062; 16371eeba16SMarcel Apfelbaum case IB_RATE_56_GBPS: return 56250; 16471eeba16SMarcel Apfelbaum case IB_RATE_112_GBPS: return 112500; 16571eeba16SMarcel Apfelbaum case IB_RATE_168_GBPS: return 168750; 16671eeba16SMarcel Apfelbaum case IB_RATE_25_GBPS: return 25781; 16771eeba16SMarcel Apfelbaum case IB_RATE_100_GBPS: return 103125; 16871eeba16SMarcel Apfelbaum case IB_RATE_200_GBPS: return 206250; 16971eeba16SMarcel Apfelbaum case IB_RATE_300_GBPS: return 309375; 17071eeba16SMarcel Apfelbaum default: return -1; 17171eeba16SMarcel Apfelbaum } 17271eeba16SMarcel Apfelbaum } 17371eeba16SMarcel Apfelbaum EXPORT_SYMBOL(ib_rate_to_mbps); 17471eeba16SMarcel Apfelbaum 1758385fd84SRoland Dreier __attribute_const__ enum rdma_transport_type 17607ebafbaSTom Tucker rdma_node_get_transport(enum rdma_node_type node_type) 17707ebafbaSTom Tucker { 17807ebafbaSTom Tucker switch (node_type) { 17907ebafbaSTom Tucker case RDMA_NODE_IB_CA: 18007ebafbaSTom Tucker case RDMA_NODE_IB_SWITCH: 18107ebafbaSTom Tucker case RDMA_NODE_IB_ROUTER: 18207ebafbaSTom Tucker return RDMA_TRANSPORT_IB; 18307ebafbaSTom Tucker case RDMA_NODE_RNIC: 18407ebafbaSTom Tucker return RDMA_TRANSPORT_IWARP; 185180771a3SUpinder Malhi \(umalhi\) case RDMA_NODE_USNIC: 1865db5765eSUpinder Malhi return RDMA_TRANSPORT_USNIC; 1875db5765eSUpinder Malhi case RDMA_NODE_USNIC_UDP: 188248567f7SUpinder Malhi return RDMA_TRANSPORT_USNIC_UDP; 18907ebafbaSTom Tucker default: 19007ebafbaSTom Tucker BUG(); 19107ebafbaSTom Tucker return 0; 19207ebafbaSTom Tucker } 19307ebafbaSTom Tucker } 19407ebafbaSTom Tucker EXPORT_SYMBOL(rdma_node_get_transport); 19507ebafbaSTom Tucker 196a3f5adafSEli Cohen enum rdma_link_layer rdma_port_get_link_layer(struct ib_device *device, u8 port_num) 197a3f5adafSEli Cohen { 198a3f5adafSEli Cohen if (device->get_link_layer) 199a3f5adafSEli Cohen return device->get_link_layer(device, port_num); 200a3f5adafSEli Cohen 201a3f5adafSEli Cohen switch (rdma_node_get_transport(device->node_type)) { 202a3f5adafSEli Cohen case RDMA_TRANSPORT_IB: 203a3f5adafSEli Cohen return IB_LINK_LAYER_INFINIBAND; 204a3f5adafSEli Cohen case RDMA_TRANSPORT_IWARP: 205180771a3SUpinder Malhi \(umalhi\) case RDMA_TRANSPORT_USNIC: 206248567f7SUpinder Malhi case RDMA_TRANSPORT_USNIC_UDP: 207a3f5adafSEli Cohen return IB_LINK_LAYER_ETHERNET; 208a3f5adafSEli Cohen default: 209a3f5adafSEli Cohen return IB_LINK_LAYER_UNSPECIFIED; 210a3f5adafSEli Cohen } 211a3f5adafSEli Cohen } 212a3f5adafSEli Cohen EXPORT_SYMBOL(rdma_port_get_link_layer); 213a3f5adafSEli Cohen 2141da177e4SLinus Torvalds /* Protection domains */ 2151da177e4SLinus Torvalds 2161da177e4SLinus Torvalds struct ib_pd *ib_alloc_pd(struct ib_device *device) 2171da177e4SLinus Torvalds { 2181da177e4SLinus Torvalds struct ib_pd *pd; 2191da177e4SLinus Torvalds 220b5e81bf5SRoland Dreier pd = device->alloc_pd(device, NULL, NULL); 2211da177e4SLinus Torvalds 2221da177e4SLinus Torvalds if (!IS_ERR(pd)) { 2231da177e4SLinus Torvalds pd->device = device; 224b5e81bf5SRoland Dreier pd->uobject = NULL; 2251da177e4SLinus Torvalds atomic_set(&pd->usecnt, 0); 2261da177e4SLinus Torvalds } 2271da177e4SLinus Torvalds 2281da177e4SLinus Torvalds return pd; 2291da177e4SLinus Torvalds } 2301da177e4SLinus Torvalds EXPORT_SYMBOL(ib_alloc_pd); 2311da177e4SLinus Torvalds 2321da177e4SLinus Torvalds int ib_dealloc_pd(struct ib_pd *pd) 2331da177e4SLinus Torvalds { 2341da177e4SLinus Torvalds if (atomic_read(&pd->usecnt)) 2351da177e4SLinus Torvalds return -EBUSY; 2361da177e4SLinus Torvalds 2371da177e4SLinus Torvalds return pd->device->dealloc_pd(pd); 2381da177e4SLinus Torvalds } 2391da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dealloc_pd); 2401da177e4SLinus Torvalds 2411da177e4SLinus Torvalds /* Address handles */ 2421da177e4SLinus Torvalds 2431da177e4SLinus Torvalds struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) 2441da177e4SLinus Torvalds { 2451da177e4SLinus Torvalds struct ib_ah *ah; 2461da177e4SLinus Torvalds 2471da177e4SLinus Torvalds ah = pd->device->create_ah(pd, ah_attr); 2481da177e4SLinus Torvalds 2491da177e4SLinus Torvalds if (!IS_ERR(ah)) { 2501da177e4SLinus Torvalds ah->device = pd->device; 2511da177e4SLinus Torvalds ah->pd = pd; 252b5e81bf5SRoland Dreier ah->uobject = NULL; 2531da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 2541da177e4SLinus Torvalds } 2551da177e4SLinus Torvalds 2561da177e4SLinus Torvalds return ah; 2571da177e4SLinus Torvalds } 2581da177e4SLinus Torvalds EXPORT_SYMBOL(ib_create_ah); 2591da177e4SLinus Torvalds 26073cdaaeeSIra Weiny int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, 26173cdaaeeSIra Weiny const struct ib_wc *wc, const struct ib_grh *grh, 26273cdaaeeSIra Weiny struct ib_ah_attr *ah_attr) 263513789edSHal Rosenstock { 264513789edSHal Rosenstock u32 flow_class; 265513789edSHal Rosenstock u16 gid_index; 266513789edSHal Rosenstock int ret; 267513789edSHal Rosenstock 2684e00d694SSean Hefty memset(ah_attr, 0, sizeof *ah_attr); 269227128fcSMichael Wang if (rdma_cap_eth_ah(device, port_num)) { 270dd5f03beSMatan Barak if (!(wc->wc_flags & IB_WC_GRH)) 271dd5f03beSMatan Barak return -EPROTOTYPE; 272dd5f03beSMatan Barak 273dd5f03beSMatan Barak if (wc->wc_flags & IB_WC_WITH_SMAC && 274dd5f03beSMatan Barak wc->wc_flags & IB_WC_WITH_VLAN) { 275dd5f03beSMatan Barak memcpy(ah_attr->dmac, wc->smac, ETH_ALEN); 276dd5f03beSMatan Barak ah_attr->vlan_id = wc->vlan_id; 277dd5f03beSMatan Barak } else { 278dd5f03beSMatan Barak ret = rdma_addr_find_dmac_by_grh(&grh->dgid, &grh->sgid, 279dd5f03beSMatan Barak ah_attr->dmac, &ah_attr->vlan_id); 280dd5f03beSMatan Barak if (ret) 281dd5f03beSMatan Barak return ret; 282dd5f03beSMatan Barak } 283dd5f03beSMatan Barak } else { 284dd5f03beSMatan Barak ah_attr->vlan_id = 0xffff; 285dd5f03beSMatan Barak } 286dd5f03beSMatan Barak 2874e00d694SSean Hefty ah_attr->dlid = wc->slid; 2884e00d694SSean Hefty ah_attr->sl = wc->sl; 2894e00d694SSean Hefty ah_attr->src_path_bits = wc->dlid_path_bits; 2904e00d694SSean Hefty ah_attr->port_num = port_num; 291513789edSHal Rosenstock 292513789edSHal Rosenstock if (wc->wc_flags & IB_WC_GRH) { 2934e00d694SSean Hefty ah_attr->ah_flags = IB_AH_GRH; 2944e00d694SSean Hefty ah_attr->grh.dgid = grh->sgid; 295513789edSHal Rosenstock 2964e00d694SSean Hefty ret = ib_find_cached_gid(device, &grh->dgid, &port_num, 297513789edSHal Rosenstock &gid_index); 298513789edSHal Rosenstock if (ret) 2994e00d694SSean Hefty return ret; 300513789edSHal Rosenstock 3014e00d694SSean Hefty ah_attr->grh.sgid_index = (u8) gid_index; 302497677abSHal Rosenstock flow_class = be32_to_cpu(grh->version_tclass_flow); 3034e00d694SSean Hefty ah_attr->grh.flow_label = flow_class & 0xFFFFF; 30447645d8dSSean Hefty ah_attr->grh.hop_limit = 0xFF; 3054e00d694SSean Hefty ah_attr->grh.traffic_class = (flow_class >> 20) & 0xFF; 306513789edSHal Rosenstock } 3074e00d694SSean Hefty return 0; 3084e00d694SSean Hefty } 3094e00d694SSean Hefty EXPORT_SYMBOL(ib_init_ah_from_wc); 3104e00d694SSean Hefty 31173cdaaeeSIra Weiny struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, const struct ib_wc *wc, 31273cdaaeeSIra Weiny const struct ib_grh *grh, u8 port_num) 3134e00d694SSean Hefty { 3144e00d694SSean Hefty struct ib_ah_attr ah_attr; 3154e00d694SSean Hefty int ret; 3164e00d694SSean Hefty 3174e00d694SSean Hefty ret = ib_init_ah_from_wc(pd->device, port_num, wc, grh, &ah_attr); 3184e00d694SSean Hefty if (ret) 3194e00d694SSean Hefty return ERR_PTR(ret); 320513789edSHal Rosenstock 321513789edSHal Rosenstock return ib_create_ah(pd, &ah_attr); 322513789edSHal Rosenstock } 323513789edSHal Rosenstock EXPORT_SYMBOL(ib_create_ah_from_wc); 324513789edSHal Rosenstock 3251da177e4SLinus Torvalds int ib_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) 3261da177e4SLinus Torvalds { 3271da177e4SLinus Torvalds return ah->device->modify_ah ? 3281da177e4SLinus Torvalds ah->device->modify_ah(ah, ah_attr) : 3291da177e4SLinus Torvalds -ENOSYS; 3301da177e4SLinus Torvalds } 3311da177e4SLinus Torvalds EXPORT_SYMBOL(ib_modify_ah); 3321da177e4SLinus Torvalds 3331da177e4SLinus Torvalds int ib_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) 3341da177e4SLinus Torvalds { 3351da177e4SLinus Torvalds return ah->device->query_ah ? 3361da177e4SLinus Torvalds ah->device->query_ah(ah, ah_attr) : 3371da177e4SLinus Torvalds -ENOSYS; 3381da177e4SLinus Torvalds } 3391da177e4SLinus Torvalds EXPORT_SYMBOL(ib_query_ah); 3401da177e4SLinus Torvalds 3411da177e4SLinus Torvalds int ib_destroy_ah(struct ib_ah *ah) 3421da177e4SLinus Torvalds { 3431da177e4SLinus Torvalds struct ib_pd *pd; 3441da177e4SLinus Torvalds int ret; 3451da177e4SLinus Torvalds 3461da177e4SLinus Torvalds pd = ah->pd; 3471da177e4SLinus Torvalds ret = ah->device->destroy_ah(ah); 3481da177e4SLinus Torvalds if (!ret) 3491da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 3501da177e4SLinus Torvalds 3511da177e4SLinus Torvalds return ret; 3521da177e4SLinus Torvalds } 3531da177e4SLinus Torvalds EXPORT_SYMBOL(ib_destroy_ah); 3541da177e4SLinus Torvalds 355d41fcc67SRoland Dreier /* Shared receive queues */ 356d41fcc67SRoland Dreier 357d41fcc67SRoland Dreier struct ib_srq *ib_create_srq(struct ib_pd *pd, 358d41fcc67SRoland Dreier struct ib_srq_init_attr *srq_init_attr) 359d41fcc67SRoland Dreier { 360d41fcc67SRoland Dreier struct ib_srq *srq; 361d41fcc67SRoland Dreier 362d41fcc67SRoland Dreier if (!pd->device->create_srq) 363d41fcc67SRoland Dreier return ERR_PTR(-ENOSYS); 364d41fcc67SRoland Dreier 365d41fcc67SRoland Dreier srq = pd->device->create_srq(pd, srq_init_attr, NULL); 366d41fcc67SRoland Dreier 367d41fcc67SRoland Dreier if (!IS_ERR(srq)) { 368d41fcc67SRoland Dreier srq->device = pd->device; 369d41fcc67SRoland Dreier srq->pd = pd; 370d41fcc67SRoland Dreier srq->uobject = NULL; 371d41fcc67SRoland Dreier srq->event_handler = srq_init_attr->event_handler; 372d41fcc67SRoland Dreier srq->srq_context = srq_init_attr->srq_context; 37396104edaSSean Hefty srq->srq_type = srq_init_attr->srq_type; 374418d5130SSean Hefty if (srq->srq_type == IB_SRQT_XRC) { 375418d5130SSean Hefty srq->ext.xrc.xrcd = srq_init_attr->ext.xrc.xrcd; 376418d5130SSean Hefty srq->ext.xrc.cq = srq_init_attr->ext.xrc.cq; 377418d5130SSean Hefty atomic_inc(&srq->ext.xrc.xrcd->usecnt); 378418d5130SSean Hefty atomic_inc(&srq->ext.xrc.cq->usecnt); 379418d5130SSean Hefty } 380d41fcc67SRoland Dreier atomic_inc(&pd->usecnt); 381d41fcc67SRoland Dreier atomic_set(&srq->usecnt, 0); 382d41fcc67SRoland Dreier } 383d41fcc67SRoland Dreier 384d41fcc67SRoland Dreier return srq; 385d41fcc67SRoland Dreier } 386d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_create_srq); 387d41fcc67SRoland Dreier 388d41fcc67SRoland Dreier int ib_modify_srq(struct ib_srq *srq, 389d41fcc67SRoland Dreier struct ib_srq_attr *srq_attr, 390d41fcc67SRoland Dreier enum ib_srq_attr_mask srq_attr_mask) 391d41fcc67SRoland Dreier { 3927ce5eacbSDotan Barak return srq->device->modify_srq ? 3937ce5eacbSDotan Barak srq->device->modify_srq(srq, srq_attr, srq_attr_mask, NULL) : 3947ce5eacbSDotan Barak -ENOSYS; 395d41fcc67SRoland Dreier } 396d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_modify_srq); 397d41fcc67SRoland Dreier 398d41fcc67SRoland Dreier int ib_query_srq(struct ib_srq *srq, 399d41fcc67SRoland Dreier struct ib_srq_attr *srq_attr) 400d41fcc67SRoland Dreier { 401d41fcc67SRoland Dreier return srq->device->query_srq ? 402d41fcc67SRoland Dreier srq->device->query_srq(srq, srq_attr) : -ENOSYS; 403d41fcc67SRoland Dreier } 404d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_query_srq); 405d41fcc67SRoland Dreier 406d41fcc67SRoland Dreier int ib_destroy_srq(struct ib_srq *srq) 407d41fcc67SRoland Dreier { 408d41fcc67SRoland Dreier struct ib_pd *pd; 409418d5130SSean Hefty enum ib_srq_type srq_type; 410418d5130SSean Hefty struct ib_xrcd *uninitialized_var(xrcd); 411418d5130SSean Hefty struct ib_cq *uninitialized_var(cq); 412d41fcc67SRoland Dreier int ret; 413d41fcc67SRoland Dreier 414d41fcc67SRoland Dreier if (atomic_read(&srq->usecnt)) 415d41fcc67SRoland Dreier return -EBUSY; 416d41fcc67SRoland Dreier 417d41fcc67SRoland Dreier pd = srq->pd; 418418d5130SSean Hefty srq_type = srq->srq_type; 419418d5130SSean Hefty if (srq_type == IB_SRQT_XRC) { 420418d5130SSean Hefty xrcd = srq->ext.xrc.xrcd; 421418d5130SSean Hefty cq = srq->ext.xrc.cq; 422418d5130SSean Hefty } 423d41fcc67SRoland Dreier 424d41fcc67SRoland Dreier ret = srq->device->destroy_srq(srq); 425418d5130SSean Hefty if (!ret) { 426d41fcc67SRoland Dreier atomic_dec(&pd->usecnt); 427418d5130SSean Hefty if (srq_type == IB_SRQT_XRC) { 428418d5130SSean Hefty atomic_dec(&xrcd->usecnt); 429418d5130SSean Hefty atomic_dec(&cq->usecnt); 430418d5130SSean Hefty } 431418d5130SSean Hefty } 432d41fcc67SRoland Dreier 433d41fcc67SRoland Dreier return ret; 434d41fcc67SRoland Dreier } 435d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_destroy_srq); 436d41fcc67SRoland Dreier 4371da177e4SLinus Torvalds /* Queue pairs */ 4381da177e4SLinus Torvalds 4390e0ec7e0SSean Hefty static void __ib_shared_qp_event_handler(struct ib_event *event, void *context) 4400e0ec7e0SSean Hefty { 4410e0ec7e0SSean Hefty struct ib_qp *qp = context; 44273c40c61SYishai Hadas unsigned long flags; 4430e0ec7e0SSean Hefty 44473c40c61SYishai Hadas spin_lock_irqsave(&qp->device->event_handler_lock, flags); 4450e0ec7e0SSean Hefty list_for_each_entry(event->element.qp, &qp->open_list, open_list) 446eec9e29fSShlomo Pongratz if (event->element.qp->event_handler) 4470e0ec7e0SSean Hefty event->element.qp->event_handler(event, event->element.qp->qp_context); 44873c40c61SYishai Hadas spin_unlock_irqrestore(&qp->device->event_handler_lock, flags); 4490e0ec7e0SSean Hefty } 4500e0ec7e0SSean Hefty 451d3d72d90SSean Hefty static void __ib_insert_xrcd_qp(struct ib_xrcd *xrcd, struct ib_qp *qp) 452d3d72d90SSean Hefty { 453d3d72d90SSean Hefty mutex_lock(&xrcd->tgt_qp_mutex); 454d3d72d90SSean Hefty list_add(&qp->xrcd_list, &xrcd->tgt_qp_list); 455d3d72d90SSean Hefty mutex_unlock(&xrcd->tgt_qp_mutex); 456d3d72d90SSean Hefty } 457d3d72d90SSean Hefty 4580e0ec7e0SSean Hefty static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp, 4590e0ec7e0SSean Hefty void (*event_handler)(struct ib_event *, void *), 4600e0ec7e0SSean Hefty void *qp_context) 461d3d72d90SSean Hefty { 4620e0ec7e0SSean Hefty struct ib_qp *qp; 4630e0ec7e0SSean Hefty unsigned long flags; 4640e0ec7e0SSean Hefty 4650e0ec7e0SSean Hefty qp = kzalloc(sizeof *qp, GFP_KERNEL); 4660e0ec7e0SSean Hefty if (!qp) 4670e0ec7e0SSean Hefty return ERR_PTR(-ENOMEM); 4680e0ec7e0SSean Hefty 4690e0ec7e0SSean Hefty qp->real_qp = real_qp; 4700e0ec7e0SSean Hefty atomic_inc(&real_qp->usecnt); 4710e0ec7e0SSean Hefty qp->device = real_qp->device; 4720e0ec7e0SSean Hefty qp->event_handler = event_handler; 4730e0ec7e0SSean Hefty qp->qp_context = qp_context; 4740e0ec7e0SSean Hefty qp->qp_num = real_qp->qp_num; 4750e0ec7e0SSean Hefty qp->qp_type = real_qp->qp_type; 4760e0ec7e0SSean Hefty 4770e0ec7e0SSean Hefty spin_lock_irqsave(&real_qp->device->event_handler_lock, flags); 4780e0ec7e0SSean Hefty list_add(&qp->open_list, &real_qp->open_list); 4790e0ec7e0SSean Hefty spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags); 4800e0ec7e0SSean Hefty 4810e0ec7e0SSean Hefty return qp; 482d3d72d90SSean Hefty } 483d3d72d90SSean Hefty 4840e0ec7e0SSean Hefty struct ib_qp *ib_open_qp(struct ib_xrcd *xrcd, 4850e0ec7e0SSean Hefty struct ib_qp_open_attr *qp_open_attr) 4860e0ec7e0SSean Hefty { 4870e0ec7e0SSean Hefty struct ib_qp *qp, *real_qp; 4880e0ec7e0SSean Hefty 4890e0ec7e0SSean Hefty if (qp_open_attr->qp_type != IB_QPT_XRC_TGT) 4900e0ec7e0SSean Hefty return ERR_PTR(-EINVAL); 4910e0ec7e0SSean Hefty 4920e0ec7e0SSean Hefty qp = ERR_PTR(-EINVAL); 4930e0ec7e0SSean Hefty mutex_lock(&xrcd->tgt_qp_mutex); 4940e0ec7e0SSean Hefty list_for_each_entry(real_qp, &xrcd->tgt_qp_list, xrcd_list) { 4950e0ec7e0SSean Hefty if (real_qp->qp_num == qp_open_attr->qp_num) { 4960e0ec7e0SSean Hefty qp = __ib_open_qp(real_qp, qp_open_attr->event_handler, 4970e0ec7e0SSean Hefty qp_open_attr->qp_context); 4980e0ec7e0SSean Hefty break; 4990e0ec7e0SSean Hefty } 5000e0ec7e0SSean Hefty } 5010e0ec7e0SSean Hefty mutex_unlock(&xrcd->tgt_qp_mutex); 5020e0ec7e0SSean Hefty return qp; 5030e0ec7e0SSean Hefty } 5040e0ec7e0SSean Hefty EXPORT_SYMBOL(ib_open_qp); 5050e0ec7e0SSean Hefty 5061da177e4SLinus Torvalds struct ib_qp *ib_create_qp(struct ib_pd *pd, 5071da177e4SLinus Torvalds struct ib_qp_init_attr *qp_init_attr) 5081da177e4SLinus Torvalds { 5090e0ec7e0SSean Hefty struct ib_qp *qp, *real_qp; 510b42b63cfSSean Hefty struct ib_device *device; 5111da177e4SLinus Torvalds 512b42b63cfSSean Hefty device = pd ? pd->device : qp_init_attr->xrcd->device; 513b42b63cfSSean Hefty qp = device->create_qp(pd, qp_init_attr, NULL); 5141da177e4SLinus Torvalds 5151da177e4SLinus Torvalds if (!IS_ERR(qp)) { 516b42b63cfSSean Hefty qp->device = device; 5170e0ec7e0SSean Hefty qp->real_qp = qp; 518b5e81bf5SRoland Dreier qp->uobject = NULL; 5190e0ec7e0SSean Hefty qp->qp_type = qp_init_attr->qp_type; 520b42b63cfSSean Hefty 521e47e321aSBernd Schubert atomic_set(&qp->usecnt, 0); 522b42b63cfSSean Hefty if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) { 5230e0ec7e0SSean Hefty qp->event_handler = __ib_shared_qp_event_handler; 5240e0ec7e0SSean Hefty qp->qp_context = qp; 525b42b63cfSSean Hefty qp->pd = NULL; 526b42b63cfSSean Hefty qp->send_cq = qp->recv_cq = NULL; 527b42b63cfSSean Hefty qp->srq = NULL; 528b42b63cfSSean Hefty qp->xrcd = qp_init_attr->xrcd; 529b42b63cfSSean Hefty atomic_inc(&qp_init_attr->xrcd->usecnt); 5300e0ec7e0SSean Hefty INIT_LIST_HEAD(&qp->open_list); 5310e0ec7e0SSean Hefty 5320e0ec7e0SSean Hefty real_qp = qp; 5330e0ec7e0SSean Hefty qp = __ib_open_qp(real_qp, qp_init_attr->event_handler, 5340e0ec7e0SSean Hefty qp_init_attr->qp_context); 5350e0ec7e0SSean Hefty if (!IS_ERR(qp)) 5360e0ec7e0SSean Hefty __ib_insert_xrcd_qp(qp_init_attr->xrcd, real_qp); 5370e0ec7e0SSean Hefty else 5380e0ec7e0SSean Hefty real_qp->device->destroy_qp(real_qp); 539b42b63cfSSean Hefty } else { 5401da177e4SLinus Torvalds qp->event_handler = qp_init_attr->event_handler; 5411da177e4SLinus Torvalds qp->qp_context = qp_init_attr->qp_context; 542b42b63cfSSean Hefty if (qp_init_attr->qp_type == IB_QPT_XRC_INI) { 543b42b63cfSSean Hefty qp->recv_cq = NULL; 544b42b63cfSSean Hefty qp->srq = NULL; 545b42b63cfSSean Hefty } else { 546b42b63cfSSean Hefty qp->recv_cq = qp_init_attr->recv_cq; 547b42b63cfSSean Hefty atomic_inc(&qp_init_attr->recv_cq->usecnt); 548b42b63cfSSean Hefty qp->srq = qp_init_attr->srq; 549b42b63cfSSean Hefty if (qp->srq) 550b42b63cfSSean Hefty atomic_inc(&qp_init_attr->srq->usecnt); 551b42b63cfSSean Hefty } 552b42b63cfSSean Hefty 5531da177e4SLinus Torvalds qp->pd = pd; 5541da177e4SLinus Torvalds qp->send_cq = qp_init_attr->send_cq; 555b42b63cfSSean Hefty qp->xrcd = NULL; 556b42b63cfSSean Hefty 5571da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 5581da177e4SLinus Torvalds atomic_inc(&qp_init_attr->send_cq->usecnt); 559b42b63cfSSean Hefty } 5601da177e4SLinus Torvalds } 5611da177e4SLinus Torvalds 5621da177e4SLinus Torvalds return qp; 5631da177e4SLinus Torvalds } 5641da177e4SLinus Torvalds EXPORT_SYMBOL(ib_create_qp); 5651da177e4SLinus Torvalds 5668a51866fSRoland Dreier static const struct { 5678a51866fSRoland Dreier int valid; 568b42b63cfSSean Hefty enum ib_qp_attr_mask req_param[IB_QPT_MAX]; 569dd5f03beSMatan Barak enum ib_qp_attr_mask req_param_add_eth[IB_QPT_MAX]; 570b42b63cfSSean Hefty enum ib_qp_attr_mask opt_param[IB_QPT_MAX]; 571dd5f03beSMatan Barak enum ib_qp_attr_mask opt_param_add_eth[IB_QPT_MAX]; 5728a51866fSRoland Dreier } qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = { 5738a51866fSRoland Dreier [IB_QPS_RESET] = { 5748a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 5758a51866fSRoland Dreier [IB_QPS_INIT] = { 5768a51866fSRoland Dreier .valid = 1, 5778a51866fSRoland Dreier .req_param = { 5788a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 5798a51866fSRoland Dreier IB_QP_PORT | 5808a51866fSRoland Dreier IB_QP_QKEY), 581c938a616SOr Gerlitz [IB_QPT_RAW_PACKET] = IB_QP_PORT, 5828a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_PKEY_INDEX | 5838a51866fSRoland Dreier IB_QP_PORT | 5848a51866fSRoland Dreier IB_QP_ACCESS_FLAGS), 5858a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_PKEY_INDEX | 5868a51866fSRoland Dreier IB_QP_PORT | 5878a51866fSRoland Dreier IB_QP_ACCESS_FLAGS), 588b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX | 589b42b63cfSSean Hefty IB_QP_PORT | 590b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS), 591b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX | 592b42b63cfSSean Hefty IB_QP_PORT | 593b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS), 5948a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 5958a51866fSRoland Dreier IB_QP_QKEY), 5968a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 5978a51866fSRoland Dreier IB_QP_QKEY), 5988a51866fSRoland Dreier } 5998a51866fSRoland Dreier }, 6008a51866fSRoland Dreier }, 6018a51866fSRoland Dreier [IB_QPS_INIT] = { 6028a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 6038a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 }, 6048a51866fSRoland Dreier [IB_QPS_INIT] = { 6058a51866fSRoland Dreier .valid = 1, 6068a51866fSRoland Dreier .opt_param = { 6078a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 6088a51866fSRoland Dreier IB_QP_PORT | 6098a51866fSRoland Dreier IB_QP_QKEY), 6108a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_PKEY_INDEX | 6118a51866fSRoland Dreier IB_QP_PORT | 6128a51866fSRoland Dreier IB_QP_ACCESS_FLAGS), 6138a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_PKEY_INDEX | 6148a51866fSRoland Dreier IB_QP_PORT | 6158a51866fSRoland Dreier IB_QP_ACCESS_FLAGS), 616b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX | 617b42b63cfSSean Hefty IB_QP_PORT | 618b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS), 619b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX | 620b42b63cfSSean Hefty IB_QP_PORT | 621b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS), 6228a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 6238a51866fSRoland Dreier IB_QP_QKEY), 6248a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 6258a51866fSRoland Dreier IB_QP_QKEY), 6268a51866fSRoland Dreier } 6278a51866fSRoland Dreier }, 6288a51866fSRoland Dreier [IB_QPS_RTR] = { 6298a51866fSRoland Dreier .valid = 1, 6308a51866fSRoland Dreier .req_param = { 6318a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_AV | 6328a51866fSRoland Dreier IB_QP_PATH_MTU | 6338a51866fSRoland Dreier IB_QP_DEST_QPN | 6348a51866fSRoland Dreier IB_QP_RQ_PSN), 6358a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_AV | 6368a51866fSRoland Dreier IB_QP_PATH_MTU | 6378a51866fSRoland Dreier IB_QP_DEST_QPN | 6388a51866fSRoland Dreier IB_QP_RQ_PSN | 6398a51866fSRoland Dreier IB_QP_MAX_DEST_RD_ATOMIC | 6408a51866fSRoland Dreier IB_QP_MIN_RNR_TIMER), 641b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_AV | 642b42b63cfSSean Hefty IB_QP_PATH_MTU | 643b42b63cfSSean Hefty IB_QP_DEST_QPN | 644b42b63cfSSean Hefty IB_QP_RQ_PSN), 645b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_AV | 646b42b63cfSSean Hefty IB_QP_PATH_MTU | 647b42b63cfSSean Hefty IB_QP_DEST_QPN | 648b42b63cfSSean Hefty IB_QP_RQ_PSN | 649b42b63cfSSean Hefty IB_QP_MAX_DEST_RD_ATOMIC | 650b42b63cfSSean Hefty IB_QP_MIN_RNR_TIMER), 6518a51866fSRoland Dreier }, 652dd5f03beSMatan Barak .req_param_add_eth = { 653dd5f03beSMatan Barak [IB_QPT_RC] = (IB_QP_SMAC), 654dd5f03beSMatan Barak [IB_QPT_UC] = (IB_QP_SMAC), 655dd5f03beSMatan Barak [IB_QPT_XRC_INI] = (IB_QP_SMAC), 656dd5f03beSMatan Barak [IB_QPT_XRC_TGT] = (IB_QP_SMAC) 657dd5f03beSMatan Barak }, 6588a51866fSRoland Dreier .opt_param = { 6598a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 6608a51866fSRoland Dreier IB_QP_QKEY), 6618a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_ALT_PATH | 6628a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 6638a51866fSRoland Dreier IB_QP_PKEY_INDEX), 6648a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_ALT_PATH | 6658a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 6668a51866fSRoland Dreier IB_QP_PKEY_INDEX), 667b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_ALT_PATH | 668b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 669b42b63cfSSean Hefty IB_QP_PKEY_INDEX), 670b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_ALT_PATH | 671b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 672b42b63cfSSean Hefty IB_QP_PKEY_INDEX), 6738a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 6748a51866fSRoland Dreier IB_QP_QKEY), 6758a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 6768a51866fSRoland Dreier IB_QP_QKEY), 677dd5f03beSMatan Barak }, 678dd5f03beSMatan Barak .opt_param_add_eth = { 679dd5f03beSMatan Barak [IB_QPT_RC] = (IB_QP_ALT_SMAC | 680dd5f03beSMatan Barak IB_QP_VID | 681dd5f03beSMatan Barak IB_QP_ALT_VID), 682dd5f03beSMatan Barak [IB_QPT_UC] = (IB_QP_ALT_SMAC | 683dd5f03beSMatan Barak IB_QP_VID | 684dd5f03beSMatan Barak IB_QP_ALT_VID), 685dd5f03beSMatan Barak [IB_QPT_XRC_INI] = (IB_QP_ALT_SMAC | 686dd5f03beSMatan Barak IB_QP_VID | 687dd5f03beSMatan Barak IB_QP_ALT_VID), 688dd5f03beSMatan Barak [IB_QPT_XRC_TGT] = (IB_QP_ALT_SMAC | 689dd5f03beSMatan Barak IB_QP_VID | 690dd5f03beSMatan Barak IB_QP_ALT_VID) 6918a51866fSRoland Dreier } 6928a51866fSRoland Dreier } 6938a51866fSRoland Dreier }, 6948a51866fSRoland Dreier [IB_QPS_RTR] = { 6958a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 6968a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 }, 6978a51866fSRoland Dreier [IB_QPS_RTS] = { 6988a51866fSRoland Dreier .valid = 1, 6998a51866fSRoland Dreier .req_param = { 7008a51866fSRoland Dreier [IB_QPT_UD] = IB_QP_SQ_PSN, 7018a51866fSRoland Dreier [IB_QPT_UC] = IB_QP_SQ_PSN, 7028a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_TIMEOUT | 7038a51866fSRoland Dreier IB_QP_RETRY_CNT | 7048a51866fSRoland Dreier IB_QP_RNR_RETRY | 7058a51866fSRoland Dreier IB_QP_SQ_PSN | 7068a51866fSRoland Dreier IB_QP_MAX_QP_RD_ATOMIC), 707b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_TIMEOUT | 708b42b63cfSSean Hefty IB_QP_RETRY_CNT | 709b42b63cfSSean Hefty IB_QP_RNR_RETRY | 710b42b63cfSSean Hefty IB_QP_SQ_PSN | 711b42b63cfSSean Hefty IB_QP_MAX_QP_RD_ATOMIC), 712b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_TIMEOUT | 713b42b63cfSSean Hefty IB_QP_SQ_PSN), 7148a51866fSRoland Dreier [IB_QPT_SMI] = IB_QP_SQ_PSN, 7158a51866fSRoland Dreier [IB_QPT_GSI] = IB_QP_SQ_PSN, 7168a51866fSRoland Dreier }, 7178a51866fSRoland Dreier .opt_param = { 7188a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_CUR_STATE | 7198a51866fSRoland Dreier IB_QP_QKEY), 7208a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_CUR_STATE | 7218a51866fSRoland Dreier IB_QP_ALT_PATH | 7228a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 7238a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 7248a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_CUR_STATE | 7258a51866fSRoland Dreier IB_QP_ALT_PATH | 7268a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 7278a51866fSRoland Dreier IB_QP_MIN_RNR_TIMER | 7288a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 729b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE | 730b42b63cfSSean Hefty IB_QP_ALT_PATH | 731b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 732b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 733b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE | 734b42b63cfSSean Hefty IB_QP_ALT_PATH | 735b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 736b42b63cfSSean Hefty IB_QP_MIN_RNR_TIMER | 737b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 7388a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_CUR_STATE | 7398a51866fSRoland Dreier IB_QP_QKEY), 7408a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_CUR_STATE | 7418a51866fSRoland Dreier IB_QP_QKEY), 7428a51866fSRoland Dreier } 7438a51866fSRoland Dreier } 7448a51866fSRoland Dreier }, 7458a51866fSRoland Dreier [IB_QPS_RTS] = { 7468a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 7478a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 }, 7488a51866fSRoland Dreier [IB_QPS_RTS] = { 7498a51866fSRoland Dreier .valid = 1, 7508a51866fSRoland Dreier .opt_param = { 7518a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_CUR_STATE | 7528a51866fSRoland Dreier IB_QP_QKEY), 7534546d31dSDotan Barak [IB_QPT_UC] = (IB_QP_CUR_STATE | 7544546d31dSDotan Barak IB_QP_ACCESS_FLAGS | 7558a51866fSRoland Dreier IB_QP_ALT_PATH | 7568a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 7574546d31dSDotan Barak [IB_QPT_RC] = (IB_QP_CUR_STATE | 7584546d31dSDotan Barak IB_QP_ACCESS_FLAGS | 7598a51866fSRoland Dreier IB_QP_ALT_PATH | 7608a51866fSRoland Dreier IB_QP_PATH_MIG_STATE | 7618a51866fSRoland Dreier IB_QP_MIN_RNR_TIMER), 762b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE | 763b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 764b42b63cfSSean Hefty IB_QP_ALT_PATH | 765b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 766b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE | 767b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 768b42b63cfSSean Hefty IB_QP_ALT_PATH | 769b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE | 770b42b63cfSSean Hefty IB_QP_MIN_RNR_TIMER), 7718a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_CUR_STATE | 7728a51866fSRoland Dreier IB_QP_QKEY), 7738a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_CUR_STATE | 7748a51866fSRoland Dreier IB_QP_QKEY), 7758a51866fSRoland Dreier } 7768a51866fSRoland Dreier }, 7778a51866fSRoland Dreier [IB_QPS_SQD] = { 7788a51866fSRoland Dreier .valid = 1, 7798a51866fSRoland Dreier .opt_param = { 7808a51866fSRoland Dreier [IB_QPT_UD] = IB_QP_EN_SQD_ASYNC_NOTIFY, 7818a51866fSRoland Dreier [IB_QPT_UC] = IB_QP_EN_SQD_ASYNC_NOTIFY, 7828a51866fSRoland Dreier [IB_QPT_RC] = IB_QP_EN_SQD_ASYNC_NOTIFY, 783b42b63cfSSean Hefty [IB_QPT_XRC_INI] = IB_QP_EN_SQD_ASYNC_NOTIFY, 784b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = IB_QP_EN_SQD_ASYNC_NOTIFY, /* ??? */ 7858a51866fSRoland Dreier [IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY, 7868a51866fSRoland Dreier [IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY 7878a51866fSRoland Dreier } 7888a51866fSRoland Dreier }, 7898a51866fSRoland Dreier }, 7908a51866fSRoland Dreier [IB_QPS_SQD] = { 7918a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 7928a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 }, 7938a51866fSRoland Dreier [IB_QPS_RTS] = { 7948a51866fSRoland Dreier .valid = 1, 7958a51866fSRoland Dreier .opt_param = { 7968a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_CUR_STATE | 7978a51866fSRoland Dreier IB_QP_QKEY), 7988a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_CUR_STATE | 7998a51866fSRoland Dreier IB_QP_ALT_PATH | 8008a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 8018a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 8028a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_CUR_STATE | 8038a51866fSRoland Dreier IB_QP_ALT_PATH | 8048a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 8058a51866fSRoland Dreier IB_QP_MIN_RNR_TIMER | 8068a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 807b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE | 808b42b63cfSSean Hefty IB_QP_ALT_PATH | 809b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 810b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 811b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE | 812b42b63cfSSean Hefty IB_QP_ALT_PATH | 813b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 814b42b63cfSSean Hefty IB_QP_MIN_RNR_TIMER | 815b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 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 [IB_QPS_SQD] = { 8238a51866fSRoland Dreier .valid = 1, 8248a51866fSRoland Dreier .opt_param = { 8258a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 8268a51866fSRoland Dreier IB_QP_QKEY), 8278a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_AV | 8288a51866fSRoland Dreier IB_QP_ALT_PATH | 8298a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 8308a51866fSRoland Dreier IB_QP_PKEY_INDEX | 8318a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 8328a51866fSRoland Dreier [IB_QPT_RC] = (IB_QP_PORT | 8338a51866fSRoland Dreier IB_QP_AV | 8348a51866fSRoland Dreier IB_QP_TIMEOUT | 8358a51866fSRoland Dreier IB_QP_RETRY_CNT | 8368a51866fSRoland Dreier IB_QP_RNR_RETRY | 8378a51866fSRoland Dreier IB_QP_MAX_QP_RD_ATOMIC | 8388a51866fSRoland Dreier IB_QP_MAX_DEST_RD_ATOMIC | 8398a51866fSRoland Dreier IB_QP_ALT_PATH | 8408a51866fSRoland Dreier IB_QP_ACCESS_FLAGS | 8418a51866fSRoland Dreier IB_QP_PKEY_INDEX | 8428a51866fSRoland Dreier IB_QP_MIN_RNR_TIMER | 8438a51866fSRoland Dreier IB_QP_PATH_MIG_STATE), 844b42b63cfSSean Hefty [IB_QPT_XRC_INI] = (IB_QP_PORT | 845b42b63cfSSean Hefty IB_QP_AV | 846b42b63cfSSean Hefty IB_QP_TIMEOUT | 847b42b63cfSSean Hefty IB_QP_RETRY_CNT | 848b42b63cfSSean Hefty IB_QP_RNR_RETRY | 849b42b63cfSSean Hefty IB_QP_MAX_QP_RD_ATOMIC | 850b42b63cfSSean Hefty IB_QP_ALT_PATH | 851b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 852b42b63cfSSean Hefty IB_QP_PKEY_INDEX | 853b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 854b42b63cfSSean Hefty [IB_QPT_XRC_TGT] = (IB_QP_PORT | 855b42b63cfSSean Hefty IB_QP_AV | 856b42b63cfSSean Hefty IB_QP_TIMEOUT | 857b42b63cfSSean Hefty IB_QP_MAX_DEST_RD_ATOMIC | 858b42b63cfSSean Hefty IB_QP_ALT_PATH | 859b42b63cfSSean Hefty IB_QP_ACCESS_FLAGS | 860b42b63cfSSean Hefty IB_QP_PKEY_INDEX | 861b42b63cfSSean Hefty IB_QP_MIN_RNR_TIMER | 862b42b63cfSSean Hefty IB_QP_PATH_MIG_STATE), 8638a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 8648a51866fSRoland Dreier IB_QP_QKEY), 8658a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 8668a51866fSRoland Dreier IB_QP_QKEY), 8678a51866fSRoland Dreier } 8688a51866fSRoland Dreier } 8698a51866fSRoland Dreier }, 8708a51866fSRoland Dreier [IB_QPS_SQE] = { 8718a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 8728a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 }, 8738a51866fSRoland Dreier [IB_QPS_RTS] = { 8748a51866fSRoland Dreier .valid = 1, 8758a51866fSRoland Dreier .opt_param = { 8768a51866fSRoland Dreier [IB_QPT_UD] = (IB_QP_CUR_STATE | 8778a51866fSRoland Dreier IB_QP_QKEY), 8788a51866fSRoland Dreier [IB_QPT_UC] = (IB_QP_CUR_STATE | 8798a51866fSRoland Dreier IB_QP_ACCESS_FLAGS), 8808a51866fSRoland Dreier [IB_QPT_SMI] = (IB_QP_CUR_STATE | 8818a51866fSRoland Dreier IB_QP_QKEY), 8828a51866fSRoland Dreier [IB_QPT_GSI] = (IB_QP_CUR_STATE | 8838a51866fSRoland Dreier IB_QP_QKEY), 8848a51866fSRoland Dreier } 8858a51866fSRoland Dreier } 8868a51866fSRoland Dreier }, 8878a51866fSRoland Dreier [IB_QPS_ERR] = { 8888a51866fSRoland Dreier [IB_QPS_RESET] = { .valid = 1 }, 8898a51866fSRoland Dreier [IB_QPS_ERR] = { .valid = 1 } 8908a51866fSRoland Dreier } 8918a51866fSRoland Dreier }; 8928a51866fSRoland Dreier 8938a51866fSRoland Dreier int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state, 894dd5f03beSMatan Barak enum ib_qp_type type, enum ib_qp_attr_mask mask, 895dd5f03beSMatan Barak enum rdma_link_layer ll) 8968a51866fSRoland Dreier { 8978a51866fSRoland Dreier enum ib_qp_attr_mask req_param, opt_param; 8988a51866fSRoland Dreier 8998a51866fSRoland Dreier if (cur_state < 0 || cur_state > IB_QPS_ERR || 9008a51866fSRoland Dreier next_state < 0 || next_state > IB_QPS_ERR) 9018a51866fSRoland Dreier return 0; 9028a51866fSRoland Dreier 9038a51866fSRoland Dreier if (mask & IB_QP_CUR_STATE && 9048a51866fSRoland Dreier cur_state != IB_QPS_RTR && cur_state != IB_QPS_RTS && 9058a51866fSRoland Dreier cur_state != IB_QPS_SQD && cur_state != IB_QPS_SQE) 9068a51866fSRoland Dreier return 0; 9078a51866fSRoland Dreier 9088a51866fSRoland Dreier if (!qp_state_table[cur_state][next_state].valid) 9098a51866fSRoland Dreier return 0; 9108a51866fSRoland Dreier 9118a51866fSRoland Dreier req_param = qp_state_table[cur_state][next_state].req_param[type]; 9128a51866fSRoland Dreier opt_param = qp_state_table[cur_state][next_state].opt_param[type]; 9138a51866fSRoland Dreier 914dd5f03beSMatan Barak if (ll == IB_LINK_LAYER_ETHERNET) { 915dd5f03beSMatan Barak req_param |= qp_state_table[cur_state][next_state]. 916dd5f03beSMatan Barak req_param_add_eth[type]; 917dd5f03beSMatan Barak opt_param |= qp_state_table[cur_state][next_state]. 918dd5f03beSMatan Barak opt_param_add_eth[type]; 919dd5f03beSMatan Barak } 920dd5f03beSMatan Barak 9218a51866fSRoland Dreier if ((mask & req_param) != req_param) 9228a51866fSRoland Dreier return 0; 9238a51866fSRoland Dreier 9248a51866fSRoland Dreier if (mask & ~(req_param | opt_param | IB_QP_STATE)) 9258a51866fSRoland Dreier return 0; 9268a51866fSRoland Dreier 9278a51866fSRoland Dreier return 1; 9288a51866fSRoland Dreier } 9298a51866fSRoland Dreier EXPORT_SYMBOL(ib_modify_qp_is_ok); 9308a51866fSRoland Dreier 931ed4c54e5SOr Gerlitz int ib_resolve_eth_l2_attrs(struct ib_qp *qp, 932ed4c54e5SOr Gerlitz struct ib_qp_attr *qp_attr, int *qp_attr_mask) 933ed4c54e5SOr Gerlitz { 934ed4c54e5SOr Gerlitz int ret = 0; 935ed4c54e5SOr Gerlitz union ib_gid sgid; 936ed4c54e5SOr Gerlitz 937ed4c54e5SOr Gerlitz if ((*qp_attr_mask & IB_QP_AV) && 938227128fcSMichael Wang (rdma_cap_eth_ah(qp->device, qp_attr->ah_attr.port_num))) { 939ed4c54e5SOr Gerlitz ret = ib_query_gid(qp->device, qp_attr->ah_attr.port_num, 940ed4c54e5SOr Gerlitz qp_attr->ah_attr.grh.sgid_index, &sgid); 941ed4c54e5SOr Gerlitz if (ret) 942ed4c54e5SOr Gerlitz goto out; 943ed4c54e5SOr Gerlitz if (rdma_link_local_addr((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw)) { 944ed4c54e5SOr Gerlitz rdma_get_ll_mac((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw, qp_attr->ah_attr.dmac); 945ed4c54e5SOr Gerlitz rdma_get_ll_mac((struct in6_addr *)sgid.raw, qp_attr->smac); 946c1bd6cdeSMoni Shoua if (!(*qp_attr_mask & IB_QP_VID)) 947ed4c54e5SOr Gerlitz qp_attr->vlan_id = rdma_get_vlan_id(&sgid); 948ed4c54e5SOr Gerlitz } else { 949ed4c54e5SOr Gerlitz ret = rdma_addr_find_dmac_by_grh(&sgid, &qp_attr->ah_attr.grh.dgid, 950ed4c54e5SOr Gerlitz qp_attr->ah_attr.dmac, &qp_attr->vlan_id); 951ed4c54e5SOr Gerlitz if (ret) 952ed4c54e5SOr Gerlitz goto out; 953ed4c54e5SOr Gerlitz ret = rdma_addr_find_smac_by_sgid(&sgid, qp_attr->smac, NULL); 954ed4c54e5SOr Gerlitz if (ret) 955ed4c54e5SOr Gerlitz goto out; 956ed4c54e5SOr Gerlitz } 957ed4c54e5SOr Gerlitz *qp_attr_mask |= IB_QP_SMAC; 958ed4c54e5SOr Gerlitz if (qp_attr->vlan_id < 0xFFFF) 959ed4c54e5SOr Gerlitz *qp_attr_mask |= IB_QP_VID; 960ed4c54e5SOr Gerlitz } 961ed4c54e5SOr Gerlitz out: 962ed4c54e5SOr Gerlitz return ret; 963ed4c54e5SOr Gerlitz } 964ed4c54e5SOr Gerlitz EXPORT_SYMBOL(ib_resolve_eth_l2_attrs); 965ed4c54e5SOr Gerlitz 966ed4c54e5SOr Gerlitz 9671da177e4SLinus Torvalds int ib_modify_qp(struct ib_qp *qp, 9681da177e4SLinus Torvalds struct ib_qp_attr *qp_attr, 9691da177e4SLinus Torvalds int qp_attr_mask) 9701da177e4SLinus Torvalds { 971ed4c54e5SOr Gerlitz int ret; 972ed4c54e5SOr Gerlitz 973ed4c54e5SOr Gerlitz ret = ib_resolve_eth_l2_attrs(qp, qp_attr, &qp_attr_mask); 974ed4c54e5SOr Gerlitz if (ret) 975ed4c54e5SOr Gerlitz return ret; 976ed4c54e5SOr Gerlitz 9770e0ec7e0SSean Hefty return qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL); 9781da177e4SLinus Torvalds } 9791da177e4SLinus Torvalds EXPORT_SYMBOL(ib_modify_qp); 9801da177e4SLinus Torvalds 9811da177e4SLinus Torvalds int ib_query_qp(struct ib_qp *qp, 9821da177e4SLinus Torvalds struct ib_qp_attr *qp_attr, 9831da177e4SLinus Torvalds int qp_attr_mask, 9841da177e4SLinus Torvalds struct ib_qp_init_attr *qp_init_attr) 9851da177e4SLinus Torvalds { 9861da177e4SLinus Torvalds return qp->device->query_qp ? 9870e0ec7e0SSean Hefty qp->device->query_qp(qp->real_qp, qp_attr, qp_attr_mask, qp_init_attr) : 9881da177e4SLinus Torvalds -ENOSYS; 9891da177e4SLinus Torvalds } 9901da177e4SLinus Torvalds EXPORT_SYMBOL(ib_query_qp); 9911da177e4SLinus Torvalds 9920e0ec7e0SSean Hefty int ib_close_qp(struct ib_qp *qp) 9930e0ec7e0SSean Hefty { 9940e0ec7e0SSean Hefty struct ib_qp *real_qp; 9950e0ec7e0SSean Hefty unsigned long flags; 9960e0ec7e0SSean Hefty 9970e0ec7e0SSean Hefty real_qp = qp->real_qp; 9980e0ec7e0SSean Hefty if (real_qp == qp) 9990e0ec7e0SSean Hefty return -EINVAL; 10000e0ec7e0SSean Hefty 10010e0ec7e0SSean Hefty spin_lock_irqsave(&real_qp->device->event_handler_lock, flags); 10020e0ec7e0SSean Hefty list_del(&qp->open_list); 10030e0ec7e0SSean Hefty spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags); 10040e0ec7e0SSean Hefty 10050e0ec7e0SSean Hefty atomic_dec(&real_qp->usecnt); 10060e0ec7e0SSean Hefty kfree(qp); 10070e0ec7e0SSean Hefty 10080e0ec7e0SSean Hefty return 0; 10090e0ec7e0SSean Hefty } 10100e0ec7e0SSean Hefty EXPORT_SYMBOL(ib_close_qp); 10110e0ec7e0SSean Hefty 10120e0ec7e0SSean Hefty static int __ib_destroy_shared_qp(struct ib_qp *qp) 10130e0ec7e0SSean Hefty { 10140e0ec7e0SSean Hefty struct ib_xrcd *xrcd; 10150e0ec7e0SSean Hefty struct ib_qp *real_qp; 10160e0ec7e0SSean Hefty int ret; 10170e0ec7e0SSean Hefty 10180e0ec7e0SSean Hefty real_qp = qp->real_qp; 10190e0ec7e0SSean Hefty xrcd = real_qp->xrcd; 10200e0ec7e0SSean Hefty 10210e0ec7e0SSean Hefty mutex_lock(&xrcd->tgt_qp_mutex); 10220e0ec7e0SSean Hefty ib_close_qp(qp); 10230e0ec7e0SSean Hefty if (atomic_read(&real_qp->usecnt) == 0) 10240e0ec7e0SSean Hefty list_del(&real_qp->xrcd_list); 10250e0ec7e0SSean Hefty else 10260e0ec7e0SSean Hefty real_qp = NULL; 10270e0ec7e0SSean Hefty mutex_unlock(&xrcd->tgt_qp_mutex); 10280e0ec7e0SSean Hefty 10290e0ec7e0SSean Hefty if (real_qp) { 10300e0ec7e0SSean Hefty ret = ib_destroy_qp(real_qp); 10310e0ec7e0SSean Hefty if (!ret) 10320e0ec7e0SSean Hefty atomic_dec(&xrcd->usecnt); 10330e0ec7e0SSean Hefty else 10340e0ec7e0SSean Hefty __ib_insert_xrcd_qp(xrcd, real_qp); 10350e0ec7e0SSean Hefty } 10360e0ec7e0SSean Hefty 10370e0ec7e0SSean Hefty return 0; 10380e0ec7e0SSean Hefty } 10390e0ec7e0SSean Hefty 10401da177e4SLinus Torvalds int ib_destroy_qp(struct ib_qp *qp) 10411da177e4SLinus Torvalds { 10421da177e4SLinus Torvalds struct ib_pd *pd; 10431da177e4SLinus Torvalds struct ib_cq *scq, *rcq; 10441da177e4SLinus Torvalds struct ib_srq *srq; 10451da177e4SLinus Torvalds int ret; 10461da177e4SLinus Torvalds 10470e0ec7e0SSean Hefty if (atomic_read(&qp->usecnt)) 10480e0ec7e0SSean Hefty return -EBUSY; 10490e0ec7e0SSean Hefty 10500e0ec7e0SSean Hefty if (qp->real_qp != qp) 10510e0ec7e0SSean Hefty return __ib_destroy_shared_qp(qp); 10520e0ec7e0SSean Hefty 10531da177e4SLinus Torvalds pd = qp->pd; 10541da177e4SLinus Torvalds scq = qp->send_cq; 10551da177e4SLinus Torvalds rcq = qp->recv_cq; 10561da177e4SLinus Torvalds srq = qp->srq; 10571da177e4SLinus Torvalds 10581da177e4SLinus Torvalds ret = qp->device->destroy_qp(qp); 10591da177e4SLinus Torvalds if (!ret) { 1060b42b63cfSSean Hefty if (pd) 10611da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 1062b42b63cfSSean Hefty if (scq) 10631da177e4SLinus Torvalds atomic_dec(&scq->usecnt); 1064b42b63cfSSean Hefty if (rcq) 10651da177e4SLinus Torvalds atomic_dec(&rcq->usecnt); 10661da177e4SLinus Torvalds if (srq) 10671da177e4SLinus Torvalds atomic_dec(&srq->usecnt); 10681da177e4SLinus Torvalds } 10691da177e4SLinus Torvalds 10701da177e4SLinus Torvalds return ret; 10711da177e4SLinus Torvalds } 10721da177e4SLinus Torvalds EXPORT_SYMBOL(ib_destroy_qp); 10731da177e4SLinus Torvalds 10741da177e4SLinus Torvalds /* Completion queues */ 10751da177e4SLinus Torvalds 10761da177e4SLinus Torvalds struct ib_cq *ib_create_cq(struct ib_device *device, 10771da177e4SLinus Torvalds ib_comp_handler comp_handler, 10781da177e4SLinus Torvalds void (*event_handler)(struct ib_event *, void *), 10798e37210bSMatan Barak void *cq_context, 10808e37210bSMatan Barak const struct ib_cq_init_attr *cq_attr) 10811da177e4SLinus Torvalds { 10821da177e4SLinus Torvalds struct ib_cq *cq; 10831da177e4SLinus Torvalds 10848e37210bSMatan Barak cq = device->create_cq(device, cq_attr, NULL, NULL); 10851da177e4SLinus Torvalds 10861da177e4SLinus Torvalds if (!IS_ERR(cq)) { 10871da177e4SLinus Torvalds cq->device = device; 1088b5e81bf5SRoland Dreier cq->uobject = NULL; 10891da177e4SLinus Torvalds cq->comp_handler = comp_handler; 10901da177e4SLinus Torvalds cq->event_handler = event_handler; 10911da177e4SLinus Torvalds cq->cq_context = cq_context; 10921da177e4SLinus Torvalds atomic_set(&cq->usecnt, 0); 10931da177e4SLinus Torvalds } 10941da177e4SLinus Torvalds 10951da177e4SLinus Torvalds return cq; 10961da177e4SLinus Torvalds } 10971da177e4SLinus Torvalds EXPORT_SYMBOL(ib_create_cq); 10981da177e4SLinus Torvalds 10992dd57162SEli Cohen int ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period) 11002dd57162SEli Cohen { 11012dd57162SEli Cohen return cq->device->modify_cq ? 11022dd57162SEli Cohen cq->device->modify_cq(cq, cq_count, cq_period) : -ENOSYS; 11032dd57162SEli Cohen } 11042dd57162SEli Cohen EXPORT_SYMBOL(ib_modify_cq); 11052dd57162SEli Cohen 11061da177e4SLinus Torvalds int ib_destroy_cq(struct ib_cq *cq) 11071da177e4SLinus Torvalds { 11081da177e4SLinus Torvalds if (atomic_read(&cq->usecnt)) 11091da177e4SLinus Torvalds return -EBUSY; 11101da177e4SLinus Torvalds 11111da177e4SLinus Torvalds return cq->device->destroy_cq(cq); 11121da177e4SLinus Torvalds } 11131da177e4SLinus Torvalds EXPORT_SYMBOL(ib_destroy_cq); 11141da177e4SLinus Torvalds 1115a74cd4afSRoland Dreier int ib_resize_cq(struct ib_cq *cq, int cqe) 11161da177e4SLinus Torvalds { 111740de2e54SRoland Dreier return cq->device->resize_cq ? 111833b9b3eeSRoland Dreier cq->device->resize_cq(cq, cqe, NULL) : -ENOSYS; 11191da177e4SLinus Torvalds } 11201da177e4SLinus Torvalds EXPORT_SYMBOL(ib_resize_cq); 11211da177e4SLinus Torvalds 11221da177e4SLinus Torvalds /* Memory regions */ 11231da177e4SLinus Torvalds 11241da177e4SLinus Torvalds struct ib_mr *ib_get_dma_mr(struct ib_pd *pd, int mr_access_flags) 11251da177e4SLinus Torvalds { 11261da177e4SLinus Torvalds struct ib_mr *mr; 11271c636f80SEli Cohen int err; 11281c636f80SEli Cohen 11291c636f80SEli Cohen err = ib_check_mr_access(mr_access_flags); 11301c636f80SEli Cohen if (err) 11311c636f80SEli Cohen return ERR_PTR(err); 11321da177e4SLinus Torvalds 11331da177e4SLinus Torvalds mr = pd->device->get_dma_mr(pd, mr_access_flags); 11341da177e4SLinus Torvalds 11351da177e4SLinus Torvalds if (!IS_ERR(mr)) { 11361da177e4SLinus Torvalds mr->device = pd->device; 11371da177e4SLinus Torvalds mr->pd = pd; 1138b5e81bf5SRoland Dreier mr->uobject = NULL; 11391da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 11401da177e4SLinus Torvalds atomic_set(&mr->usecnt, 0); 11411da177e4SLinus Torvalds } 11421da177e4SLinus Torvalds 11431da177e4SLinus Torvalds return mr; 11441da177e4SLinus Torvalds } 11451da177e4SLinus Torvalds EXPORT_SYMBOL(ib_get_dma_mr); 11461da177e4SLinus Torvalds 11471da177e4SLinus Torvalds struct ib_mr *ib_reg_phys_mr(struct ib_pd *pd, 11481da177e4SLinus Torvalds struct ib_phys_buf *phys_buf_array, 11491da177e4SLinus Torvalds int num_phys_buf, 11501da177e4SLinus Torvalds int mr_access_flags, 11511da177e4SLinus Torvalds u64 *iova_start) 11521da177e4SLinus Torvalds { 11531da177e4SLinus Torvalds struct ib_mr *mr; 11541c636f80SEli Cohen int err; 11551c636f80SEli Cohen 11561c636f80SEli Cohen err = ib_check_mr_access(mr_access_flags); 11571c636f80SEli Cohen if (err) 11581c636f80SEli Cohen return ERR_PTR(err); 11591da177e4SLinus Torvalds 11607ce5eacbSDotan Barak if (!pd->device->reg_phys_mr) 11617ce5eacbSDotan Barak return ERR_PTR(-ENOSYS); 11627ce5eacbSDotan Barak 11631da177e4SLinus Torvalds mr = pd->device->reg_phys_mr(pd, phys_buf_array, num_phys_buf, 11641da177e4SLinus Torvalds mr_access_flags, iova_start); 11651da177e4SLinus Torvalds 11661da177e4SLinus Torvalds if (!IS_ERR(mr)) { 11671da177e4SLinus Torvalds mr->device = pd->device; 11681da177e4SLinus Torvalds mr->pd = pd; 1169b5e81bf5SRoland Dreier mr->uobject = NULL; 11701da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 11711da177e4SLinus Torvalds atomic_set(&mr->usecnt, 0); 11721da177e4SLinus Torvalds } 11731da177e4SLinus Torvalds 11741da177e4SLinus Torvalds return mr; 11751da177e4SLinus Torvalds } 11761da177e4SLinus Torvalds EXPORT_SYMBOL(ib_reg_phys_mr); 11771da177e4SLinus Torvalds 11781da177e4SLinus Torvalds int ib_rereg_phys_mr(struct ib_mr *mr, 11791da177e4SLinus Torvalds int mr_rereg_mask, 11801da177e4SLinus Torvalds struct ib_pd *pd, 11811da177e4SLinus Torvalds struct ib_phys_buf *phys_buf_array, 11821da177e4SLinus Torvalds int num_phys_buf, 11831da177e4SLinus Torvalds int mr_access_flags, 11841da177e4SLinus Torvalds u64 *iova_start) 11851da177e4SLinus Torvalds { 11861da177e4SLinus Torvalds struct ib_pd *old_pd; 11871da177e4SLinus Torvalds int ret; 11881da177e4SLinus Torvalds 11891c636f80SEli Cohen ret = ib_check_mr_access(mr_access_flags); 11901c636f80SEli Cohen if (ret) 11911c636f80SEli Cohen return ret; 11921c636f80SEli Cohen 11931da177e4SLinus Torvalds if (!mr->device->rereg_phys_mr) 11941da177e4SLinus Torvalds return -ENOSYS; 11951da177e4SLinus Torvalds 11961da177e4SLinus Torvalds if (atomic_read(&mr->usecnt)) 11971da177e4SLinus Torvalds return -EBUSY; 11981da177e4SLinus Torvalds 11991da177e4SLinus Torvalds old_pd = mr->pd; 12001da177e4SLinus Torvalds 12011da177e4SLinus Torvalds ret = mr->device->rereg_phys_mr(mr, mr_rereg_mask, pd, 12021da177e4SLinus Torvalds phys_buf_array, num_phys_buf, 12031da177e4SLinus Torvalds mr_access_flags, iova_start); 12041da177e4SLinus Torvalds 12051da177e4SLinus Torvalds if (!ret && (mr_rereg_mask & IB_MR_REREG_PD)) { 12061da177e4SLinus Torvalds atomic_dec(&old_pd->usecnt); 12071da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 12081da177e4SLinus Torvalds } 12091da177e4SLinus Torvalds 12101da177e4SLinus Torvalds return ret; 12111da177e4SLinus Torvalds } 12121da177e4SLinus Torvalds EXPORT_SYMBOL(ib_rereg_phys_mr); 12131da177e4SLinus Torvalds 12141da177e4SLinus Torvalds int ib_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr) 12151da177e4SLinus Torvalds { 12161da177e4SLinus Torvalds return mr->device->query_mr ? 12171da177e4SLinus Torvalds mr->device->query_mr(mr, mr_attr) : -ENOSYS; 12181da177e4SLinus Torvalds } 12191da177e4SLinus Torvalds EXPORT_SYMBOL(ib_query_mr); 12201da177e4SLinus Torvalds 12211da177e4SLinus Torvalds int ib_dereg_mr(struct ib_mr *mr) 12221da177e4SLinus Torvalds { 12231da177e4SLinus Torvalds struct ib_pd *pd; 12241da177e4SLinus Torvalds int ret; 12251da177e4SLinus Torvalds 12261da177e4SLinus Torvalds if (atomic_read(&mr->usecnt)) 12271da177e4SLinus Torvalds return -EBUSY; 12281da177e4SLinus Torvalds 12291da177e4SLinus Torvalds pd = mr->pd; 12301da177e4SLinus Torvalds ret = mr->device->dereg_mr(mr); 12311da177e4SLinus Torvalds if (!ret) 12321da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 12331da177e4SLinus Torvalds 12341da177e4SLinus Torvalds return ret; 12351da177e4SLinus Torvalds } 12361da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dereg_mr); 12371da177e4SLinus Torvalds 12389bee178bSSagi Grimberg /** 12399bee178bSSagi Grimberg * ib_alloc_mr() - Allocates a memory region 12409bee178bSSagi Grimberg * @pd: protection domain associated with the region 12419bee178bSSagi Grimberg * @mr_type: memory region type 12429bee178bSSagi Grimberg * @max_num_sg: maximum sg entries available for registration. 12439bee178bSSagi Grimberg * 12449bee178bSSagi Grimberg * Notes: 12459bee178bSSagi Grimberg * Memory registeration page/sg lists must not exceed max_num_sg. 12469bee178bSSagi Grimberg * For mr_type IB_MR_TYPE_MEM_REG, the total length cannot exceed 12479bee178bSSagi Grimberg * max_num_sg * used_page_size. 12489bee178bSSagi Grimberg * 12499bee178bSSagi Grimberg */ 12509bee178bSSagi Grimberg struct ib_mr *ib_alloc_mr(struct ib_pd *pd, 12519bee178bSSagi Grimberg enum ib_mr_type mr_type, 12529bee178bSSagi Grimberg u32 max_num_sg) 125317cd3a2dSSagi Grimberg { 125417cd3a2dSSagi Grimberg struct ib_mr *mr; 125517cd3a2dSSagi Grimberg 1256d9f272c5SSagi Grimberg if (!pd->device->alloc_mr) 125717cd3a2dSSagi Grimberg return ERR_PTR(-ENOSYS); 125817cd3a2dSSagi Grimberg 1259d9f272c5SSagi Grimberg mr = pd->device->alloc_mr(pd, mr_type, max_num_sg); 126017cd3a2dSSagi Grimberg if (!IS_ERR(mr)) { 126117cd3a2dSSagi Grimberg mr->device = pd->device; 126217cd3a2dSSagi Grimberg mr->pd = pd; 126317cd3a2dSSagi Grimberg mr->uobject = NULL; 126417cd3a2dSSagi Grimberg atomic_inc(&pd->usecnt); 126517cd3a2dSSagi Grimberg atomic_set(&mr->usecnt, 0); 126617cd3a2dSSagi Grimberg } 126717cd3a2dSSagi Grimberg 126817cd3a2dSSagi Grimberg return mr; 126917cd3a2dSSagi Grimberg } 12709bee178bSSagi Grimberg EXPORT_SYMBOL(ib_alloc_mr); 127117cd3a2dSSagi Grimberg 127200f7ec36SSteve Wise struct ib_fast_reg_page_list *ib_alloc_fast_reg_page_list(struct ib_device *device, 127300f7ec36SSteve Wise int max_page_list_len) 127400f7ec36SSteve Wise { 127500f7ec36SSteve Wise struct ib_fast_reg_page_list *page_list; 127600f7ec36SSteve Wise 127700f7ec36SSteve Wise if (!device->alloc_fast_reg_page_list) 127800f7ec36SSteve Wise return ERR_PTR(-ENOSYS); 127900f7ec36SSteve Wise 128000f7ec36SSteve Wise page_list = device->alloc_fast_reg_page_list(device, max_page_list_len); 128100f7ec36SSteve Wise 128200f7ec36SSteve Wise if (!IS_ERR(page_list)) { 128300f7ec36SSteve Wise page_list->device = device; 128400f7ec36SSteve Wise page_list->max_page_list_len = max_page_list_len; 128500f7ec36SSteve Wise } 128600f7ec36SSteve Wise 128700f7ec36SSteve Wise return page_list; 128800f7ec36SSteve Wise } 128900f7ec36SSteve Wise EXPORT_SYMBOL(ib_alloc_fast_reg_page_list); 129000f7ec36SSteve Wise 129100f7ec36SSteve Wise void ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list) 129200f7ec36SSteve Wise { 129300f7ec36SSteve Wise page_list->device->free_fast_reg_page_list(page_list); 129400f7ec36SSteve Wise } 129500f7ec36SSteve Wise EXPORT_SYMBOL(ib_free_fast_reg_page_list); 129600f7ec36SSteve Wise 12971da177e4SLinus Torvalds /* Memory windows */ 12981da177e4SLinus Torvalds 12997083e42eSShani Michaeli struct ib_mw *ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type) 13001da177e4SLinus Torvalds { 13011da177e4SLinus Torvalds struct ib_mw *mw; 13021da177e4SLinus Torvalds 13031da177e4SLinus Torvalds if (!pd->device->alloc_mw) 13041da177e4SLinus Torvalds return ERR_PTR(-ENOSYS); 13051da177e4SLinus Torvalds 13067083e42eSShani Michaeli mw = pd->device->alloc_mw(pd, type); 13071da177e4SLinus Torvalds if (!IS_ERR(mw)) { 13081da177e4SLinus Torvalds mw->device = pd->device; 13091da177e4SLinus Torvalds mw->pd = pd; 1310b5e81bf5SRoland Dreier mw->uobject = NULL; 13117083e42eSShani Michaeli mw->type = type; 13121da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 13131da177e4SLinus Torvalds } 13141da177e4SLinus Torvalds 13151da177e4SLinus Torvalds return mw; 13161da177e4SLinus Torvalds } 13171da177e4SLinus Torvalds EXPORT_SYMBOL(ib_alloc_mw); 13181da177e4SLinus Torvalds 13191da177e4SLinus Torvalds int ib_dealloc_mw(struct ib_mw *mw) 13201da177e4SLinus Torvalds { 13211da177e4SLinus Torvalds struct ib_pd *pd; 13221da177e4SLinus Torvalds int ret; 13231da177e4SLinus Torvalds 13241da177e4SLinus Torvalds pd = mw->pd; 13251da177e4SLinus Torvalds ret = mw->device->dealloc_mw(mw); 13261da177e4SLinus Torvalds if (!ret) 13271da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 13281da177e4SLinus Torvalds 13291da177e4SLinus Torvalds return ret; 13301da177e4SLinus Torvalds } 13311da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dealloc_mw); 13321da177e4SLinus Torvalds 13331da177e4SLinus Torvalds /* "Fast" memory regions */ 13341da177e4SLinus Torvalds 13351da177e4SLinus Torvalds struct ib_fmr *ib_alloc_fmr(struct ib_pd *pd, 13361da177e4SLinus Torvalds int mr_access_flags, 13371da177e4SLinus Torvalds struct ib_fmr_attr *fmr_attr) 13381da177e4SLinus Torvalds { 13391da177e4SLinus Torvalds struct ib_fmr *fmr; 13401da177e4SLinus Torvalds 13411da177e4SLinus Torvalds if (!pd->device->alloc_fmr) 13421da177e4SLinus Torvalds return ERR_PTR(-ENOSYS); 13431da177e4SLinus Torvalds 13441da177e4SLinus Torvalds fmr = pd->device->alloc_fmr(pd, mr_access_flags, fmr_attr); 13451da177e4SLinus Torvalds if (!IS_ERR(fmr)) { 13461da177e4SLinus Torvalds fmr->device = pd->device; 13471da177e4SLinus Torvalds fmr->pd = pd; 13481da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 13491da177e4SLinus Torvalds } 13501da177e4SLinus Torvalds 13511da177e4SLinus Torvalds return fmr; 13521da177e4SLinus Torvalds } 13531da177e4SLinus Torvalds EXPORT_SYMBOL(ib_alloc_fmr); 13541da177e4SLinus Torvalds 13551da177e4SLinus Torvalds int ib_unmap_fmr(struct list_head *fmr_list) 13561da177e4SLinus Torvalds { 13571da177e4SLinus Torvalds struct ib_fmr *fmr; 13581da177e4SLinus Torvalds 13591da177e4SLinus Torvalds if (list_empty(fmr_list)) 13601da177e4SLinus Torvalds return 0; 13611da177e4SLinus Torvalds 13621da177e4SLinus Torvalds fmr = list_entry(fmr_list->next, struct ib_fmr, list); 13631da177e4SLinus Torvalds return fmr->device->unmap_fmr(fmr_list); 13641da177e4SLinus Torvalds } 13651da177e4SLinus Torvalds EXPORT_SYMBOL(ib_unmap_fmr); 13661da177e4SLinus Torvalds 13671da177e4SLinus Torvalds int ib_dealloc_fmr(struct ib_fmr *fmr) 13681da177e4SLinus Torvalds { 13691da177e4SLinus Torvalds struct ib_pd *pd; 13701da177e4SLinus Torvalds int ret; 13711da177e4SLinus Torvalds 13721da177e4SLinus Torvalds pd = fmr->pd; 13731da177e4SLinus Torvalds ret = fmr->device->dealloc_fmr(fmr); 13741da177e4SLinus Torvalds if (!ret) 13751da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 13761da177e4SLinus Torvalds 13771da177e4SLinus Torvalds return ret; 13781da177e4SLinus Torvalds } 13791da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dealloc_fmr); 13801da177e4SLinus Torvalds 13811da177e4SLinus Torvalds /* Multicast groups */ 13821da177e4SLinus Torvalds 13831da177e4SLinus Torvalds int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid) 13841da177e4SLinus Torvalds { 1385c3bccbfbSOr Gerlitz int ret; 1386c3bccbfbSOr Gerlitz 13870c33aeedSJack Morgenstein if (!qp->device->attach_mcast) 13880c33aeedSJack Morgenstein return -ENOSYS; 13890c33aeedSJack Morgenstein if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD) 13900c33aeedSJack Morgenstein return -EINVAL; 13910c33aeedSJack Morgenstein 1392c3bccbfbSOr Gerlitz ret = qp->device->attach_mcast(qp, gid, lid); 1393c3bccbfbSOr Gerlitz if (!ret) 1394c3bccbfbSOr Gerlitz atomic_inc(&qp->usecnt); 1395c3bccbfbSOr Gerlitz return ret; 13961da177e4SLinus Torvalds } 13971da177e4SLinus Torvalds EXPORT_SYMBOL(ib_attach_mcast); 13981da177e4SLinus Torvalds 13991da177e4SLinus Torvalds int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid) 14001da177e4SLinus Torvalds { 1401c3bccbfbSOr Gerlitz int ret; 1402c3bccbfbSOr Gerlitz 14030c33aeedSJack Morgenstein if (!qp->device->detach_mcast) 14040c33aeedSJack Morgenstein return -ENOSYS; 14050c33aeedSJack Morgenstein if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD) 14060c33aeedSJack Morgenstein return -EINVAL; 14070c33aeedSJack Morgenstein 1408c3bccbfbSOr Gerlitz ret = qp->device->detach_mcast(qp, gid, lid); 1409c3bccbfbSOr Gerlitz if (!ret) 1410c3bccbfbSOr Gerlitz atomic_dec(&qp->usecnt); 1411c3bccbfbSOr Gerlitz return ret; 14121da177e4SLinus Torvalds } 14131da177e4SLinus Torvalds EXPORT_SYMBOL(ib_detach_mcast); 141459991f94SSean Hefty 141559991f94SSean Hefty struct ib_xrcd *ib_alloc_xrcd(struct ib_device *device) 141659991f94SSean Hefty { 141759991f94SSean Hefty struct ib_xrcd *xrcd; 141859991f94SSean Hefty 141959991f94SSean Hefty if (!device->alloc_xrcd) 142059991f94SSean Hefty return ERR_PTR(-ENOSYS); 142159991f94SSean Hefty 142259991f94SSean Hefty xrcd = device->alloc_xrcd(device, NULL, NULL); 142359991f94SSean Hefty if (!IS_ERR(xrcd)) { 142459991f94SSean Hefty xrcd->device = device; 142553d0bd1eSSean Hefty xrcd->inode = NULL; 142659991f94SSean Hefty atomic_set(&xrcd->usecnt, 0); 1427d3d72d90SSean Hefty mutex_init(&xrcd->tgt_qp_mutex); 1428d3d72d90SSean Hefty INIT_LIST_HEAD(&xrcd->tgt_qp_list); 142959991f94SSean Hefty } 143059991f94SSean Hefty 143159991f94SSean Hefty return xrcd; 143259991f94SSean Hefty } 143359991f94SSean Hefty EXPORT_SYMBOL(ib_alloc_xrcd); 143459991f94SSean Hefty 143559991f94SSean Hefty int ib_dealloc_xrcd(struct ib_xrcd *xrcd) 143659991f94SSean Hefty { 1437d3d72d90SSean Hefty struct ib_qp *qp; 1438d3d72d90SSean Hefty int ret; 1439d3d72d90SSean Hefty 144059991f94SSean Hefty if (atomic_read(&xrcd->usecnt)) 144159991f94SSean Hefty return -EBUSY; 144259991f94SSean Hefty 1443d3d72d90SSean Hefty while (!list_empty(&xrcd->tgt_qp_list)) { 1444d3d72d90SSean Hefty qp = list_entry(xrcd->tgt_qp_list.next, struct ib_qp, xrcd_list); 1445d3d72d90SSean Hefty ret = ib_destroy_qp(qp); 1446d3d72d90SSean Hefty if (ret) 1447d3d72d90SSean Hefty return ret; 1448d3d72d90SSean Hefty } 1449d3d72d90SSean Hefty 145059991f94SSean Hefty return xrcd->device->dealloc_xrcd(xrcd); 145159991f94SSean Hefty } 145259991f94SSean Hefty EXPORT_SYMBOL(ib_dealloc_xrcd); 1453319a441dSHadar Hen Zion 1454319a441dSHadar Hen Zion struct ib_flow *ib_create_flow(struct ib_qp *qp, 1455319a441dSHadar Hen Zion struct ib_flow_attr *flow_attr, 1456319a441dSHadar Hen Zion int domain) 1457319a441dSHadar Hen Zion { 1458319a441dSHadar Hen Zion struct ib_flow *flow_id; 1459319a441dSHadar Hen Zion if (!qp->device->create_flow) 1460319a441dSHadar Hen Zion return ERR_PTR(-ENOSYS); 1461319a441dSHadar Hen Zion 1462319a441dSHadar Hen Zion flow_id = qp->device->create_flow(qp, flow_attr, domain); 1463319a441dSHadar Hen Zion if (!IS_ERR(flow_id)) 1464319a441dSHadar Hen Zion atomic_inc(&qp->usecnt); 1465319a441dSHadar Hen Zion return flow_id; 1466319a441dSHadar Hen Zion } 1467319a441dSHadar Hen Zion EXPORT_SYMBOL(ib_create_flow); 1468319a441dSHadar Hen Zion 1469319a441dSHadar Hen Zion int ib_destroy_flow(struct ib_flow *flow_id) 1470319a441dSHadar Hen Zion { 1471319a441dSHadar Hen Zion int err; 1472319a441dSHadar Hen Zion struct ib_qp *qp = flow_id->qp; 1473319a441dSHadar Hen Zion 1474319a441dSHadar Hen Zion err = qp->device->destroy_flow(flow_id); 1475319a441dSHadar Hen Zion if (!err) 1476319a441dSHadar Hen Zion atomic_dec(&qp->usecnt); 1477319a441dSHadar Hen Zion return err; 1478319a441dSHadar Hen Zion } 1479319a441dSHadar Hen Zion EXPORT_SYMBOL(ib_destroy_flow); 14801b01d335SSagi Grimberg 14811b01d335SSagi Grimberg int ib_check_mr_status(struct ib_mr *mr, u32 check_mask, 14821b01d335SSagi Grimberg struct ib_mr_status *mr_status) 14831b01d335SSagi Grimberg { 14841b01d335SSagi Grimberg return mr->device->check_mr_status ? 14851b01d335SSagi Grimberg mr->device->check_mr_status(mr, check_mask, mr_status) : -ENOSYS; 14861b01d335SSagi Grimberg } 14871b01d335SSagi Grimberg EXPORT_SYMBOL(ib_check_mr_status); 1488