1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved. 3219820Sjeff * Copyright (c) 2004 Infinicon Corporation. All rights reserved. 4219820Sjeff * Copyright (c) 2004 Intel Corporation. All rights reserved. 5219820Sjeff * Copyright (c) 2004 Topspin Corporation. All rights reserved. 6219820Sjeff * Copyright (c) 2004 Voltaire Corporation. All rights reserved. 7219820Sjeff * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 8219820Sjeff * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. 9219820Sjeff * 10219820Sjeff * This software is available to you under a choice of one of two 11219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 12219820Sjeff * General Public License (GPL) Version 2, available from the file 13219820Sjeff * COPYING in the main directory of this source tree, or the 14219820Sjeff * OpenIB.org BSD license below: 15219820Sjeff * 16219820Sjeff * Redistribution and use in source and binary forms, with or 17219820Sjeff * without modification, are permitted provided that the following 18219820Sjeff * conditions are met: 19219820Sjeff * 20219820Sjeff * - Redistributions of source code must retain the above 21219820Sjeff * copyright notice, this list of conditions and the following 22219820Sjeff * disclaimer. 23219820Sjeff * 24219820Sjeff * - Redistributions in binary form must reproduce the above 25219820Sjeff * copyright notice, this list of conditions and the following 26219820Sjeff * disclaimer in the documentation and/or other materials 27219820Sjeff * provided with the distribution. 28219820Sjeff * 29219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 30219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 31219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 32219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 33219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 34219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 35219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 36219820Sjeff * SOFTWARE. 37219820Sjeff */ 38219820Sjeff 39219820Sjeff#include <linux/errno.h> 40219820Sjeff#include <linux/err.h> 41278886Shselasky#include <linux/module.h> 42219820Sjeff#include <linux/string.h> 43278886Shselasky#include <linux/slab.h> 44219820Sjeff 45219820Sjeff#include <rdma/ib_verbs.h> 46219820Sjeff#include <rdma/ib_cache.h> 47278886Shselasky#include <rdma/ib_addr.h> 48219820Sjeff 49219820Sjeffint ib_rate_to_mult(enum ib_rate rate) 50219820Sjeff{ 51219820Sjeff switch (rate) { 52219820Sjeff case IB_RATE_2_5_GBPS: return 1; 53219820Sjeff case IB_RATE_5_GBPS: return 2; 54219820Sjeff case IB_RATE_10_GBPS: return 4; 55219820Sjeff case IB_RATE_20_GBPS: return 8; 56219820Sjeff case IB_RATE_30_GBPS: return 12; 57219820Sjeff case IB_RATE_40_GBPS: return 16; 58219820Sjeff case IB_RATE_60_GBPS: return 24; 59219820Sjeff case IB_RATE_80_GBPS: return 32; 60219820Sjeff case IB_RATE_120_GBPS: return 48; 61219820Sjeff default: return -1; 62219820Sjeff } 63219820Sjeff} 64219820SjeffEXPORT_SYMBOL(ib_rate_to_mult); 65219820Sjeff 66219820Sjeffenum ib_rate mult_to_ib_rate(int mult) 67219820Sjeff{ 68219820Sjeff switch (mult) { 69219820Sjeff case 1: return IB_RATE_2_5_GBPS; 70219820Sjeff case 2: return IB_RATE_5_GBPS; 71219820Sjeff case 4: return IB_RATE_10_GBPS; 72219820Sjeff case 8: return IB_RATE_20_GBPS; 73219820Sjeff case 12: return IB_RATE_30_GBPS; 74219820Sjeff case 16: return IB_RATE_40_GBPS; 75219820Sjeff case 24: return IB_RATE_60_GBPS; 76219820Sjeff case 32: return IB_RATE_80_GBPS; 77219820Sjeff case 48: return IB_RATE_120_GBPS; 78219820Sjeff default: return IB_RATE_PORT_CURRENT; 79219820Sjeff } 80219820Sjeff} 81219820SjeffEXPORT_SYMBOL(mult_to_ib_rate); 82219820Sjeff 83278886Shselaskyint ib_rate_to_mbps(enum ib_rate rate) 84278886Shselasky{ 85278886Shselasky switch (rate) { 86278886Shselasky case IB_RATE_2_5_GBPS: return 2500; 87278886Shselasky case IB_RATE_5_GBPS: return 5000; 88278886Shselasky case IB_RATE_10_GBPS: return 10000; 89278886Shselasky case IB_RATE_20_GBPS: return 20000; 90278886Shselasky case IB_RATE_30_GBPS: return 30000; 91278886Shselasky case IB_RATE_40_GBPS: return 40000; 92278886Shselasky case IB_RATE_60_GBPS: return 60000; 93278886Shselasky case IB_RATE_80_GBPS: return 80000; 94278886Shselasky case IB_RATE_120_GBPS: return 120000; 95278886Shselasky case IB_RATE_14_GBPS: return 14062; 96278886Shselasky case IB_RATE_56_GBPS: return 56250; 97278886Shselasky case IB_RATE_112_GBPS: return 112500; 98278886Shselasky case IB_RATE_168_GBPS: return 168750; 99278886Shselasky case IB_RATE_25_GBPS: return 25781; 100278886Shselasky case IB_RATE_100_GBPS: return 103125; 101278886Shselasky case IB_RATE_200_GBPS: return 206250; 102278886Shselasky case IB_RATE_300_GBPS: return 309375; 103278886Shselasky default: return -1; 104278886Shselasky } 105278886Shselasky} 106278886ShselaskyEXPORT_SYMBOL(ib_rate_to_mbps); 107278886Shselasky 108219820Sjeffenum rdma_transport_type 109219820Sjeffrdma_node_get_transport(enum rdma_node_type node_type) 110219820Sjeff{ 111219820Sjeff switch (node_type) { 112219820Sjeff case RDMA_NODE_IB_CA: 113219820Sjeff case RDMA_NODE_IB_SWITCH: 114219820Sjeff case RDMA_NODE_IB_ROUTER: 115219820Sjeff return RDMA_TRANSPORT_IB; 116219820Sjeff case RDMA_NODE_RNIC: 117219820Sjeff return RDMA_TRANSPORT_IWARP; 118278886Shselasky case RDMA_NODE_MIC: 119278886Shselasky return RDMA_TRANSPORT_SCIF; 120219820Sjeff default: 121219820Sjeff BUG(); 122219820Sjeff return 0; 123219820Sjeff } 124219820Sjeff} 125219820SjeffEXPORT_SYMBOL(rdma_node_get_transport); 126219820Sjeff 127219820Sjeffenum rdma_link_layer rdma_port_get_link_layer(struct ib_device *device, u8 port_num) 128219820Sjeff{ 129219820Sjeff if (device->get_link_layer) 130219820Sjeff return device->get_link_layer(device, port_num); 131219820Sjeff 132219820Sjeff switch (rdma_node_get_transport(device->node_type)) { 133219820Sjeff case RDMA_TRANSPORT_IB: 134219820Sjeff return IB_LINK_LAYER_INFINIBAND; 135219820Sjeff case RDMA_TRANSPORT_IWARP: 136219820Sjeff return IB_LINK_LAYER_ETHERNET; 137278886Shselasky case RDMA_TRANSPORT_SCIF: 138278886Shselasky return IB_LINK_LAYER_SCIF; 139219820Sjeff default: 140219820Sjeff return IB_LINK_LAYER_UNSPECIFIED; 141219820Sjeff } 142219820Sjeff} 143219820SjeffEXPORT_SYMBOL(rdma_port_get_link_layer); 144219820Sjeff 145219820Sjeff/* Protection domains */ 146219820Sjeff 147219820Sjeffstruct ib_pd *ib_alloc_pd(struct ib_device *device) 148219820Sjeff{ 149219820Sjeff struct ib_pd *pd; 150219820Sjeff 151219820Sjeff pd = device->alloc_pd(device, NULL, NULL); 152219820Sjeff 153219820Sjeff if (!IS_ERR(pd)) { 154219820Sjeff pd->device = device; 155219820Sjeff pd->uobject = NULL; 156219820Sjeff atomic_set(&pd->usecnt, 0); 157219820Sjeff } 158219820Sjeff 159219820Sjeff return pd; 160219820Sjeff} 161219820SjeffEXPORT_SYMBOL(ib_alloc_pd); 162219820Sjeff 163219820Sjeffint ib_dealloc_pd(struct ib_pd *pd) 164219820Sjeff{ 165219820Sjeff if (atomic_read(&pd->usecnt)) 166219820Sjeff return -EBUSY; 167219820Sjeff 168219820Sjeff return pd->device->dealloc_pd(pd); 169219820Sjeff} 170219820SjeffEXPORT_SYMBOL(ib_dealloc_pd); 171219820Sjeff 172219820Sjeff/* Address handles */ 173219820Sjeff 174219820Sjeffstruct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) 175219820Sjeff{ 176219820Sjeff struct ib_ah *ah; 177219820Sjeff 178219820Sjeff ah = pd->device->create_ah(pd, ah_attr); 179219820Sjeff 180219820Sjeff if (!IS_ERR(ah)) { 181219820Sjeff ah->device = pd->device; 182219820Sjeff ah->pd = pd; 183219820Sjeff ah->uobject = NULL; 184219820Sjeff atomic_inc(&pd->usecnt); 185219820Sjeff } 186219820Sjeff 187219820Sjeff return ah; 188219820Sjeff} 189219820SjeffEXPORT_SYMBOL(ib_create_ah); 190219820Sjeff 191219820Sjeffint ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc, 192219820Sjeff struct ib_grh *grh, struct ib_ah_attr *ah_attr) 193219820Sjeff{ 194219820Sjeff u32 flow_class; 195219820Sjeff u16 gid_index; 196219820Sjeff int ret; 197278886Shselasky int is_eth = (rdma_port_get_link_layer(device, port_num) == 198278886Shselasky IB_LINK_LAYER_ETHERNET); 199219820Sjeff 200219820Sjeff memset(ah_attr, 0, sizeof *ah_attr); 201278886Shselasky if (is_eth) { 202278886Shselasky if (!(wc->wc_flags & IB_WC_GRH)) 203278886Shselasky return -EPROTOTYPE; 204278886Shselasky 205278886Shselasky if (wc->wc_flags & IB_WC_WITH_SMAC && 206278886Shselasky wc->wc_flags & IB_WC_WITH_VLAN) { 207278886Shselasky memcpy(ah_attr->dmac, wc->smac, ETH_ALEN); 208278886Shselasky ah_attr->vlan_id = wc->vlan_id; 209278886Shselasky } else { 210298486Shselasky u32 scope_id = rdma_get_ipv6_scope_id(device, port_num); 211278886Shselasky ret = rdma_addr_find_dmac_by_grh(&grh->dgid, &grh->sgid, 212298486Shselasky ah_attr->dmac, &ah_attr->vlan_id, 213298486Shselasky scope_id); 214278886Shselasky if (ret) 215278886Shselasky return ret; 216278886Shselasky } 217278886Shselasky } else { 218278886Shselasky ah_attr->vlan_id = 0xffff; 219278886Shselasky } 220278886Shselasky 221278886Shselasky 222219820Sjeff ah_attr->dlid = wc->slid; 223219820Sjeff ah_attr->sl = wc->sl; 224219820Sjeff ah_attr->src_path_bits = wc->dlid_path_bits; 225219820Sjeff ah_attr->port_num = port_num; 226219820Sjeff 227219820Sjeff if (wc->wc_flags & IB_WC_GRH) { 228219820Sjeff ah_attr->ah_flags = IB_AH_GRH; 229219820Sjeff ah_attr->grh.dgid = grh->sgid; 230219820Sjeff 231219820Sjeff ret = ib_find_cached_gid(device, &grh->dgid, &port_num, 232219820Sjeff &gid_index); 233219820Sjeff if (ret) 234219820Sjeff return ret; 235219820Sjeff 236219820Sjeff ah_attr->grh.sgid_index = (u8) gid_index; 237219820Sjeff flow_class = be32_to_cpu(grh->version_tclass_flow); 238219820Sjeff ah_attr->grh.flow_label = flow_class & 0xFFFFF; 239219820Sjeff ah_attr->grh.hop_limit = 0xFF; 240219820Sjeff ah_attr->grh.traffic_class = (flow_class >> 20) & 0xFF; 241219820Sjeff } 242219820Sjeff return 0; 243219820Sjeff} 244219820SjeffEXPORT_SYMBOL(ib_init_ah_from_wc); 245219820Sjeff 246219820Sjeffstruct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc, 247219820Sjeff struct ib_grh *grh, u8 port_num) 248219820Sjeff{ 249219820Sjeff struct ib_ah_attr ah_attr; 250219820Sjeff int ret; 251219820Sjeff 252219820Sjeff ret = ib_init_ah_from_wc(pd->device, port_num, wc, grh, &ah_attr); 253219820Sjeff if (ret) 254219820Sjeff return ERR_PTR(ret); 255219820Sjeff 256219820Sjeff return ib_create_ah(pd, &ah_attr); 257219820Sjeff} 258219820SjeffEXPORT_SYMBOL(ib_create_ah_from_wc); 259219820Sjeff 260219820Sjeffint ib_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) 261219820Sjeff{ 262219820Sjeff return ah->device->modify_ah ? 263219820Sjeff ah->device->modify_ah(ah, ah_attr) : 264219820Sjeff -ENOSYS; 265219820Sjeff} 266219820SjeffEXPORT_SYMBOL(ib_modify_ah); 267219820Sjeff 268219820Sjeffint ib_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) 269219820Sjeff{ 270219820Sjeff return ah->device->query_ah ? 271219820Sjeff ah->device->query_ah(ah, ah_attr) : 272219820Sjeff -ENOSYS; 273219820Sjeff} 274219820SjeffEXPORT_SYMBOL(ib_query_ah); 275219820Sjeff 276219820Sjeffint ib_destroy_ah(struct ib_ah *ah) 277219820Sjeff{ 278219820Sjeff struct ib_pd *pd; 279219820Sjeff int ret; 280219820Sjeff 281219820Sjeff pd = ah->pd; 282219820Sjeff ret = ah->device->destroy_ah(ah); 283219820Sjeff if (!ret) 284219820Sjeff atomic_dec(&pd->usecnt); 285219820Sjeff 286219820Sjeff return ret; 287219820Sjeff} 288219820SjeffEXPORT_SYMBOL(ib_destroy_ah); 289219820Sjeff 290219820Sjeff/* Shared receive queues */ 291219820Sjeff 292219820Sjeffstruct ib_srq *ib_create_srq(struct ib_pd *pd, 293219820Sjeff struct ib_srq_init_attr *srq_init_attr) 294219820Sjeff{ 295219820Sjeff struct ib_srq *srq; 296219820Sjeff 297219820Sjeff if (!pd->device->create_srq) 298219820Sjeff return ERR_PTR(-ENOSYS); 299219820Sjeff 300219820Sjeff srq = pd->device->create_srq(pd, srq_init_attr, NULL); 301219820Sjeff 302219820Sjeff if (!IS_ERR(srq)) { 303219820Sjeff srq->device = pd->device; 304219820Sjeff srq->pd = pd; 305219820Sjeff srq->uobject = NULL; 306219820Sjeff srq->event_handler = srq_init_attr->event_handler; 307219820Sjeff srq->srq_context = srq_init_attr->srq_context; 308278886Shselasky srq->srq_type = srq_init_attr->srq_type; 309278886Shselasky if (srq->srq_type == IB_SRQT_XRC) { 310278886Shselasky srq->ext.xrc.xrcd = srq_init_attr->ext.xrc.xrcd; 311278886Shselasky srq->ext.xrc.cq = srq_init_attr->ext.xrc.cq; 312278886Shselasky atomic_inc(&srq->ext.xrc.xrcd->usecnt); 313278886Shselasky atomic_inc(&srq->ext.xrc.cq->usecnt); 314278886Shselasky } 315219820Sjeff atomic_inc(&pd->usecnt); 316219820Sjeff atomic_set(&srq->usecnt, 0); 317219820Sjeff } 318219820Sjeff 319219820Sjeff return srq; 320219820Sjeff} 321219820SjeffEXPORT_SYMBOL(ib_create_srq); 322219820Sjeff 323219820Sjeffint ib_modify_srq(struct ib_srq *srq, 324219820Sjeff struct ib_srq_attr *srq_attr, 325219820Sjeff enum ib_srq_attr_mask srq_attr_mask) 326219820Sjeff{ 327219820Sjeff return srq->device->modify_srq ? 328219820Sjeff srq->device->modify_srq(srq, srq_attr, srq_attr_mask, NULL) : 329219820Sjeff -ENOSYS; 330219820Sjeff} 331219820SjeffEXPORT_SYMBOL(ib_modify_srq); 332219820Sjeff 333219820Sjeffint ib_query_srq(struct ib_srq *srq, 334219820Sjeff struct ib_srq_attr *srq_attr) 335219820Sjeff{ 336219820Sjeff return srq->device->query_srq ? 337219820Sjeff srq->device->query_srq(srq, srq_attr) : -ENOSYS; 338219820Sjeff} 339219820SjeffEXPORT_SYMBOL(ib_query_srq); 340219820Sjeff 341278886Shselaskyint ib_query_values(struct ib_device *device, 342278886Shselasky int q_values, struct ib_device_values *values) 343278886Shselasky{ 344278886Shselasky return device->query_values ? 345278886Shselasky device->query_values(device, q_values, values) : -ENOSYS; 346278886Shselasky} 347278886ShselaskyEXPORT_SYMBOL(ib_query_values); 348278886Shselasky 349219820Sjeffint ib_destroy_srq(struct ib_srq *srq) 350219820Sjeff{ 351219820Sjeff struct ib_pd *pd; 352278886Shselasky enum ib_srq_type srq_type; 353278886Shselasky struct ib_xrcd *uninitialized_var(xrcd); 354278886Shselasky struct ib_cq *uninitialized_var(cq); 355219820Sjeff int ret; 356219820Sjeff 357219820Sjeff if (atomic_read(&srq->usecnt)) 358219820Sjeff return -EBUSY; 359219820Sjeff 360219820Sjeff pd = srq->pd; 361278886Shselasky srq_type = srq->srq_type; 362278886Shselasky if (srq_type == IB_SRQT_XRC) { 363255932Salfred xrcd = srq->ext.xrc.xrcd; 364278886Shselasky cq = srq->ext.xrc.cq; 365278886Shselasky } 366219820Sjeff 367219820Sjeff ret = srq->device->destroy_srq(srq); 368219820Sjeff if (!ret) { 369219820Sjeff atomic_dec(&pd->usecnt); 370278886Shselasky if (srq_type == IB_SRQT_XRC) { 371219820Sjeff atomic_dec(&xrcd->usecnt); 372278886Shselasky atomic_dec(&cq->usecnt); 373278886Shselasky } 374219820Sjeff } 375219820Sjeff 376219820Sjeff return ret; 377219820Sjeff} 378219820SjeffEXPORT_SYMBOL(ib_destroy_srq); 379219820Sjeff 380219820Sjeff/* Queue pairs */ 381219820Sjeff 382278886Shselaskystatic void __ib_shared_qp_event_handler(struct ib_event *event, void *context) 383278886Shselasky{ 384278886Shselasky struct ib_qp *qp = context; 385278886Shselasky unsigned long flags; 386278886Shselasky 387278886Shselasky /* The code below must be synced with deletions of existing qps (ib_close_qp) -- 388278886Shselasky * because a qp from the list may be closed during the scan, resulting in a kernel Oops. 389278886Shselasky */ 390278886Shselasky spin_lock_irqsave(&qp->device->event_handler_lock, flags); 391278886Shselasky list_for_each_entry(event->element.qp, &qp->open_list, open_list) 392278886Shselasky if (event->element.qp->event_handler) 393278886Shselasky event->element.qp->event_handler(event, event->element.qp->qp_context); 394278886Shselasky spin_unlock_irqrestore(&qp->device->event_handler_lock, flags); 395278886Shselasky} 396278886Shselasky 397278886Shselaskystatic void __ib_insert_xrcd_qp(struct ib_xrcd *xrcd, struct ib_qp *qp) 398278886Shselasky{ 399278886Shselasky mutex_lock(&xrcd->tgt_qp_mutex); 400278886Shselasky list_add(&qp->xrcd_list, &xrcd->tgt_qp_list); 401278886Shselasky mutex_unlock(&xrcd->tgt_qp_mutex); 402278886Shselasky} 403278886Shselasky 404278886Shselaskystatic struct ib_qp *__ib_open_qp(struct ib_qp *real_qp, 405278886Shselasky void (*event_handler)(struct ib_event *, void *), 406278886Shselasky void *qp_context) 407278886Shselasky{ 408278886Shselasky struct ib_qp *qp; 409278886Shselasky unsigned long flags; 410278886Shselasky 411278886Shselasky qp = kzalloc(sizeof *qp, GFP_KERNEL); 412278886Shselasky if (!qp) 413278886Shselasky return ERR_PTR(-ENOMEM); 414278886Shselasky 415278886Shselasky qp->real_qp = real_qp; 416278886Shselasky atomic_inc(&real_qp->usecnt); 417278886Shselasky qp->device = real_qp->device; 418278886Shselasky qp->event_handler = event_handler; 419278886Shselasky qp->qp_context = qp_context; 420278886Shselasky qp->qp_num = real_qp->qp_num; 421278886Shselasky qp->qp_type = real_qp->qp_type; 422278886Shselasky 423278886Shselasky spin_lock_irqsave(&real_qp->device->event_handler_lock, flags); 424278886Shselasky list_add(&qp->open_list, &real_qp->open_list); 425278886Shselasky spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags); 426278886Shselasky 427278886Shselasky return qp; 428278886Shselasky} 429278886Shselasky 430278886Shselaskystruct ib_qp *ib_open_qp(struct ib_xrcd *xrcd, 431278886Shselasky struct ib_qp_open_attr *qp_open_attr) 432278886Shselasky{ 433278886Shselasky struct ib_qp *qp, *real_qp; 434278886Shselasky 435278886Shselasky if (qp_open_attr->qp_type != IB_QPT_XRC_TGT) 436278886Shselasky return ERR_PTR(-EINVAL); 437278886Shselasky 438278886Shselasky qp = ERR_PTR(-EINVAL); 439278886Shselasky mutex_lock(&xrcd->tgt_qp_mutex); 440278886Shselasky list_for_each_entry(real_qp, &xrcd->tgt_qp_list, xrcd_list) { 441278886Shselasky if (real_qp->qp_num == qp_open_attr->qp_num) { 442278886Shselasky qp = __ib_open_qp(real_qp, qp_open_attr->event_handler, 443278886Shselasky qp_open_attr->qp_context); 444278886Shselasky break; 445278886Shselasky } 446278886Shselasky } 447278886Shselasky mutex_unlock(&xrcd->tgt_qp_mutex); 448278886Shselasky return qp; 449278886Shselasky} 450278886ShselaskyEXPORT_SYMBOL(ib_open_qp); 451278886Shselasky 452219820Sjeffstruct ib_qp *ib_create_qp(struct ib_pd *pd, 453219820Sjeff struct ib_qp_init_attr *qp_init_attr) 454219820Sjeff{ 455278886Shselasky struct ib_qp *qp, *real_qp; 456278886Shselasky struct ib_device *device; 457219820Sjeff 458278886Shselasky device = pd ? pd->device : qp_init_attr->xrcd->device; 459278886Shselasky qp = device->create_qp(pd, qp_init_attr, NULL); 460219820Sjeff 461219820Sjeff if (!IS_ERR(qp)) { 462278886Shselasky qp->device = device; 463278886Shselasky qp->real_qp = qp; 464219820Sjeff qp->uobject = NULL; 465278886Shselasky qp->qp_type = qp_init_attr->qp_type; 466278886Shselasky 467278886Shselasky atomic_set(&qp->usecnt, 0); 468278886Shselasky if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) { 469278886Shselasky qp->event_handler = __ib_shared_qp_event_handler; 470278886Shselasky qp->qp_context = qp; 471278886Shselasky qp->pd = NULL; 472278886Shselasky qp->send_cq = qp->recv_cq = NULL; 473278886Shselasky qp->srq = NULL; 474278886Shselasky qp->xrcd = qp_init_attr->xrcd; 475278886Shselasky atomic_inc(&qp_init_attr->xrcd->usecnt); 476278886Shselasky INIT_LIST_HEAD(&qp->open_list); 477278886Shselasky 478278886Shselasky real_qp = qp; 479278886Shselasky qp = __ib_open_qp(real_qp, qp_init_attr->event_handler, 480278886Shselasky qp_init_attr->qp_context); 481278886Shselasky if (!IS_ERR(qp)) 482278886Shselasky __ib_insert_xrcd_qp(qp_init_attr->xrcd, real_qp); 483278886Shselasky else 484278886Shselasky real_qp->device->destroy_qp(real_qp); 485278886Shselasky } else { 486219820Sjeff qp->event_handler = qp_init_attr->event_handler; 487219820Sjeff qp->qp_context = qp_init_attr->qp_context; 488278886Shselasky if (qp_init_attr->qp_type == IB_QPT_XRC_INI) { 489278886Shselasky qp->recv_cq = NULL; 490278886Shselasky qp->srq = NULL; 491278886Shselasky } else { 492278886Shselasky qp->recv_cq = qp_init_attr->recv_cq; 493219820Sjeff atomic_inc(&qp_init_attr->recv_cq->usecnt); 494278886Shselasky qp->srq = qp_init_attr->srq; 495278886Shselasky if (qp->srq) 496219820Sjeff atomic_inc(&qp_init_attr->srq->usecnt); 497278886Shselasky } 498278886Shselasky 499278886Shselasky qp->pd = pd; 500278886Shselasky qp->send_cq = qp_init_attr->send_cq; 501278886Shselasky qp->xrcd = NULL; 502278886Shselasky 503278886Shselasky atomic_inc(&pd->usecnt); 504278886Shselasky atomic_inc(&qp_init_attr->send_cq->usecnt); 505278886Shselasky } 506219820Sjeff } 507219820Sjeff 508219820Sjeff return qp; 509219820Sjeff} 510219820SjeffEXPORT_SYMBOL(ib_create_qp); 511219820Sjeff 512219820Sjeffstatic const struct { 513219820Sjeff int valid; 514278886Shselasky enum ib_qp_attr_mask req_param[IB_QPT_MAX]; 515278886Shselasky enum ib_qp_attr_mask req_param_add_eth[IB_QPT_MAX]; 516278886Shselasky enum ib_qp_attr_mask opt_param[IB_QPT_MAX]; 517278886Shselasky enum ib_qp_attr_mask opt_param_add_eth[IB_QPT_MAX]; 518219820Sjeff} qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = { 519219820Sjeff [IB_QPS_RESET] = { 520219820Sjeff [IB_QPS_RESET] = { .valid = 1 }, 521219820Sjeff [IB_QPS_INIT] = { 522219820Sjeff .valid = 1, 523219820Sjeff .req_param = { 524219820Sjeff [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 525219820Sjeff IB_QP_PORT | 526219820Sjeff IB_QP_QKEY), 527255932Salfred [IB_QPT_RAW_PACKET] = IB_QP_PORT, 528219820Sjeff [IB_QPT_UC] = (IB_QP_PKEY_INDEX | 529219820Sjeff IB_QP_PORT | 530219820Sjeff IB_QP_ACCESS_FLAGS), 531219820Sjeff [IB_QPT_RC] = (IB_QP_PKEY_INDEX | 532219820Sjeff IB_QP_PORT | 533219820Sjeff IB_QP_ACCESS_FLAGS), 534278886Shselasky [IB_QPT_DC_INI] = (IB_QP_PKEY_INDEX | 535278886Shselasky IB_QP_PORT | 536278886Shselasky IB_QP_ACCESS_FLAGS | 537278886Shselasky IB_QP_DC_KEY), 538278886Shselasky [IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX | 539278886Shselasky IB_QP_PORT | 540278886Shselasky IB_QP_ACCESS_FLAGS), 541278886Shselasky [IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX | 542219820Sjeff IB_QP_PORT | 543219820Sjeff IB_QP_ACCESS_FLAGS), 544219820Sjeff [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 545219820Sjeff IB_QP_QKEY), 546219820Sjeff [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 547219820Sjeff IB_QP_QKEY), 548278886Shselasky }, 549278886Shselasky .opt_param = { 550278886Shselasky [IB_QPT_UD] = IB_QP_GROUP_RSS, 551278886Shselasky [IB_QPT_RAW_PACKET] = IB_QP_GROUP_RSS 552219820Sjeff } 553219820Sjeff }, 554219820Sjeff }, 555219820Sjeff [IB_QPS_INIT] = { 556219820Sjeff [IB_QPS_RESET] = { .valid = 1 }, 557219820Sjeff [IB_QPS_ERR] = { .valid = 1 }, 558219820Sjeff [IB_QPS_INIT] = { 559219820Sjeff .valid = 1, 560219820Sjeff .opt_param = { 561219820Sjeff [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 562219820Sjeff IB_QP_PORT | 563219820Sjeff IB_QP_QKEY), 564219820Sjeff [IB_QPT_UC] = (IB_QP_PKEY_INDEX | 565219820Sjeff IB_QP_PORT | 566219820Sjeff IB_QP_ACCESS_FLAGS), 567219820Sjeff [IB_QPT_RC] = (IB_QP_PKEY_INDEX | 568219820Sjeff IB_QP_PORT | 569219820Sjeff IB_QP_ACCESS_FLAGS), 570278886Shselasky [IB_QPT_DC_INI] = (IB_QP_PKEY_INDEX | 571278886Shselasky IB_QP_PORT | 572278886Shselasky IB_QP_ACCESS_FLAGS), 573278886Shselasky [IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX | 574219820Sjeff IB_QP_PORT | 575219820Sjeff IB_QP_ACCESS_FLAGS), 576278886Shselasky [IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX | 577278886Shselasky IB_QP_PORT | 578278886Shselasky IB_QP_ACCESS_FLAGS), 579219820Sjeff [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 580219820Sjeff IB_QP_QKEY), 581219820Sjeff [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 582219820Sjeff IB_QP_QKEY), 583219820Sjeff } 584219820Sjeff }, 585219820Sjeff [IB_QPS_RTR] = { 586219820Sjeff .valid = 1, 587219820Sjeff .req_param = { 588219820Sjeff [IB_QPT_UC] = (IB_QP_AV | 589219820Sjeff IB_QP_PATH_MTU | 590219820Sjeff IB_QP_DEST_QPN | 591219820Sjeff IB_QP_RQ_PSN), 592219820Sjeff [IB_QPT_RC] = (IB_QP_AV | 593219820Sjeff IB_QP_PATH_MTU | 594219820Sjeff IB_QP_DEST_QPN | 595219820Sjeff IB_QP_RQ_PSN | 596219820Sjeff IB_QP_MAX_DEST_RD_ATOMIC | 597219820Sjeff IB_QP_MIN_RNR_TIMER), 598278886Shselasky [IB_QPT_DC_INI] = (IB_QP_PATH_MTU | 599278886Shselasky IB_QP_MAX_DEST_RD_ATOMIC | 600278886Shselasky IB_QP_MIN_RNR_TIMER), 601278886Shselasky [IB_QPT_XRC_INI] = (IB_QP_AV | 602219820Sjeff IB_QP_PATH_MTU | 603219820Sjeff IB_QP_DEST_QPN | 604278886Shselasky IB_QP_RQ_PSN), 605278886Shselasky [IB_QPT_XRC_TGT] = (IB_QP_AV | 606278886Shselasky IB_QP_PATH_MTU | 607278886Shselasky IB_QP_DEST_QPN | 608219820Sjeff IB_QP_RQ_PSN | 609219820Sjeff IB_QP_MAX_DEST_RD_ATOMIC | 610219820Sjeff IB_QP_MIN_RNR_TIMER), 611219820Sjeff }, 612278886Shselasky .req_param_add_eth = { 613278886Shselasky [IB_QPT_RC] = (IB_QP_SMAC), 614278886Shselasky [IB_QPT_UC] = (IB_QP_SMAC), 615278886Shselasky [IB_QPT_XRC_INI] = (IB_QP_SMAC), 616278886Shselasky [IB_QPT_XRC_TGT] = (IB_QP_SMAC) 617278886Shselasky }, 618219820Sjeff .opt_param = { 619219820Sjeff [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 620219820Sjeff IB_QP_QKEY), 621219820Sjeff [IB_QPT_UC] = (IB_QP_ALT_PATH | 622219820Sjeff IB_QP_ACCESS_FLAGS | 623219820Sjeff IB_QP_PKEY_INDEX), 624219820Sjeff [IB_QPT_RC] = (IB_QP_ALT_PATH | 625219820Sjeff IB_QP_ACCESS_FLAGS | 626219820Sjeff IB_QP_PKEY_INDEX), 627278886Shselasky [IB_QPT_DC_INI] = (IB_QP_ALT_PATH | 628278886Shselasky IB_QP_ACCESS_FLAGS | 629278886Shselasky IB_QP_PKEY_INDEX), 630278886Shselasky [IB_QPT_XRC_INI] = (IB_QP_ALT_PATH | 631278886Shselasky IB_QP_ACCESS_FLAGS | 632278886Shselasky IB_QP_PKEY_INDEX), 633278886Shselasky [IB_QPT_XRC_TGT] = (IB_QP_ALT_PATH | 634219820Sjeff IB_QP_ACCESS_FLAGS | 635219820Sjeff IB_QP_PKEY_INDEX), 636219820Sjeff [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 637219820Sjeff IB_QP_QKEY), 638219820Sjeff [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 639219820Sjeff IB_QP_QKEY), 640278886Shselasky [IB_QPT_RAW_PACKET] = IB_QP_AV, 641278886Shselasky }, 642278886Shselasky .opt_param_add_eth = { 643278886Shselasky [IB_QPT_RC] = (IB_QP_ALT_SMAC | 644278886Shselasky IB_QP_VID | 645278886Shselasky IB_QP_ALT_VID), 646278886Shselasky [IB_QPT_UC] = (IB_QP_ALT_SMAC | 647278886Shselasky IB_QP_VID | 648278886Shselasky IB_QP_ALT_VID), 649278886Shselasky [IB_QPT_XRC_INI] = (IB_QP_ALT_SMAC | 650278886Shselasky IB_QP_VID | 651278886Shselasky IB_QP_ALT_VID), 652278886Shselasky [IB_QPT_XRC_TGT] = (IB_QP_ALT_SMAC | 653278886Shselasky IB_QP_VID | 654278886Shselasky IB_QP_ALT_VID) 655219820Sjeff } 656219820Sjeff } 657219820Sjeff }, 658219820Sjeff [IB_QPS_RTR] = { 659219820Sjeff [IB_QPS_RESET] = { .valid = 1 }, 660219820Sjeff [IB_QPS_ERR] = { .valid = 1 }, 661219820Sjeff [IB_QPS_RTS] = { 662219820Sjeff .valid = 1, 663219820Sjeff .req_param = { 664219820Sjeff [IB_QPT_UD] = IB_QP_SQ_PSN, 665219820Sjeff [IB_QPT_UC] = IB_QP_SQ_PSN, 666219820Sjeff [IB_QPT_RC] = (IB_QP_TIMEOUT | 667219820Sjeff IB_QP_RETRY_CNT | 668219820Sjeff IB_QP_RNR_RETRY | 669219820Sjeff IB_QP_SQ_PSN | 670219820Sjeff IB_QP_MAX_QP_RD_ATOMIC), 671278886Shselasky [IB_QPT_DC_INI] = (IB_QP_TIMEOUT | 672278886Shselasky IB_QP_RETRY_CNT | 673278886Shselasky IB_QP_RNR_RETRY | 674278886Shselasky IB_QP_MAX_QP_RD_ATOMIC), 675278886Shselasky [IB_QPT_XRC_INI] = (IB_QP_TIMEOUT | 676219820Sjeff IB_QP_RETRY_CNT | 677219820Sjeff IB_QP_RNR_RETRY | 678219820Sjeff IB_QP_SQ_PSN | 679219820Sjeff IB_QP_MAX_QP_RD_ATOMIC), 680278886Shselasky [IB_QPT_XRC_TGT] = (IB_QP_TIMEOUT | 681278886Shselasky IB_QP_SQ_PSN), 682219820Sjeff [IB_QPT_SMI] = IB_QP_SQ_PSN, 683219820Sjeff [IB_QPT_GSI] = IB_QP_SQ_PSN, 684219820Sjeff }, 685219820Sjeff .opt_param = { 686219820Sjeff [IB_QPT_UD] = (IB_QP_CUR_STATE | 687219820Sjeff IB_QP_QKEY), 688219820Sjeff [IB_QPT_UC] = (IB_QP_CUR_STATE | 689219820Sjeff IB_QP_ALT_PATH | 690219820Sjeff IB_QP_ACCESS_FLAGS | 691219820Sjeff IB_QP_PATH_MIG_STATE), 692219820Sjeff [IB_QPT_RC] = (IB_QP_CUR_STATE | 693219820Sjeff IB_QP_ALT_PATH | 694219820Sjeff IB_QP_ACCESS_FLAGS | 695219820Sjeff IB_QP_MIN_RNR_TIMER | 696219820Sjeff IB_QP_PATH_MIG_STATE), 697278886Shselasky [IB_QPT_DC_INI] = (IB_QP_CUR_STATE | 698278886Shselasky IB_QP_ALT_PATH | 699278886Shselasky IB_QP_ACCESS_FLAGS | 700278886Shselasky IB_QP_MIN_RNR_TIMER | 701278886Shselasky IB_QP_PATH_MIG_STATE), 702278886Shselasky [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE | 703278886Shselasky IB_QP_ALT_PATH | 704278886Shselasky IB_QP_ACCESS_FLAGS | 705278886Shselasky IB_QP_PATH_MIG_STATE), 706278886Shselasky [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE | 707219820Sjeff IB_QP_ALT_PATH | 708219820Sjeff IB_QP_ACCESS_FLAGS | 709219820Sjeff IB_QP_MIN_RNR_TIMER | 710219820Sjeff IB_QP_PATH_MIG_STATE), 711219820Sjeff [IB_QPT_SMI] = (IB_QP_CUR_STATE | 712219820Sjeff IB_QP_QKEY), 713219820Sjeff [IB_QPT_GSI] = (IB_QP_CUR_STATE | 714219820Sjeff IB_QP_QKEY), 715219820Sjeff } 716219820Sjeff } 717219820Sjeff }, 718219820Sjeff [IB_QPS_RTS] = { 719219820Sjeff [IB_QPS_RESET] = { .valid = 1 }, 720219820Sjeff [IB_QPS_ERR] = { .valid = 1 }, 721219820Sjeff [IB_QPS_RTS] = { 722219820Sjeff .valid = 1, 723219820Sjeff .opt_param = { 724219820Sjeff [IB_QPT_UD] = (IB_QP_CUR_STATE | 725219820Sjeff IB_QP_QKEY), 726219820Sjeff [IB_QPT_UC] = (IB_QP_CUR_STATE | 727219820Sjeff IB_QP_ACCESS_FLAGS | 728219820Sjeff IB_QP_ALT_PATH | 729219820Sjeff IB_QP_PATH_MIG_STATE), 730219820Sjeff [IB_QPT_RC] = (IB_QP_CUR_STATE | 731219820Sjeff IB_QP_ACCESS_FLAGS | 732219820Sjeff IB_QP_ALT_PATH | 733219820Sjeff IB_QP_PATH_MIG_STATE | 734219820Sjeff IB_QP_MIN_RNR_TIMER), 735278886Shselasky [IB_QPT_DC_INI] = (IB_QP_CUR_STATE | 736278886Shselasky IB_QP_ACCESS_FLAGS | 737278886Shselasky IB_QP_ALT_PATH | 738278886Shselasky IB_QP_PATH_MIG_STATE | 739278886Shselasky IB_QP_MIN_RNR_TIMER), 740278886Shselasky [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE | 741219820Sjeff IB_QP_ACCESS_FLAGS | 742219820Sjeff IB_QP_ALT_PATH | 743278886Shselasky IB_QP_PATH_MIG_STATE), 744278886Shselasky [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE | 745278886Shselasky IB_QP_ACCESS_FLAGS | 746278886Shselasky IB_QP_ALT_PATH | 747219820Sjeff IB_QP_PATH_MIG_STATE | 748219820Sjeff IB_QP_MIN_RNR_TIMER), 749219820Sjeff [IB_QPT_SMI] = (IB_QP_CUR_STATE | 750219820Sjeff IB_QP_QKEY), 751219820Sjeff [IB_QPT_GSI] = (IB_QP_CUR_STATE | 752219820Sjeff IB_QP_QKEY), 753219820Sjeff } 754219820Sjeff }, 755219820Sjeff [IB_QPS_SQD] = { 756219820Sjeff .valid = 1, 757219820Sjeff .opt_param = { 758219820Sjeff [IB_QPT_UD] = IB_QP_EN_SQD_ASYNC_NOTIFY, 759219820Sjeff [IB_QPT_UC] = IB_QP_EN_SQD_ASYNC_NOTIFY, 760219820Sjeff [IB_QPT_RC] = IB_QP_EN_SQD_ASYNC_NOTIFY, 761278886Shselasky [IB_QPT_XRC_INI] = IB_QP_EN_SQD_ASYNC_NOTIFY, 762278886Shselasky [IB_QPT_XRC_TGT] = IB_QP_EN_SQD_ASYNC_NOTIFY, /* ??? */ 763219820Sjeff [IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY, 764219820Sjeff [IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY 765219820Sjeff } 766219820Sjeff }, 767219820Sjeff }, 768219820Sjeff [IB_QPS_SQD] = { 769219820Sjeff [IB_QPS_RESET] = { .valid = 1 }, 770219820Sjeff [IB_QPS_ERR] = { .valid = 1 }, 771219820Sjeff [IB_QPS_RTS] = { 772219820Sjeff .valid = 1, 773219820Sjeff .opt_param = { 774219820Sjeff [IB_QPT_UD] = (IB_QP_CUR_STATE | 775219820Sjeff IB_QP_QKEY), 776219820Sjeff [IB_QPT_UC] = (IB_QP_CUR_STATE | 777219820Sjeff IB_QP_ALT_PATH | 778219820Sjeff IB_QP_ACCESS_FLAGS | 779219820Sjeff IB_QP_PATH_MIG_STATE), 780219820Sjeff [IB_QPT_RC] = (IB_QP_CUR_STATE | 781219820Sjeff IB_QP_ALT_PATH | 782219820Sjeff IB_QP_ACCESS_FLAGS | 783219820Sjeff IB_QP_MIN_RNR_TIMER | 784219820Sjeff IB_QP_PATH_MIG_STATE), 785278886Shselasky [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE | 786219820Sjeff IB_QP_ALT_PATH | 787219820Sjeff IB_QP_ACCESS_FLAGS | 788278886Shselasky IB_QP_PATH_MIG_STATE), 789278886Shselasky [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE | 790278886Shselasky IB_QP_ALT_PATH | 791278886Shselasky IB_QP_ACCESS_FLAGS | 792219820Sjeff IB_QP_MIN_RNR_TIMER | 793219820Sjeff IB_QP_PATH_MIG_STATE), 794219820Sjeff [IB_QPT_SMI] = (IB_QP_CUR_STATE | 795219820Sjeff IB_QP_QKEY), 796219820Sjeff [IB_QPT_GSI] = (IB_QP_CUR_STATE | 797219820Sjeff IB_QP_QKEY), 798219820Sjeff } 799219820Sjeff }, 800219820Sjeff [IB_QPS_SQD] = { 801219820Sjeff .valid = 1, 802219820Sjeff .opt_param = { 803219820Sjeff [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 804219820Sjeff IB_QP_QKEY), 805219820Sjeff [IB_QPT_UC] = (IB_QP_AV | 806219820Sjeff IB_QP_ALT_PATH | 807219820Sjeff IB_QP_ACCESS_FLAGS | 808219820Sjeff IB_QP_PKEY_INDEX | 809219820Sjeff IB_QP_PATH_MIG_STATE), 810219820Sjeff [IB_QPT_RC] = (IB_QP_PORT | 811219820Sjeff IB_QP_AV | 812219820Sjeff IB_QP_TIMEOUT | 813219820Sjeff IB_QP_RETRY_CNT | 814219820Sjeff IB_QP_RNR_RETRY | 815219820Sjeff IB_QP_MAX_QP_RD_ATOMIC | 816219820Sjeff IB_QP_MAX_DEST_RD_ATOMIC | 817219820Sjeff IB_QP_ALT_PATH | 818219820Sjeff IB_QP_ACCESS_FLAGS | 819219820Sjeff IB_QP_PKEY_INDEX | 820219820Sjeff IB_QP_MIN_RNR_TIMER | 821219820Sjeff IB_QP_PATH_MIG_STATE), 822278886Shselasky [IB_QPT_XRC_INI] = (IB_QP_PORT | 823219820Sjeff IB_QP_AV | 824219820Sjeff IB_QP_TIMEOUT | 825219820Sjeff IB_QP_RETRY_CNT | 826219820Sjeff IB_QP_RNR_RETRY | 827219820Sjeff IB_QP_MAX_QP_RD_ATOMIC | 828278886Shselasky IB_QP_ALT_PATH | 829278886Shselasky IB_QP_ACCESS_FLAGS | 830278886Shselasky IB_QP_PKEY_INDEX | 831278886Shselasky IB_QP_PATH_MIG_STATE), 832278886Shselasky [IB_QPT_XRC_TGT] = (IB_QP_PORT | 833278886Shselasky IB_QP_AV | 834278886Shselasky IB_QP_TIMEOUT | 835219820Sjeff IB_QP_MAX_DEST_RD_ATOMIC | 836219820Sjeff IB_QP_ALT_PATH | 837219820Sjeff IB_QP_ACCESS_FLAGS | 838219820Sjeff IB_QP_PKEY_INDEX | 839219820Sjeff IB_QP_MIN_RNR_TIMER | 840219820Sjeff IB_QP_PATH_MIG_STATE), 841219820Sjeff [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 842219820Sjeff IB_QP_QKEY), 843219820Sjeff [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 844219820Sjeff IB_QP_QKEY), 845219820Sjeff } 846219820Sjeff } 847219820Sjeff }, 848219820Sjeff [IB_QPS_SQE] = { 849219820Sjeff [IB_QPS_RESET] = { .valid = 1 }, 850219820Sjeff [IB_QPS_ERR] = { .valid = 1 }, 851219820Sjeff [IB_QPS_RTS] = { 852219820Sjeff .valid = 1, 853219820Sjeff .opt_param = { 854219820Sjeff [IB_QPT_UD] = (IB_QP_CUR_STATE | 855219820Sjeff IB_QP_QKEY), 856219820Sjeff [IB_QPT_UC] = (IB_QP_CUR_STATE | 857219820Sjeff IB_QP_ACCESS_FLAGS), 858219820Sjeff [IB_QPT_SMI] = (IB_QP_CUR_STATE | 859219820Sjeff IB_QP_QKEY), 860219820Sjeff [IB_QPT_GSI] = (IB_QP_CUR_STATE | 861219820Sjeff IB_QP_QKEY), 862219820Sjeff } 863219820Sjeff } 864219820Sjeff }, 865219820Sjeff [IB_QPS_ERR] = { 866219820Sjeff [IB_QPS_RESET] = { .valid = 1 }, 867219820Sjeff [IB_QPS_ERR] = { .valid = 1 } 868219820Sjeff } 869219820Sjeff}; 870219820Sjeff 871219820Sjeffint ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state, 872278886Shselasky enum ib_qp_type type, enum ib_qp_attr_mask mask, 873278886Shselasky enum rdma_link_layer ll) 874219820Sjeff{ 875219820Sjeff enum ib_qp_attr_mask req_param, opt_param; 876219820Sjeff 877219820Sjeff if (cur_state < 0 || cur_state > IB_QPS_ERR || 878219820Sjeff next_state < 0 || next_state > IB_QPS_ERR) 879219820Sjeff return 0; 880219820Sjeff 881219820Sjeff if (mask & IB_QP_CUR_STATE && 882219820Sjeff cur_state != IB_QPS_RTR && cur_state != IB_QPS_RTS && 883219820Sjeff cur_state != IB_QPS_SQD && cur_state != IB_QPS_SQE) 884219820Sjeff return 0; 885219820Sjeff 886219820Sjeff if (!qp_state_table[cur_state][next_state].valid) 887219820Sjeff return 0; 888219820Sjeff 889219820Sjeff req_param = qp_state_table[cur_state][next_state].req_param[type]; 890219820Sjeff opt_param = qp_state_table[cur_state][next_state].opt_param[type]; 891219820Sjeff 892278886Shselasky if (ll == IB_LINK_LAYER_ETHERNET) { 893278886Shselasky req_param |= qp_state_table[cur_state][next_state]. 894278886Shselasky req_param_add_eth[type]; 895278886Shselasky opt_param |= qp_state_table[cur_state][next_state]. 896278886Shselasky opt_param_add_eth[type]; 897278886Shselasky } 898278886Shselasky 899219820Sjeff if ((mask & req_param) != req_param) 900219820Sjeff return 0; 901219820Sjeff 902219820Sjeff if (mask & ~(req_param | opt_param | IB_QP_STATE)) 903219820Sjeff return 0; 904219820Sjeff 905219820Sjeff return 1; 906219820Sjeff} 907219820SjeffEXPORT_SYMBOL(ib_modify_qp_is_ok); 908219820Sjeff 909219820Sjeffint ib_modify_qp(struct ib_qp *qp, 910219820Sjeff struct ib_qp_attr *qp_attr, 911219820Sjeff int qp_attr_mask) 912219820Sjeff{ 913278886Shselasky int ret; 914278886Shselasky 915278886Shselasky ret = qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL); 916278886Shselasky if (!ret && (qp_attr_mask & IB_QP_PORT)) 917278886Shselasky qp->port_num = qp_attr->port_num; 918278886Shselasky 919278886Shselasky return ret; 920219820Sjeff} 921219820SjeffEXPORT_SYMBOL(ib_modify_qp); 922219820Sjeff 923219820Sjeffint ib_query_qp(struct ib_qp *qp, 924219820Sjeff struct ib_qp_attr *qp_attr, 925219820Sjeff int qp_attr_mask, 926219820Sjeff struct ib_qp_init_attr *qp_init_attr) 927219820Sjeff{ 928219820Sjeff return qp->device->query_qp ? 929278886Shselasky qp->device->query_qp(qp->real_qp, qp_attr, qp_attr_mask, qp_init_attr) : 930219820Sjeff -ENOSYS; 931219820Sjeff} 932219820SjeffEXPORT_SYMBOL(ib_query_qp); 933219820Sjeff 934278886Shselaskyint ib_close_qp(struct ib_qp *qp) 935278886Shselasky{ 936278886Shselasky struct ib_qp *real_qp; 937278886Shselasky unsigned long flags; 938278886Shselasky 939278886Shselasky real_qp = qp->real_qp; 940278886Shselasky if (real_qp == qp) 941278886Shselasky return -EINVAL; 942278886Shselasky 943278886Shselasky spin_lock_irqsave(&real_qp->device->event_handler_lock, flags); 944278886Shselasky list_del(&qp->open_list); 945278886Shselasky spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags); 946278886Shselasky 947278886Shselasky atomic_dec(&real_qp->usecnt); 948278886Shselasky kfree(qp); 949278886Shselasky 950278886Shselasky return 0; 951278886Shselasky} 952278886ShselaskyEXPORT_SYMBOL(ib_close_qp); 953278886Shselasky 954278886Shselaskystatic int __ib_destroy_shared_qp(struct ib_qp *qp) 955278886Shselasky{ 956278886Shselasky struct ib_xrcd *xrcd; 957278886Shselasky struct ib_qp *real_qp; 958278886Shselasky int ret; 959278886Shselasky 960278886Shselasky real_qp = qp->real_qp; 961278886Shselasky xrcd = real_qp->xrcd; 962278886Shselasky 963278886Shselasky mutex_lock(&xrcd->tgt_qp_mutex); 964278886Shselasky ib_close_qp(qp); 965278886Shselasky if (atomic_read(&real_qp->usecnt) == 0) 966278886Shselasky list_del(&real_qp->xrcd_list); 967278886Shselasky else 968278886Shselasky real_qp = NULL; 969278886Shselasky mutex_unlock(&xrcd->tgt_qp_mutex); 970278886Shselasky 971278886Shselasky if (real_qp) { 972278886Shselasky ret = ib_destroy_qp(real_qp); 973278886Shselasky if (!ret) 974278886Shselasky atomic_dec(&xrcd->usecnt); 975278886Shselasky else 976278886Shselasky __ib_insert_xrcd_qp(xrcd, real_qp); 977278886Shselasky } 978278886Shselasky 979278886Shselasky return 0; 980278886Shselasky} 981278886Shselasky 982219820Sjeffint ib_destroy_qp(struct ib_qp *qp) 983219820Sjeff{ 984219820Sjeff struct ib_pd *pd; 985219820Sjeff struct ib_cq *scq, *rcq; 986219820Sjeff struct ib_srq *srq; 987219820Sjeff int ret; 988219820Sjeff 989278886Shselasky if (atomic_read(&qp->usecnt)) 990278886Shselasky return -EBUSY; 991278886Shselasky 992278886Shselasky if (qp->real_qp != qp) 993278886Shselasky return __ib_destroy_shared_qp(qp); 994278886Shselasky 995219820Sjeff pd = qp->pd; 996219820Sjeff scq = qp->send_cq; 997219820Sjeff rcq = qp->recv_cq; 998219820Sjeff srq = qp->srq; 999219820Sjeff 1000219820Sjeff ret = qp->device->destroy_qp(qp); 1001219820Sjeff if (!ret) { 1002278886Shselasky if (pd) 1003219820Sjeff atomic_dec(&pd->usecnt); 1004278886Shselasky if (scq) 1005219820Sjeff atomic_dec(&scq->usecnt); 1006278886Shselasky if (rcq) 1007219820Sjeff atomic_dec(&rcq->usecnt); 1008219820Sjeff if (srq) 1009219820Sjeff atomic_dec(&srq->usecnt); 1010219820Sjeff } 1011219820Sjeff 1012219820Sjeff return ret; 1013219820Sjeff} 1014219820SjeffEXPORT_SYMBOL(ib_destroy_qp); 1015219820Sjeff 1016219820Sjeff/* Completion queues */ 1017219820Sjeff 1018219820Sjeffstruct ib_cq *ib_create_cq(struct ib_device *device, 1019219820Sjeff ib_comp_handler comp_handler, 1020219820Sjeff void (*event_handler)(struct ib_event *, void *), 1021219820Sjeff void *cq_context, int cqe, int comp_vector) 1022219820Sjeff{ 1023219820Sjeff struct ib_cq *cq; 1024278886Shselasky struct ib_cq_init_attr attr = { 1025278886Shselasky .cqe = cqe, 1026278886Shselasky .comp_vector = comp_vector, 1027278886Shselasky .flags = 0, 1028278886Shselasky }; 1029219820Sjeff 1030278886Shselasky cq = device->create_cq(device, &attr, NULL, NULL); 1031219820Sjeff 1032219820Sjeff if (!IS_ERR(cq)) { 1033219820Sjeff cq->device = device; 1034219820Sjeff cq->uobject = NULL; 1035219820Sjeff cq->comp_handler = comp_handler; 1036219820Sjeff cq->event_handler = event_handler; 1037219820Sjeff cq->cq_context = cq_context; 1038219820Sjeff atomic_set(&cq->usecnt, 0); 1039219820Sjeff } 1040219820Sjeff 1041219820Sjeff return cq; 1042219820Sjeff} 1043219820SjeffEXPORT_SYMBOL(ib_create_cq); 1044219820Sjeff 1045278886Shselaskyint ib_modify_cq(struct ib_cq *cq, 1046278886Shselasky struct ib_cq_attr *cq_attr, 1047278886Shselasky int cq_attr_mask) 1048219820Sjeff{ 1049219820Sjeff return cq->device->modify_cq ? 1050278886Shselasky cq->device->modify_cq(cq, cq_attr, cq_attr_mask) : -ENOSYS; 1051219820Sjeff} 1052219820SjeffEXPORT_SYMBOL(ib_modify_cq); 1053219820Sjeff 1054219820Sjeffint ib_destroy_cq(struct ib_cq *cq) 1055219820Sjeff{ 1056219820Sjeff if (atomic_read(&cq->usecnt)) 1057219820Sjeff return -EBUSY; 1058219820Sjeff 1059219820Sjeff return cq->device->destroy_cq(cq); 1060219820Sjeff} 1061219820SjeffEXPORT_SYMBOL(ib_destroy_cq); 1062219820Sjeff 1063219820Sjeffint ib_resize_cq(struct ib_cq *cq, int cqe) 1064219820Sjeff{ 1065219820Sjeff return cq->device->resize_cq ? 1066219820Sjeff cq->device->resize_cq(cq, cqe, NULL) : -ENOSYS; 1067219820Sjeff} 1068219820SjeffEXPORT_SYMBOL(ib_resize_cq); 1069219820Sjeff 1070219820Sjeff/* Memory regions */ 1071219820Sjeff 1072219820Sjeffstruct ib_mr *ib_get_dma_mr(struct ib_pd *pd, int mr_access_flags) 1073219820Sjeff{ 1074219820Sjeff struct ib_mr *mr; 1075278886Shselasky int err; 1076219820Sjeff 1077278886Shselasky err = ib_check_mr_access(mr_access_flags); 1078278886Shselasky if (err) 1079278886Shselasky return ERR_PTR(err); 1080278886Shselasky 1081219820Sjeff mr = pd->device->get_dma_mr(pd, mr_access_flags); 1082219820Sjeff 1083219820Sjeff if (!IS_ERR(mr)) { 1084219820Sjeff mr->device = pd->device; 1085219820Sjeff mr->pd = pd; 1086219820Sjeff mr->uobject = NULL; 1087219820Sjeff atomic_inc(&pd->usecnt); 1088219820Sjeff atomic_set(&mr->usecnt, 0); 1089219820Sjeff } 1090219820Sjeff 1091219820Sjeff return mr; 1092219820Sjeff} 1093219820SjeffEXPORT_SYMBOL(ib_get_dma_mr); 1094219820Sjeff 1095219820Sjeffstruct ib_mr *ib_reg_phys_mr(struct ib_pd *pd, 1096219820Sjeff struct ib_phys_buf *phys_buf_array, 1097219820Sjeff int num_phys_buf, 1098219820Sjeff int mr_access_flags, 1099219820Sjeff u64 *iova_start) 1100219820Sjeff{ 1101219820Sjeff struct ib_mr *mr; 1102278886Shselasky int err; 1103219820Sjeff 1104278886Shselasky err = ib_check_mr_access(mr_access_flags); 1105278886Shselasky if (err) 1106278886Shselasky return ERR_PTR(err); 1107278886Shselasky 1108219820Sjeff if (!pd->device->reg_phys_mr) 1109219820Sjeff return ERR_PTR(-ENOSYS); 1110219820Sjeff 1111219820Sjeff mr = pd->device->reg_phys_mr(pd, phys_buf_array, num_phys_buf, 1112219820Sjeff mr_access_flags, iova_start); 1113219820Sjeff 1114219820Sjeff if (!IS_ERR(mr)) { 1115219820Sjeff mr->device = pd->device; 1116219820Sjeff mr->pd = pd; 1117219820Sjeff mr->uobject = NULL; 1118219820Sjeff atomic_inc(&pd->usecnt); 1119219820Sjeff atomic_set(&mr->usecnt, 0); 1120219820Sjeff } 1121219820Sjeff 1122219820Sjeff return mr; 1123219820Sjeff} 1124219820SjeffEXPORT_SYMBOL(ib_reg_phys_mr); 1125219820Sjeff 1126219820Sjeffint ib_rereg_phys_mr(struct ib_mr *mr, 1127219820Sjeff int mr_rereg_mask, 1128219820Sjeff struct ib_pd *pd, 1129219820Sjeff struct ib_phys_buf *phys_buf_array, 1130219820Sjeff int num_phys_buf, 1131219820Sjeff int mr_access_flags, 1132219820Sjeff u64 *iova_start) 1133219820Sjeff{ 1134219820Sjeff struct ib_pd *old_pd; 1135219820Sjeff int ret; 1136219820Sjeff 1137278886Shselasky ret = ib_check_mr_access(mr_access_flags); 1138278886Shselasky if (ret) 1139278886Shselasky return ret; 1140278886Shselasky 1141219820Sjeff if (!mr->device->rereg_phys_mr) 1142219820Sjeff return -ENOSYS; 1143219820Sjeff 1144219820Sjeff if (atomic_read(&mr->usecnt)) 1145219820Sjeff return -EBUSY; 1146219820Sjeff 1147219820Sjeff old_pd = mr->pd; 1148219820Sjeff 1149219820Sjeff ret = mr->device->rereg_phys_mr(mr, mr_rereg_mask, pd, 1150219820Sjeff phys_buf_array, num_phys_buf, 1151219820Sjeff mr_access_flags, iova_start); 1152219820Sjeff 1153219820Sjeff if (!ret && (mr_rereg_mask & IB_MR_REREG_PD)) { 1154219820Sjeff atomic_dec(&old_pd->usecnt); 1155219820Sjeff atomic_inc(&pd->usecnt); 1156219820Sjeff } 1157219820Sjeff 1158219820Sjeff return ret; 1159219820Sjeff} 1160219820SjeffEXPORT_SYMBOL(ib_rereg_phys_mr); 1161219820Sjeff 1162219820Sjeffint ib_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr) 1163219820Sjeff{ 1164219820Sjeff return mr->device->query_mr ? 1165219820Sjeff mr->device->query_mr(mr, mr_attr) : -ENOSYS; 1166219820Sjeff} 1167219820SjeffEXPORT_SYMBOL(ib_query_mr); 1168219820Sjeff 1169219820Sjeffint ib_dereg_mr(struct ib_mr *mr) 1170219820Sjeff{ 1171219820Sjeff struct ib_pd *pd; 1172219820Sjeff int ret; 1173219820Sjeff 1174219820Sjeff if (atomic_read(&mr->usecnt)) 1175219820Sjeff return -EBUSY; 1176219820Sjeff 1177219820Sjeff pd = mr->pd; 1178219820Sjeff ret = mr->device->dereg_mr(mr); 1179219820Sjeff if (!ret) 1180219820Sjeff atomic_dec(&pd->usecnt); 1181219820Sjeff 1182219820Sjeff return ret; 1183219820Sjeff} 1184219820SjeffEXPORT_SYMBOL(ib_dereg_mr); 1185219820Sjeff 1186278886Shselaskystruct ib_mr *ib_create_mr(struct ib_pd *pd, 1187278886Shselasky struct ib_mr_init_attr *mr_init_attr) 1188278886Shselasky{ 1189278886Shselasky struct ib_mr *mr; 1190278886Shselasky 1191278886Shselasky if (!pd->device->create_mr) 1192278886Shselasky return ERR_PTR(-ENOSYS); 1193278886Shselasky 1194278886Shselasky mr = pd->device->create_mr(pd, mr_init_attr); 1195278886Shselasky 1196278886Shselasky if (!IS_ERR(mr)) { 1197278886Shselasky mr->device = pd->device; 1198278886Shselasky mr->pd = pd; 1199278886Shselasky mr->uobject = NULL; 1200278886Shselasky atomic_inc(&pd->usecnt); 1201278886Shselasky atomic_set(&mr->usecnt, 0); 1202278886Shselasky } 1203278886Shselasky 1204278886Shselasky return mr; 1205278886Shselasky} 1206278886ShselaskyEXPORT_SYMBOL(ib_create_mr); 1207278886Shselasky 1208278886Shselaskyint ib_destroy_mr(struct ib_mr *mr) 1209278886Shselasky{ 1210278886Shselasky struct ib_pd *pd; 1211278886Shselasky int ret; 1212278886Shselasky 1213278886Shselasky if (atomic_read(&mr->usecnt)) 1214278886Shselasky return -EBUSY; 1215278886Shselasky 1216278886Shselasky pd = mr->pd; 1217278886Shselasky ret = mr->device->destroy_mr(mr); 1218278886Shselasky if (!ret) 1219278886Shselasky atomic_dec(&pd->usecnt); 1220278886Shselasky 1221278886Shselasky return ret; 1222278886Shselasky} 1223278886ShselaskyEXPORT_SYMBOL(ib_destroy_mr); 1224278886Shselasky 1225219820Sjeffstruct ib_mr *ib_alloc_fast_reg_mr(struct ib_pd *pd, int max_page_list_len) 1226219820Sjeff{ 1227219820Sjeff struct ib_mr *mr; 1228219820Sjeff 1229219820Sjeff if (!pd->device->alloc_fast_reg_mr) 1230219820Sjeff return ERR_PTR(-ENOSYS); 1231219820Sjeff 1232219820Sjeff mr = pd->device->alloc_fast_reg_mr(pd, max_page_list_len); 1233219820Sjeff 1234219820Sjeff if (!IS_ERR(mr)) { 1235219820Sjeff mr->device = pd->device; 1236219820Sjeff mr->pd = pd; 1237219820Sjeff mr->uobject = NULL; 1238219820Sjeff atomic_inc(&pd->usecnt); 1239219820Sjeff atomic_set(&mr->usecnt, 0); 1240219820Sjeff } 1241219820Sjeff 1242219820Sjeff return mr; 1243219820Sjeff} 1244219820SjeffEXPORT_SYMBOL(ib_alloc_fast_reg_mr); 1245219820Sjeff 1246219820Sjeffstruct ib_fast_reg_page_list *ib_alloc_fast_reg_page_list(struct ib_device *device, 1247219820Sjeff int max_page_list_len) 1248219820Sjeff{ 1249219820Sjeff struct ib_fast_reg_page_list *page_list; 1250219820Sjeff 1251219820Sjeff if (!device->alloc_fast_reg_page_list) 1252219820Sjeff return ERR_PTR(-ENOSYS); 1253219820Sjeff 1254219820Sjeff page_list = device->alloc_fast_reg_page_list(device, max_page_list_len); 1255219820Sjeff 1256219820Sjeff if (!IS_ERR(page_list)) { 1257219820Sjeff page_list->device = device; 1258219820Sjeff page_list->max_page_list_len = max_page_list_len; 1259219820Sjeff } 1260219820Sjeff 1261219820Sjeff return page_list; 1262219820Sjeff} 1263219820SjeffEXPORT_SYMBOL(ib_alloc_fast_reg_page_list); 1264219820Sjeff 1265219820Sjeffvoid ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list) 1266219820Sjeff{ 1267219820Sjeff page_list->device->free_fast_reg_page_list(page_list); 1268219820Sjeff} 1269219820SjeffEXPORT_SYMBOL(ib_free_fast_reg_page_list); 1270219820Sjeff 1271219820Sjeff/* Memory windows */ 1272219820Sjeff 1273278886Shselaskystruct ib_mw *ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type) 1274219820Sjeff{ 1275219820Sjeff struct ib_mw *mw; 1276219820Sjeff 1277219820Sjeff if (!pd->device->alloc_mw) 1278219820Sjeff return ERR_PTR(-ENOSYS); 1279219820Sjeff 1280278886Shselasky mw = pd->device->alloc_mw(pd, type); 1281219820Sjeff if (!IS_ERR(mw)) { 1282219820Sjeff mw->device = pd->device; 1283219820Sjeff mw->pd = pd; 1284219820Sjeff mw->uobject = NULL; 1285278886Shselasky mw->type = type; 1286219820Sjeff atomic_inc(&pd->usecnt); 1287219820Sjeff } 1288219820Sjeff 1289219820Sjeff return mw; 1290219820Sjeff} 1291219820SjeffEXPORT_SYMBOL(ib_alloc_mw); 1292219820Sjeff 1293219820Sjeffint ib_dealloc_mw(struct ib_mw *mw) 1294219820Sjeff{ 1295219820Sjeff struct ib_pd *pd; 1296219820Sjeff int ret; 1297219820Sjeff 1298219820Sjeff pd = mw->pd; 1299219820Sjeff ret = mw->device->dealloc_mw(mw); 1300219820Sjeff if (!ret) 1301219820Sjeff atomic_dec(&pd->usecnt); 1302219820Sjeff 1303219820Sjeff return ret; 1304219820Sjeff} 1305219820SjeffEXPORT_SYMBOL(ib_dealloc_mw); 1306219820Sjeff 1307219820Sjeff/* "Fast" memory regions */ 1308219820Sjeff 1309219820Sjeffstruct ib_fmr *ib_alloc_fmr(struct ib_pd *pd, 1310219820Sjeff int mr_access_flags, 1311219820Sjeff struct ib_fmr_attr *fmr_attr) 1312219820Sjeff{ 1313219820Sjeff struct ib_fmr *fmr; 1314219820Sjeff 1315219820Sjeff if (!pd->device->alloc_fmr) 1316219820Sjeff return ERR_PTR(-ENOSYS); 1317219820Sjeff 1318219820Sjeff fmr = pd->device->alloc_fmr(pd, mr_access_flags, fmr_attr); 1319219820Sjeff if (!IS_ERR(fmr)) { 1320219820Sjeff fmr->device = pd->device; 1321219820Sjeff fmr->pd = pd; 1322219820Sjeff atomic_inc(&pd->usecnt); 1323219820Sjeff } 1324219820Sjeff 1325219820Sjeff return fmr; 1326219820Sjeff} 1327219820SjeffEXPORT_SYMBOL(ib_alloc_fmr); 1328219820Sjeff 1329219820Sjeffint ib_unmap_fmr(struct list_head *fmr_list) 1330219820Sjeff{ 1331219820Sjeff struct ib_fmr *fmr; 1332219820Sjeff 1333219820Sjeff if (list_empty(fmr_list)) 1334219820Sjeff return 0; 1335219820Sjeff 1336219820Sjeff fmr = list_entry(fmr_list->next, struct ib_fmr, list); 1337219820Sjeff return fmr->device->unmap_fmr(fmr_list); 1338219820Sjeff} 1339219820SjeffEXPORT_SYMBOL(ib_unmap_fmr); 1340219820Sjeff 1341219820Sjeffint ib_dealloc_fmr(struct ib_fmr *fmr) 1342219820Sjeff{ 1343219820Sjeff struct ib_pd *pd; 1344219820Sjeff int ret; 1345219820Sjeff 1346219820Sjeff pd = fmr->pd; 1347219820Sjeff ret = fmr->device->dealloc_fmr(fmr); 1348219820Sjeff if (!ret) 1349219820Sjeff atomic_dec(&pd->usecnt); 1350219820Sjeff 1351219820Sjeff return ret; 1352219820Sjeff} 1353219820SjeffEXPORT_SYMBOL(ib_dealloc_fmr); 1354219820Sjeff 1355219820Sjeff/* Multicast groups */ 1356219820Sjeff 1357219820Sjeffint ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid) 1358219820Sjeff{ 1359278886Shselasky int ret; 1360278886Shselasky 1361219820Sjeff if (!qp->device->attach_mcast) 1362219820Sjeff return -ENOSYS; 1363219820Sjeff 1364219820Sjeff switch (rdma_node_get_transport(qp->device->node_type)) { 1365219820Sjeff case RDMA_TRANSPORT_IB: 1366278886Shselasky if ((gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD) && 1367278886Shselasky qp->qp_type != IB_QPT_RAW_PACKET) 1368219820Sjeff return -EINVAL; 1369219820Sjeff break; 1370219820Sjeff case RDMA_TRANSPORT_IWARP: 1371278886Shselasky case RDMA_TRANSPORT_SCIF: 1372255932Salfred if (qp->qp_type != IB_QPT_RAW_PACKET) 1373219820Sjeff return -EINVAL; 1374219820Sjeff break; 1375219820Sjeff } 1376278886Shselasky 1377278886Shselasky ret = qp->device->attach_mcast(qp, gid, lid); 1378278886Shselasky if (!ret) 1379278886Shselasky atomic_inc(&qp->usecnt); 1380278886Shselasky return ret; 1381219820Sjeff} 1382219820SjeffEXPORT_SYMBOL(ib_attach_mcast); 1383219820Sjeff 1384219820Sjeffint ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid) 1385219820Sjeff{ 1386278886Shselasky int ret; 1387278886Shselasky 1388219820Sjeff if (!qp->device->detach_mcast) 1389219820Sjeff return -ENOSYS; 1390219820Sjeff 1391219820Sjeff switch (rdma_node_get_transport(qp->device->node_type)) { 1392219820Sjeff case RDMA_TRANSPORT_IB: 1393278886Shselasky if ((gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD) && 1394278886Shselasky qp->qp_type != IB_QPT_RAW_PACKET) 1395219820Sjeff return -EINVAL; 1396219820Sjeff break; 1397219820Sjeff case RDMA_TRANSPORT_IWARP: 1398278886Shselasky case RDMA_TRANSPORT_SCIF: 1399278886Shselasky 1400255932Salfred if (qp->qp_type != IB_QPT_RAW_PACKET) 1401219820Sjeff return -EINVAL; 1402219820Sjeff break; 1403219820Sjeff } 1404278886Shselasky 1405278886Shselasky ret = qp->device->detach_mcast(qp, gid, lid); 1406278886Shselasky if (!ret) 1407278886Shselasky atomic_dec(&qp->usecnt); 1408278886Shselasky return ret; 1409219820Sjeff} 1410219820SjeffEXPORT_SYMBOL(ib_detach_mcast); 1411219820Sjeff 1412219820Sjeffstruct ib_xrcd *ib_alloc_xrcd(struct ib_device *device) 1413219820Sjeff{ 1414219820Sjeff struct ib_xrcd *xrcd; 1415219820Sjeff 1416219820Sjeff if (!device->alloc_xrcd) 1417219820Sjeff return ERR_PTR(-ENOSYS); 1418219820Sjeff 1419219820Sjeff xrcd = device->alloc_xrcd(device, NULL, NULL); 1420219820Sjeff if (!IS_ERR(xrcd)) { 1421219820Sjeff xrcd->device = device; 1422219820Sjeff xrcd->inode = NULL; 1423219820Sjeff atomic_set(&xrcd->usecnt, 0); 1424278886Shselasky mutex_init(&xrcd->tgt_qp_mutex); 1425278886Shselasky INIT_LIST_HEAD(&xrcd->tgt_qp_list); 1426219820Sjeff } 1427278886Shselasky 1428219820Sjeff return xrcd; 1429219820Sjeff} 1430219820SjeffEXPORT_SYMBOL(ib_alloc_xrcd); 1431219820Sjeff 1432278886Shselaskyint ib_dealloc_xrcd(struct ib_xrcd *xrcd) 1433278886Shselasky{ 1434278886Shselasky struct ib_qp *qp; 1435278886Shselasky int ret; 1436278886Shselasky 1437278886Shselasky if (atomic_read(&xrcd->usecnt)) 1438278886Shselasky return -EBUSY; 1439278886Shselasky 1440278886Shselasky while (!list_empty(&xrcd->tgt_qp_list)) { 1441278886Shselasky qp = list_entry(xrcd->tgt_qp_list.next, struct ib_qp, xrcd_list); 1442278886Shselasky ret = ib_destroy_qp(qp); 1443278886Shselasky if (ret) 1444278886Shselasky return ret; 1445278886Shselasky } 1446278886Shselasky 1447278886Shselasky return xrcd->device->dealloc_xrcd(xrcd); 1448278886Shselasky} 1449278886ShselaskyEXPORT_SYMBOL(ib_dealloc_xrcd); 1450278886Shselasky 1451278886Shselaskystruct ib_flow *ib_create_flow(struct ib_qp *qp, 1452278886Shselasky struct ib_flow_attr *flow_attr, 1453278886Shselasky int domain) 1454278886Shselasky{ 1455278886Shselasky struct ib_flow *flow_id; 1456278886Shselasky if (!qp->device->create_flow) 1457278886Shselasky return ERR_PTR(-ENOSYS); 1458278886Shselasky 1459278886Shselasky flow_id = qp->device->create_flow(qp, flow_attr, domain); 1460278886Shselasky if (!IS_ERR(flow_id)) 1461278886Shselasky atomic_inc(&qp->usecnt); 1462278886Shselasky return flow_id; 1463278886Shselasky} 1464278886ShselaskyEXPORT_SYMBOL(ib_create_flow); 1465278886Shselasky 1466278886Shselaskyint ib_destroy_flow(struct ib_flow *flow_id) 1467278886Shselasky{ 1468278886Shselasky int err; 1469278886Shselasky struct ib_qp *qp; 1470278886Shselasky 1471278886Shselasky if (!flow_id) 1472278886Shselasky return -EINVAL; 1473278886Shselasky qp = flow_id->qp; 1474278886Shselasky if (!qp->device->destroy_flow) 1475278886Shselasky return -ENOSYS; 1476278886Shselasky err = qp->device->destroy_flow(flow_id); 1477278886Shselasky if (!err) 1478278886Shselasky atomic_dec(&qp->usecnt); 1479278886Shselasky return err; 1480278886Shselasky} 1481278886ShselaskyEXPORT_SYMBOL(ib_destroy_flow); 1482278886Shselasky 1483278886Shselaskystruct ib_dct *ib_create_dct(struct ib_pd *pd, struct ib_dct_init_attr *attr, 1484278886Shselasky struct ib_udata *udata) 1485278886Shselasky{ 1486278886Shselasky struct ib_dct *dct; 1487278886Shselasky 1488278886Shselasky if (!pd->device->exp_create_dct) 1489278886Shselasky return ERR_PTR(-ENOSYS); 1490278886Shselasky 1491278886Shselasky dct = pd->device->exp_create_dct(pd, attr, udata); 1492278886Shselasky if (!IS_ERR(dct)) { 1493278886Shselasky dct->pd = pd; 1494278886Shselasky dct->srq = attr->srq; 1495278886Shselasky dct->cq = attr->cq; 1496278886Shselasky atomic_inc(&dct->srq->usecnt); 1497278886Shselasky atomic_inc(&dct->cq->usecnt); 1498278886Shselasky atomic_inc(&dct->pd->usecnt); 1499278886Shselasky } 1500278886Shselasky 1501278886Shselasky return dct; 1502278886Shselasky} 1503278886ShselaskyEXPORT_SYMBOL(ib_create_dct); 1504278886Shselasky 1505278886Shselaskyint ib_destroy_dct(struct ib_dct *dct) 1506278886Shselasky{ 1507278886Shselasky int err; 1508278886Shselasky 1509278886Shselasky if (!dct->device->exp_destroy_dct) 1510278886Shselasky return -ENOSYS; 1511278886Shselasky 1512278886Shselasky err = dct->device->exp_destroy_dct(dct); 1513278886Shselasky if (!err) { 1514278886Shselasky atomic_dec(&dct->srq->usecnt); 1515278886Shselasky atomic_dec(&dct->cq->usecnt); 1516278886Shselasky atomic_dec(&dct->pd->usecnt); 1517278886Shselasky } 1518278886Shselasky 1519278886Shselasky return err; 1520278886Shselasky} 1521278886ShselaskyEXPORT_SYMBOL(ib_destroy_dct); 1522278886Shselasky 1523278886Shselaskyint ib_query_dct(struct ib_dct *dct, struct ib_dct_attr *attr) 1524278886Shselasky{ 1525278886Shselasky if (!dct->device->exp_query_dct) 1526278886Shselasky return -ENOSYS; 1527278886Shselasky 1528278886Shselasky return dct->device->exp_query_dct(dct, attr); 1529278886Shselasky} 1530278886ShselaskyEXPORT_SYMBOL(ib_query_dct); 1531278886Shselasky 1532278886Shselaskyint ib_check_mr_status(struct ib_mr *mr, u32 check_mask, 1533278886Shselasky struct ib_mr_status *mr_status) 1534278886Shselasky{ 1535278886Shselasky return mr->device->check_mr_status ? 1536278886Shselasky mr->device->check_mr_status(mr, check_mask, mr_status) : -ENOSYS; 1537278886Shselasky} 1538278886ShselaskyEXPORT_SYMBOL(ib_check_mr_status); 1539