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> 41219820Sjeff#include <linux/string.h> 42219820Sjeff 43219820Sjeff#include <rdma/ib_verbs.h> 44219820Sjeff#include <rdma/ib_cache.h> 45219820Sjeff 46219820Sjeffint ib_rate_to_mult(enum ib_rate rate) 47219820Sjeff{ 48219820Sjeff switch (rate) { 49219820Sjeff case IB_RATE_2_5_GBPS: return 1; 50219820Sjeff case IB_RATE_5_GBPS: return 2; 51219820Sjeff case IB_RATE_10_GBPS: return 4; 52219820Sjeff case IB_RATE_20_GBPS: return 8; 53219820Sjeff case IB_RATE_30_GBPS: return 12; 54219820Sjeff case IB_RATE_40_GBPS: return 16; 55219820Sjeff case IB_RATE_60_GBPS: return 24; 56219820Sjeff case IB_RATE_80_GBPS: return 32; 57219820Sjeff case IB_RATE_120_GBPS: return 48; 58219820Sjeff default: return -1; 59219820Sjeff } 60219820Sjeff} 61219820SjeffEXPORT_SYMBOL(ib_rate_to_mult); 62219820Sjeff 63219820Sjeffenum ib_rate mult_to_ib_rate(int mult) 64219820Sjeff{ 65219820Sjeff switch (mult) { 66219820Sjeff case 1: return IB_RATE_2_5_GBPS; 67219820Sjeff case 2: return IB_RATE_5_GBPS; 68219820Sjeff case 4: return IB_RATE_10_GBPS; 69219820Sjeff case 8: return IB_RATE_20_GBPS; 70219820Sjeff case 12: return IB_RATE_30_GBPS; 71219820Sjeff case 16: return IB_RATE_40_GBPS; 72219820Sjeff case 24: return IB_RATE_60_GBPS; 73219820Sjeff case 32: return IB_RATE_80_GBPS; 74219820Sjeff case 48: return IB_RATE_120_GBPS; 75219820Sjeff default: return IB_RATE_PORT_CURRENT; 76219820Sjeff } 77219820Sjeff} 78219820SjeffEXPORT_SYMBOL(mult_to_ib_rate); 79219820Sjeff 80219820Sjeffenum rdma_transport_type 81219820Sjeffrdma_node_get_transport(enum rdma_node_type node_type) 82219820Sjeff{ 83219820Sjeff switch (node_type) { 84219820Sjeff case RDMA_NODE_IB_CA: 85219820Sjeff case RDMA_NODE_IB_SWITCH: 86219820Sjeff case RDMA_NODE_IB_ROUTER: 87219820Sjeff return RDMA_TRANSPORT_IB; 88219820Sjeff case RDMA_NODE_RNIC: 89219820Sjeff return RDMA_TRANSPORT_IWARP; 90219820Sjeff default: 91219820Sjeff BUG(); 92219820Sjeff return 0; 93219820Sjeff } 94219820Sjeff} 95219820SjeffEXPORT_SYMBOL(rdma_node_get_transport); 96219820Sjeff 97219820Sjeffenum rdma_link_layer rdma_port_get_link_layer(struct ib_device *device, u8 port_num) 98219820Sjeff{ 99219820Sjeff if (device->get_link_layer) 100219820Sjeff return device->get_link_layer(device, port_num); 101219820Sjeff 102219820Sjeff switch (rdma_node_get_transport(device->node_type)) { 103219820Sjeff case RDMA_TRANSPORT_IB: 104219820Sjeff return IB_LINK_LAYER_INFINIBAND; 105219820Sjeff case RDMA_TRANSPORT_IWARP: 106219820Sjeff return IB_LINK_LAYER_ETHERNET; 107219820Sjeff default: 108219820Sjeff return IB_LINK_LAYER_UNSPECIFIED; 109219820Sjeff } 110219820Sjeff} 111219820SjeffEXPORT_SYMBOL(rdma_port_get_link_layer); 112219820Sjeff 113219820Sjeff/* Protection domains */ 114219820Sjeff 115219820Sjeffstruct ib_pd *ib_alloc_pd(struct ib_device *device) 116219820Sjeff{ 117219820Sjeff struct ib_pd *pd; 118219820Sjeff 119219820Sjeff pd = device->alloc_pd(device, NULL, NULL); 120219820Sjeff 121219820Sjeff if (!IS_ERR(pd)) { 122219820Sjeff pd->device = device; 123219820Sjeff pd->uobject = NULL; 124219820Sjeff atomic_set(&pd->usecnt, 0); 125219820Sjeff } 126219820Sjeff 127219820Sjeff return pd; 128219820Sjeff} 129219820SjeffEXPORT_SYMBOL(ib_alloc_pd); 130219820Sjeff 131219820Sjeffint ib_dealloc_pd(struct ib_pd *pd) 132219820Sjeff{ 133219820Sjeff if (atomic_read(&pd->usecnt)) 134219820Sjeff return -EBUSY; 135219820Sjeff 136219820Sjeff return pd->device->dealloc_pd(pd); 137219820Sjeff} 138219820SjeffEXPORT_SYMBOL(ib_dealloc_pd); 139219820Sjeff 140219820Sjeff/* Address handles */ 141219820Sjeff 142219820Sjeffstruct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) 143219820Sjeff{ 144219820Sjeff struct ib_ah *ah; 145219820Sjeff 146219820Sjeff ah = pd->device->create_ah(pd, ah_attr); 147219820Sjeff 148219820Sjeff if (!IS_ERR(ah)) { 149219820Sjeff ah->device = pd->device; 150219820Sjeff ah->pd = pd; 151219820Sjeff ah->uobject = NULL; 152219820Sjeff atomic_inc(&pd->usecnt); 153219820Sjeff } 154219820Sjeff 155219820Sjeff return ah; 156219820Sjeff} 157219820SjeffEXPORT_SYMBOL(ib_create_ah); 158219820Sjeff 159219820Sjeffint ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc, 160219820Sjeff struct ib_grh *grh, struct ib_ah_attr *ah_attr) 161219820Sjeff{ 162219820Sjeff u32 flow_class; 163219820Sjeff u16 gid_index; 164219820Sjeff int ret; 165219820Sjeff 166219820Sjeff memset(ah_attr, 0, sizeof *ah_attr); 167219820Sjeff ah_attr->dlid = wc->slid; 168219820Sjeff ah_attr->sl = wc->sl; 169219820Sjeff ah_attr->src_path_bits = wc->dlid_path_bits; 170219820Sjeff ah_attr->port_num = port_num; 171219820Sjeff 172219820Sjeff if (wc->wc_flags & IB_WC_GRH) { 173219820Sjeff ah_attr->ah_flags = IB_AH_GRH; 174219820Sjeff ah_attr->grh.dgid = grh->sgid; 175219820Sjeff 176219820Sjeff ret = ib_find_cached_gid(device, &grh->dgid, &port_num, 177219820Sjeff &gid_index); 178219820Sjeff if (ret) 179219820Sjeff return ret; 180219820Sjeff 181219820Sjeff ah_attr->grh.sgid_index = (u8) gid_index; 182219820Sjeff flow_class = be32_to_cpu(grh->version_tclass_flow); 183219820Sjeff ah_attr->grh.flow_label = flow_class & 0xFFFFF; 184219820Sjeff ah_attr->grh.hop_limit = 0xFF; 185219820Sjeff ah_attr->grh.traffic_class = (flow_class >> 20) & 0xFF; 186219820Sjeff } 187219820Sjeff return 0; 188219820Sjeff} 189219820SjeffEXPORT_SYMBOL(ib_init_ah_from_wc); 190219820Sjeff 191219820Sjeffstruct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc, 192219820Sjeff struct ib_grh *grh, u8 port_num) 193219820Sjeff{ 194219820Sjeff struct ib_ah_attr ah_attr; 195219820Sjeff int ret; 196219820Sjeff 197219820Sjeff ret = ib_init_ah_from_wc(pd->device, port_num, wc, grh, &ah_attr); 198219820Sjeff if (ret) 199219820Sjeff return ERR_PTR(ret); 200219820Sjeff 201219820Sjeff return ib_create_ah(pd, &ah_attr); 202219820Sjeff} 203219820SjeffEXPORT_SYMBOL(ib_create_ah_from_wc); 204219820Sjeff 205219820Sjeffint ib_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) 206219820Sjeff{ 207219820Sjeff return ah->device->modify_ah ? 208219820Sjeff ah->device->modify_ah(ah, ah_attr) : 209219820Sjeff -ENOSYS; 210219820Sjeff} 211219820SjeffEXPORT_SYMBOL(ib_modify_ah); 212219820Sjeff 213219820Sjeffint ib_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) 214219820Sjeff{ 215219820Sjeff return ah->device->query_ah ? 216219820Sjeff ah->device->query_ah(ah, ah_attr) : 217219820Sjeff -ENOSYS; 218219820Sjeff} 219219820SjeffEXPORT_SYMBOL(ib_query_ah); 220219820Sjeff 221219820Sjeffint ib_destroy_ah(struct ib_ah *ah) 222219820Sjeff{ 223219820Sjeff struct ib_pd *pd; 224219820Sjeff int ret; 225219820Sjeff 226219820Sjeff pd = ah->pd; 227219820Sjeff ret = ah->device->destroy_ah(ah); 228219820Sjeff if (!ret) 229219820Sjeff atomic_dec(&pd->usecnt); 230219820Sjeff 231219820Sjeff return ret; 232219820Sjeff} 233219820SjeffEXPORT_SYMBOL(ib_destroy_ah); 234219820Sjeff 235219820Sjeff/* Shared receive queues */ 236219820Sjeff 237219820Sjeffstruct ib_srq *ib_create_srq(struct ib_pd *pd, 238219820Sjeff struct ib_srq_init_attr *srq_init_attr) 239219820Sjeff{ 240219820Sjeff struct ib_srq *srq; 241219820Sjeff 242219820Sjeff if (!pd->device->create_srq) 243219820Sjeff return ERR_PTR(-ENOSYS); 244219820Sjeff 245219820Sjeff srq = pd->device->create_srq(pd, srq_init_attr, NULL); 246219820Sjeff 247219820Sjeff if (!IS_ERR(srq)) { 248219820Sjeff srq->device = pd->device; 249219820Sjeff srq->pd = pd; 250219820Sjeff srq->uobject = NULL; 251219820Sjeff srq->event_handler = srq_init_attr->event_handler; 252219820Sjeff srq->srq_context = srq_init_attr->srq_context; 253219820Sjeff srq->xrc_cq = NULL; 254219820Sjeff srq->xrcd = NULL; 255219820Sjeff atomic_inc(&pd->usecnt); 256219820Sjeff atomic_set(&srq->usecnt, 0); 257219820Sjeff } 258219820Sjeff 259219820Sjeff return srq; 260219820Sjeff} 261219820SjeffEXPORT_SYMBOL(ib_create_srq); 262219820Sjeff 263219820Sjeffstruct ib_srq *ib_create_xrc_srq(struct ib_pd *pd, 264219820Sjeff struct ib_cq *xrc_cq, 265219820Sjeff struct ib_xrcd *xrcd, 266219820Sjeff struct ib_srq_init_attr *srq_init_attr) 267219820Sjeff{ 268219820Sjeff struct ib_srq *srq; 269219820Sjeff 270219820Sjeff if (!pd->device->create_xrc_srq) 271219820Sjeff return ERR_PTR(-ENOSYS); 272219820Sjeff 273219820Sjeff srq = pd->device->create_xrc_srq(pd, xrc_cq, xrcd, srq_init_attr, NULL); 274219820Sjeff 275219820Sjeff if (!IS_ERR(srq)) { 276219820Sjeff srq->device = pd->device; 277219820Sjeff srq->pd = pd; 278219820Sjeff srq->uobject = NULL; 279219820Sjeff srq->event_handler = srq_init_attr->event_handler; 280219820Sjeff srq->srq_context = srq_init_attr->srq_context; 281219820Sjeff srq->xrc_cq = xrc_cq; 282219820Sjeff srq->xrcd = xrcd; 283219820Sjeff atomic_inc(&pd->usecnt); 284219820Sjeff atomic_inc(&xrcd->usecnt); 285219820Sjeff atomic_inc(&xrc_cq->usecnt); 286219820Sjeff atomic_set(&srq->usecnt, 0); 287219820Sjeff } 288219820Sjeff 289219820Sjeff return srq; 290219820Sjeff} 291219820SjeffEXPORT_SYMBOL(ib_create_xrc_srq); 292219820Sjeff 293219820Sjeffint ib_modify_srq(struct ib_srq *srq, 294219820Sjeff struct ib_srq_attr *srq_attr, 295219820Sjeff enum ib_srq_attr_mask srq_attr_mask) 296219820Sjeff{ 297219820Sjeff return srq->device->modify_srq ? 298219820Sjeff srq->device->modify_srq(srq, srq_attr, srq_attr_mask, NULL) : 299219820Sjeff -ENOSYS; 300219820Sjeff} 301219820SjeffEXPORT_SYMBOL(ib_modify_srq); 302219820Sjeff 303219820Sjeffint ib_query_srq(struct ib_srq *srq, 304219820Sjeff struct ib_srq_attr *srq_attr) 305219820Sjeff{ 306219820Sjeff return srq->device->query_srq ? 307219820Sjeff srq->device->query_srq(srq, srq_attr) : -ENOSYS; 308219820Sjeff} 309219820SjeffEXPORT_SYMBOL(ib_query_srq); 310219820Sjeff 311219820Sjeffint ib_destroy_srq(struct ib_srq *srq) 312219820Sjeff{ 313219820Sjeff struct ib_pd *pd; 314219820Sjeff struct ib_cq *xrc_cq; 315219820Sjeff struct ib_xrcd *xrcd; 316219820Sjeff int ret; 317219820Sjeff 318219820Sjeff if (atomic_read(&srq->usecnt)) 319219820Sjeff return -EBUSY; 320219820Sjeff 321219820Sjeff pd = srq->pd; 322219820Sjeff xrc_cq = srq->xrc_cq; 323219820Sjeff xrcd = srq->xrcd; 324219820Sjeff 325219820Sjeff ret = srq->device->destroy_srq(srq); 326219820Sjeff if (!ret) { 327219820Sjeff atomic_dec(&pd->usecnt); 328219820Sjeff if (xrc_cq) 329219820Sjeff atomic_dec(&xrc_cq->usecnt); 330219820Sjeff if (xrcd) 331219820Sjeff atomic_dec(&xrcd->usecnt); 332219820Sjeff } 333219820Sjeff 334219820Sjeff return ret; 335219820Sjeff} 336219820SjeffEXPORT_SYMBOL(ib_destroy_srq); 337219820Sjeff 338219820Sjeff/* Queue pairs */ 339219820Sjeff 340219820Sjeffstruct ib_qp *ib_create_qp(struct ib_pd *pd, 341219820Sjeff struct ib_qp_init_attr *qp_init_attr) 342219820Sjeff{ 343219820Sjeff struct ib_qp *qp; 344219820Sjeff 345219820Sjeff qp = pd->device->create_qp(pd, qp_init_attr, NULL); 346219820Sjeff 347219820Sjeff if (!IS_ERR(qp)) { 348219820Sjeff qp->device = pd->device; 349219820Sjeff qp->pd = pd; 350219820Sjeff qp->send_cq = qp_init_attr->send_cq; 351219820Sjeff qp->recv_cq = qp_init_attr->recv_cq; 352219820Sjeff qp->srq = qp_init_attr->srq; 353219820Sjeff qp->uobject = NULL; 354219820Sjeff qp->event_handler = qp_init_attr->event_handler; 355219820Sjeff qp->qp_context = qp_init_attr->qp_context; 356219820Sjeff qp->qp_type = qp_init_attr->qp_type; 357219820Sjeff qp->xrcd = qp->qp_type == IB_QPT_XRC ? 358219820Sjeff qp_init_attr->xrc_domain : NULL; 359219820Sjeff atomic_inc(&pd->usecnt); 360219820Sjeff atomic_inc(&qp_init_attr->send_cq->usecnt); 361219820Sjeff atomic_inc(&qp_init_attr->recv_cq->usecnt); 362219820Sjeff if (qp_init_attr->srq) 363219820Sjeff atomic_inc(&qp_init_attr->srq->usecnt); 364219820Sjeff if (qp->qp_type == IB_QPT_XRC) 365219820Sjeff atomic_inc(&qp->xrcd->usecnt); 366219820Sjeff } 367219820Sjeff 368219820Sjeff return qp; 369219820Sjeff} 370219820SjeffEXPORT_SYMBOL(ib_create_qp); 371219820Sjeff 372219820Sjeffstatic const struct { 373219820Sjeff int valid; 374219820Sjeff enum ib_qp_attr_mask req_param[IB_QPT_RAW_ETH + 1]; 375219820Sjeff enum ib_qp_attr_mask opt_param[IB_QPT_RAW_ETH + 1]; 376219820Sjeff} qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = { 377219820Sjeff [IB_QPS_RESET] = { 378219820Sjeff [IB_QPS_RESET] = { .valid = 1 }, 379219820Sjeff [IB_QPS_INIT] = { 380219820Sjeff .valid = 1, 381219820Sjeff .req_param = { 382219820Sjeff [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 383219820Sjeff IB_QP_PORT | 384219820Sjeff IB_QP_QKEY), 385219820Sjeff [IB_QPT_RAW_ETH] = IB_QP_PORT, 386219820Sjeff [IB_QPT_UC] = (IB_QP_PKEY_INDEX | 387219820Sjeff IB_QP_PORT | 388219820Sjeff IB_QP_ACCESS_FLAGS), 389219820Sjeff [IB_QPT_RC] = (IB_QP_PKEY_INDEX | 390219820Sjeff IB_QP_PORT | 391219820Sjeff IB_QP_ACCESS_FLAGS), 392219820Sjeff [IB_QPT_XRC] = (IB_QP_PKEY_INDEX | 393219820Sjeff IB_QP_PORT | 394219820Sjeff IB_QP_ACCESS_FLAGS), 395219820Sjeff [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 396219820Sjeff IB_QP_QKEY), 397219820Sjeff [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 398219820Sjeff IB_QP_QKEY), 399219820Sjeff } 400219820Sjeff }, 401219820Sjeff }, 402219820Sjeff [IB_QPS_INIT] = { 403219820Sjeff [IB_QPS_RESET] = { .valid = 1 }, 404219820Sjeff [IB_QPS_ERR] = { .valid = 1 }, 405219820Sjeff [IB_QPS_INIT] = { 406219820Sjeff .valid = 1, 407219820Sjeff .opt_param = { 408219820Sjeff [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 409219820Sjeff IB_QP_PORT | 410219820Sjeff IB_QP_QKEY), 411219820Sjeff [IB_QPT_UC] = (IB_QP_PKEY_INDEX | 412219820Sjeff IB_QP_PORT | 413219820Sjeff IB_QP_ACCESS_FLAGS), 414219820Sjeff [IB_QPT_RC] = (IB_QP_PKEY_INDEX | 415219820Sjeff IB_QP_PORT | 416219820Sjeff IB_QP_ACCESS_FLAGS), 417219820Sjeff [IB_QPT_XRC] = (IB_QP_PKEY_INDEX | 418219820Sjeff IB_QP_PORT | 419219820Sjeff IB_QP_ACCESS_FLAGS), 420219820Sjeff [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 421219820Sjeff IB_QP_QKEY), 422219820Sjeff [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 423219820Sjeff IB_QP_QKEY), 424219820Sjeff } 425219820Sjeff }, 426219820Sjeff [IB_QPS_RTR] = { 427219820Sjeff .valid = 1, 428219820Sjeff .req_param = { 429219820Sjeff [IB_QPT_UC] = (IB_QP_AV | 430219820Sjeff IB_QP_PATH_MTU | 431219820Sjeff IB_QP_DEST_QPN | 432219820Sjeff IB_QP_RQ_PSN), 433219820Sjeff [IB_QPT_RC] = (IB_QP_AV | 434219820Sjeff IB_QP_PATH_MTU | 435219820Sjeff IB_QP_DEST_QPN | 436219820Sjeff IB_QP_RQ_PSN | 437219820Sjeff IB_QP_MAX_DEST_RD_ATOMIC | 438219820Sjeff IB_QP_MIN_RNR_TIMER), 439219820Sjeff [IB_QPT_XRC] = (IB_QP_AV | 440219820Sjeff IB_QP_PATH_MTU | 441219820Sjeff IB_QP_DEST_QPN | 442219820Sjeff IB_QP_RQ_PSN | 443219820Sjeff IB_QP_MAX_DEST_RD_ATOMIC | 444219820Sjeff IB_QP_MIN_RNR_TIMER), 445219820Sjeff }, 446219820Sjeff .opt_param = { 447219820Sjeff [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 448219820Sjeff IB_QP_QKEY), 449219820Sjeff [IB_QPT_UC] = (IB_QP_ALT_PATH | 450219820Sjeff IB_QP_ACCESS_FLAGS | 451219820Sjeff IB_QP_PKEY_INDEX), 452219820Sjeff [IB_QPT_RC] = (IB_QP_ALT_PATH | 453219820Sjeff IB_QP_ACCESS_FLAGS | 454219820Sjeff IB_QP_PKEY_INDEX), 455219820Sjeff [IB_QPT_XRC] = (IB_QP_ALT_PATH | 456219820Sjeff IB_QP_ACCESS_FLAGS | 457219820Sjeff IB_QP_PKEY_INDEX), 458219820Sjeff [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 459219820Sjeff IB_QP_QKEY), 460219820Sjeff [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 461219820Sjeff IB_QP_QKEY), 462219820Sjeff } 463219820Sjeff } 464219820Sjeff }, 465219820Sjeff [IB_QPS_RTR] = { 466219820Sjeff [IB_QPS_RESET] = { .valid = 1 }, 467219820Sjeff [IB_QPS_ERR] = { .valid = 1 }, 468219820Sjeff [IB_QPS_RTS] = { 469219820Sjeff .valid = 1, 470219820Sjeff .req_param = { 471219820Sjeff [IB_QPT_UD] = IB_QP_SQ_PSN, 472219820Sjeff [IB_QPT_UC] = IB_QP_SQ_PSN, 473219820Sjeff [IB_QPT_RC] = (IB_QP_TIMEOUT | 474219820Sjeff IB_QP_RETRY_CNT | 475219820Sjeff IB_QP_RNR_RETRY | 476219820Sjeff IB_QP_SQ_PSN | 477219820Sjeff IB_QP_MAX_QP_RD_ATOMIC), 478219820Sjeff [IB_QPT_XRC] = (IB_QP_TIMEOUT | 479219820Sjeff IB_QP_RETRY_CNT | 480219820Sjeff IB_QP_RNR_RETRY | 481219820Sjeff IB_QP_SQ_PSN | 482219820Sjeff IB_QP_MAX_QP_RD_ATOMIC), 483219820Sjeff [IB_QPT_SMI] = IB_QP_SQ_PSN, 484219820Sjeff [IB_QPT_GSI] = IB_QP_SQ_PSN, 485219820Sjeff }, 486219820Sjeff .opt_param = { 487219820Sjeff [IB_QPT_UD] = (IB_QP_CUR_STATE | 488219820Sjeff IB_QP_QKEY), 489219820Sjeff [IB_QPT_UC] = (IB_QP_CUR_STATE | 490219820Sjeff IB_QP_ALT_PATH | 491219820Sjeff IB_QP_ACCESS_FLAGS | 492219820Sjeff IB_QP_PATH_MIG_STATE), 493219820Sjeff [IB_QPT_RC] = (IB_QP_CUR_STATE | 494219820Sjeff IB_QP_ALT_PATH | 495219820Sjeff IB_QP_ACCESS_FLAGS | 496219820Sjeff IB_QP_MIN_RNR_TIMER | 497219820Sjeff IB_QP_PATH_MIG_STATE), 498219820Sjeff [IB_QPT_XRC] = (IB_QP_CUR_STATE | 499219820Sjeff IB_QP_ALT_PATH | 500219820Sjeff IB_QP_ACCESS_FLAGS | 501219820Sjeff IB_QP_MIN_RNR_TIMER | 502219820Sjeff IB_QP_PATH_MIG_STATE), 503219820Sjeff [IB_QPT_SMI] = (IB_QP_CUR_STATE | 504219820Sjeff IB_QP_QKEY), 505219820Sjeff [IB_QPT_GSI] = (IB_QP_CUR_STATE | 506219820Sjeff IB_QP_QKEY), 507219820Sjeff } 508219820Sjeff } 509219820Sjeff }, 510219820Sjeff [IB_QPS_RTS] = { 511219820Sjeff [IB_QPS_RESET] = { .valid = 1 }, 512219820Sjeff [IB_QPS_ERR] = { .valid = 1 }, 513219820Sjeff [IB_QPS_RTS] = { 514219820Sjeff .valid = 1, 515219820Sjeff .opt_param = { 516219820Sjeff [IB_QPT_UD] = (IB_QP_CUR_STATE | 517219820Sjeff IB_QP_QKEY), 518219820Sjeff [IB_QPT_UC] = (IB_QP_CUR_STATE | 519219820Sjeff IB_QP_ACCESS_FLAGS | 520219820Sjeff IB_QP_ALT_PATH | 521219820Sjeff IB_QP_PATH_MIG_STATE), 522219820Sjeff [IB_QPT_RC] = (IB_QP_CUR_STATE | 523219820Sjeff IB_QP_ACCESS_FLAGS | 524219820Sjeff IB_QP_ALT_PATH | 525219820Sjeff IB_QP_PATH_MIG_STATE | 526219820Sjeff IB_QP_MIN_RNR_TIMER), 527219820Sjeff [IB_QPT_XRC] = (IB_QP_CUR_STATE | 528219820Sjeff IB_QP_ACCESS_FLAGS | 529219820Sjeff IB_QP_ALT_PATH | 530219820Sjeff IB_QP_PATH_MIG_STATE | 531219820Sjeff IB_QP_MIN_RNR_TIMER), 532219820Sjeff [IB_QPT_SMI] = (IB_QP_CUR_STATE | 533219820Sjeff IB_QP_QKEY), 534219820Sjeff [IB_QPT_GSI] = (IB_QP_CUR_STATE | 535219820Sjeff IB_QP_QKEY), 536219820Sjeff } 537219820Sjeff }, 538219820Sjeff [IB_QPS_SQD] = { 539219820Sjeff .valid = 1, 540219820Sjeff .opt_param = { 541219820Sjeff [IB_QPT_UD] = IB_QP_EN_SQD_ASYNC_NOTIFY, 542219820Sjeff [IB_QPT_UC] = IB_QP_EN_SQD_ASYNC_NOTIFY, 543219820Sjeff [IB_QPT_RC] = IB_QP_EN_SQD_ASYNC_NOTIFY, 544219820Sjeff [IB_QPT_XRC] = IB_QP_EN_SQD_ASYNC_NOTIFY, 545219820Sjeff [IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY, 546219820Sjeff [IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY 547219820Sjeff } 548219820Sjeff }, 549219820Sjeff }, 550219820Sjeff [IB_QPS_SQD] = { 551219820Sjeff [IB_QPS_RESET] = { .valid = 1 }, 552219820Sjeff [IB_QPS_ERR] = { .valid = 1 }, 553219820Sjeff [IB_QPS_RTS] = { 554219820Sjeff .valid = 1, 555219820Sjeff .opt_param = { 556219820Sjeff [IB_QPT_UD] = (IB_QP_CUR_STATE | 557219820Sjeff IB_QP_QKEY), 558219820Sjeff [IB_QPT_UC] = (IB_QP_CUR_STATE | 559219820Sjeff IB_QP_ALT_PATH | 560219820Sjeff IB_QP_ACCESS_FLAGS | 561219820Sjeff IB_QP_PATH_MIG_STATE), 562219820Sjeff [IB_QPT_RC] = (IB_QP_CUR_STATE | 563219820Sjeff IB_QP_ALT_PATH | 564219820Sjeff IB_QP_ACCESS_FLAGS | 565219820Sjeff IB_QP_MIN_RNR_TIMER | 566219820Sjeff IB_QP_PATH_MIG_STATE), 567219820Sjeff [IB_QPT_XRC] = (IB_QP_CUR_STATE | 568219820Sjeff IB_QP_ALT_PATH | 569219820Sjeff IB_QP_ACCESS_FLAGS | 570219820Sjeff IB_QP_MIN_RNR_TIMER | 571219820Sjeff IB_QP_PATH_MIG_STATE), 572219820Sjeff [IB_QPT_SMI] = (IB_QP_CUR_STATE | 573219820Sjeff IB_QP_QKEY), 574219820Sjeff [IB_QPT_GSI] = (IB_QP_CUR_STATE | 575219820Sjeff IB_QP_QKEY), 576219820Sjeff } 577219820Sjeff }, 578219820Sjeff [IB_QPS_SQD] = { 579219820Sjeff .valid = 1, 580219820Sjeff .opt_param = { 581219820Sjeff [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 582219820Sjeff IB_QP_QKEY), 583219820Sjeff [IB_QPT_UC] = (IB_QP_AV | 584219820Sjeff IB_QP_ALT_PATH | 585219820Sjeff IB_QP_ACCESS_FLAGS | 586219820Sjeff IB_QP_PKEY_INDEX | 587219820Sjeff IB_QP_PATH_MIG_STATE), 588219820Sjeff [IB_QPT_RC] = (IB_QP_PORT | 589219820Sjeff IB_QP_AV | 590219820Sjeff IB_QP_TIMEOUT | 591219820Sjeff IB_QP_RETRY_CNT | 592219820Sjeff IB_QP_RNR_RETRY | 593219820Sjeff IB_QP_MAX_QP_RD_ATOMIC | 594219820Sjeff IB_QP_MAX_DEST_RD_ATOMIC | 595219820Sjeff IB_QP_ALT_PATH | 596219820Sjeff IB_QP_ACCESS_FLAGS | 597219820Sjeff IB_QP_PKEY_INDEX | 598219820Sjeff IB_QP_MIN_RNR_TIMER | 599219820Sjeff IB_QP_PATH_MIG_STATE), 600219820Sjeff [IB_QPT_XRC] = (IB_QP_PORT | 601219820Sjeff IB_QP_AV | 602219820Sjeff IB_QP_TIMEOUT | 603219820Sjeff IB_QP_RETRY_CNT | 604219820Sjeff IB_QP_RNR_RETRY | 605219820Sjeff IB_QP_MAX_QP_RD_ATOMIC | 606219820Sjeff IB_QP_MAX_DEST_RD_ATOMIC | 607219820Sjeff IB_QP_ALT_PATH | 608219820Sjeff IB_QP_ACCESS_FLAGS | 609219820Sjeff IB_QP_PKEY_INDEX | 610219820Sjeff IB_QP_MIN_RNR_TIMER | 611219820Sjeff IB_QP_PATH_MIG_STATE), 612219820Sjeff [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | 613219820Sjeff IB_QP_QKEY), 614219820Sjeff [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 615219820Sjeff IB_QP_QKEY), 616219820Sjeff } 617219820Sjeff } 618219820Sjeff }, 619219820Sjeff [IB_QPS_SQE] = { 620219820Sjeff [IB_QPS_RESET] = { .valid = 1 }, 621219820Sjeff [IB_QPS_ERR] = { .valid = 1 }, 622219820Sjeff [IB_QPS_RTS] = { 623219820Sjeff .valid = 1, 624219820Sjeff .opt_param = { 625219820Sjeff [IB_QPT_UD] = (IB_QP_CUR_STATE | 626219820Sjeff IB_QP_QKEY), 627219820Sjeff [IB_QPT_UC] = (IB_QP_CUR_STATE | 628219820Sjeff IB_QP_ACCESS_FLAGS), 629219820Sjeff [IB_QPT_SMI] = (IB_QP_CUR_STATE | 630219820Sjeff IB_QP_QKEY), 631219820Sjeff [IB_QPT_GSI] = (IB_QP_CUR_STATE | 632219820Sjeff IB_QP_QKEY), 633219820Sjeff } 634219820Sjeff } 635219820Sjeff }, 636219820Sjeff [IB_QPS_ERR] = { 637219820Sjeff [IB_QPS_RESET] = { .valid = 1 }, 638219820Sjeff [IB_QPS_ERR] = { .valid = 1 } 639219820Sjeff } 640219820Sjeff}; 641219820Sjeff 642219820Sjeffint ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state, 643219820Sjeff enum ib_qp_type type, enum ib_qp_attr_mask mask) 644219820Sjeff{ 645219820Sjeff enum ib_qp_attr_mask req_param, opt_param; 646219820Sjeff 647219820Sjeff if (cur_state < 0 || cur_state > IB_QPS_ERR || 648219820Sjeff next_state < 0 || next_state > IB_QPS_ERR) 649219820Sjeff return 0; 650219820Sjeff 651219820Sjeff if (mask & IB_QP_CUR_STATE && 652219820Sjeff cur_state != IB_QPS_RTR && cur_state != IB_QPS_RTS && 653219820Sjeff cur_state != IB_QPS_SQD && cur_state != IB_QPS_SQE) 654219820Sjeff return 0; 655219820Sjeff 656219820Sjeff if (!qp_state_table[cur_state][next_state].valid) 657219820Sjeff return 0; 658219820Sjeff 659219820Sjeff req_param = qp_state_table[cur_state][next_state].req_param[type]; 660219820Sjeff opt_param = qp_state_table[cur_state][next_state].opt_param[type]; 661219820Sjeff 662219820Sjeff if ((mask & req_param) != req_param) 663219820Sjeff return 0; 664219820Sjeff 665219820Sjeff if (mask & ~(req_param | opt_param | IB_QP_STATE)) 666219820Sjeff return 0; 667219820Sjeff 668219820Sjeff return 1; 669219820Sjeff} 670219820SjeffEXPORT_SYMBOL(ib_modify_qp_is_ok); 671219820Sjeff 672219820Sjeffint ib_modify_qp(struct ib_qp *qp, 673219820Sjeff struct ib_qp_attr *qp_attr, 674219820Sjeff int qp_attr_mask) 675219820Sjeff{ 676219820Sjeff return qp->device->modify_qp(qp, qp_attr, qp_attr_mask, NULL); 677219820Sjeff} 678219820SjeffEXPORT_SYMBOL(ib_modify_qp); 679219820Sjeff 680219820Sjeffint ib_query_qp(struct ib_qp *qp, 681219820Sjeff struct ib_qp_attr *qp_attr, 682219820Sjeff int qp_attr_mask, 683219820Sjeff struct ib_qp_init_attr *qp_init_attr) 684219820Sjeff{ 685219820Sjeff return qp->device->query_qp ? 686219820Sjeff qp->device->query_qp(qp, qp_attr, qp_attr_mask, qp_init_attr) : 687219820Sjeff -ENOSYS; 688219820Sjeff} 689219820SjeffEXPORT_SYMBOL(ib_query_qp); 690219820Sjeff 691219820Sjeffint ib_destroy_qp(struct ib_qp *qp) 692219820Sjeff{ 693219820Sjeff struct ib_pd *pd; 694219820Sjeff struct ib_cq *scq, *rcq; 695219820Sjeff struct ib_srq *srq; 696219820Sjeff struct ib_xrcd *xrcd; 697219820Sjeff enum ib_qp_type qp_type = qp->qp_type; 698219820Sjeff int ret; 699219820Sjeff 700219820Sjeff pd = qp->pd; 701219820Sjeff scq = qp->send_cq; 702219820Sjeff rcq = qp->recv_cq; 703219820Sjeff srq = qp->srq; 704219820Sjeff xrcd = qp->xrcd; 705219820Sjeff 706219820Sjeff ret = qp->device->destroy_qp(qp); 707219820Sjeff if (!ret) { 708219820Sjeff atomic_dec(&pd->usecnt); 709219820Sjeff atomic_dec(&scq->usecnt); 710219820Sjeff atomic_dec(&rcq->usecnt); 711219820Sjeff if (srq) 712219820Sjeff atomic_dec(&srq->usecnt); 713219820Sjeff if (qp_type == IB_QPT_XRC) 714219820Sjeff atomic_dec(&xrcd->usecnt); 715219820Sjeff } 716219820Sjeff 717219820Sjeff return ret; 718219820Sjeff} 719219820SjeffEXPORT_SYMBOL(ib_destroy_qp); 720219820Sjeff 721219820Sjeff/* Completion queues */ 722219820Sjeff 723219820Sjeffstruct ib_cq *ib_create_cq(struct ib_device *device, 724219820Sjeff ib_comp_handler comp_handler, 725219820Sjeff void (*event_handler)(struct ib_event *, void *), 726219820Sjeff void *cq_context, int cqe, int comp_vector) 727219820Sjeff{ 728219820Sjeff struct ib_cq *cq; 729219820Sjeff 730219820Sjeff cq = device->create_cq(device, cqe, comp_vector, NULL, NULL); 731219820Sjeff 732219820Sjeff if (!IS_ERR(cq)) { 733219820Sjeff cq->device = device; 734219820Sjeff cq->uobject = NULL; 735219820Sjeff cq->comp_handler = comp_handler; 736219820Sjeff cq->event_handler = event_handler; 737219820Sjeff cq->cq_context = cq_context; 738219820Sjeff atomic_set(&cq->usecnt, 0); 739219820Sjeff } 740219820Sjeff 741219820Sjeff return cq; 742219820Sjeff} 743219820SjeffEXPORT_SYMBOL(ib_create_cq); 744219820Sjeff 745219820Sjeffint ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period) 746219820Sjeff{ 747219820Sjeff return cq->device->modify_cq ? 748219820Sjeff cq->device->modify_cq(cq, cq_count, cq_period) : -ENOSYS; 749219820Sjeff} 750219820SjeffEXPORT_SYMBOL(ib_modify_cq); 751219820Sjeff 752219820Sjeffint ib_destroy_cq(struct ib_cq *cq) 753219820Sjeff{ 754219820Sjeff if (atomic_read(&cq->usecnt)) 755219820Sjeff return -EBUSY; 756219820Sjeff 757219820Sjeff return cq->device->destroy_cq(cq); 758219820Sjeff} 759219820SjeffEXPORT_SYMBOL(ib_destroy_cq); 760219820Sjeff 761219820Sjeffint ib_resize_cq(struct ib_cq *cq, int cqe) 762219820Sjeff{ 763219820Sjeff return cq->device->resize_cq ? 764219820Sjeff cq->device->resize_cq(cq, cqe, NULL) : -ENOSYS; 765219820Sjeff} 766219820SjeffEXPORT_SYMBOL(ib_resize_cq); 767219820Sjeff 768219820Sjeff/* Memory regions */ 769219820Sjeff 770219820Sjeffstruct ib_mr *ib_get_dma_mr(struct ib_pd *pd, int mr_access_flags) 771219820Sjeff{ 772219820Sjeff struct ib_mr *mr; 773219820Sjeff 774219820Sjeff mr = pd->device->get_dma_mr(pd, mr_access_flags); 775219820Sjeff 776219820Sjeff if (!IS_ERR(mr)) { 777219820Sjeff mr->device = pd->device; 778219820Sjeff mr->pd = pd; 779219820Sjeff mr->uobject = NULL; 780219820Sjeff atomic_inc(&pd->usecnt); 781219820Sjeff atomic_set(&mr->usecnt, 0); 782219820Sjeff } 783219820Sjeff 784219820Sjeff return mr; 785219820Sjeff} 786219820SjeffEXPORT_SYMBOL(ib_get_dma_mr); 787219820Sjeff 788219820Sjeffstruct ib_mr *ib_reg_phys_mr(struct ib_pd *pd, 789219820Sjeff struct ib_phys_buf *phys_buf_array, 790219820Sjeff int num_phys_buf, 791219820Sjeff int mr_access_flags, 792219820Sjeff u64 *iova_start) 793219820Sjeff{ 794219820Sjeff struct ib_mr *mr; 795219820Sjeff 796219820Sjeff if (!pd->device->reg_phys_mr) 797219820Sjeff return ERR_PTR(-ENOSYS); 798219820Sjeff 799219820Sjeff mr = pd->device->reg_phys_mr(pd, phys_buf_array, num_phys_buf, 800219820Sjeff mr_access_flags, iova_start); 801219820Sjeff 802219820Sjeff if (!IS_ERR(mr)) { 803219820Sjeff mr->device = pd->device; 804219820Sjeff mr->pd = pd; 805219820Sjeff mr->uobject = NULL; 806219820Sjeff atomic_inc(&pd->usecnt); 807219820Sjeff atomic_set(&mr->usecnt, 0); 808219820Sjeff } 809219820Sjeff 810219820Sjeff return mr; 811219820Sjeff} 812219820SjeffEXPORT_SYMBOL(ib_reg_phys_mr); 813219820Sjeff 814219820Sjeffint ib_rereg_phys_mr(struct ib_mr *mr, 815219820Sjeff int mr_rereg_mask, 816219820Sjeff struct ib_pd *pd, 817219820Sjeff struct ib_phys_buf *phys_buf_array, 818219820Sjeff int num_phys_buf, 819219820Sjeff int mr_access_flags, 820219820Sjeff u64 *iova_start) 821219820Sjeff{ 822219820Sjeff struct ib_pd *old_pd; 823219820Sjeff int ret; 824219820Sjeff 825219820Sjeff if (!mr->device->rereg_phys_mr) 826219820Sjeff return -ENOSYS; 827219820Sjeff 828219820Sjeff if (atomic_read(&mr->usecnt)) 829219820Sjeff return -EBUSY; 830219820Sjeff 831219820Sjeff old_pd = mr->pd; 832219820Sjeff 833219820Sjeff ret = mr->device->rereg_phys_mr(mr, mr_rereg_mask, pd, 834219820Sjeff phys_buf_array, num_phys_buf, 835219820Sjeff mr_access_flags, iova_start); 836219820Sjeff 837219820Sjeff if (!ret && (mr_rereg_mask & IB_MR_REREG_PD)) { 838219820Sjeff atomic_dec(&old_pd->usecnt); 839219820Sjeff atomic_inc(&pd->usecnt); 840219820Sjeff } 841219820Sjeff 842219820Sjeff return ret; 843219820Sjeff} 844219820SjeffEXPORT_SYMBOL(ib_rereg_phys_mr); 845219820Sjeff 846219820Sjeffint ib_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr) 847219820Sjeff{ 848219820Sjeff return mr->device->query_mr ? 849219820Sjeff mr->device->query_mr(mr, mr_attr) : -ENOSYS; 850219820Sjeff} 851219820SjeffEXPORT_SYMBOL(ib_query_mr); 852219820Sjeff 853219820Sjeffint ib_dereg_mr(struct ib_mr *mr) 854219820Sjeff{ 855219820Sjeff struct ib_pd *pd; 856219820Sjeff int ret; 857219820Sjeff 858219820Sjeff if (atomic_read(&mr->usecnt)) 859219820Sjeff return -EBUSY; 860219820Sjeff 861219820Sjeff pd = mr->pd; 862219820Sjeff ret = mr->device->dereg_mr(mr); 863219820Sjeff if (!ret) 864219820Sjeff atomic_dec(&pd->usecnt); 865219820Sjeff 866219820Sjeff return ret; 867219820Sjeff} 868219820SjeffEXPORT_SYMBOL(ib_dereg_mr); 869219820Sjeff 870219820Sjeffstruct ib_mr *ib_alloc_fast_reg_mr(struct ib_pd *pd, int max_page_list_len) 871219820Sjeff{ 872219820Sjeff struct ib_mr *mr; 873219820Sjeff 874219820Sjeff if (!pd->device->alloc_fast_reg_mr) 875219820Sjeff return ERR_PTR(-ENOSYS); 876219820Sjeff 877219820Sjeff mr = pd->device->alloc_fast_reg_mr(pd, max_page_list_len); 878219820Sjeff 879219820Sjeff if (!IS_ERR(mr)) { 880219820Sjeff mr->device = pd->device; 881219820Sjeff mr->pd = pd; 882219820Sjeff mr->uobject = NULL; 883219820Sjeff atomic_inc(&pd->usecnt); 884219820Sjeff atomic_set(&mr->usecnt, 0); 885219820Sjeff } 886219820Sjeff 887219820Sjeff return mr; 888219820Sjeff} 889219820SjeffEXPORT_SYMBOL(ib_alloc_fast_reg_mr); 890219820Sjeff 891219820Sjeffstruct ib_fast_reg_page_list *ib_alloc_fast_reg_page_list(struct ib_device *device, 892219820Sjeff int max_page_list_len) 893219820Sjeff{ 894219820Sjeff struct ib_fast_reg_page_list *page_list; 895219820Sjeff 896219820Sjeff if (!device->alloc_fast_reg_page_list) 897219820Sjeff return ERR_PTR(-ENOSYS); 898219820Sjeff 899219820Sjeff page_list = device->alloc_fast_reg_page_list(device, max_page_list_len); 900219820Sjeff 901219820Sjeff if (!IS_ERR(page_list)) { 902219820Sjeff page_list->device = device; 903219820Sjeff page_list->max_page_list_len = max_page_list_len; 904219820Sjeff } 905219820Sjeff 906219820Sjeff return page_list; 907219820Sjeff} 908219820SjeffEXPORT_SYMBOL(ib_alloc_fast_reg_page_list); 909219820Sjeff 910219820Sjeffvoid ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list) 911219820Sjeff{ 912219820Sjeff page_list->device->free_fast_reg_page_list(page_list); 913219820Sjeff} 914219820SjeffEXPORT_SYMBOL(ib_free_fast_reg_page_list); 915219820Sjeff 916219820Sjeff/* Memory windows */ 917219820Sjeff 918219820Sjeffstruct ib_mw *ib_alloc_mw(struct ib_pd *pd) 919219820Sjeff{ 920219820Sjeff struct ib_mw *mw; 921219820Sjeff 922219820Sjeff if (!pd->device->alloc_mw) 923219820Sjeff return ERR_PTR(-ENOSYS); 924219820Sjeff 925219820Sjeff mw = pd->device->alloc_mw(pd); 926219820Sjeff if (!IS_ERR(mw)) { 927219820Sjeff mw->device = pd->device; 928219820Sjeff mw->pd = pd; 929219820Sjeff mw->uobject = NULL; 930219820Sjeff atomic_inc(&pd->usecnt); 931219820Sjeff } 932219820Sjeff 933219820Sjeff return mw; 934219820Sjeff} 935219820SjeffEXPORT_SYMBOL(ib_alloc_mw); 936219820Sjeff 937219820Sjeffint ib_dealloc_mw(struct ib_mw *mw) 938219820Sjeff{ 939219820Sjeff struct ib_pd *pd; 940219820Sjeff int ret; 941219820Sjeff 942219820Sjeff pd = mw->pd; 943219820Sjeff ret = mw->device->dealloc_mw(mw); 944219820Sjeff if (!ret) 945219820Sjeff atomic_dec(&pd->usecnt); 946219820Sjeff 947219820Sjeff return ret; 948219820Sjeff} 949219820SjeffEXPORT_SYMBOL(ib_dealloc_mw); 950219820Sjeff 951219820Sjeff/* "Fast" memory regions */ 952219820Sjeff 953219820Sjeffstruct ib_fmr *ib_alloc_fmr(struct ib_pd *pd, 954219820Sjeff int mr_access_flags, 955219820Sjeff struct ib_fmr_attr *fmr_attr) 956219820Sjeff{ 957219820Sjeff struct ib_fmr *fmr; 958219820Sjeff 959219820Sjeff if (!pd->device->alloc_fmr) 960219820Sjeff return ERR_PTR(-ENOSYS); 961219820Sjeff 962219820Sjeff fmr = pd->device->alloc_fmr(pd, mr_access_flags, fmr_attr); 963219820Sjeff if (!IS_ERR(fmr)) { 964219820Sjeff fmr->device = pd->device; 965219820Sjeff fmr->pd = pd; 966219820Sjeff atomic_inc(&pd->usecnt); 967219820Sjeff } 968219820Sjeff 969219820Sjeff return fmr; 970219820Sjeff} 971219820SjeffEXPORT_SYMBOL(ib_alloc_fmr); 972219820Sjeff 973219820Sjeffint ib_unmap_fmr(struct list_head *fmr_list) 974219820Sjeff{ 975219820Sjeff struct ib_fmr *fmr; 976219820Sjeff 977219820Sjeff if (list_empty(fmr_list)) 978219820Sjeff return 0; 979219820Sjeff 980219820Sjeff fmr = list_entry(fmr_list->next, struct ib_fmr, list); 981219820Sjeff return fmr->device->unmap_fmr(fmr_list); 982219820Sjeff} 983219820SjeffEXPORT_SYMBOL(ib_unmap_fmr); 984219820Sjeff 985219820Sjeffint ib_dealloc_fmr(struct ib_fmr *fmr) 986219820Sjeff{ 987219820Sjeff struct ib_pd *pd; 988219820Sjeff int ret; 989219820Sjeff 990219820Sjeff pd = fmr->pd; 991219820Sjeff ret = fmr->device->dealloc_fmr(fmr); 992219820Sjeff if (!ret) 993219820Sjeff atomic_dec(&pd->usecnt); 994219820Sjeff 995219820Sjeff return ret; 996219820Sjeff} 997219820SjeffEXPORT_SYMBOL(ib_dealloc_fmr); 998219820Sjeff 999219820Sjeff/* Multicast groups */ 1000219820Sjeff 1001219820Sjeffint ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid) 1002219820Sjeff{ 1003219820Sjeff if (!qp->device->attach_mcast) 1004219820Sjeff return -ENOSYS; 1005219820Sjeff 1006219820Sjeff switch (rdma_node_get_transport(qp->device->node_type)) { 1007219820Sjeff case RDMA_TRANSPORT_IB: 1008219820Sjeff if (qp->qp_type == IB_QPT_RAW_ETH) { 1009219820Sjeff /* In raw Etherent mgids the 63 msb's should be 0 */ 1010219820Sjeff if (gid->global.subnet_prefix & cpu_to_be64(~1ULL)) 1011219820Sjeff return -EINVAL; 1012219820Sjeff } else if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD) 1013219820Sjeff return -EINVAL; 1014219820Sjeff break; 1015219820Sjeff case RDMA_TRANSPORT_IWARP: 1016219820Sjeff if (qp->qp_type != IB_QPT_RAW_ETH) 1017219820Sjeff return -EINVAL; 1018219820Sjeff break; 1019219820Sjeff } 1020219820Sjeff return qp->device->attach_mcast(qp, gid, lid); 1021219820Sjeff} 1022219820SjeffEXPORT_SYMBOL(ib_attach_mcast); 1023219820Sjeff 1024219820Sjeffint ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid) 1025219820Sjeff{ 1026219820Sjeff if (!qp->device->detach_mcast) 1027219820Sjeff return -ENOSYS; 1028219820Sjeff 1029219820Sjeff switch (rdma_node_get_transport(qp->device->node_type)) { 1030219820Sjeff case RDMA_TRANSPORT_IB: 1031219820Sjeff if (qp->qp_type == IB_QPT_RAW_ETH) { 1032219820Sjeff /* In raw Etherent mgids the 63 msb's should be 0 */ 1033219820Sjeff if (gid->global.subnet_prefix & cpu_to_be64(~1ULL)) 1034219820Sjeff return -EINVAL; 1035219820Sjeff } else if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD) 1036219820Sjeff return -EINVAL; 1037219820Sjeff break; 1038219820Sjeff case RDMA_TRANSPORT_IWARP: 1039219820Sjeff if (qp->qp_type != IB_QPT_RAW_ETH) 1040219820Sjeff return -EINVAL; 1041219820Sjeff break; 1042219820Sjeff } 1043219820Sjeff return qp->device->detach_mcast(qp, gid, lid); 1044219820Sjeff} 1045219820SjeffEXPORT_SYMBOL(ib_detach_mcast); 1046219820Sjeff 1047219820Sjeffint ib_dealloc_xrcd(struct ib_xrcd *xrcd) 1048219820Sjeff{ 1049219820Sjeff if (atomic_read(&xrcd->usecnt)) 1050219820Sjeff return -EBUSY; 1051219820Sjeff 1052219820Sjeff return xrcd->device->dealloc_xrcd(xrcd); 1053219820Sjeff} 1054219820SjeffEXPORT_SYMBOL(ib_dealloc_xrcd); 1055219820Sjeff 1056219820Sjeffstruct ib_xrcd *ib_alloc_xrcd(struct ib_device *device) 1057219820Sjeff{ 1058219820Sjeff struct ib_xrcd *xrcd; 1059219820Sjeff 1060219820Sjeff if (!device->alloc_xrcd) 1061219820Sjeff return ERR_PTR(-ENOSYS); 1062219820Sjeff 1063219820Sjeff xrcd = device->alloc_xrcd(device, NULL, NULL); 1064219820Sjeff if (!IS_ERR(xrcd)) { 1065219820Sjeff xrcd->device = device; 1066219820Sjeff xrcd->inode = NULL; 1067219820Sjeff xrcd->uobject = NULL; 1068219820Sjeff atomic_set(&xrcd->usecnt, 0); 1069219820Sjeff } 1070219820Sjeff return xrcd; 1071219820Sjeff} 1072219820SjeffEXPORT_SYMBOL(ib_alloc_xrcd); 1073219820Sjeff 1074