11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved. 31da177e4SLinus Torvalds * Copyright (c) 2004 Infinicon Corporation. All rights reserved. 41da177e4SLinus Torvalds * Copyright (c) 2004 Intel Corporation. All rights reserved. 51da177e4SLinus Torvalds * Copyright (c) 2004 Topspin Corporation. All rights reserved. 61da177e4SLinus Torvalds * Copyright (c) 2004 Voltaire Corporation. All rights reserved. 72a1d9b7fSRoland Dreier * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 8b5e81bf5SRoland Dreier * Copyright (c) 2005 Cisco Systems. All rights reserved. 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * This software is available to you under a choice of one of two 111da177e4SLinus Torvalds * licenses. You may choose to be licensed under the terms of the GNU 121da177e4SLinus Torvalds * General Public License (GPL) Version 2, available from the file 131da177e4SLinus Torvalds * COPYING in the main directory of this source tree, or the 141da177e4SLinus Torvalds * OpenIB.org BSD license below: 151da177e4SLinus Torvalds * 161da177e4SLinus Torvalds * Redistribution and use in source and binary forms, with or 171da177e4SLinus Torvalds * without modification, are permitted provided that the following 181da177e4SLinus Torvalds * conditions are met: 191da177e4SLinus Torvalds * 201da177e4SLinus Torvalds * - Redistributions of source code must retain the above 211da177e4SLinus Torvalds * copyright notice, this list of conditions and the following 221da177e4SLinus Torvalds * disclaimer. 231da177e4SLinus Torvalds * 241da177e4SLinus Torvalds * - Redistributions in binary form must reproduce the above 251da177e4SLinus Torvalds * copyright notice, this list of conditions and the following 261da177e4SLinus Torvalds * disclaimer in the documentation and/or other materials 271da177e4SLinus Torvalds * provided with the distribution. 281da177e4SLinus Torvalds * 291da177e4SLinus Torvalds * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 301da177e4SLinus Torvalds * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 311da177e4SLinus Torvalds * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 321da177e4SLinus Torvalds * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 331da177e4SLinus Torvalds * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 341da177e4SLinus Torvalds * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 351da177e4SLinus Torvalds * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 361da177e4SLinus Torvalds * SOFTWARE. 371da177e4SLinus Torvalds * 381da177e4SLinus Torvalds * $Id: verbs.c 1349 2004-12-16 21:09:43Z roland $ 391da177e4SLinus Torvalds */ 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds #include <linux/errno.h> 421da177e4SLinus Torvalds #include <linux/err.h> 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds #include <ib_verbs.h> 45513789edSHal Rosenstock #include <ib_cache.h> 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds /* Protection domains */ 481da177e4SLinus Torvalds 491da177e4SLinus Torvalds struct ib_pd *ib_alloc_pd(struct ib_device *device) 501da177e4SLinus Torvalds { 511da177e4SLinus Torvalds struct ib_pd *pd; 521da177e4SLinus Torvalds 53b5e81bf5SRoland Dreier pd = device->alloc_pd(device, NULL, NULL); 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds if (!IS_ERR(pd)) { 561da177e4SLinus Torvalds pd->device = device; 57b5e81bf5SRoland Dreier pd->uobject = NULL; 581da177e4SLinus Torvalds atomic_set(&pd->usecnt, 0); 591da177e4SLinus Torvalds } 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds return pd; 621da177e4SLinus Torvalds } 631da177e4SLinus Torvalds EXPORT_SYMBOL(ib_alloc_pd); 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds int ib_dealloc_pd(struct ib_pd *pd) 661da177e4SLinus Torvalds { 671da177e4SLinus Torvalds if (atomic_read(&pd->usecnt)) 681da177e4SLinus Torvalds return -EBUSY; 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds return pd->device->dealloc_pd(pd); 711da177e4SLinus Torvalds } 721da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dealloc_pd); 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds /* Address handles */ 751da177e4SLinus Torvalds 761da177e4SLinus Torvalds struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) 771da177e4SLinus Torvalds { 781da177e4SLinus Torvalds struct ib_ah *ah; 791da177e4SLinus Torvalds 801da177e4SLinus Torvalds ah = pd->device->create_ah(pd, ah_attr); 811da177e4SLinus Torvalds 821da177e4SLinus Torvalds if (!IS_ERR(ah)) { 831da177e4SLinus Torvalds ah->device = pd->device; 841da177e4SLinus Torvalds ah->pd = pd; 85b5e81bf5SRoland Dreier ah->uobject = NULL; 861da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 871da177e4SLinus Torvalds } 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds return ah; 901da177e4SLinus Torvalds } 911da177e4SLinus Torvalds EXPORT_SYMBOL(ib_create_ah); 921da177e4SLinus Torvalds 93513789edSHal Rosenstock struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc, 94513789edSHal Rosenstock struct ib_grh *grh, u8 port_num) 95513789edSHal Rosenstock { 96513789edSHal Rosenstock struct ib_ah_attr ah_attr; 97513789edSHal Rosenstock u32 flow_class; 98513789edSHal Rosenstock u16 gid_index; 99513789edSHal Rosenstock int ret; 100513789edSHal Rosenstock 101513789edSHal Rosenstock memset(&ah_attr, 0, sizeof ah_attr); 102513789edSHal Rosenstock ah_attr.dlid = wc->slid; 103513789edSHal Rosenstock ah_attr.sl = wc->sl; 104513789edSHal Rosenstock ah_attr.src_path_bits = wc->dlid_path_bits; 105513789edSHal Rosenstock ah_attr.port_num = port_num; 106513789edSHal Rosenstock 107513789edSHal Rosenstock if (wc->wc_flags & IB_WC_GRH) { 108513789edSHal Rosenstock ah_attr.ah_flags = IB_AH_GRH; 109513789edSHal Rosenstock ah_attr.grh.dgid = grh->dgid; 110513789edSHal Rosenstock 111513789edSHal Rosenstock ret = ib_find_cached_gid(pd->device, &grh->sgid, &port_num, 112513789edSHal Rosenstock &gid_index); 113513789edSHal Rosenstock if (ret) 114513789edSHal Rosenstock return ERR_PTR(ret); 115513789edSHal Rosenstock 116513789edSHal Rosenstock ah_attr.grh.sgid_index = (u8) gid_index; 117497677abSHal Rosenstock flow_class = be32_to_cpu(grh->version_tclass_flow); 118513789edSHal Rosenstock ah_attr.grh.flow_label = flow_class & 0xFFFFF; 119513789edSHal Rosenstock ah_attr.grh.traffic_class = (flow_class >> 20) & 0xFF; 120513789edSHal Rosenstock ah_attr.grh.hop_limit = grh->hop_limit; 121513789edSHal Rosenstock } 122513789edSHal Rosenstock 123513789edSHal Rosenstock return ib_create_ah(pd, &ah_attr); 124513789edSHal Rosenstock } 125513789edSHal Rosenstock EXPORT_SYMBOL(ib_create_ah_from_wc); 126513789edSHal Rosenstock 1271da177e4SLinus Torvalds int ib_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) 1281da177e4SLinus Torvalds { 1291da177e4SLinus Torvalds return ah->device->modify_ah ? 1301da177e4SLinus Torvalds ah->device->modify_ah(ah, ah_attr) : 1311da177e4SLinus Torvalds -ENOSYS; 1321da177e4SLinus Torvalds } 1331da177e4SLinus Torvalds EXPORT_SYMBOL(ib_modify_ah); 1341da177e4SLinus Torvalds 1351da177e4SLinus Torvalds int ib_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) 1361da177e4SLinus Torvalds { 1371da177e4SLinus Torvalds return ah->device->query_ah ? 1381da177e4SLinus Torvalds ah->device->query_ah(ah, ah_attr) : 1391da177e4SLinus Torvalds -ENOSYS; 1401da177e4SLinus Torvalds } 1411da177e4SLinus Torvalds EXPORT_SYMBOL(ib_query_ah); 1421da177e4SLinus Torvalds 1431da177e4SLinus Torvalds int ib_destroy_ah(struct ib_ah *ah) 1441da177e4SLinus Torvalds { 1451da177e4SLinus Torvalds struct ib_pd *pd; 1461da177e4SLinus Torvalds int ret; 1471da177e4SLinus Torvalds 1481da177e4SLinus Torvalds pd = ah->pd; 1491da177e4SLinus Torvalds ret = ah->device->destroy_ah(ah); 1501da177e4SLinus Torvalds if (!ret) 1511da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds return ret; 1541da177e4SLinus Torvalds } 1551da177e4SLinus Torvalds EXPORT_SYMBOL(ib_destroy_ah); 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds /* Queue pairs */ 1581da177e4SLinus Torvalds 1591da177e4SLinus Torvalds struct ib_qp *ib_create_qp(struct ib_pd *pd, 1601da177e4SLinus Torvalds struct ib_qp_init_attr *qp_init_attr) 1611da177e4SLinus Torvalds { 1621da177e4SLinus Torvalds struct ib_qp *qp; 1631da177e4SLinus Torvalds 164b5e81bf5SRoland Dreier qp = pd->device->create_qp(pd, qp_init_attr, NULL); 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds if (!IS_ERR(qp)) { 1671da177e4SLinus Torvalds qp->device = pd->device; 1681da177e4SLinus Torvalds qp->pd = pd; 1691da177e4SLinus Torvalds qp->send_cq = qp_init_attr->send_cq; 1701da177e4SLinus Torvalds qp->recv_cq = qp_init_attr->recv_cq; 1711da177e4SLinus Torvalds qp->srq = qp_init_attr->srq; 172b5e81bf5SRoland Dreier qp->uobject = NULL; 1731da177e4SLinus Torvalds qp->event_handler = qp_init_attr->event_handler; 1741da177e4SLinus Torvalds qp->qp_context = qp_init_attr->qp_context; 1751da177e4SLinus Torvalds qp->qp_type = qp_init_attr->qp_type; 1761da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 1771da177e4SLinus Torvalds atomic_inc(&qp_init_attr->send_cq->usecnt); 1781da177e4SLinus Torvalds atomic_inc(&qp_init_attr->recv_cq->usecnt); 1791da177e4SLinus Torvalds if (qp_init_attr->srq) 1801da177e4SLinus Torvalds atomic_inc(&qp_init_attr->srq->usecnt); 1811da177e4SLinus Torvalds } 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds return qp; 1841da177e4SLinus Torvalds } 1851da177e4SLinus Torvalds EXPORT_SYMBOL(ib_create_qp); 1861da177e4SLinus Torvalds 1871da177e4SLinus Torvalds int ib_modify_qp(struct ib_qp *qp, 1881da177e4SLinus Torvalds struct ib_qp_attr *qp_attr, 1891da177e4SLinus Torvalds int qp_attr_mask) 1901da177e4SLinus Torvalds { 1911da177e4SLinus Torvalds return qp->device->modify_qp(qp, qp_attr, qp_attr_mask); 1921da177e4SLinus Torvalds } 1931da177e4SLinus Torvalds EXPORT_SYMBOL(ib_modify_qp); 1941da177e4SLinus Torvalds 1951da177e4SLinus Torvalds int ib_query_qp(struct ib_qp *qp, 1961da177e4SLinus Torvalds struct ib_qp_attr *qp_attr, 1971da177e4SLinus Torvalds int qp_attr_mask, 1981da177e4SLinus Torvalds struct ib_qp_init_attr *qp_init_attr) 1991da177e4SLinus Torvalds { 2001da177e4SLinus Torvalds return qp->device->query_qp ? 2011da177e4SLinus Torvalds qp->device->query_qp(qp, qp_attr, qp_attr_mask, qp_init_attr) : 2021da177e4SLinus Torvalds -ENOSYS; 2031da177e4SLinus Torvalds } 2041da177e4SLinus Torvalds EXPORT_SYMBOL(ib_query_qp); 2051da177e4SLinus Torvalds 2061da177e4SLinus Torvalds int ib_destroy_qp(struct ib_qp *qp) 2071da177e4SLinus Torvalds { 2081da177e4SLinus Torvalds struct ib_pd *pd; 2091da177e4SLinus Torvalds struct ib_cq *scq, *rcq; 2101da177e4SLinus Torvalds struct ib_srq *srq; 2111da177e4SLinus Torvalds int ret; 2121da177e4SLinus Torvalds 2131da177e4SLinus Torvalds pd = qp->pd; 2141da177e4SLinus Torvalds scq = qp->send_cq; 2151da177e4SLinus Torvalds rcq = qp->recv_cq; 2161da177e4SLinus Torvalds srq = qp->srq; 2171da177e4SLinus Torvalds 2181da177e4SLinus Torvalds ret = qp->device->destroy_qp(qp); 2191da177e4SLinus Torvalds if (!ret) { 2201da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 2211da177e4SLinus Torvalds atomic_dec(&scq->usecnt); 2221da177e4SLinus Torvalds atomic_dec(&rcq->usecnt); 2231da177e4SLinus Torvalds if (srq) 2241da177e4SLinus Torvalds atomic_dec(&srq->usecnt); 2251da177e4SLinus Torvalds } 2261da177e4SLinus Torvalds 2271da177e4SLinus Torvalds return ret; 2281da177e4SLinus Torvalds } 2291da177e4SLinus Torvalds EXPORT_SYMBOL(ib_destroy_qp); 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds /* Completion queues */ 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds struct ib_cq *ib_create_cq(struct ib_device *device, 2341da177e4SLinus Torvalds ib_comp_handler comp_handler, 2351da177e4SLinus Torvalds void (*event_handler)(struct ib_event *, void *), 2361da177e4SLinus Torvalds void *cq_context, int cqe) 2371da177e4SLinus Torvalds { 2381da177e4SLinus Torvalds struct ib_cq *cq; 2391da177e4SLinus Torvalds 240b5e81bf5SRoland Dreier cq = device->create_cq(device, cqe, NULL, NULL); 2411da177e4SLinus Torvalds 2421da177e4SLinus Torvalds if (!IS_ERR(cq)) { 2431da177e4SLinus Torvalds cq->device = device; 244b5e81bf5SRoland Dreier cq->uobject = NULL; 2451da177e4SLinus Torvalds cq->comp_handler = comp_handler; 2461da177e4SLinus Torvalds cq->event_handler = event_handler; 2471da177e4SLinus Torvalds cq->cq_context = cq_context; 2481da177e4SLinus Torvalds atomic_set(&cq->usecnt, 0); 2491da177e4SLinus Torvalds } 2501da177e4SLinus Torvalds 2511da177e4SLinus Torvalds return cq; 2521da177e4SLinus Torvalds } 2531da177e4SLinus Torvalds EXPORT_SYMBOL(ib_create_cq); 2541da177e4SLinus Torvalds 2551da177e4SLinus Torvalds int ib_destroy_cq(struct ib_cq *cq) 2561da177e4SLinus Torvalds { 2571da177e4SLinus Torvalds if (atomic_read(&cq->usecnt)) 2581da177e4SLinus Torvalds return -EBUSY; 2591da177e4SLinus Torvalds 2601da177e4SLinus Torvalds return cq->device->destroy_cq(cq); 2611da177e4SLinus Torvalds } 2621da177e4SLinus Torvalds EXPORT_SYMBOL(ib_destroy_cq); 2631da177e4SLinus Torvalds 2641da177e4SLinus Torvalds int ib_resize_cq(struct ib_cq *cq, 2651da177e4SLinus Torvalds int cqe) 2661da177e4SLinus Torvalds { 2671da177e4SLinus Torvalds int ret; 2681da177e4SLinus Torvalds 2691da177e4SLinus Torvalds if (!cq->device->resize_cq) 2701da177e4SLinus Torvalds return -ENOSYS; 2711da177e4SLinus Torvalds 2721da177e4SLinus Torvalds ret = cq->device->resize_cq(cq, &cqe); 2731da177e4SLinus Torvalds if (!ret) 2741da177e4SLinus Torvalds cq->cqe = cqe; 2751da177e4SLinus Torvalds 2761da177e4SLinus Torvalds return ret; 2771da177e4SLinus Torvalds } 2781da177e4SLinus Torvalds EXPORT_SYMBOL(ib_resize_cq); 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds /* Memory regions */ 2811da177e4SLinus Torvalds 2821da177e4SLinus Torvalds struct ib_mr *ib_get_dma_mr(struct ib_pd *pd, int mr_access_flags) 2831da177e4SLinus Torvalds { 2841da177e4SLinus Torvalds struct ib_mr *mr; 2851da177e4SLinus Torvalds 2861da177e4SLinus Torvalds mr = pd->device->get_dma_mr(pd, mr_access_flags); 2871da177e4SLinus Torvalds 2881da177e4SLinus Torvalds if (!IS_ERR(mr)) { 2891da177e4SLinus Torvalds mr->device = pd->device; 2901da177e4SLinus Torvalds mr->pd = pd; 291b5e81bf5SRoland Dreier mr->uobject = NULL; 2921da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 2931da177e4SLinus Torvalds atomic_set(&mr->usecnt, 0); 2941da177e4SLinus Torvalds } 2951da177e4SLinus Torvalds 2961da177e4SLinus Torvalds return mr; 2971da177e4SLinus Torvalds } 2981da177e4SLinus Torvalds EXPORT_SYMBOL(ib_get_dma_mr); 2991da177e4SLinus Torvalds 3001da177e4SLinus Torvalds struct ib_mr *ib_reg_phys_mr(struct ib_pd *pd, 3011da177e4SLinus Torvalds struct ib_phys_buf *phys_buf_array, 3021da177e4SLinus Torvalds int num_phys_buf, 3031da177e4SLinus Torvalds int mr_access_flags, 3041da177e4SLinus Torvalds u64 *iova_start) 3051da177e4SLinus Torvalds { 3061da177e4SLinus Torvalds struct ib_mr *mr; 3071da177e4SLinus Torvalds 3081da177e4SLinus Torvalds mr = pd->device->reg_phys_mr(pd, phys_buf_array, num_phys_buf, 3091da177e4SLinus Torvalds mr_access_flags, iova_start); 3101da177e4SLinus Torvalds 3111da177e4SLinus Torvalds if (!IS_ERR(mr)) { 3121da177e4SLinus Torvalds mr->device = pd->device; 3131da177e4SLinus Torvalds mr->pd = pd; 314b5e81bf5SRoland Dreier mr->uobject = NULL; 3151da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 3161da177e4SLinus Torvalds atomic_set(&mr->usecnt, 0); 3171da177e4SLinus Torvalds } 3181da177e4SLinus Torvalds 3191da177e4SLinus Torvalds return mr; 3201da177e4SLinus Torvalds } 3211da177e4SLinus Torvalds EXPORT_SYMBOL(ib_reg_phys_mr); 3221da177e4SLinus Torvalds 3231da177e4SLinus Torvalds int ib_rereg_phys_mr(struct ib_mr *mr, 3241da177e4SLinus Torvalds int mr_rereg_mask, 3251da177e4SLinus Torvalds struct ib_pd *pd, 3261da177e4SLinus Torvalds struct ib_phys_buf *phys_buf_array, 3271da177e4SLinus Torvalds int num_phys_buf, 3281da177e4SLinus Torvalds int mr_access_flags, 3291da177e4SLinus Torvalds u64 *iova_start) 3301da177e4SLinus Torvalds { 3311da177e4SLinus Torvalds struct ib_pd *old_pd; 3321da177e4SLinus Torvalds int ret; 3331da177e4SLinus Torvalds 3341da177e4SLinus Torvalds if (!mr->device->rereg_phys_mr) 3351da177e4SLinus Torvalds return -ENOSYS; 3361da177e4SLinus Torvalds 3371da177e4SLinus Torvalds if (atomic_read(&mr->usecnt)) 3381da177e4SLinus Torvalds return -EBUSY; 3391da177e4SLinus Torvalds 3401da177e4SLinus Torvalds old_pd = mr->pd; 3411da177e4SLinus Torvalds 3421da177e4SLinus Torvalds ret = mr->device->rereg_phys_mr(mr, mr_rereg_mask, pd, 3431da177e4SLinus Torvalds phys_buf_array, num_phys_buf, 3441da177e4SLinus Torvalds mr_access_flags, iova_start); 3451da177e4SLinus Torvalds 3461da177e4SLinus Torvalds if (!ret && (mr_rereg_mask & IB_MR_REREG_PD)) { 3471da177e4SLinus Torvalds atomic_dec(&old_pd->usecnt); 3481da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 3491da177e4SLinus Torvalds } 3501da177e4SLinus Torvalds 3511da177e4SLinus Torvalds return ret; 3521da177e4SLinus Torvalds } 3531da177e4SLinus Torvalds EXPORT_SYMBOL(ib_rereg_phys_mr); 3541da177e4SLinus Torvalds 3551da177e4SLinus Torvalds int ib_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr) 3561da177e4SLinus Torvalds { 3571da177e4SLinus Torvalds return mr->device->query_mr ? 3581da177e4SLinus Torvalds mr->device->query_mr(mr, mr_attr) : -ENOSYS; 3591da177e4SLinus Torvalds } 3601da177e4SLinus Torvalds EXPORT_SYMBOL(ib_query_mr); 3611da177e4SLinus Torvalds 3621da177e4SLinus Torvalds int ib_dereg_mr(struct ib_mr *mr) 3631da177e4SLinus Torvalds { 3641da177e4SLinus Torvalds struct ib_pd *pd; 3651da177e4SLinus Torvalds int ret; 3661da177e4SLinus Torvalds 3671da177e4SLinus Torvalds if (atomic_read(&mr->usecnt)) 3681da177e4SLinus Torvalds return -EBUSY; 3691da177e4SLinus Torvalds 3701da177e4SLinus Torvalds pd = mr->pd; 3711da177e4SLinus Torvalds ret = mr->device->dereg_mr(mr); 3721da177e4SLinus Torvalds if (!ret) 3731da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 3741da177e4SLinus Torvalds 3751da177e4SLinus Torvalds return ret; 3761da177e4SLinus Torvalds } 3771da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dereg_mr); 3781da177e4SLinus Torvalds 3791da177e4SLinus Torvalds /* Memory windows */ 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds struct ib_mw *ib_alloc_mw(struct ib_pd *pd) 3821da177e4SLinus Torvalds { 3831da177e4SLinus Torvalds struct ib_mw *mw; 3841da177e4SLinus Torvalds 3851da177e4SLinus Torvalds if (!pd->device->alloc_mw) 3861da177e4SLinus Torvalds return ERR_PTR(-ENOSYS); 3871da177e4SLinus Torvalds 3881da177e4SLinus Torvalds mw = pd->device->alloc_mw(pd); 3891da177e4SLinus Torvalds if (!IS_ERR(mw)) { 3901da177e4SLinus Torvalds mw->device = pd->device; 3911da177e4SLinus Torvalds mw->pd = pd; 392b5e81bf5SRoland Dreier mw->uobject = NULL; 3931da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 3941da177e4SLinus Torvalds } 3951da177e4SLinus Torvalds 3961da177e4SLinus Torvalds return mw; 3971da177e4SLinus Torvalds } 3981da177e4SLinus Torvalds EXPORT_SYMBOL(ib_alloc_mw); 3991da177e4SLinus Torvalds 4001da177e4SLinus Torvalds int ib_dealloc_mw(struct ib_mw *mw) 4011da177e4SLinus Torvalds { 4021da177e4SLinus Torvalds struct ib_pd *pd; 4031da177e4SLinus Torvalds int ret; 4041da177e4SLinus Torvalds 4051da177e4SLinus Torvalds pd = mw->pd; 4061da177e4SLinus Torvalds ret = mw->device->dealloc_mw(mw); 4071da177e4SLinus Torvalds if (!ret) 4081da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 4091da177e4SLinus Torvalds 4101da177e4SLinus Torvalds return ret; 4111da177e4SLinus Torvalds } 4121da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dealloc_mw); 4131da177e4SLinus Torvalds 4141da177e4SLinus Torvalds /* "Fast" memory regions */ 4151da177e4SLinus Torvalds 4161da177e4SLinus Torvalds struct ib_fmr *ib_alloc_fmr(struct ib_pd *pd, 4171da177e4SLinus Torvalds int mr_access_flags, 4181da177e4SLinus Torvalds struct ib_fmr_attr *fmr_attr) 4191da177e4SLinus Torvalds { 4201da177e4SLinus Torvalds struct ib_fmr *fmr; 4211da177e4SLinus Torvalds 4221da177e4SLinus Torvalds if (!pd->device->alloc_fmr) 4231da177e4SLinus Torvalds return ERR_PTR(-ENOSYS); 4241da177e4SLinus Torvalds 4251da177e4SLinus Torvalds fmr = pd->device->alloc_fmr(pd, mr_access_flags, fmr_attr); 4261da177e4SLinus Torvalds if (!IS_ERR(fmr)) { 4271da177e4SLinus Torvalds fmr->device = pd->device; 4281da177e4SLinus Torvalds fmr->pd = pd; 4291da177e4SLinus Torvalds atomic_inc(&pd->usecnt); 4301da177e4SLinus Torvalds } 4311da177e4SLinus Torvalds 4321da177e4SLinus Torvalds return fmr; 4331da177e4SLinus Torvalds } 4341da177e4SLinus Torvalds EXPORT_SYMBOL(ib_alloc_fmr); 4351da177e4SLinus Torvalds 4361da177e4SLinus Torvalds int ib_unmap_fmr(struct list_head *fmr_list) 4371da177e4SLinus Torvalds { 4381da177e4SLinus Torvalds struct ib_fmr *fmr; 4391da177e4SLinus Torvalds 4401da177e4SLinus Torvalds if (list_empty(fmr_list)) 4411da177e4SLinus Torvalds return 0; 4421da177e4SLinus Torvalds 4431da177e4SLinus Torvalds fmr = list_entry(fmr_list->next, struct ib_fmr, list); 4441da177e4SLinus Torvalds return fmr->device->unmap_fmr(fmr_list); 4451da177e4SLinus Torvalds } 4461da177e4SLinus Torvalds EXPORT_SYMBOL(ib_unmap_fmr); 4471da177e4SLinus Torvalds 4481da177e4SLinus Torvalds int ib_dealloc_fmr(struct ib_fmr *fmr) 4491da177e4SLinus Torvalds { 4501da177e4SLinus Torvalds struct ib_pd *pd; 4511da177e4SLinus Torvalds int ret; 4521da177e4SLinus Torvalds 4531da177e4SLinus Torvalds pd = fmr->pd; 4541da177e4SLinus Torvalds ret = fmr->device->dealloc_fmr(fmr); 4551da177e4SLinus Torvalds if (!ret) 4561da177e4SLinus Torvalds atomic_dec(&pd->usecnt); 4571da177e4SLinus Torvalds 4581da177e4SLinus Torvalds return ret; 4591da177e4SLinus Torvalds } 4601da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dealloc_fmr); 4611da177e4SLinus Torvalds 4621da177e4SLinus Torvalds /* Multicast groups */ 4631da177e4SLinus Torvalds 4641da177e4SLinus Torvalds int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid) 4651da177e4SLinus Torvalds { 4661da177e4SLinus Torvalds return qp->device->attach_mcast ? 4671da177e4SLinus Torvalds qp->device->attach_mcast(qp, gid, lid) : 4681da177e4SLinus Torvalds -ENOSYS; 4691da177e4SLinus Torvalds } 4701da177e4SLinus Torvalds EXPORT_SYMBOL(ib_attach_mcast); 4711da177e4SLinus Torvalds 4721da177e4SLinus Torvalds int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid) 4731da177e4SLinus Torvalds { 4741da177e4SLinus Torvalds return qp->device->detach_mcast ? 4751da177e4SLinus Torvalds qp->device->detach_mcast(qp, gid, lid) : 4761da177e4SLinus Torvalds -ENOSYS; 4771da177e4SLinus Torvalds } 4781da177e4SLinus Torvalds EXPORT_SYMBOL(ib_detach_mcast); 479