xref: /openbmc/linux/drivers/infiniband/core/verbs.c (revision 2a1d9b7f)
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