xref: /openbmc/linux/drivers/infiniband/core/verbs.c (revision 40de2e54)
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 
44a4d61e84SRoland Dreier #include <rdma/ib_verbs.h>
45a4d61e84SRoland Dreier #include <rdma/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 
157d41fcc67SRoland Dreier /* Shared receive queues */
158d41fcc67SRoland Dreier 
159d41fcc67SRoland Dreier struct ib_srq *ib_create_srq(struct ib_pd *pd,
160d41fcc67SRoland Dreier 			     struct ib_srq_init_attr *srq_init_attr)
161d41fcc67SRoland Dreier {
162d41fcc67SRoland Dreier 	struct ib_srq *srq;
163d41fcc67SRoland Dreier 
164d41fcc67SRoland Dreier 	if (!pd->device->create_srq)
165d41fcc67SRoland Dreier 		return ERR_PTR(-ENOSYS);
166d41fcc67SRoland Dreier 
167d41fcc67SRoland Dreier 	srq = pd->device->create_srq(pd, srq_init_attr, NULL);
168d41fcc67SRoland Dreier 
169d41fcc67SRoland Dreier 	if (!IS_ERR(srq)) {
170d41fcc67SRoland Dreier 		srq->device    	   = pd->device;
171d41fcc67SRoland Dreier 		srq->pd        	   = pd;
172d41fcc67SRoland Dreier 		srq->uobject       = NULL;
173d41fcc67SRoland Dreier 		srq->event_handler = srq_init_attr->event_handler;
174d41fcc67SRoland Dreier 		srq->srq_context   = srq_init_attr->srq_context;
175d41fcc67SRoland Dreier 		atomic_inc(&pd->usecnt);
176d41fcc67SRoland Dreier 		atomic_set(&srq->usecnt, 0);
177d41fcc67SRoland Dreier 	}
178d41fcc67SRoland Dreier 
179d41fcc67SRoland Dreier 	return srq;
180d41fcc67SRoland Dreier }
181d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_create_srq);
182d41fcc67SRoland Dreier 
183d41fcc67SRoland Dreier int ib_modify_srq(struct ib_srq *srq,
184d41fcc67SRoland Dreier 		  struct ib_srq_attr *srq_attr,
185d41fcc67SRoland Dreier 		  enum ib_srq_attr_mask srq_attr_mask)
186d41fcc67SRoland Dreier {
187d41fcc67SRoland Dreier 	return srq->device->modify_srq(srq, srq_attr, srq_attr_mask);
188d41fcc67SRoland Dreier }
189d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_modify_srq);
190d41fcc67SRoland Dreier 
191d41fcc67SRoland Dreier int ib_query_srq(struct ib_srq *srq,
192d41fcc67SRoland Dreier 		 struct ib_srq_attr *srq_attr)
193d41fcc67SRoland Dreier {
194d41fcc67SRoland Dreier 	return srq->device->query_srq ?
195d41fcc67SRoland Dreier 		srq->device->query_srq(srq, srq_attr) : -ENOSYS;
196d41fcc67SRoland Dreier }
197d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_query_srq);
198d41fcc67SRoland Dreier 
199d41fcc67SRoland Dreier int ib_destroy_srq(struct ib_srq *srq)
200d41fcc67SRoland Dreier {
201d41fcc67SRoland Dreier 	struct ib_pd *pd;
202d41fcc67SRoland Dreier 	int ret;
203d41fcc67SRoland Dreier 
204d41fcc67SRoland Dreier 	if (atomic_read(&srq->usecnt))
205d41fcc67SRoland Dreier 		return -EBUSY;
206d41fcc67SRoland Dreier 
207d41fcc67SRoland Dreier 	pd = srq->pd;
208d41fcc67SRoland Dreier 
209d41fcc67SRoland Dreier 	ret = srq->device->destroy_srq(srq);
210d41fcc67SRoland Dreier 	if (!ret)
211d41fcc67SRoland Dreier 		atomic_dec(&pd->usecnt);
212d41fcc67SRoland Dreier 
213d41fcc67SRoland Dreier 	return ret;
214d41fcc67SRoland Dreier }
215d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_destroy_srq);
216d41fcc67SRoland Dreier 
2171da177e4SLinus Torvalds /* Queue pairs */
2181da177e4SLinus Torvalds 
2191da177e4SLinus Torvalds struct ib_qp *ib_create_qp(struct ib_pd *pd,
2201da177e4SLinus Torvalds 			   struct ib_qp_init_attr *qp_init_attr)
2211da177e4SLinus Torvalds {
2221da177e4SLinus Torvalds 	struct ib_qp *qp;
2231da177e4SLinus Torvalds 
224b5e81bf5SRoland Dreier 	qp = pd->device->create_qp(pd, qp_init_attr, NULL);
2251da177e4SLinus Torvalds 
2261da177e4SLinus Torvalds 	if (!IS_ERR(qp)) {
2271da177e4SLinus Torvalds 		qp->device     	  = pd->device;
2281da177e4SLinus Torvalds 		qp->pd         	  = pd;
2291da177e4SLinus Torvalds 		qp->send_cq    	  = qp_init_attr->send_cq;
2301da177e4SLinus Torvalds 		qp->recv_cq    	  = qp_init_attr->recv_cq;
2311da177e4SLinus Torvalds 		qp->srq	       	  = qp_init_attr->srq;
232b5e81bf5SRoland Dreier 		qp->uobject       = NULL;
2331da177e4SLinus Torvalds 		qp->event_handler = qp_init_attr->event_handler;
2341da177e4SLinus Torvalds 		qp->qp_context    = qp_init_attr->qp_context;
2351da177e4SLinus Torvalds 		qp->qp_type	  = qp_init_attr->qp_type;
2361da177e4SLinus Torvalds 		atomic_inc(&pd->usecnt);
2371da177e4SLinus Torvalds 		atomic_inc(&qp_init_attr->send_cq->usecnt);
2381da177e4SLinus Torvalds 		atomic_inc(&qp_init_attr->recv_cq->usecnt);
2391da177e4SLinus Torvalds 		if (qp_init_attr->srq)
2401da177e4SLinus Torvalds 			atomic_inc(&qp_init_attr->srq->usecnt);
2411da177e4SLinus Torvalds 	}
2421da177e4SLinus Torvalds 
2431da177e4SLinus Torvalds 	return qp;
2441da177e4SLinus Torvalds }
2451da177e4SLinus Torvalds EXPORT_SYMBOL(ib_create_qp);
2461da177e4SLinus Torvalds 
2471da177e4SLinus Torvalds int ib_modify_qp(struct ib_qp *qp,
2481da177e4SLinus Torvalds 		 struct ib_qp_attr *qp_attr,
2491da177e4SLinus Torvalds 		 int qp_attr_mask)
2501da177e4SLinus Torvalds {
2511da177e4SLinus Torvalds 	return qp->device->modify_qp(qp, qp_attr, qp_attr_mask);
2521da177e4SLinus Torvalds }
2531da177e4SLinus Torvalds EXPORT_SYMBOL(ib_modify_qp);
2541da177e4SLinus Torvalds 
2551da177e4SLinus Torvalds int ib_query_qp(struct ib_qp *qp,
2561da177e4SLinus Torvalds 		struct ib_qp_attr *qp_attr,
2571da177e4SLinus Torvalds 		int qp_attr_mask,
2581da177e4SLinus Torvalds 		struct ib_qp_init_attr *qp_init_attr)
2591da177e4SLinus Torvalds {
2601da177e4SLinus Torvalds 	return qp->device->query_qp ?
2611da177e4SLinus Torvalds 		qp->device->query_qp(qp, qp_attr, qp_attr_mask, qp_init_attr) :
2621da177e4SLinus Torvalds 		-ENOSYS;
2631da177e4SLinus Torvalds }
2641da177e4SLinus Torvalds EXPORT_SYMBOL(ib_query_qp);
2651da177e4SLinus Torvalds 
2661da177e4SLinus Torvalds int ib_destroy_qp(struct ib_qp *qp)
2671da177e4SLinus Torvalds {
2681da177e4SLinus Torvalds 	struct ib_pd *pd;
2691da177e4SLinus Torvalds 	struct ib_cq *scq, *rcq;
2701da177e4SLinus Torvalds 	struct ib_srq *srq;
2711da177e4SLinus Torvalds 	int ret;
2721da177e4SLinus Torvalds 
2731da177e4SLinus Torvalds 	pd  = qp->pd;
2741da177e4SLinus Torvalds 	scq = qp->send_cq;
2751da177e4SLinus Torvalds 	rcq = qp->recv_cq;
2761da177e4SLinus Torvalds 	srq = qp->srq;
2771da177e4SLinus Torvalds 
2781da177e4SLinus Torvalds 	ret = qp->device->destroy_qp(qp);
2791da177e4SLinus Torvalds 	if (!ret) {
2801da177e4SLinus Torvalds 		atomic_dec(&pd->usecnt);
2811da177e4SLinus Torvalds 		atomic_dec(&scq->usecnt);
2821da177e4SLinus Torvalds 		atomic_dec(&rcq->usecnt);
2831da177e4SLinus Torvalds 		if (srq)
2841da177e4SLinus Torvalds 			atomic_dec(&srq->usecnt);
2851da177e4SLinus Torvalds 	}
2861da177e4SLinus Torvalds 
2871da177e4SLinus Torvalds 	return ret;
2881da177e4SLinus Torvalds }
2891da177e4SLinus Torvalds EXPORT_SYMBOL(ib_destroy_qp);
2901da177e4SLinus Torvalds 
2911da177e4SLinus Torvalds /* Completion queues */
2921da177e4SLinus Torvalds 
2931da177e4SLinus Torvalds struct ib_cq *ib_create_cq(struct ib_device *device,
2941da177e4SLinus Torvalds 			   ib_comp_handler comp_handler,
2951da177e4SLinus Torvalds 			   void (*event_handler)(struct ib_event *, void *),
2961da177e4SLinus Torvalds 			   void *cq_context, int cqe)
2971da177e4SLinus Torvalds {
2981da177e4SLinus Torvalds 	struct ib_cq *cq;
2991da177e4SLinus Torvalds 
300b5e81bf5SRoland Dreier 	cq = device->create_cq(device, cqe, NULL, NULL);
3011da177e4SLinus Torvalds 
3021da177e4SLinus Torvalds 	if (!IS_ERR(cq)) {
3031da177e4SLinus Torvalds 		cq->device        = device;
304b5e81bf5SRoland Dreier 		cq->uobject       = NULL;
3051da177e4SLinus Torvalds 		cq->comp_handler  = comp_handler;
3061da177e4SLinus Torvalds 		cq->event_handler = event_handler;
3071da177e4SLinus Torvalds 		cq->cq_context    = cq_context;
3081da177e4SLinus Torvalds 		atomic_set(&cq->usecnt, 0);
3091da177e4SLinus Torvalds 	}
3101da177e4SLinus Torvalds 
3111da177e4SLinus Torvalds 	return cq;
3121da177e4SLinus Torvalds }
3131da177e4SLinus Torvalds EXPORT_SYMBOL(ib_create_cq);
3141da177e4SLinus Torvalds 
3151da177e4SLinus Torvalds int ib_destroy_cq(struct ib_cq *cq)
3161da177e4SLinus Torvalds {
3171da177e4SLinus Torvalds 	if (atomic_read(&cq->usecnt))
3181da177e4SLinus Torvalds 		return -EBUSY;
3191da177e4SLinus Torvalds 
3201da177e4SLinus Torvalds 	return cq->device->destroy_cq(cq);
3211da177e4SLinus Torvalds }
3221da177e4SLinus Torvalds EXPORT_SYMBOL(ib_destroy_cq);
3231da177e4SLinus Torvalds 
3241da177e4SLinus Torvalds int ib_resize_cq(struct ib_cq *cq,
3251da177e4SLinus Torvalds                  int           cqe)
3261da177e4SLinus Torvalds {
32740de2e54SRoland Dreier 	return cq->device->resize_cq ?
32840de2e54SRoland Dreier 		cq->device->resize_cq(cq, cqe) : -ENOSYS;
3291da177e4SLinus Torvalds }
3301da177e4SLinus Torvalds EXPORT_SYMBOL(ib_resize_cq);
3311da177e4SLinus Torvalds 
3321da177e4SLinus Torvalds /* Memory regions */
3331da177e4SLinus Torvalds 
3341da177e4SLinus Torvalds struct ib_mr *ib_get_dma_mr(struct ib_pd *pd, int mr_access_flags)
3351da177e4SLinus Torvalds {
3361da177e4SLinus Torvalds 	struct ib_mr *mr;
3371da177e4SLinus Torvalds 
3381da177e4SLinus Torvalds 	mr = pd->device->get_dma_mr(pd, mr_access_flags);
3391da177e4SLinus Torvalds 
3401da177e4SLinus Torvalds 	if (!IS_ERR(mr)) {
3411da177e4SLinus Torvalds 		mr->device  = pd->device;
3421da177e4SLinus Torvalds 		mr->pd      = pd;
343b5e81bf5SRoland Dreier 		mr->uobject = NULL;
3441da177e4SLinus Torvalds 		atomic_inc(&pd->usecnt);
3451da177e4SLinus Torvalds 		atomic_set(&mr->usecnt, 0);
3461da177e4SLinus Torvalds 	}
3471da177e4SLinus Torvalds 
3481da177e4SLinus Torvalds 	return mr;
3491da177e4SLinus Torvalds }
3501da177e4SLinus Torvalds EXPORT_SYMBOL(ib_get_dma_mr);
3511da177e4SLinus Torvalds 
3521da177e4SLinus Torvalds struct ib_mr *ib_reg_phys_mr(struct ib_pd *pd,
3531da177e4SLinus Torvalds 			     struct ib_phys_buf *phys_buf_array,
3541da177e4SLinus Torvalds 			     int num_phys_buf,
3551da177e4SLinus Torvalds 			     int mr_access_flags,
3561da177e4SLinus Torvalds 			     u64 *iova_start)
3571da177e4SLinus Torvalds {
3581da177e4SLinus Torvalds 	struct ib_mr *mr;
3591da177e4SLinus Torvalds 
3601da177e4SLinus Torvalds 	mr = pd->device->reg_phys_mr(pd, phys_buf_array, num_phys_buf,
3611da177e4SLinus Torvalds 				     mr_access_flags, iova_start);
3621da177e4SLinus Torvalds 
3631da177e4SLinus Torvalds 	if (!IS_ERR(mr)) {
3641da177e4SLinus Torvalds 		mr->device  = pd->device;
3651da177e4SLinus Torvalds 		mr->pd      = pd;
366b5e81bf5SRoland Dreier 		mr->uobject = NULL;
3671da177e4SLinus Torvalds 		atomic_inc(&pd->usecnt);
3681da177e4SLinus Torvalds 		atomic_set(&mr->usecnt, 0);
3691da177e4SLinus Torvalds 	}
3701da177e4SLinus Torvalds 
3711da177e4SLinus Torvalds 	return mr;
3721da177e4SLinus Torvalds }
3731da177e4SLinus Torvalds EXPORT_SYMBOL(ib_reg_phys_mr);
3741da177e4SLinus Torvalds 
3751da177e4SLinus Torvalds int ib_rereg_phys_mr(struct ib_mr *mr,
3761da177e4SLinus Torvalds 		     int mr_rereg_mask,
3771da177e4SLinus Torvalds 		     struct ib_pd *pd,
3781da177e4SLinus Torvalds 		     struct ib_phys_buf *phys_buf_array,
3791da177e4SLinus Torvalds 		     int num_phys_buf,
3801da177e4SLinus Torvalds 		     int mr_access_flags,
3811da177e4SLinus Torvalds 		     u64 *iova_start)
3821da177e4SLinus Torvalds {
3831da177e4SLinus Torvalds 	struct ib_pd *old_pd;
3841da177e4SLinus Torvalds 	int ret;
3851da177e4SLinus Torvalds 
3861da177e4SLinus Torvalds 	if (!mr->device->rereg_phys_mr)
3871da177e4SLinus Torvalds 		return -ENOSYS;
3881da177e4SLinus Torvalds 
3891da177e4SLinus Torvalds 	if (atomic_read(&mr->usecnt))
3901da177e4SLinus Torvalds 		return -EBUSY;
3911da177e4SLinus Torvalds 
3921da177e4SLinus Torvalds 	old_pd = mr->pd;
3931da177e4SLinus Torvalds 
3941da177e4SLinus Torvalds 	ret = mr->device->rereg_phys_mr(mr, mr_rereg_mask, pd,
3951da177e4SLinus Torvalds 					phys_buf_array, num_phys_buf,
3961da177e4SLinus Torvalds 					mr_access_flags, iova_start);
3971da177e4SLinus Torvalds 
3981da177e4SLinus Torvalds 	if (!ret && (mr_rereg_mask & IB_MR_REREG_PD)) {
3991da177e4SLinus Torvalds 		atomic_dec(&old_pd->usecnt);
4001da177e4SLinus Torvalds 		atomic_inc(&pd->usecnt);
4011da177e4SLinus Torvalds 	}
4021da177e4SLinus Torvalds 
4031da177e4SLinus Torvalds 	return ret;
4041da177e4SLinus Torvalds }
4051da177e4SLinus Torvalds EXPORT_SYMBOL(ib_rereg_phys_mr);
4061da177e4SLinus Torvalds 
4071da177e4SLinus Torvalds int ib_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr)
4081da177e4SLinus Torvalds {
4091da177e4SLinus Torvalds 	return mr->device->query_mr ?
4101da177e4SLinus Torvalds 		mr->device->query_mr(mr, mr_attr) : -ENOSYS;
4111da177e4SLinus Torvalds }
4121da177e4SLinus Torvalds EXPORT_SYMBOL(ib_query_mr);
4131da177e4SLinus Torvalds 
4141da177e4SLinus Torvalds int ib_dereg_mr(struct ib_mr *mr)
4151da177e4SLinus Torvalds {
4161da177e4SLinus Torvalds 	struct ib_pd *pd;
4171da177e4SLinus Torvalds 	int ret;
4181da177e4SLinus Torvalds 
4191da177e4SLinus Torvalds 	if (atomic_read(&mr->usecnt))
4201da177e4SLinus Torvalds 		return -EBUSY;
4211da177e4SLinus Torvalds 
4221da177e4SLinus Torvalds 	pd = mr->pd;
4231da177e4SLinus Torvalds 	ret = mr->device->dereg_mr(mr);
4241da177e4SLinus Torvalds 	if (!ret)
4251da177e4SLinus Torvalds 		atomic_dec(&pd->usecnt);
4261da177e4SLinus Torvalds 
4271da177e4SLinus Torvalds 	return ret;
4281da177e4SLinus Torvalds }
4291da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dereg_mr);
4301da177e4SLinus Torvalds 
4311da177e4SLinus Torvalds /* Memory windows */
4321da177e4SLinus Torvalds 
4331da177e4SLinus Torvalds struct ib_mw *ib_alloc_mw(struct ib_pd *pd)
4341da177e4SLinus Torvalds {
4351da177e4SLinus Torvalds 	struct ib_mw *mw;
4361da177e4SLinus Torvalds 
4371da177e4SLinus Torvalds 	if (!pd->device->alloc_mw)
4381da177e4SLinus Torvalds 		return ERR_PTR(-ENOSYS);
4391da177e4SLinus Torvalds 
4401da177e4SLinus Torvalds 	mw = pd->device->alloc_mw(pd);
4411da177e4SLinus Torvalds 	if (!IS_ERR(mw)) {
4421da177e4SLinus Torvalds 		mw->device  = pd->device;
4431da177e4SLinus Torvalds 		mw->pd      = pd;
444b5e81bf5SRoland Dreier 		mw->uobject = NULL;
4451da177e4SLinus Torvalds 		atomic_inc(&pd->usecnt);
4461da177e4SLinus Torvalds 	}
4471da177e4SLinus Torvalds 
4481da177e4SLinus Torvalds 	return mw;
4491da177e4SLinus Torvalds }
4501da177e4SLinus Torvalds EXPORT_SYMBOL(ib_alloc_mw);
4511da177e4SLinus Torvalds 
4521da177e4SLinus Torvalds int ib_dealloc_mw(struct ib_mw *mw)
4531da177e4SLinus Torvalds {
4541da177e4SLinus Torvalds 	struct ib_pd *pd;
4551da177e4SLinus Torvalds 	int ret;
4561da177e4SLinus Torvalds 
4571da177e4SLinus Torvalds 	pd = mw->pd;
4581da177e4SLinus Torvalds 	ret = mw->device->dealloc_mw(mw);
4591da177e4SLinus Torvalds 	if (!ret)
4601da177e4SLinus Torvalds 		atomic_dec(&pd->usecnt);
4611da177e4SLinus Torvalds 
4621da177e4SLinus Torvalds 	return ret;
4631da177e4SLinus Torvalds }
4641da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dealloc_mw);
4651da177e4SLinus Torvalds 
4661da177e4SLinus Torvalds /* "Fast" memory regions */
4671da177e4SLinus Torvalds 
4681da177e4SLinus Torvalds struct ib_fmr *ib_alloc_fmr(struct ib_pd *pd,
4691da177e4SLinus Torvalds 			    int mr_access_flags,
4701da177e4SLinus Torvalds 			    struct ib_fmr_attr *fmr_attr)
4711da177e4SLinus Torvalds {
4721da177e4SLinus Torvalds 	struct ib_fmr *fmr;
4731da177e4SLinus Torvalds 
4741da177e4SLinus Torvalds 	if (!pd->device->alloc_fmr)
4751da177e4SLinus Torvalds 		return ERR_PTR(-ENOSYS);
4761da177e4SLinus Torvalds 
4771da177e4SLinus Torvalds 	fmr = pd->device->alloc_fmr(pd, mr_access_flags, fmr_attr);
4781da177e4SLinus Torvalds 	if (!IS_ERR(fmr)) {
4791da177e4SLinus Torvalds 		fmr->device = pd->device;
4801da177e4SLinus Torvalds 		fmr->pd     = pd;
4811da177e4SLinus Torvalds 		atomic_inc(&pd->usecnt);
4821da177e4SLinus Torvalds 	}
4831da177e4SLinus Torvalds 
4841da177e4SLinus Torvalds 	return fmr;
4851da177e4SLinus Torvalds }
4861da177e4SLinus Torvalds EXPORT_SYMBOL(ib_alloc_fmr);
4871da177e4SLinus Torvalds 
4881da177e4SLinus Torvalds int ib_unmap_fmr(struct list_head *fmr_list)
4891da177e4SLinus Torvalds {
4901da177e4SLinus Torvalds 	struct ib_fmr *fmr;
4911da177e4SLinus Torvalds 
4921da177e4SLinus Torvalds 	if (list_empty(fmr_list))
4931da177e4SLinus Torvalds 		return 0;
4941da177e4SLinus Torvalds 
4951da177e4SLinus Torvalds 	fmr = list_entry(fmr_list->next, struct ib_fmr, list);
4961da177e4SLinus Torvalds 	return fmr->device->unmap_fmr(fmr_list);
4971da177e4SLinus Torvalds }
4981da177e4SLinus Torvalds EXPORT_SYMBOL(ib_unmap_fmr);
4991da177e4SLinus Torvalds 
5001da177e4SLinus Torvalds int ib_dealloc_fmr(struct ib_fmr *fmr)
5011da177e4SLinus Torvalds {
5021da177e4SLinus Torvalds 	struct ib_pd *pd;
5031da177e4SLinus Torvalds 	int ret;
5041da177e4SLinus Torvalds 
5051da177e4SLinus Torvalds 	pd = fmr->pd;
5061da177e4SLinus Torvalds 	ret = fmr->device->dealloc_fmr(fmr);
5071da177e4SLinus Torvalds 	if (!ret)
5081da177e4SLinus Torvalds 		atomic_dec(&pd->usecnt);
5091da177e4SLinus Torvalds 
5101da177e4SLinus Torvalds 	return ret;
5111da177e4SLinus Torvalds }
5121da177e4SLinus Torvalds EXPORT_SYMBOL(ib_dealloc_fmr);
5131da177e4SLinus Torvalds 
5141da177e4SLinus Torvalds /* Multicast groups */
5151da177e4SLinus Torvalds 
5161da177e4SLinus Torvalds int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
5171da177e4SLinus Torvalds {
5180c33aeedSJack Morgenstein 	if (!qp->device->attach_mcast)
5190c33aeedSJack Morgenstein 		return -ENOSYS;
5200c33aeedSJack Morgenstein 	if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD)
5210c33aeedSJack Morgenstein 		return -EINVAL;
5220c33aeedSJack Morgenstein 
5230c33aeedSJack Morgenstein 	return qp->device->attach_mcast(qp, gid, lid);
5241da177e4SLinus Torvalds }
5251da177e4SLinus Torvalds EXPORT_SYMBOL(ib_attach_mcast);
5261da177e4SLinus Torvalds 
5271da177e4SLinus Torvalds int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
5281da177e4SLinus Torvalds {
5290c33aeedSJack Morgenstein 	if (!qp->device->detach_mcast)
5300c33aeedSJack Morgenstein 		return -ENOSYS;
5310c33aeedSJack Morgenstein 	if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD)
5320c33aeedSJack Morgenstein 		return -EINVAL;
5330c33aeedSJack Morgenstein 
5340c33aeedSJack Morgenstein 	return qp->device->detach_mcast(qp, gid, lid);
5351da177e4SLinus Torvalds }
5361da177e4SLinus Torvalds EXPORT_SYMBOL(ib_detach_mcast);
537