xref: /openbmc/linux/drivers/infiniband/core/verbs.c (revision 13ef5539)
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.
833b9b3eeSRoland Dreier  * Copyright (c) 2005, 2006 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 
391da177e4SLinus Torvalds #include <linux/errno.h>
401da177e4SLinus Torvalds #include <linux/err.h>
41b108d976SPaul Gortmaker #include <linux/export.h>
428c65b4a6STim Schmielau #include <linux/string.h>
430e0ec7e0SSean Hefty #include <linux/slab.h>
44dbf727deSMatan Barak #include <linux/in.h>
45dbf727deSMatan Barak #include <linux/in6.h>
46dbf727deSMatan Barak #include <net/addrconf.h>
47d291f1a6SDaniel Jurgens #include <linux/security.h>
481da177e4SLinus Torvalds 
49a4d61e84SRoland Dreier #include <rdma/ib_verbs.h>
50a4d61e84SRoland Dreier #include <rdma/ib_cache.h>
51dd5f03beSMatan Barak #include <rdma/ib_addr.h>
52a060b562SChristoph Hellwig #include <rdma/rw.h>
5351aab126SMaor Gottlieb #include <rdma/lag.h>
541da177e4SLinus Torvalds 
55ed4c54e5SOr Gerlitz #include "core_priv.h"
56622db5b6SChuck Lever #include <trace/events/rdma_core.h>
571da177e4SLinus Torvalds 
58c0348eb0SParav Pandit static int ib_resolve_eth_dmac(struct ib_device *device,
59c0348eb0SParav Pandit 			       struct rdma_ah_attr *ah_attr);
60c0348eb0SParav Pandit 
612b1b5b60SSagi Grimberg static const char * const ib_events[] = {
622b1b5b60SSagi Grimberg 	[IB_EVENT_CQ_ERR]		= "CQ error",
632b1b5b60SSagi Grimberg 	[IB_EVENT_QP_FATAL]		= "QP fatal error",
642b1b5b60SSagi Grimberg 	[IB_EVENT_QP_REQ_ERR]		= "QP request error",
652b1b5b60SSagi Grimberg 	[IB_EVENT_QP_ACCESS_ERR]	= "QP access error",
662b1b5b60SSagi Grimberg 	[IB_EVENT_COMM_EST]		= "communication established",
672b1b5b60SSagi Grimberg 	[IB_EVENT_SQ_DRAINED]		= "send queue drained",
682b1b5b60SSagi Grimberg 	[IB_EVENT_PATH_MIG]		= "path migration successful",
692b1b5b60SSagi Grimberg 	[IB_EVENT_PATH_MIG_ERR]		= "path migration error",
702b1b5b60SSagi Grimberg 	[IB_EVENT_DEVICE_FATAL]		= "device fatal error",
712b1b5b60SSagi Grimberg 	[IB_EVENT_PORT_ACTIVE]		= "port active",
722b1b5b60SSagi Grimberg 	[IB_EVENT_PORT_ERR]		= "port error",
732b1b5b60SSagi Grimberg 	[IB_EVENT_LID_CHANGE]		= "LID change",
742b1b5b60SSagi Grimberg 	[IB_EVENT_PKEY_CHANGE]		= "P_key change",
752b1b5b60SSagi Grimberg 	[IB_EVENT_SM_CHANGE]		= "SM change",
762b1b5b60SSagi Grimberg 	[IB_EVENT_SRQ_ERR]		= "SRQ error",
772b1b5b60SSagi Grimberg 	[IB_EVENT_SRQ_LIMIT_REACHED]	= "SRQ limit reached",
782b1b5b60SSagi Grimberg 	[IB_EVENT_QP_LAST_WQE_REACHED]	= "last WQE reached",
792b1b5b60SSagi Grimberg 	[IB_EVENT_CLIENT_REREGISTER]	= "client reregister",
802b1b5b60SSagi Grimberg 	[IB_EVENT_GID_CHANGE]		= "GID changed",
812b1b5b60SSagi Grimberg };
822b1b5b60SSagi Grimberg 
83db7489e0SBart Van Assche const char *__attribute_const__ ib_event_msg(enum ib_event_type event)
842b1b5b60SSagi Grimberg {
852b1b5b60SSagi Grimberg 	size_t index = event;
862b1b5b60SSagi Grimberg 
872b1b5b60SSagi Grimberg 	return (index < ARRAY_SIZE(ib_events) && ib_events[index]) ?
882b1b5b60SSagi Grimberg 			ib_events[index] : "unrecognized event";
892b1b5b60SSagi Grimberg }
902b1b5b60SSagi Grimberg EXPORT_SYMBOL(ib_event_msg);
912b1b5b60SSagi Grimberg 
922b1b5b60SSagi Grimberg static const char * const wc_statuses[] = {
932b1b5b60SSagi Grimberg 	[IB_WC_SUCCESS]			= "success",
942b1b5b60SSagi Grimberg 	[IB_WC_LOC_LEN_ERR]		= "local length error",
952b1b5b60SSagi Grimberg 	[IB_WC_LOC_QP_OP_ERR]		= "local QP operation error",
962b1b5b60SSagi Grimberg 	[IB_WC_LOC_EEC_OP_ERR]		= "local EE context operation error",
972b1b5b60SSagi Grimberg 	[IB_WC_LOC_PROT_ERR]		= "local protection error",
982b1b5b60SSagi Grimberg 	[IB_WC_WR_FLUSH_ERR]		= "WR flushed",
992b1b5b60SSagi Grimberg 	[IB_WC_MW_BIND_ERR]		= "memory management operation error",
1002b1b5b60SSagi Grimberg 	[IB_WC_BAD_RESP_ERR]		= "bad response error",
1012b1b5b60SSagi Grimberg 	[IB_WC_LOC_ACCESS_ERR]		= "local access error",
1022b1b5b60SSagi Grimberg 	[IB_WC_REM_INV_REQ_ERR]		= "invalid request error",
1032b1b5b60SSagi Grimberg 	[IB_WC_REM_ACCESS_ERR]		= "remote access error",
1042b1b5b60SSagi Grimberg 	[IB_WC_REM_OP_ERR]		= "remote operation error",
1052b1b5b60SSagi Grimberg 	[IB_WC_RETRY_EXC_ERR]		= "transport retry counter exceeded",
1062b1b5b60SSagi Grimberg 	[IB_WC_RNR_RETRY_EXC_ERR]	= "RNR retry counter exceeded",
1072b1b5b60SSagi Grimberg 	[IB_WC_LOC_RDD_VIOL_ERR]	= "local RDD violation error",
1082b1b5b60SSagi Grimberg 	[IB_WC_REM_INV_RD_REQ_ERR]	= "remote invalid RD request",
1092b1b5b60SSagi Grimberg 	[IB_WC_REM_ABORT_ERR]		= "operation aborted",
1102b1b5b60SSagi Grimberg 	[IB_WC_INV_EECN_ERR]		= "invalid EE context number",
1112b1b5b60SSagi Grimberg 	[IB_WC_INV_EEC_STATE_ERR]	= "invalid EE context state",
1122b1b5b60SSagi Grimberg 	[IB_WC_FATAL_ERR]		= "fatal error",
1132b1b5b60SSagi Grimberg 	[IB_WC_RESP_TIMEOUT_ERR]	= "response timeout error",
1142b1b5b60SSagi Grimberg 	[IB_WC_GENERAL_ERR]		= "general error",
1152b1b5b60SSagi Grimberg };
1162b1b5b60SSagi Grimberg 
117db7489e0SBart Van Assche const char *__attribute_const__ ib_wc_status_msg(enum ib_wc_status status)
1182b1b5b60SSagi Grimberg {
1192b1b5b60SSagi Grimberg 	size_t index = status;
1202b1b5b60SSagi Grimberg 
1212b1b5b60SSagi Grimberg 	return (index < ARRAY_SIZE(wc_statuses) && wc_statuses[index]) ?
1222b1b5b60SSagi Grimberg 			wc_statuses[index] : "unrecognized status";
1232b1b5b60SSagi Grimberg }
1242b1b5b60SSagi Grimberg EXPORT_SYMBOL(ib_wc_status_msg);
1252b1b5b60SSagi Grimberg 
1268385fd84SRoland Dreier __attribute_const__ int ib_rate_to_mult(enum ib_rate rate)
127bf6a9e31SJack Morgenstein {
128bf6a9e31SJack Morgenstein 	switch (rate) {
129bf6a9e31SJack Morgenstein 	case IB_RATE_2_5_GBPS: return   1;
130bf6a9e31SJack Morgenstein 	case IB_RATE_5_GBPS:   return   2;
131bf6a9e31SJack Morgenstein 	case IB_RATE_10_GBPS:  return   4;
132bf6a9e31SJack Morgenstein 	case IB_RATE_20_GBPS:  return   8;
133bf6a9e31SJack Morgenstein 	case IB_RATE_30_GBPS:  return  12;
134bf6a9e31SJack Morgenstein 	case IB_RATE_40_GBPS:  return  16;
135bf6a9e31SJack Morgenstein 	case IB_RATE_60_GBPS:  return  24;
136bf6a9e31SJack Morgenstein 	case IB_RATE_80_GBPS:  return  32;
137bf6a9e31SJack Morgenstein 	case IB_RATE_120_GBPS: return  48;
138e2dda368SHans Westgaard Ry 	case IB_RATE_14_GBPS:  return   6;
139e2dda368SHans Westgaard Ry 	case IB_RATE_56_GBPS:  return  22;
140e2dda368SHans Westgaard Ry 	case IB_RATE_112_GBPS: return  45;
141e2dda368SHans Westgaard Ry 	case IB_RATE_168_GBPS: return  67;
142e2dda368SHans Westgaard Ry 	case IB_RATE_25_GBPS:  return  10;
143e2dda368SHans Westgaard Ry 	case IB_RATE_100_GBPS: return  40;
144e2dda368SHans Westgaard Ry 	case IB_RATE_200_GBPS: return  80;
145e2dda368SHans Westgaard Ry 	case IB_RATE_300_GBPS: return 120;
146a5a5d199SMichael Guralnik 	case IB_RATE_28_GBPS:  return  11;
147a5a5d199SMichael Guralnik 	case IB_RATE_50_GBPS:  return  20;
148a5a5d199SMichael Guralnik 	case IB_RATE_400_GBPS: return 160;
149a5a5d199SMichael Guralnik 	case IB_RATE_600_GBPS: return 240;
150bf6a9e31SJack Morgenstein 	default:	       return  -1;
151bf6a9e31SJack Morgenstein 	}
152bf6a9e31SJack Morgenstein }
153bf6a9e31SJack Morgenstein EXPORT_SYMBOL(ib_rate_to_mult);
154bf6a9e31SJack Morgenstein 
1558385fd84SRoland Dreier __attribute_const__ enum ib_rate mult_to_ib_rate(int mult)
156bf6a9e31SJack Morgenstein {
157bf6a9e31SJack Morgenstein 	switch (mult) {
158bf6a9e31SJack Morgenstein 	case 1:   return IB_RATE_2_5_GBPS;
159bf6a9e31SJack Morgenstein 	case 2:   return IB_RATE_5_GBPS;
160bf6a9e31SJack Morgenstein 	case 4:   return IB_RATE_10_GBPS;
161bf6a9e31SJack Morgenstein 	case 8:   return IB_RATE_20_GBPS;
162bf6a9e31SJack Morgenstein 	case 12:  return IB_RATE_30_GBPS;
163bf6a9e31SJack Morgenstein 	case 16:  return IB_RATE_40_GBPS;
164bf6a9e31SJack Morgenstein 	case 24:  return IB_RATE_60_GBPS;
165bf6a9e31SJack Morgenstein 	case 32:  return IB_RATE_80_GBPS;
166bf6a9e31SJack Morgenstein 	case 48:  return IB_RATE_120_GBPS;
167e2dda368SHans Westgaard Ry 	case 6:   return IB_RATE_14_GBPS;
168e2dda368SHans Westgaard Ry 	case 22:  return IB_RATE_56_GBPS;
169e2dda368SHans Westgaard Ry 	case 45:  return IB_RATE_112_GBPS;
170e2dda368SHans Westgaard Ry 	case 67:  return IB_RATE_168_GBPS;
171e2dda368SHans Westgaard Ry 	case 10:  return IB_RATE_25_GBPS;
172e2dda368SHans Westgaard Ry 	case 40:  return IB_RATE_100_GBPS;
173e2dda368SHans Westgaard Ry 	case 80:  return IB_RATE_200_GBPS;
174e2dda368SHans Westgaard Ry 	case 120: return IB_RATE_300_GBPS;
175a5a5d199SMichael Guralnik 	case 11:  return IB_RATE_28_GBPS;
176a5a5d199SMichael Guralnik 	case 20:  return IB_RATE_50_GBPS;
177a5a5d199SMichael Guralnik 	case 160: return IB_RATE_400_GBPS;
178a5a5d199SMichael Guralnik 	case 240: return IB_RATE_600_GBPS;
179bf6a9e31SJack Morgenstein 	default:  return IB_RATE_PORT_CURRENT;
180bf6a9e31SJack Morgenstein 	}
181bf6a9e31SJack Morgenstein }
182bf6a9e31SJack Morgenstein EXPORT_SYMBOL(mult_to_ib_rate);
183bf6a9e31SJack Morgenstein 
1848385fd84SRoland Dreier __attribute_const__ int ib_rate_to_mbps(enum ib_rate rate)
18571eeba16SMarcel Apfelbaum {
18671eeba16SMarcel Apfelbaum 	switch (rate) {
18771eeba16SMarcel Apfelbaum 	case IB_RATE_2_5_GBPS: return 2500;
18871eeba16SMarcel Apfelbaum 	case IB_RATE_5_GBPS:   return 5000;
18971eeba16SMarcel Apfelbaum 	case IB_RATE_10_GBPS:  return 10000;
19071eeba16SMarcel Apfelbaum 	case IB_RATE_20_GBPS:  return 20000;
19171eeba16SMarcel Apfelbaum 	case IB_RATE_30_GBPS:  return 30000;
19271eeba16SMarcel Apfelbaum 	case IB_RATE_40_GBPS:  return 40000;
19371eeba16SMarcel Apfelbaum 	case IB_RATE_60_GBPS:  return 60000;
19471eeba16SMarcel Apfelbaum 	case IB_RATE_80_GBPS:  return 80000;
19571eeba16SMarcel Apfelbaum 	case IB_RATE_120_GBPS: return 120000;
19671eeba16SMarcel Apfelbaum 	case IB_RATE_14_GBPS:  return 14062;
19771eeba16SMarcel Apfelbaum 	case IB_RATE_56_GBPS:  return 56250;
19871eeba16SMarcel Apfelbaum 	case IB_RATE_112_GBPS: return 112500;
19971eeba16SMarcel Apfelbaum 	case IB_RATE_168_GBPS: return 168750;
20071eeba16SMarcel Apfelbaum 	case IB_RATE_25_GBPS:  return 25781;
20171eeba16SMarcel Apfelbaum 	case IB_RATE_100_GBPS: return 103125;
20271eeba16SMarcel Apfelbaum 	case IB_RATE_200_GBPS: return 206250;
20371eeba16SMarcel Apfelbaum 	case IB_RATE_300_GBPS: return 309375;
204a5a5d199SMichael Guralnik 	case IB_RATE_28_GBPS:  return 28125;
205a5a5d199SMichael Guralnik 	case IB_RATE_50_GBPS:  return 53125;
206a5a5d199SMichael Guralnik 	case IB_RATE_400_GBPS: return 425000;
207a5a5d199SMichael Guralnik 	case IB_RATE_600_GBPS: return 637500;
20871eeba16SMarcel Apfelbaum 	default:	       return -1;
20971eeba16SMarcel Apfelbaum 	}
21071eeba16SMarcel Apfelbaum }
21171eeba16SMarcel Apfelbaum EXPORT_SYMBOL(ib_rate_to_mbps);
21271eeba16SMarcel Apfelbaum 
2138385fd84SRoland Dreier __attribute_const__ enum rdma_transport_type
2145d60c111SJason Gunthorpe rdma_node_get_transport(unsigned int node_type)
21507ebafbaSTom Tucker {
216cdc596d8SLeon Romanovsky 
217cdc596d8SLeon Romanovsky 	if (node_type == RDMA_NODE_USNIC)
2185db5765eSUpinder Malhi 		return RDMA_TRANSPORT_USNIC;
219cdc596d8SLeon Romanovsky 	if (node_type == RDMA_NODE_USNIC_UDP)
220248567f7SUpinder Malhi 		return RDMA_TRANSPORT_USNIC_UDP;
221cdc596d8SLeon Romanovsky 	if (node_type == RDMA_NODE_RNIC)
222cdc596d8SLeon Romanovsky 		return RDMA_TRANSPORT_IWARP;
223f95be3d2SGal Pressman 	if (node_type == RDMA_NODE_UNSPECIFIED)
224f95be3d2SGal Pressman 		return RDMA_TRANSPORT_UNSPECIFIED;
225cdc596d8SLeon Romanovsky 
226cdc596d8SLeon Romanovsky 	return RDMA_TRANSPORT_IB;
22707ebafbaSTom Tucker }
22807ebafbaSTom Tucker EXPORT_SYMBOL(rdma_node_get_transport);
22907ebafbaSTom Tucker 
230a3f5adafSEli Cohen enum rdma_link_layer rdma_port_get_link_layer(struct ib_device *device, u8 port_num)
231a3f5adafSEli Cohen {
23282901e3eSLeon Romanovsky 	enum rdma_transport_type lt;
2333023a1e9SKamal Heib 	if (device->ops.get_link_layer)
2343023a1e9SKamal Heib 		return device->ops.get_link_layer(device, port_num);
235a3f5adafSEli Cohen 
23682901e3eSLeon Romanovsky 	lt = rdma_node_get_transport(device->node_type);
23782901e3eSLeon Romanovsky 	if (lt == RDMA_TRANSPORT_IB)
238a3f5adafSEli Cohen 		return IB_LINK_LAYER_INFINIBAND;
23982901e3eSLeon Romanovsky 
240a3f5adafSEli Cohen 	return IB_LINK_LAYER_ETHERNET;
241a3f5adafSEli Cohen }
242a3f5adafSEli Cohen EXPORT_SYMBOL(rdma_port_get_link_layer);
243a3f5adafSEli Cohen 
2441da177e4SLinus Torvalds /* Protection domains */
2451da177e4SLinus Torvalds 
24696249d70SJason Gunthorpe /**
24796249d70SJason Gunthorpe  * ib_alloc_pd - Allocates an unused protection domain.
24896249d70SJason Gunthorpe  * @device: The device on which to allocate the protection domain.
249094c88f3Srd.dunlab@gmail.com  * @flags: protection domain flags
250094c88f3Srd.dunlab@gmail.com  * @caller: caller's build-time module name
25196249d70SJason Gunthorpe  *
25296249d70SJason Gunthorpe  * A protection domain object provides an association between QPs, shared
25396249d70SJason Gunthorpe  * receive queues, address handles, memory regions, and memory windows.
25496249d70SJason Gunthorpe  *
25596249d70SJason Gunthorpe  * Every PD has a local_dma_lkey which can be used as the lkey value for local
25696249d70SJason Gunthorpe  * memory operations.
25796249d70SJason Gunthorpe  */
258ed082d36SChristoph Hellwig struct ib_pd *__ib_alloc_pd(struct ib_device *device, unsigned int flags,
259ed082d36SChristoph Hellwig 		const char *caller)
2601da177e4SLinus Torvalds {
2611da177e4SLinus Torvalds 	struct ib_pd *pd;
262ed082d36SChristoph Hellwig 	int mr_access_flags = 0;
26321a428a0SLeon Romanovsky 	int ret;
2641da177e4SLinus Torvalds 
26521a428a0SLeon Romanovsky 	pd = rdma_zalloc_drv_obj(device, ib_pd);
26621a428a0SLeon Romanovsky 	if (!pd)
26721a428a0SLeon Romanovsky 		return ERR_PTR(-ENOMEM);
2681da177e4SLinus Torvalds 
2691da177e4SLinus Torvalds 	pd->device = device;
270b5e81bf5SRoland Dreier 	pd->uobject = NULL;
27150d46335SChristoph Hellwig 	pd->__internal_mr = NULL;
2721da177e4SLinus Torvalds 	atomic_set(&pd->usecnt, 0);
273ed082d36SChristoph Hellwig 	pd->flags = flags;
27496249d70SJason Gunthorpe 
27513ef5539SLeon Romanovsky 	rdma_restrack_new(&pd->res, RDMA_RESTRACK_PD);
27621a428a0SLeon Romanovsky 	rdma_restrack_set_task(&pd->res, caller);
27721a428a0SLeon Romanovsky 
278ff23dfa1SShamir Rabinovitch 	ret = device->ops.alloc_pd(pd, NULL);
27921a428a0SLeon Romanovsky 	if (ret) {
28013ef5539SLeon Romanovsky 		rdma_restrack_put(&pd->res);
28121a428a0SLeon Romanovsky 		kfree(pd);
28221a428a0SLeon Romanovsky 		return ERR_PTR(ret);
28321a428a0SLeon Romanovsky 	}
28421a428a0SLeon Romanovsky 	rdma_restrack_kadd(&pd->res);
28521a428a0SLeon Romanovsky 
28686bee4c9SOr Gerlitz 	if (device->attrs.device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY)
28796249d70SJason Gunthorpe 		pd->local_dma_lkey = device->local_dma_lkey;
288ed082d36SChristoph Hellwig 	else
289ed082d36SChristoph Hellwig 		mr_access_flags |= IB_ACCESS_LOCAL_WRITE;
290ed082d36SChristoph Hellwig 
291ed082d36SChristoph Hellwig 	if (flags & IB_PD_UNSAFE_GLOBAL_RKEY) {
292ed082d36SChristoph Hellwig 		pr_warn("%s: enabling unsafe global rkey\n", caller);
293ed082d36SChristoph Hellwig 		mr_access_flags |= IB_ACCESS_REMOTE_READ | IB_ACCESS_REMOTE_WRITE;
294ed082d36SChristoph Hellwig 	}
295ed082d36SChristoph Hellwig 
296ed082d36SChristoph Hellwig 	if (mr_access_flags) {
29796249d70SJason Gunthorpe 		struct ib_mr *mr;
29896249d70SJason Gunthorpe 
2993023a1e9SKamal Heib 		mr = pd->device->ops.get_dma_mr(pd, mr_access_flags);
30096249d70SJason Gunthorpe 		if (IS_ERR(mr)) {
30196249d70SJason Gunthorpe 			ib_dealloc_pd(pd);
3025ef990f0SChristoph Hellwig 			return ERR_CAST(mr);
3031da177e4SLinus Torvalds 		}
3041da177e4SLinus Torvalds 
3055ef990f0SChristoph Hellwig 		mr->device	= pd->device;
3065ef990f0SChristoph Hellwig 		mr->pd		= pd;
307a0bc099aSMax Gurtovoy 		mr->type        = IB_MR_TYPE_DMA;
3085ef990f0SChristoph Hellwig 		mr->uobject	= NULL;
3095ef990f0SChristoph Hellwig 		mr->need_inval	= false;
3105ef990f0SChristoph Hellwig 
31150d46335SChristoph Hellwig 		pd->__internal_mr = mr;
312ed082d36SChristoph Hellwig 
313ed082d36SChristoph Hellwig 		if (!(device->attrs.device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY))
31450d46335SChristoph Hellwig 			pd->local_dma_lkey = pd->__internal_mr->lkey;
315ed082d36SChristoph Hellwig 
316ed082d36SChristoph Hellwig 		if (flags & IB_PD_UNSAFE_GLOBAL_RKEY)
317ed082d36SChristoph Hellwig 			pd->unsafe_global_rkey = pd->__internal_mr->rkey;
31896249d70SJason Gunthorpe 	}
319ed082d36SChristoph Hellwig 
3201da177e4SLinus Torvalds 	return pd;
3211da177e4SLinus Torvalds }
322ed082d36SChristoph Hellwig EXPORT_SYMBOL(__ib_alloc_pd);
3231da177e4SLinus Torvalds 
3247dd78647SJason Gunthorpe /**
32591f57129SIsrael Rukshin  * ib_dealloc_pd_user - Deallocates a protection domain.
3267dd78647SJason Gunthorpe  * @pd: The protection domain to deallocate.
327c4367a26SShamir Rabinovitch  * @udata: Valid user data or NULL for kernel object
3287dd78647SJason Gunthorpe  *
3297dd78647SJason Gunthorpe  * It is an error to call this function while any resources in the pd still
3307dd78647SJason Gunthorpe  * exist.  The caller is responsible to synchronously destroy them and
3317dd78647SJason Gunthorpe  * guarantee no new allocations will happen.
3327dd78647SJason Gunthorpe  */
33391a7c58fSLeon Romanovsky int ib_dealloc_pd_user(struct ib_pd *pd, struct ib_udata *udata)
3341da177e4SLinus Torvalds {
3357dd78647SJason Gunthorpe 	int ret;
3361da177e4SLinus Torvalds 
33750d46335SChristoph Hellwig 	if (pd->__internal_mr) {
338c4367a26SShamir Rabinovitch 		ret = pd->device->ops.dereg_mr(pd->__internal_mr, NULL);
3397dd78647SJason Gunthorpe 		WARN_ON(ret);
34050d46335SChristoph Hellwig 		pd->__internal_mr = NULL;
34196249d70SJason Gunthorpe 	}
34296249d70SJason Gunthorpe 
3437dd78647SJason Gunthorpe 	/* uverbs manipulates usecnt with proper locking, while the kabi
3447dd78647SJason Gunthorpe 	   requires the caller to guarantee we can't race here. */
3457dd78647SJason Gunthorpe 	WARN_ON(atomic_read(&pd->usecnt));
3461da177e4SLinus Torvalds 
34791a7c58fSLeon Romanovsky 	ret = pd->device->ops.dealloc_pd(pd, udata);
34891a7c58fSLeon Romanovsky 	if (ret)
34991a7c58fSLeon Romanovsky 		return ret;
35091a7c58fSLeon Romanovsky 
3519d5f8c20SLeon Romanovsky 	rdma_restrack_del(&pd->res);
35221a428a0SLeon Romanovsky 	kfree(pd);
35391a7c58fSLeon Romanovsky 	return ret;
3541da177e4SLinus Torvalds }
355c4367a26SShamir Rabinovitch EXPORT_SYMBOL(ib_dealloc_pd_user);
3561da177e4SLinus Torvalds 
3571da177e4SLinus Torvalds /* Address handles */
3581da177e4SLinus Torvalds 
359d97099feSJason Gunthorpe /**
360d97099feSJason Gunthorpe  * rdma_copy_ah_attr - Copy rdma ah attribute from source to destination.
361d97099feSJason Gunthorpe  * @dest:       Pointer to destination ah_attr. Contents of the destination
362d97099feSJason Gunthorpe  *              pointer is assumed to be invalid and attribute are overwritten.
363d97099feSJason Gunthorpe  * @src:        Pointer to source ah_attr.
364d97099feSJason Gunthorpe  */
365d97099feSJason Gunthorpe void rdma_copy_ah_attr(struct rdma_ah_attr *dest,
366d97099feSJason Gunthorpe 		       const struct rdma_ah_attr *src)
367d97099feSJason Gunthorpe {
368d97099feSJason Gunthorpe 	*dest = *src;
369d97099feSJason Gunthorpe 	if (dest->grh.sgid_attr)
370d97099feSJason Gunthorpe 		rdma_hold_gid_attr(dest->grh.sgid_attr);
371d97099feSJason Gunthorpe }
372d97099feSJason Gunthorpe EXPORT_SYMBOL(rdma_copy_ah_attr);
373d97099feSJason Gunthorpe 
374d97099feSJason Gunthorpe /**
375d97099feSJason Gunthorpe  * rdma_replace_ah_attr - Replace valid ah_attr with new new one.
376d97099feSJason Gunthorpe  * @old:        Pointer to existing ah_attr which needs to be replaced.
377d97099feSJason Gunthorpe  *              old is assumed to be valid or zero'd
378d97099feSJason Gunthorpe  * @new:        Pointer to the new ah_attr.
379d97099feSJason Gunthorpe  *
380d97099feSJason Gunthorpe  * rdma_replace_ah_attr() first releases any reference in the old ah_attr if
381d97099feSJason Gunthorpe  * old the ah_attr is valid; after that it copies the new attribute and holds
382d97099feSJason Gunthorpe  * the reference to the replaced ah_attr.
383d97099feSJason Gunthorpe  */
384d97099feSJason Gunthorpe void rdma_replace_ah_attr(struct rdma_ah_attr *old,
385d97099feSJason Gunthorpe 			  const struct rdma_ah_attr *new)
386d97099feSJason Gunthorpe {
387d97099feSJason Gunthorpe 	rdma_destroy_ah_attr(old);
388d97099feSJason Gunthorpe 	*old = *new;
389d97099feSJason Gunthorpe 	if (old->grh.sgid_attr)
390d97099feSJason Gunthorpe 		rdma_hold_gid_attr(old->grh.sgid_attr);
391d97099feSJason Gunthorpe }
392d97099feSJason Gunthorpe EXPORT_SYMBOL(rdma_replace_ah_attr);
393d97099feSJason Gunthorpe 
394d97099feSJason Gunthorpe /**
395d97099feSJason Gunthorpe  * rdma_move_ah_attr - Move ah_attr pointed by source to destination.
396d97099feSJason Gunthorpe  * @dest:       Pointer to destination ah_attr to copy to.
397d97099feSJason Gunthorpe  *              dest is assumed to be valid or zero'd
398d97099feSJason Gunthorpe  * @src:        Pointer to the new ah_attr.
399d97099feSJason Gunthorpe  *
400d97099feSJason Gunthorpe  * rdma_move_ah_attr() first releases any reference in the destination ah_attr
401d97099feSJason Gunthorpe  * if it is valid. This also transfers ownership of internal references from
402d97099feSJason Gunthorpe  * src to dest, making src invalid in the process. No new reference of the src
403d97099feSJason Gunthorpe  * ah_attr is taken.
404d97099feSJason Gunthorpe  */
405d97099feSJason Gunthorpe void rdma_move_ah_attr(struct rdma_ah_attr *dest, struct rdma_ah_attr *src)
406d97099feSJason Gunthorpe {
407d97099feSJason Gunthorpe 	rdma_destroy_ah_attr(dest);
408d97099feSJason Gunthorpe 	*dest = *src;
409d97099feSJason Gunthorpe 	src->grh.sgid_attr = NULL;
410d97099feSJason Gunthorpe }
411d97099feSJason Gunthorpe EXPORT_SYMBOL(rdma_move_ah_attr);
412d97099feSJason Gunthorpe 
4138d9ec9adSJason Gunthorpe /*
4148d9ec9adSJason Gunthorpe  * Validate that the rdma_ah_attr is valid for the device before passing it
4158d9ec9adSJason Gunthorpe  * off to the driver.
4168d9ec9adSJason Gunthorpe  */
4178d9ec9adSJason Gunthorpe static int rdma_check_ah_attr(struct ib_device *device,
4188d9ec9adSJason Gunthorpe 			      struct rdma_ah_attr *ah_attr)
4198d9ec9adSJason Gunthorpe {
4208d9ec9adSJason Gunthorpe 	if (!rdma_is_port_valid(device, ah_attr->port_num))
4218d9ec9adSJason Gunthorpe 		return -EINVAL;
4228d9ec9adSJason Gunthorpe 
423b02289b3SArtemy Kovalyov 	if ((rdma_is_grh_required(device, ah_attr->port_num) ||
424b02289b3SArtemy Kovalyov 	     ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) &&
4258d9ec9adSJason Gunthorpe 	    !(ah_attr->ah_flags & IB_AH_GRH))
4268d9ec9adSJason Gunthorpe 		return -EINVAL;
4278d9ec9adSJason Gunthorpe 
4288d9ec9adSJason Gunthorpe 	if (ah_attr->grh.sgid_attr) {
4298d9ec9adSJason Gunthorpe 		/*
4308d9ec9adSJason Gunthorpe 		 * Make sure the passed sgid_attr is consistent with the
4318d9ec9adSJason Gunthorpe 		 * parameters
4328d9ec9adSJason Gunthorpe 		 */
4338d9ec9adSJason Gunthorpe 		if (ah_attr->grh.sgid_attr->index != ah_attr->grh.sgid_index ||
4348d9ec9adSJason Gunthorpe 		    ah_attr->grh.sgid_attr->port_num != ah_attr->port_num)
4358d9ec9adSJason Gunthorpe 			return -EINVAL;
4368d9ec9adSJason Gunthorpe 	}
4378d9ec9adSJason Gunthorpe 	return 0;
4388d9ec9adSJason Gunthorpe }
4398d9ec9adSJason Gunthorpe 
4408d9ec9adSJason Gunthorpe /*
4418d9ec9adSJason Gunthorpe  * If the ah requires a GRH then ensure that sgid_attr pointer is filled in.
4428d9ec9adSJason Gunthorpe  * On success the caller is responsible to call rdma_unfill_sgid_attr().
4438d9ec9adSJason Gunthorpe  */
4448d9ec9adSJason Gunthorpe static int rdma_fill_sgid_attr(struct ib_device *device,
4458d9ec9adSJason Gunthorpe 			       struct rdma_ah_attr *ah_attr,
4468d9ec9adSJason Gunthorpe 			       const struct ib_gid_attr **old_sgid_attr)
4478d9ec9adSJason Gunthorpe {
4488d9ec9adSJason Gunthorpe 	const struct ib_gid_attr *sgid_attr;
4498d9ec9adSJason Gunthorpe 	struct ib_global_route *grh;
4508d9ec9adSJason Gunthorpe 	int ret;
4518d9ec9adSJason Gunthorpe 
4528d9ec9adSJason Gunthorpe 	*old_sgid_attr = ah_attr->grh.sgid_attr;
4538d9ec9adSJason Gunthorpe 
4548d9ec9adSJason Gunthorpe 	ret = rdma_check_ah_attr(device, ah_attr);
4558d9ec9adSJason Gunthorpe 	if (ret)
4568d9ec9adSJason Gunthorpe 		return ret;
4578d9ec9adSJason Gunthorpe 
4588d9ec9adSJason Gunthorpe 	if (!(ah_attr->ah_flags & IB_AH_GRH))
4598d9ec9adSJason Gunthorpe 		return 0;
4608d9ec9adSJason Gunthorpe 
4618d9ec9adSJason Gunthorpe 	grh = rdma_ah_retrieve_grh(ah_attr);
4628d9ec9adSJason Gunthorpe 	if (grh->sgid_attr)
4638d9ec9adSJason Gunthorpe 		return 0;
4648d9ec9adSJason Gunthorpe 
4658d9ec9adSJason Gunthorpe 	sgid_attr =
4668d9ec9adSJason Gunthorpe 		rdma_get_gid_attr(device, ah_attr->port_num, grh->sgid_index);
4678d9ec9adSJason Gunthorpe 	if (IS_ERR(sgid_attr))
4688d9ec9adSJason Gunthorpe 		return PTR_ERR(sgid_attr);
4698d9ec9adSJason Gunthorpe 
4708d9ec9adSJason Gunthorpe 	/* Move ownerhip of the kref into the ah_attr */
4718d9ec9adSJason Gunthorpe 	grh->sgid_attr = sgid_attr;
4728d9ec9adSJason Gunthorpe 	return 0;
4738d9ec9adSJason Gunthorpe }
4748d9ec9adSJason Gunthorpe 
4758d9ec9adSJason Gunthorpe static void rdma_unfill_sgid_attr(struct rdma_ah_attr *ah_attr,
4768d9ec9adSJason Gunthorpe 				  const struct ib_gid_attr *old_sgid_attr)
4778d9ec9adSJason Gunthorpe {
4788d9ec9adSJason Gunthorpe 	/*
4798d9ec9adSJason Gunthorpe 	 * Fill didn't change anything, the caller retains ownership of
4808d9ec9adSJason Gunthorpe 	 * whatever it passed
4818d9ec9adSJason Gunthorpe 	 */
4828d9ec9adSJason Gunthorpe 	if (ah_attr->grh.sgid_attr == old_sgid_attr)
4838d9ec9adSJason Gunthorpe 		return;
4848d9ec9adSJason Gunthorpe 
4858d9ec9adSJason Gunthorpe 	/*
4868d9ec9adSJason Gunthorpe 	 * Otherwise, we need to undo what rdma_fill_sgid_attr so the caller
4878d9ec9adSJason Gunthorpe 	 * doesn't see any change in the rdma_ah_attr. If we get here
4888d9ec9adSJason Gunthorpe 	 * old_sgid_attr is NULL.
4898d9ec9adSJason Gunthorpe 	 */
4908d9ec9adSJason Gunthorpe 	rdma_destroy_ah_attr(ah_attr);
4918d9ec9adSJason Gunthorpe }
4928d9ec9adSJason Gunthorpe 
4931a1f460fSJason Gunthorpe static const struct ib_gid_attr *
4941a1f460fSJason Gunthorpe rdma_update_sgid_attr(struct rdma_ah_attr *ah_attr,
4951a1f460fSJason Gunthorpe 		      const struct ib_gid_attr *old_attr)
4961a1f460fSJason Gunthorpe {
4971a1f460fSJason Gunthorpe 	if (old_attr)
4981a1f460fSJason Gunthorpe 		rdma_put_gid_attr(old_attr);
4991a1f460fSJason Gunthorpe 	if (ah_attr->ah_flags & IB_AH_GRH) {
5001a1f460fSJason Gunthorpe 		rdma_hold_gid_attr(ah_attr->grh.sgid_attr);
5011a1f460fSJason Gunthorpe 		return ah_attr->grh.sgid_attr;
5021a1f460fSJason Gunthorpe 	}
5031a1f460fSJason Gunthorpe 	return NULL;
5041a1f460fSJason Gunthorpe }
5051a1f460fSJason Gunthorpe 
5065cda6587SParav Pandit static struct ib_ah *_rdma_create_ah(struct ib_pd *pd,
5075cda6587SParav Pandit 				     struct rdma_ah_attr *ah_attr,
508b090c4e3SGal Pressman 				     u32 flags,
50951aab126SMaor Gottlieb 				     struct ib_udata *udata,
51051aab126SMaor Gottlieb 				     struct net_device *xmit_slave)
5111da177e4SLinus Torvalds {
512fa5d010cSMaor Gottlieb 	struct rdma_ah_init_attr init_attr = {};
513d3456914SLeon Romanovsky 	struct ib_device *device = pd->device;
5141da177e4SLinus Torvalds 	struct ib_ah *ah;
515d3456914SLeon Romanovsky 	int ret;
5161da177e4SLinus Torvalds 
517b090c4e3SGal Pressman 	might_sleep_if(flags & RDMA_CREATE_AH_SLEEPABLE);
518b090c4e3SGal Pressman 
519d3456914SLeon Romanovsky 	if (!device->ops.create_ah)
5200584c47bSKamal Heib 		return ERR_PTR(-EOPNOTSUPP);
5210584c47bSKamal Heib 
522d3456914SLeon Romanovsky 	ah = rdma_zalloc_drv_obj_gfp(
523d3456914SLeon Romanovsky 		device, ib_ah,
524d3456914SLeon Romanovsky 		(flags & RDMA_CREATE_AH_SLEEPABLE) ? GFP_KERNEL : GFP_ATOMIC);
525d3456914SLeon Romanovsky 	if (!ah)
526d3456914SLeon Romanovsky 		return ERR_PTR(-ENOMEM);
5271da177e4SLinus Torvalds 
528d3456914SLeon Romanovsky 	ah->device = device;
5291da177e4SLinus Torvalds 	ah->pd = pd;
53044c58487SDasaratharaman Chandramouli 	ah->type = ah_attr->type;
5311a1f460fSJason Gunthorpe 	ah->sgid_attr = rdma_update_sgid_attr(ah_attr, NULL);
532fa5d010cSMaor Gottlieb 	init_attr.ah_attr = ah_attr;
533fa5d010cSMaor Gottlieb 	init_attr.flags = flags;
53451aab126SMaor Gottlieb 	init_attr.xmit_slave = xmit_slave;
5351a1f460fSJason Gunthorpe 
536fa5d010cSMaor Gottlieb 	ret = device->ops.create_ah(ah, &init_attr, udata);
537d3456914SLeon Romanovsky 	if (ret) {
538d3456914SLeon Romanovsky 		kfree(ah);
539d3456914SLeon Romanovsky 		return ERR_PTR(ret);
5401da177e4SLinus Torvalds 	}
5411da177e4SLinus Torvalds 
542d3456914SLeon Romanovsky 	atomic_inc(&pd->usecnt);
5431da177e4SLinus Torvalds 	return ah;
5441da177e4SLinus Torvalds }
5455cda6587SParav Pandit 
5468d9ec9adSJason Gunthorpe /**
5478d9ec9adSJason Gunthorpe  * rdma_create_ah - Creates an address handle for the
5488d9ec9adSJason Gunthorpe  * given address vector.
5498d9ec9adSJason Gunthorpe  * @pd: The protection domain associated with the address handle.
5508d9ec9adSJason Gunthorpe  * @ah_attr: The attributes of the address vector.
551b090c4e3SGal Pressman  * @flags: Create address handle flags (see enum rdma_create_ah_flags).
5528d9ec9adSJason Gunthorpe  *
5538d9ec9adSJason Gunthorpe  * It returns 0 on success and returns appropriate error code on error.
5548d9ec9adSJason Gunthorpe  * The address handle is used to reference a local or global destination
5558d9ec9adSJason Gunthorpe  * in all UD QP post sends.
5568d9ec9adSJason Gunthorpe  */
557b090c4e3SGal Pressman struct ib_ah *rdma_create_ah(struct ib_pd *pd, struct rdma_ah_attr *ah_attr,
558b090c4e3SGal Pressman 			     u32 flags)
5595cda6587SParav Pandit {
5608d9ec9adSJason Gunthorpe 	const struct ib_gid_attr *old_sgid_attr;
56151aab126SMaor Gottlieb 	struct net_device *slave;
5628d9ec9adSJason Gunthorpe 	struct ib_ah *ah;
5638d9ec9adSJason Gunthorpe 	int ret;
5648d9ec9adSJason Gunthorpe 
5658d9ec9adSJason Gunthorpe 	ret = rdma_fill_sgid_attr(pd->device, ah_attr, &old_sgid_attr);
5668d9ec9adSJason Gunthorpe 	if (ret)
5678d9ec9adSJason Gunthorpe 		return ERR_PTR(ret);
56851aab126SMaor Gottlieb 	slave = rdma_lag_get_ah_roce_slave(pd->device, ah_attr,
56951aab126SMaor Gottlieb 					   (flags & RDMA_CREATE_AH_SLEEPABLE) ?
57051aab126SMaor Gottlieb 					   GFP_KERNEL : GFP_ATOMIC);
57151aab126SMaor Gottlieb 	if (IS_ERR(slave)) {
57251aab126SMaor Gottlieb 		rdma_unfill_sgid_attr(ah_attr, old_sgid_attr);
57351aab126SMaor Gottlieb 		return (void *)slave;
57451aab126SMaor Gottlieb 	}
57551aab126SMaor Gottlieb 	ah = _rdma_create_ah(pd, ah_attr, flags, NULL, slave);
57651aab126SMaor Gottlieb 	rdma_lag_put_ah_roce_slave(slave);
5778d9ec9adSJason Gunthorpe 	rdma_unfill_sgid_attr(ah_attr, old_sgid_attr);
5788d9ec9adSJason Gunthorpe 	return ah;
5795cda6587SParav Pandit }
5800a18cfe4SDasaratharaman Chandramouli EXPORT_SYMBOL(rdma_create_ah);
5811da177e4SLinus Torvalds 
5825cda6587SParav Pandit /**
5835cda6587SParav Pandit  * rdma_create_user_ah - Creates an address handle for the
5845cda6587SParav Pandit  * given address vector.
5855cda6587SParav Pandit  * It resolves destination mac address for ah attribute of RoCE type.
5865cda6587SParav Pandit  * @pd: The protection domain associated with the address handle.
5875cda6587SParav Pandit  * @ah_attr: The attributes of the address vector.
5885cda6587SParav Pandit  * @udata: pointer to user's input output buffer information need by
5895cda6587SParav Pandit  *         provider driver.
5905cda6587SParav Pandit  *
5915cda6587SParav Pandit  * It returns 0 on success and returns appropriate error code on error.
5925cda6587SParav Pandit  * The address handle is used to reference a local or global destination
5935cda6587SParav Pandit  * in all UD QP post sends.
5945cda6587SParav Pandit  */
5955cda6587SParav Pandit struct ib_ah *rdma_create_user_ah(struct ib_pd *pd,
5965cda6587SParav Pandit 				  struct rdma_ah_attr *ah_attr,
5975cda6587SParav Pandit 				  struct ib_udata *udata)
5985cda6587SParav Pandit {
5998d9ec9adSJason Gunthorpe 	const struct ib_gid_attr *old_sgid_attr;
6008d9ec9adSJason Gunthorpe 	struct ib_ah *ah;
6015cda6587SParav Pandit 	int err;
6025cda6587SParav Pandit 
6038d9ec9adSJason Gunthorpe 	err = rdma_fill_sgid_attr(pd->device, ah_attr, &old_sgid_attr);
6048d9ec9adSJason Gunthorpe 	if (err)
6058d9ec9adSJason Gunthorpe 		return ERR_PTR(err);
6068d9ec9adSJason Gunthorpe 
6075cda6587SParav Pandit 	if (ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) {
6085cda6587SParav Pandit 		err = ib_resolve_eth_dmac(pd->device, ah_attr);
6098d9ec9adSJason Gunthorpe 		if (err) {
6108d9ec9adSJason Gunthorpe 			ah = ERR_PTR(err);
6118d9ec9adSJason Gunthorpe 			goto out;
6128d9ec9adSJason Gunthorpe 		}
6135cda6587SParav Pandit 	}
6145cda6587SParav Pandit 
61551aab126SMaor Gottlieb 	ah = _rdma_create_ah(pd, ah_attr, RDMA_CREATE_AH_SLEEPABLE,
61651aab126SMaor Gottlieb 			     udata, NULL);
6178d9ec9adSJason Gunthorpe 
6188d9ec9adSJason Gunthorpe out:
6198d9ec9adSJason Gunthorpe 	rdma_unfill_sgid_attr(ah_attr, old_sgid_attr);
6208d9ec9adSJason Gunthorpe 	return ah;
6215cda6587SParav Pandit }
6225cda6587SParav Pandit EXPORT_SYMBOL(rdma_create_user_ah);
6235cda6587SParav Pandit 
624850d8fd7SMoni Shoua int ib_get_rdma_header_version(const union rdma_network_hdr *hdr)
625c865f246SSomnath Kotur {
626c865f246SSomnath Kotur 	const struct iphdr *ip4h = (struct iphdr *)&hdr->roce4grh;
627c865f246SSomnath Kotur 	struct iphdr ip4h_checked;
628c865f246SSomnath Kotur 	const struct ipv6hdr *ip6h = (struct ipv6hdr *)&hdr->ibgrh;
629c865f246SSomnath Kotur 
630c865f246SSomnath Kotur 	/* If it's IPv6, the version must be 6, otherwise, the first
631c865f246SSomnath Kotur 	 * 20 bytes (before the IPv4 header) are garbled.
632c865f246SSomnath Kotur 	 */
633c865f246SSomnath Kotur 	if (ip6h->version != 6)
634c865f246SSomnath Kotur 		return (ip4h->version == 4) ? 4 : 0;
635c865f246SSomnath Kotur 	/* version may be 6 or 4 because the first 20 bytes could be garbled */
636c865f246SSomnath Kotur 
637c865f246SSomnath Kotur 	/* RoCE v2 requires no options, thus header length
638c865f246SSomnath Kotur 	 * must be 5 words
639c865f246SSomnath Kotur 	 */
640c865f246SSomnath Kotur 	if (ip4h->ihl != 5)
641c865f246SSomnath Kotur 		return 6;
642c865f246SSomnath Kotur 
643c865f246SSomnath Kotur 	/* Verify checksum.
644c865f246SSomnath Kotur 	 * We can't write on scattered buffers so we need to copy to
645c865f246SSomnath Kotur 	 * temp buffer.
646c865f246SSomnath Kotur 	 */
647c865f246SSomnath Kotur 	memcpy(&ip4h_checked, ip4h, sizeof(ip4h_checked));
648c865f246SSomnath Kotur 	ip4h_checked.check = 0;
649c865f246SSomnath Kotur 	ip4h_checked.check = ip_fast_csum((u8 *)&ip4h_checked, 5);
650c865f246SSomnath Kotur 	/* if IPv4 header checksum is OK, believe it */
651c865f246SSomnath Kotur 	if (ip4h->check == ip4h_checked.check)
652c865f246SSomnath Kotur 		return 4;
653c865f246SSomnath Kotur 	return 6;
654c865f246SSomnath Kotur }
655850d8fd7SMoni Shoua EXPORT_SYMBOL(ib_get_rdma_header_version);
656c865f246SSomnath Kotur 
657c865f246SSomnath Kotur static enum rdma_network_type ib_get_net_type_by_grh(struct ib_device *device,
658c865f246SSomnath Kotur 						     u8 port_num,
659c865f246SSomnath Kotur 						     const struct ib_grh *grh)
660c865f246SSomnath Kotur {
661c865f246SSomnath Kotur 	int grh_version;
662c865f246SSomnath Kotur 
663c865f246SSomnath Kotur 	if (rdma_protocol_ib(device, port_num))
664c865f246SSomnath Kotur 		return RDMA_NETWORK_IB;
665c865f246SSomnath Kotur 
666850d8fd7SMoni Shoua 	grh_version = ib_get_rdma_header_version((union rdma_network_hdr *)grh);
667c865f246SSomnath Kotur 
668c865f246SSomnath Kotur 	if (grh_version == 4)
669c865f246SSomnath Kotur 		return RDMA_NETWORK_IPV4;
670c865f246SSomnath Kotur 
671c865f246SSomnath Kotur 	if (grh->next_hdr == IPPROTO_UDP)
672c865f246SSomnath Kotur 		return RDMA_NETWORK_IPV6;
673c865f246SSomnath Kotur 
674c865f246SSomnath Kotur 	return RDMA_NETWORK_ROCE_V1;
675c865f246SSomnath Kotur }
676c865f246SSomnath Kotur 
677dbf727deSMatan Barak struct find_gid_index_context {
678dbf727deSMatan Barak 	u16 vlan_id;
679c865f246SSomnath Kotur 	enum ib_gid_type gid_type;
680dbf727deSMatan Barak };
681dbf727deSMatan Barak 
682dbf727deSMatan Barak static bool find_gid_index(const union ib_gid *gid,
683dbf727deSMatan Barak 			   const struct ib_gid_attr *gid_attr,
684dbf727deSMatan Barak 			   void *context)
685dbf727deSMatan Barak {
686b0dd0d33SParav Pandit 	struct find_gid_index_context *ctx = context;
687777a8b32SParav Pandit 	u16 vlan_id = 0xffff;
688777a8b32SParav Pandit 	int ret;
689dbf727deSMatan Barak 
690c865f246SSomnath Kotur 	if (ctx->gid_type != gid_attr->gid_type)
691c865f246SSomnath Kotur 		return false;
692c865f246SSomnath Kotur 
693777a8b32SParav Pandit 	ret = rdma_read_gid_l2_fields(gid_attr, &vlan_id, NULL);
694777a8b32SParav Pandit 	if (ret)
695dbf727deSMatan Barak 		return false;
696dbf727deSMatan Barak 
697777a8b32SParav Pandit 	return ctx->vlan_id == vlan_id;
698dbf727deSMatan Barak }
699dbf727deSMatan Barak 
700b7403217SParav Pandit static const struct ib_gid_attr *
701b7403217SParav Pandit get_sgid_attr_from_eth(struct ib_device *device, u8 port_num,
702dbf727deSMatan Barak 		       u16 vlan_id, const union ib_gid *sgid,
703b7403217SParav Pandit 		       enum ib_gid_type gid_type)
704dbf727deSMatan Barak {
705c865f246SSomnath Kotur 	struct find_gid_index_context context = {.vlan_id = vlan_id,
706c865f246SSomnath Kotur 						 .gid_type = gid_type};
707dbf727deSMatan Barak 
708b7403217SParav Pandit 	return rdma_find_gid_by_filter(device, sgid, port_num, find_gid_index,
709b7403217SParav Pandit 				       &context);
710dbf727deSMatan Barak }
711dbf727deSMatan Barak 
712850d8fd7SMoni Shoua int ib_get_gids_from_rdma_hdr(const union rdma_network_hdr *hdr,
713c865f246SSomnath Kotur 			      enum rdma_network_type net_type,
714c865f246SSomnath Kotur 			      union ib_gid *sgid, union ib_gid *dgid)
715c865f246SSomnath Kotur {
716c865f246SSomnath Kotur 	struct sockaddr_in  src_in;
717c865f246SSomnath Kotur 	struct sockaddr_in  dst_in;
718c865f246SSomnath Kotur 	__be32 src_saddr, dst_saddr;
719c865f246SSomnath Kotur 
720c865f246SSomnath Kotur 	if (!sgid || !dgid)
721c865f246SSomnath Kotur 		return -EINVAL;
722c865f246SSomnath Kotur 
723c865f246SSomnath Kotur 	if (net_type == RDMA_NETWORK_IPV4) {
724c865f246SSomnath Kotur 		memcpy(&src_in.sin_addr.s_addr,
725c865f246SSomnath Kotur 		       &hdr->roce4grh.saddr, 4);
726c865f246SSomnath Kotur 		memcpy(&dst_in.sin_addr.s_addr,
727c865f246SSomnath Kotur 		       &hdr->roce4grh.daddr, 4);
728c865f246SSomnath Kotur 		src_saddr = src_in.sin_addr.s_addr;
729c865f246SSomnath Kotur 		dst_saddr = dst_in.sin_addr.s_addr;
730c865f246SSomnath Kotur 		ipv6_addr_set_v4mapped(src_saddr,
731c865f246SSomnath Kotur 				       (struct in6_addr *)sgid);
732c865f246SSomnath Kotur 		ipv6_addr_set_v4mapped(dst_saddr,
733c865f246SSomnath Kotur 				       (struct in6_addr *)dgid);
734c865f246SSomnath Kotur 		return 0;
735c865f246SSomnath Kotur 	} else if (net_type == RDMA_NETWORK_IPV6 ||
736c865f246SSomnath Kotur 		   net_type == RDMA_NETWORK_IB) {
737c865f246SSomnath Kotur 		*dgid = hdr->ibgrh.dgid;
738c865f246SSomnath Kotur 		*sgid = hdr->ibgrh.sgid;
739c865f246SSomnath Kotur 		return 0;
740c865f246SSomnath Kotur 	} else {
741c865f246SSomnath Kotur 		return -EINVAL;
742c865f246SSomnath Kotur 	}
743c865f246SSomnath Kotur }
744850d8fd7SMoni Shoua EXPORT_SYMBOL(ib_get_gids_from_rdma_hdr);
745c865f246SSomnath Kotur 
7461060f865SParav Pandit /* Resolve destination mac address and hop limit for unicast destination
7471060f865SParav Pandit  * GID entry, considering the source GID entry as well.
7481060f865SParav Pandit  * ah_attribute must have have valid port_num, sgid_index.
7491060f865SParav Pandit  */
7501060f865SParav Pandit static int ib_resolve_unicast_gid_dmac(struct ib_device *device,
7511060f865SParav Pandit 				       struct rdma_ah_attr *ah_attr)
7521060f865SParav Pandit {
753b7403217SParav Pandit 	struct ib_global_route *grh = rdma_ah_retrieve_grh(ah_attr);
754b7403217SParav Pandit 	const struct ib_gid_attr *sgid_attr = grh->sgid_attr;
7551060f865SParav Pandit 	int hop_limit = 0xff;
756b7403217SParav Pandit 	int ret = 0;
7571060f865SParav Pandit 
75856d0a7d9SParav Pandit 	/* If destination is link local and source GID is RoCEv1,
75956d0a7d9SParav Pandit 	 * IP stack is not used.
76056d0a7d9SParav Pandit 	 */
76156d0a7d9SParav Pandit 	if (rdma_link_local_addr((struct in6_addr *)grh->dgid.raw) &&
762b7403217SParav Pandit 	    sgid_attr->gid_type == IB_GID_TYPE_ROCE) {
76356d0a7d9SParav Pandit 		rdma_get_ll_mac((struct in6_addr *)grh->dgid.raw,
76456d0a7d9SParav Pandit 				ah_attr->roce.dmac);
765b7403217SParav Pandit 		return ret;
76656d0a7d9SParav Pandit 	}
76756d0a7d9SParav Pandit 
768b7403217SParav Pandit 	ret = rdma_addr_find_l2_eth_by_grh(&sgid_attr->gid, &grh->dgid,
7691060f865SParav Pandit 					   ah_attr->roce.dmac,
7700e9d2c19SParav Pandit 					   sgid_attr, &hop_limit);
7711060f865SParav Pandit 
7721060f865SParav Pandit 	grh->hop_limit = hop_limit;
7731060f865SParav Pandit 	return ret;
7741060f865SParav Pandit }
7751060f865SParav Pandit 
77628b5b3a2SGustavo A. R. Silva /*
777f6bdb142SParav Pandit  * This function initializes address handle attributes from the incoming packet.
77828b5b3a2SGustavo A. R. Silva  * Incoming packet has dgid of the receiver node on which this code is
77928b5b3a2SGustavo A. R. Silva  * getting executed and, sgid contains the GID of the sender.
78028b5b3a2SGustavo A. R. Silva  *
78128b5b3a2SGustavo A. R. Silva  * When resolving mac address of destination, the arrived dgid is used
78228b5b3a2SGustavo A. R. Silva  * as sgid and, sgid is used as dgid because sgid contains destinations
78328b5b3a2SGustavo A. R. Silva  * GID whom to respond to.
78428b5b3a2SGustavo A. R. Silva  *
785b7403217SParav Pandit  * On success the caller is responsible to call rdma_destroy_ah_attr on the
786b7403217SParav Pandit  * attr.
78728b5b3a2SGustavo A. R. Silva  */
788f6bdb142SParav Pandit int ib_init_ah_attr_from_wc(struct ib_device *device, u8 port_num,
78973cdaaeeSIra Weiny 			    const struct ib_wc *wc, const struct ib_grh *grh,
79090898850SDasaratharaman Chandramouli 			    struct rdma_ah_attr *ah_attr)
791513789edSHal Rosenstock {
792513789edSHal Rosenstock 	u32 flow_class;
793513789edSHal Rosenstock 	int ret;
794c865f246SSomnath Kotur 	enum rdma_network_type net_type = RDMA_NETWORK_IB;
795c865f246SSomnath Kotur 	enum ib_gid_type gid_type = IB_GID_TYPE_IB;
796b7403217SParav Pandit 	const struct ib_gid_attr *sgid_attr;
797c3efe750SMatan Barak 	int hoplimit = 0xff;
798c865f246SSomnath Kotur 	union ib_gid dgid;
799c865f246SSomnath Kotur 	union ib_gid sgid;
800513789edSHal Rosenstock 
80179364227SRoland Dreier 	might_sleep();
80279364227SRoland Dreier 
8034e00d694SSean Hefty 	memset(ah_attr, 0, sizeof *ah_attr);
80444c58487SDasaratharaman Chandramouli 	ah_attr->type = rdma_ah_find_type(device, port_num);
805227128fcSMichael Wang 	if (rdma_cap_eth_ah(device, port_num)) {
806c865f246SSomnath Kotur 		if (wc->wc_flags & IB_WC_WITH_NETWORK_HDR_TYPE)
807c865f246SSomnath Kotur 			net_type = wc->network_hdr_type;
808c865f246SSomnath Kotur 		else
809c865f246SSomnath Kotur 			net_type = ib_get_net_type_by_grh(device, port_num, grh);
810c865f246SSomnath Kotur 		gid_type = ib_network_to_gid_type(net_type);
811c865f246SSomnath Kotur 	}
812850d8fd7SMoni Shoua 	ret = ib_get_gids_from_rdma_hdr((union rdma_network_hdr *)grh, net_type,
813c865f246SSomnath Kotur 					&sgid, &dgid);
814c865f246SSomnath Kotur 	if (ret)
815c865f246SSomnath Kotur 		return ret;
816c865f246SSomnath Kotur 
8171060f865SParav Pandit 	rdma_ah_set_sl(ah_attr, wc->sl);
8181060f865SParav Pandit 	rdma_ah_set_port_num(ah_attr, port_num);
8191060f865SParav Pandit 
820c865f246SSomnath Kotur 	if (rdma_protocol_roce(device, port_num)) {
821dbf727deSMatan Barak 		u16 vlan_id = wc->wc_flags & IB_WC_WITH_VLAN ?
822dbf727deSMatan Barak 				wc->vlan_id : 0xffff;
823dbf727deSMatan Barak 
824dd5f03beSMatan Barak 		if (!(wc->wc_flags & IB_WC_GRH))
825dd5f03beSMatan Barak 			return -EPROTOTYPE;
826dd5f03beSMatan Barak 
827b7403217SParav Pandit 		sgid_attr = get_sgid_attr_from_eth(device, port_num,
8281060f865SParav Pandit 						   vlan_id, &dgid,
829b7403217SParav Pandit 						   gid_type);
830b7403217SParav Pandit 		if (IS_ERR(sgid_attr))
831b7403217SParav Pandit 			return PTR_ERR(sgid_attr);
83220029832SMatan Barak 
8331060f865SParav Pandit 		flow_class = be32_to_cpu(grh->version_tclass_flow);
834b7403217SParav Pandit 		rdma_move_grh_sgid_attr(ah_attr,
835b7403217SParav Pandit 					&sgid,
8361060f865SParav Pandit 					flow_class & 0xFFFFF,
837b7403217SParav Pandit 					hoplimit,
838b7403217SParav Pandit 					(flow_class >> 20) & 0xFF,
839b7403217SParav Pandit 					sgid_attr);
840b7403217SParav Pandit 
841b7403217SParav Pandit 		ret = ib_resolve_unicast_gid_dmac(device, ah_attr);
842b7403217SParav Pandit 		if (ret)
843b7403217SParav Pandit 			rdma_destroy_ah_attr(ah_attr);
844b7403217SParav Pandit 
845b7403217SParav Pandit 		return ret;
8461060f865SParav Pandit 	} else {
847d8966fcdSDasaratharaman Chandramouli 		rdma_ah_set_dlid(ah_attr, wc->slid);
848d8966fcdSDasaratharaman Chandramouli 		rdma_ah_set_path_bits(ah_attr, wc->dlid_path_bits);
849513789edSHal Rosenstock 
850b7403217SParav Pandit 		if ((wc->wc_flags & IB_WC_GRH) == 0)
851b7403217SParav Pandit 			return 0;
852513789edSHal Rosenstock 
853b7403217SParav Pandit 		if (dgid.global.interface_id !=
854b7403217SParav Pandit 					cpu_to_be64(IB_SA_WELL_KNOWN_GUID)) {
855b7403217SParav Pandit 			sgid_attr = rdma_find_gid_by_port(
856b7403217SParav Pandit 				device, &dgid, IB_GID_TYPE_IB, port_num, NULL);
857b7403217SParav Pandit 		} else
858b7403217SParav Pandit 			sgid_attr = rdma_get_gid_attr(device, port_num, 0);
859b7403217SParav Pandit 
860b7403217SParav Pandit 		if (IS_ERR(sgid_attr))
861b7403217SParav Pandit 			return PTR_ERR(sgid_attr);
862497677abSHal Rosenstock 		flow_class = be32_to_cpu(grh->version_tclass_flow);
863b7403217SParav Pandit 		rdma_move_grh_sgid_attr(ah_attr,
864b7403217SParav Pandit 					&sgid,
865d8966fcdSDasaratharaman Chandramouli 					flow_class & 0xFFFFF,
866b7403217SParav Pandit 					hoplimit,
867b7403217SParav Pandit 					(flow_class >> 20) & 0xFF,
868b7403217SParav Pandit 					sgid_attr);
869b7403217SParav Pandit 
8704e00d694SSean Hefty 		return 0;
8714e00d694SSean Hefty 	}
8721060f865SParav Pandit }
873f6bdb142SParav Pandit EXPORT_SYMBOL(ib_init_ah_attr_from_wc);
8744e00d694SSean Hefty 
8758d9ec9adSJason Gunthorpe /**
8768d9ec9adSJason Gunthorpe  * rdma_move_grh_sgid_attr - Sets the sgid attribute of GRH, taking ownership
8778d9ec9adSJason Gunthorpe  * of the reference
8788d9ec9adSJason Gunthorpe  *
8798d9ec9adSJason Gunthorpe  * @attr:	Pointer to AH attribute structure
8808d9ec9adSJason Gunthorpe  * @dgid:	Destination GID
8818d9ec9adSJason Gunthorpe  * @flow_label:	Flow label
8828d9ec9adSJason Gunthorpe  * @hop_limit:	Hop limit
8838d9ec9adSJason Gunthorpe  * @traffic_class: traffic class
8848d9ec9adSJason Gunthorpe  * @sgid_attr:	Pointer to SGID attribute
8858d9ec9adSJason Gunthorpe  *
8868d9ec9adSJason Gunthorpe  * This takes ownership of the sgid_attr reference. The caller must ensure
8878d9ec9adSJason Gunthorpe  * rdma_destroy_ah_attr() is called before destroying the rdma_ah_attr after
8888d9ec9adSJason Gunthorpe  * calling this function.
8898d9ec9adSJason Gunthorpe  */
8908d9ec9adSJason Gunthorpe void rdma_move_grh_sgid_attr(struct rdma_ah_attr *attr, union ib_gid *dgid,
8918d9ec9adSJason Gunthorpe 			     u32 flow_label, u8 hop_limit, u8 traffic_class,
8928d9ec9adSJason Gunthorpe 			     const struct ib_gid_attr *sgid_attr)
8938d9ec9adSJason Gunthorpe {
8948d9ec9adSJason Gunthorpe 	rdma_ah_set_grh(attr, dgid, flow_label, sgid_attr->index, hop_limit,
8958d9ec9adSJason Gunthorpe 			traffic_class);
8968d9ec9adSJason Gunthorpe 	attr->grh.sgid_attr = sgid_attr;
8978d9ec9adSJason Gunthorpe }
8988d9ec9adSJason Gunthorpe EXPORT_SYMBOL(rdma_move_grh_sgid_attr);
8998d9ec9adSJason Gunthorpe 
9008d9ec9adSJason Gunthorpe /**
9018d9ec9adSJason Gunthorpe  * rdma_destroy_ah_attr - Release reference to SGID attribute of
9028d9ec9adSJason Gunthorpe  * ah attribute.
9038d9ec9adSJason Gunthorpe  * @ah_attr: Pointer to ah attribute
9048d9ec9adSJason Gunthorpe  *
9058d9ec9adSJason Gunthorpe  * Release reference to the SGID attribute of the ah attribute if it is
9068d9ec9adSJason Gunthorpe  * non NULL. It is safe to call this multiple times, and safe to call it on
9078d9ec9adSJason Gunthorpe  * a zero initialized ah_attr.
9088d9ec9adSJason Gunthorpe  */
9098d9ec9adSJason Gunthorpe void rdma_destroy_ah_attr(struct rdma_ah_attr *ah_attr)
9108d9ec9adSJason Gunthorpe {
9118d9ec9adSJason Gunthorpe 	if (ah_attr->grh.sgid_attr) {
9128d9ec9adSJason Gunthorpe 		rdma_put_gid_attr(ah_attr->grh.sgid_attr);
9138d9ec9adSJason Gunthorpe 		ah_attr->grh.sgid_attr = NULL;
9148d9ec9adSJason Gunthorpe 	}
9158d9ec9adSJason Gunthorpe }
9168d9ec9adSJason Gunthorpe EXPORT_SYMBOL(rdma_destroy_ah_attr);
9178d9ec9adSJason Gunthorpe 
91873cdaaeeSIra Weiny struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, const struct ib_wc *wc,
91973cdaaeeSIra Weiny 				   const struct ib_grh *grh, u8 port_num)
9204e00d694SSean Hefty {
92190898850SDasaratharaman Chandramouli 	struct rdma_ah_attr ah_attr;
922b7403217SParav Pandit 	struct ib_ah *ah;
9234e00d694SSean Hefty 	int ret;
9244e00d694SSean Hefty 
925f6bdb142SParav Pandit 	ret = ib_init_ah_attr_from_wc(pd->device, port_num, wc, grh, &ah_attr);
9264e00d694SSean Hefty 	if (ret)
9274e00d694SSean Hefty 		return ERR_PTR(ret);
928513789edSHal Rosenstock 
929b090c4e3SGal Pressman 	ah = rdma_create_ah(pd, &ah_attr, RDMA_CREATE_AH_SLEEPABLE);
930b7403217SParav Pandit 
931b7403217SParav Pandit 	rdma_destroy_ah_attr(&ah_attr);
932b7403217SParav Pandit 	return ah;
933513789edSHal Rosenstock }
934513789edSHal Rosenstock EXPORT_SYMBOL(ib_create_ah_from_wc);
935513789edSHal Rosenstock 
93667b985b6SDasaratharaman Chandramouli int rdma_modify_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr)
9371da177e4SLinus Torvalds {
9388d9ec9adSJason Gunthorpe 	const struct ib_gid_attr *old_sgid_attr;
9398d9ec9adSJason Gunthorpe 	int ret;
9408d9ec9adSJason Gunthorpe 
94144c58487SDasaratharaman Chandramouli 	if (ah->type != ah_attr->type)
94244c58487SDasaratharaman Chandramouli 		return -EINVAL;
94344c58487SDasaratharaman Chandramouli 
9448d9ec9adSJason Gunthorpe 	ret = rdma_fill_sgid_attr(ah->device, ah_attr, &old_sgid_attr);
9458d9ec9adSJason Gunthorpe 	if (ret)
9468d9ec9adSJason Gunthorpe 		return ret;
9478d9ec9adSJason Gunthorpe 
9483023a1e9SKamal Heib 	ret = ah->device->ops.modify_ah ?
9493023a1e9SKamal Heib 		ah->device->ops.modify_ah(ah, ah_attr) :
95087915bf8SLeon Romanovsky 		-EOPNOTSUPP;
9518d9ec9adSJason Gunthorpe 
9521a1f460fSJason Gunthorpe 	ah->sgid_attr = rdma_update_sgid_attr(ah_attr, ah->sgid_attr);
9538d9ec9adSJason Gunthorpe 	rdma_unfill_sgid_attr(ah_attr, old_sgid_attr);
9548d9ec9adSJason Gunthorpe 	return ret;
9551da177e4SLinus Torvalds }
95667b985b6SDasaratharaman Chandramouli EXPORT_SYMBOL(rdma_modify_ah);
9571da177e4SLinus Torvalds 
958bfbfd661SDasaratharaman Chandramouli int rdma_query_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr)
9591da177e4SLinus Torvalds {
9608d9ec9adSJason Gunthorpe 	ah_attr->grh.sgid_attr = NULL;
9618d9ec9adSJason Gunthorpe 
9623023a1e9SKamal Heib 	return ah->device->ops.query_ah ?
9633023a1e9SKamal Heib 		ah->device->ops.query_ah(ah, ah_attr) :
96487915bf8SLeon Romanovsky 		-EOPNOTSUPP;
9651da177e4SLinus Torvalds }
966bfbfd661SDasaratharaman Chandramouli EXPORT_SYMBOL(rdma_query_ah);
9671da177e4SLinus Torvalds 
968c4367a26SShamir Rabinovitch int rdma_destroy_ah_user(struct ib_ah *ah, u32 flags, struct ib_udata *udata)
9691da177e4SLinus Torvalds {
9701a1f460fSJason Gunthorpe 	const struct ib_gid_attr *sgid_attr = ah->sgid_attr;
9711da177e4SLinus Torvalds 	struct ib_pd *pd;
9729a9ebf8cSLeon Romanovsky 	int ret;
9731da177e4SLinus Torvalds 
9742553ba21SGal Pressman 	might_sleep_if(flags & RDMA_DESTROY_AH_SLEEPABLE);
9752553ba21SGal Pressman 
9761da177e4SLinus Torvalds 	pd = ah->pd;
977d3456914SLeon Romanovsky 
9789a9ebf8cSLeon Romanovsky 	ret = ah->device->ops.destroy_ah(ah, flags);
9799a9ebf8cSLeon Romanovsky 	if (ret)
9809a9ebf8cSLeon Romanovsky 		return ret;
9819a9ebf8cSLeon Romanovsky 
9821da177e4SLinus Torvalds 	atomic_dec(&pd->usecnt);
9831a1f460fSJason Gunthorpe 	if (sgid_attr)
9841a1f460fSJason Gunthorpe 		rdma_put_gid_attr(sgid_attr);
9851da177e4SLinus Torvalds 
986d3456914SLeon Romanovsky 	kfree(ah);
9879a9ebf8cSLeon Romanovsky 	return ret;
9881da177e4SLinus Torvalds }
989c4367a26SShamir Rabinovitch EXPORT_SYMBOL(rdma_destroy_ah_user);
9901da177e4SLinus Torvalds 
991d41fcc67SRoland Dreier /* Shared receive queues */
992d41fcc67SRoland Dreier 
993b0810b03SJason Gunthorpe /**
994b0810b03SJason Gunthorpe  * ib_create_srq_user - Creates a SRQ associated with the specified protection
995b0810b03SJason Gunthorpe  *   domain.
996b0810b03SJason Gunthorpe  * @pd: The protection domain associated with the SRQ.
997b0810b03SJason Gunthorpe  * @srq_init_attr: A list of initial attributes required to create the
998b0810b03SJason Gunthorpe  *   SRQ.  If SRQ creation succeeds, then the attributes are updated to
999b0810b03SJason Gunthorpe  *   the actual capabilities of the created SRQ.
100011708142SColton Lewis  * @uobject: uobject pointer if this is not a kernel SRQ
100111708142SColton Lewis  * @udata: udata pointer if this is not a kernel SRQ
1002b0810b03SJason Gunthorpe  *
1003b0810b03SJason Gunthorpe  * srq_attr->max_wr and srq_attr->max_sge are read the determine the
1004b0810b03SJason Gunthorpe  * requested size of the SRQ, and set to the actual values allocated
1005b0810b03SJason Gunthorpe  * on return.  If ib_create_srq() succeeds, then max_wr and max_sge
1006b0810b03SJason Gunthorpe  * will always be at least as large as the requested values.
1007b0810b03SJason Gunthorpe  */
1008b0810b03SJason Gunthorpe struct ib_srq *ib_create_srq_user(struct ib_pd *pd,
1009b0810b03SJason Gunthorpe 				  struct ib_srq_init_attr *srq_init_attr,
1010b0810b03SJason Gunthorpe 				  struct ib_usrq_object *uobject,
1011b0810b03SJason Gunthorpe 				  struct ib_udata *udata)
1012d41fcc67SRoland Dreier {
1013d41fcc67SRoland Dreier 	struct ib_srq *srq;
101468e326deSLeon Romanovsky 	int ret;
1015d41fcc67SRoland Dreier 
101668e326deSLeon Romanovsky 	srq = rdma_zalloc_drv_obj(pd->device, ib_srq);
101768e326deSLeon Romanovsky 	if (!srq)
101868e326deSLeon Romanovsky 		return ERR_PTR(-ENOMEM);
1019d41fcc67SRoland Dreier 
1020d41fcc67SRoland Dreier 	srq->device = pd->device;
1021d41fcc67SRoland Dreier 	srq->pd = pd;
1022d41fcc67SRoland Dreier 	srq->event_handler = srq_init_attr->event_handler;
1023d41fcc67SRoland Dreier 	srq->srq_context = srq_init_attr->srq_context;
102496104edaSSean Hefty 	srq->srq_type = srq_init_attr->srq_type;
1025b0810b03SJason Gunthorpe 	srq->uobject = uobject;
102668e326deSLeon Romanovsky 
10271a56ff6dSArtemy Kovalyov 	if (ib_srq_has_cq(srq->srq_type)) {
10281a56ff6dSArtemy Kovalyov 		srq->ext.cq = srq_init_attr->ext.cq;
10291a56ff6dSArtemy Kovalyov 		atomic_inc(&srq->ext.cq->usecnt);
10301a56ff6dSArtemy Kovalyov 	}
1031418d5130SSean Hefty 	if (srq->srq_type == IB_SRQT_XRC) {
1032418d5130SSean Hefty 		srq->ext.xrc.xrcd = srq_init_attr->ext.xrc.xrcd;
1033418d5130SSean Hefty 		atomic_inc(&srq->ext.xrc.xrcd->usecnt);
1034418d5130SSean Hefty 	}
1035d41fcc67SRoland Dreier 	atomic_inc(&pd->usecnt);
103668e326deSLeon Romanovsky 
1037b0810b03SJason Gunthorpe 	ret = pd->device->ops.create_srq(srq, srq_init_attr, udata);
103868e326deSLeon Romanovsky 	if (ret) {
103968e326deSLeon Romanovsky 		atomic_dec(&srq->pd->usecnt);
104068e326deSLeon Romanovsky 		if (srq->srq_type == IB_SRQT_XRC)
104168e326deSLeon Romanovsky 			atomic_dec(&srq->ext.xrc.xrcd->usecnt);
104268e326deSLeon Romanovsky 		if (ib_srq_has_cq(srq->srq_type))
104368e326deSLeon Romanovsky 			atomic_dec(&srq->ext.cq->usecnt);
104468e326deSLeon Romanovsky 		kfree(srq);
104568e326deSLeon Romanovsky 		return ERR_PTR(ret);
1046d41fcc67SRoland Dreier 	}
1047d41fcc67SRoland Dreier 
1048d41fcc67SRoland Dreier 	return srq;
1049d41fcc67SRoland Dreier }
1050b0810b03SJason Gunthorpe EXPORT_SYMBOL(ib_create_srq_user);
1051d41fcc67SRoland Dreier 
1052d41fcc67SRoland Dreier int ib_modify_srq(struct ib_srq *srq,
1053d41fcc67SRoland Dreier 		  struct ib_srq_attr *srq_attr,
1054d41fcc67SRoland Dreier 		  enum ib_srq_attr_mask srq_attr_mask)
1055d41fcc67SRoland Dreier {
10563023a1e9SKamal Heib 	return srq->device->ops.modify_srq ?
10573023a1e9SKamal Heib 		srq->device->ops.modify_srq(srq, srq_attr, srq_attr_mask,
10583023a1e9SKamal Heib 					    NULL) : -EOPNOTSUPP;
1059d41fcc67SRoland Dreier }
1060d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_modify_srq);
1061d41fcc67SRoland Dreier 
1062d41fcc67SRoland Dreier int ib_query_srq(struct ib_srq *srq,
1063d41fcc67SRoland Dreier 		 struct ib_srq_attr *srq_attr)
1064d41fcc67SRoland Dreier {
10653023a1e9SKamal Heib 	return srq->device->ops.query_srq ?
10663023a1e9SKamal Heib 		srq->device->ops.query_srq(srq, srq_attr) : -EOPNOTSUPP;
1067d41fcc67SRoland Dreier }
1068d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_query_srq);
1069d41fcc67SRoland Dreier 
1070c4367a26SShamir Rabinovitch int ib_destroy_srq_user(struct ib_srq *srq, struct ib_udata *udata)
1071d41fcc67SRoland Dreier {
1072119181d1SLeon Romanovsky 	int ret;
1073119181d1SLeon Romanovsky 
1074d41fcc67SRoland Dreier 	if (atomic_read(&srq->usecnt))
1075d41fcc67SRoland Dreier 		return -EBUSY;
1076d41fcc67SRoland Dreier 
1077119181d1SLeon Romanovsky 	ret = srq->device->ops.destroy_srq(srq, udata);
1078119181d1SLeon Romanovsky 	if (ret)
1079119181d1SLeon Romanovsky 		return ret;
1080d41fcc67SRoland Dreier 
108168e326deSLeon Romanovsky 	atomic_dec(&srq->pd->usecnt);
108268e326deSLeon Romanovsky 	if (srq->srq_type == IB_SRQT_XRC)
108368e326deSLeon Romanovsky 		atomic_dec(&srq->ext.xrc.xrcd->usecnt);
108468e326deSLeon Romanovsky 	if (ib_srq_has_cq(srq->srq_type))
108568e326deSLeon Romanovsky 		atomic_dec(&srq->ext.cq->usecnt);
108668e326deSLeon Romanovsky 	kfree(srq);
1087d41fcc67SRoland Dreier 
1088119181d1SLeon Romanovsky 	return ret;
1089d41fcc67SRoland Dreier }
1090c4367a26SShamir Rabinovitch EXPORT_SYMBOL(ib_destroy_srq_user);
1091d41fcc67SRoland Dreier 
10921da177e4SLinus Torvalds /* Queue pairs */
10931da177e4SLinus Torvalds 
10940e0ec7e0SSean Hefty static void __ib_shared_qp_event_handler(struct ib_event *event, void *context)
10950e0ec7e0SSean Hefty {
10960e0ec7e0SSean Hefty 	struct ib_qp *qp = context;
109773c40c61SYishai Hadas 	unsigned long flags;
10980e0ec7e0SSean Hefty 
109940adf686SParav Pandit 	spin_lock_irqsave(&qp->device->qp_open_list_lock, flags);
11000e0ec7e0SSean Hefty 	list_for_each_entry(event->element.qp, &qp->open_list, open_list)
1101eec9e29fSShlomo Pongratz 		if (event->element.qp->event_handler)
11020e0ec7e0SSean Hefty 			event->element.qp->event_handler(event, event->element.qp->qp_context);
110340adf686SParav Pandit 	spin_unlock_irqrestore(&qp->device->qp_open_list_lock, flags);
11040e0ec7e0SSean Hefty }
11050e0ec7e0SSean Hefty 
11060e0ec7e0SSean Hefty static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp,
11070e0ec7e0SSean Hefty 				  void (*event_handler)(struct ib_event *, void *),
11080e0ec7e0SSean Hefty 				  void *qp_context)
1109d3d72d90SSean Hefty {
11100e0ec7e0SSean Hefty 	struct ib_qp *qp;
11110e0ec7e0SSean Hefty 	unsigned long flags;
1112d291f1a6SDaniel Jurgens 	int err;
11130e0ec7e0SSean Hefty 
11140e0ec7e0SSean Hefty 	qp = kzalloc(sizeof *qp, GFP_KERNEL);
11150e0ec7e0SSean Hefty 	if (!qp)
11160e0ec7e0SSean Hefty 		return ERR_PTR(-ENOMEM);
11170e0ec7e0SSean Hefty 
11180e0ec7e0SSean Hefty 	qp->real_qp = real_qp;
1119d291f1a6SDaniel Jurgens 	err = ib_open_shared_qp_security(qp, real_qp->device);
1120d291f1a6SDaniel Jurgens 	if (err) {
1121d291f1a6SDaniel Jurgens 		kfree(qp);
1122d291f1a6SDaniel Jurgens 		return ERR_PTR(err);
1123d291f1a6SDaniel Jurgens 	}
1124d291f1a6SDaniel Jurgens 
1125d291f1a6SDaniel Jurgens 	qp->real_qp = real_qp;
11260e0ec7e0SSean Hefty 	atomic_inc(&real_qp->usecnt);
11270e0ec7e0SSean Hefty 	qp->device = real_qp->device;
11280e0ec7e0SSean Hefty 	qp->event_handler = event_handler;
11290e0ec7e0SSean Hefty 	qp->qp_context = qp_context;
11300e0ec7e0SSean Hefty 	qp->qp_num = real_qp->qp_num;
11310e0ec7e0SSean Hefty 	qp->qp_type = real_qp->qp_type;
11320e0ec7e0SSean Hefty 
113340adf686SParav Pandit 	spin_lock_irqsave(&real_qp->device->qp_open_list_lock, flags);
11340e0ec7e0SSean Hefty 	list_add(&qp->open_list, &real_qp->open_list);
113540adf686SParav Pandit 	spin_unlock_irqrestore(&real_qp->device->qp_open_list_lock, flags);
11360e0ec7e0SSean Hefty 
11370e0ec7e0SSean Hefty 	return qp;
1138d3d72d90SSean Hefty }
1139d3d72d90SSean Hefty 
11400e0ec7e0SSean Hefty struct ib_qp *ib_open_qp(struct ib_xrcd *xrcd,
11410e0ec7e0SSean Hefty 			 struct ib_qp_open_attr *qp_open_attr)
11420e0ec7e0SSean Hefty {
11430e0ec7e0SSean Hefty 	struct ib_qp *qp, *real_qp;
11440e0ec7e0SSean Hefty 
11450e0ec7e0SSean Hefty 	if (qp_open_attr->qp_type != IB_QPT_XRC_TGT)
11460e0ec7e0SSean Hefty 		return ERR_PTR(-EINVAL);
11470e0ec7e0SSean Hefty 
11486f3ca6f4SMaor Gottlieb 	down_read(&xrcd->tgt_qps_rwsem);
11496f3ca6f4SMaor Gottlieb 	real_qp = xa_load(&xrcd->tgt_qps, qp_open_attr->qp_num);
11506f3ca6f4SMaor Gottlieb 	if (!real_qp) {
11516f3ca6f4SMaor Gottlieb 		up_read(&xrcd->tgt_qps_rwsem);
11526f3ca6f4SMaor Gottlieb 		return ERR_PTR(-EINVAL);
11536f3ca6f4SMaor Gottlieb 	}
11540e0ec7e0SSean Hefty 	qp = __ib_open_qp(real_qp, qp_open_attr->event_handler,
11550e0ec7e0SSean Hefty 			  qp_open_attr->qp_context);
11566f3ca6f4SMaor Gottlieb 	up_read(&xrcd->tgt_qps_rwsem);
11570e0ec7e0SSean Hefty 	return qp;
11580e0ec7e0SSean Hefty }
11590e0ec7e0SSean Hefty EXPORT_SYMBOL(ib_open_qp);
11600e0ec7e0SSean Hefty 
1161c4367a26SShamir Rabinovitch static struct ib_qp *create_xrc_qp_user(struct ib_qp *qp,
1162b72bfc96SJason Gunthorpe 					struct ib_qp_init_attr *qp_init_attr)
11631da177e4SLinus Torvalds {
116404c41bf3SChristoph Hellwig 	struct ib_qp *real_qp = qp;
11656f3ca6f4SMaor Gottlieb 	int err;
11661da177e4SLinus Torvalds 
11670e0ec7e0SSean Hefty 	qp->event_handler = __ib_shared_qp_event_handler;
11680e0ec7e0SSean Hefty 	qp->qp_context = qp;
1169b42b63cfSSean Hefty 	qp->pd = NULL;
1170b42b63cfSSean Hefty 	qp->send_cq = qp->recv_cq = NULL;
1171b42b63cfSSean Hefty 	qp->srq = NULL;
1172b42b63cfSSean Hefty 	qp->xrcd = qp_init_attr->xrcd;
1173b42b63cfSSean Hefty 	atomic_inc(&qp_init_attr->xrcd->usecnt);
11740e0ec7e0SSean Hefty 	INIT_LIST_HEAD(&qp->open_list);
11750e0ec7e0SSean Hefty 
11760e0ec7e0SSean Hefty 	qp = __ib_open_qp(real_qp, qp_init_attr->event_handler,
11770e0ec7e0SSean Hefty 			  qp_init_attr->qp_context);
1178535005caSYuval Avnery 	if (IS_ERR(qp))
1179535005caSYuval Avnery 		return qp;
1180535005caSYuval Avnery 
11816f3ca6f4SMaor Gottlieb 	err = xa_err(xa_store(&qp_init_attr->xrcd->tgt_qps, real_qp->qp_num,
11826f3ca6f4SMaor Gottlieb 			      real_qp, GFP_KERNEL));
11836f3ca6f4SMaor Gottlieb 	if (err) {
11846f3ca6f4SMaor Gottlieb 		ib_close_qp(qp);
11856f3ca6f4SMaor Gottlieb 		return ERR_PTR(err);
11866f3ca6f4SMaor Gottlieb 	}
118704c41bf3SChristoph Hellwig 	return qp;
118804c41bf3SChristoph Hellwig }
118904c41bf3SChristoph Hellwig 
1190b72bfc96SJason Gunthorpe /**
1191b72bfc96SJason Gunthorpe  * ib_create_qp - Creates a kernel QP associated with the specified protection
1192b72bfc96SJason Gunthorpe  *   domain.
1193b72bfc96SJason Gunthorpe  * @pd: The protection domain associated with the QP.
1194b72bfc96SJason Gunthorpe  * @qp_init_attr: A list of initial attributes required to create the
1195b72bfc96SJason Gunthorpe  *   QP.  If QP creation succeeds, then the attributes are updated to
1196b72bfc96SJason Gunthorpe  *   the actual capabilities of the created QP.
1197b72bfc96SJason Gunthorpe  *
1198b72bfc96SJason Gunthorpe  * NOTE: for user qp use ib_create_qp_user with valid udata!
1199b72bfc96SJason Gunthorpe  */
1200b72bfc96SJason Gunthorpe struct ib_qp *ib_create_qp(struct ib_pd *pd,
1201b72bfc96SJason Gunthorpe 			   struct ib_qp_init_attr *qp_init_attr)
120204c41bf3SChristoph Hellwig {
120304c41bf3SChristoph Hellwig 	struct ib_device *device = pd ? pd->device : qp_init_attr->xrcd->device;
120404c41bf3SChristoph Hellwig 	struct ib_qp *qp;
1205a060b562SChristoph Hellwig 	int ret;
1206a060b562SChristoph Hellwig 
1207a9017e23SYishai Hadas 	if (qp_init_attr->rwq_ind_tbl &&
1208a9017e23SYishai Hadas 	    (qp_init_attr->recv_cq ||
1209a9017e23SYishai Hadas 	    qp_init_attr->srq || qp_init_attr->cap.max_recv_wr ||
1210a9017e23SYishai Hadas 	    qp_init_attr->cap.max_recv_sge))
1211a9017e23SYishai Hadas 		return ERR_PTR(-EINVAL);
1212a9017e23SYishai Hadas 
1213185eddc4SMax Gurtovoy 	if ((qp_init_attr->create_flags & IB_QP_CREATE_INTEGRITY_EN) &&
1214185eddc4SMax Gurtovoy 	    !(device->attrs.device_cap_flags & IB_DEVICE_INTEGRITY_HANDOVER))
1215185eddc4SMax Gurtovoy 		return ERR_PTR(-EINVAL);
1216185eddc4SMax Gurtovoy 
1217a060b562SChristoph Hellwig 	/*
1218a060b562SChristoph Hellwig 	 * If the callers is using the RDMA API calculate the resources
1219a060b562SChristoph Hellwig 	 * needed for the RDMA READ/WRITE operations.
1220a060b562SChristoph Hellwig 	 *
1221a060b562SChristoph Hellwig 	 * Note that these callers need to pass in a port number.
1222a060b562SChristoph Hellwig 	 */
1223a060b562SChristoph Hellwig 	if (qp_init_attr->cap.max_rdma_ctxs)
1224a060b562SChristoph Hellwig 		rdma_rw_init_qp(device, qp_init_attr);
122504c41bf3SChristoph Hellwig 
12262f08ee36SSteve Wise 	qp = _ib_create_qp(device, pd, qp_init_attr, NULL, NULL);
122704c41bf3SChristoph Hellwig 	if (IS_ERR(qp))
122804c41bf3SChristoph Hellwig 		return qp;
122904c41bf3SChristoph Hellwig 
1230d291f1a6SDaniel Jurgens 	ret = ib_create_qp_security(qp, device);
1231535005caSYuval Avnery 	if (ret)
1232535005caSYuval Avnery 		goto err;
1233d291f1a6SDaniel Jurgens 
1234535005caSYuval Avnery 	if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) {
1235c4367a26SShamir Rabinovitch 		struct ib_qp *xrc_qp =
1236b72bfc96SJason Gunthorpe 			create_xrc_qp_user(qp, qp_init_attr);
1237535005caSYuval Avnery 
1238535005caSYuval Avnery 		if (IS_ERR(xrc_qp)) {
1239535005caSYuval Avnery 			ret = PTR_ERR(xrc_qp);
1240535005caSYuval Avnery 			goto err;
1241535005caSYuval Avnery 		}
1242535005caSYuval Avnery 		return xrc_qp;
1243535005caSYuval Avnery 	}
124404c41bf3SChristoph Hellwig 
12451da177e4SLinus Torvalds 	qp->event_handler = qp_init_attr->event_handler;
12461da177e4SLinus Torvalds 	qp->qp_context = qp_init_attr->qp_context;
1247b42b63cfSSean Hefty 	if (qp_init_attr->qp_type == IB_QPT_XRC_INI) {
1248b42b63cfSSean Hefty 		qp->recv_cq = NULL;
1249b42b63cfSSean Hefty 		qp->srq = NULL;
1250b42b63cfSSean Hefty 	} else {
1251b42b63cfSSean Hefty 		qp->recv_cq = qp_init_attr->recv_cq;
1252a9017e23SYishai Hadas 		if (qp_init_attr->recv_cq)
1253b42b63cfSSean Hefty 			atomic_inc(&qp_init_attr->recv_cq->usecnt);
1254b42b63cfSSean Hefty 		qp->srq = qp_init_attr->srq;
1255b42b63cfSSean Hefty 		if (qp->srq)
1256b42b63cfSSean Hefty 			atomic_inc(&qp_init_attr->srq->usecnt);
1257b42b63cfSSean Hefty 	}
1258b42b63cfSSean Hefty 
12591da177e4SLinus Torvalds 	qp->send_cq = qp_init_attr->send_cq;
1260b42b63cfSSean Hefty 	qp->xrcd    = NULL;
1261b42b63cfSSean Hefty 
12621da177e4SLinus Torvalds 	atomic_inc(&pd->usecnt);
1263a9017e23SYishai Hadas 	if (qp_init_attr->send_cq)
12641da177e4SLinus Torvalds 		atomic_inc(&qp_init_attr->send_cq->usecnt);
1265a9017e23SYishai Hadas 	if (qp_init_attr->rwq_ind_tbl)
1266a9017e23SYishai Hadas 		atomic_inc(&qp->rwq_ind_tbl->usecnt);
1267a060b562SChristoph Hellwig 
1268a060b562SChristoph Hellwig 	if (qp_init_attr->cap.max_rdma_ctxs) {
1269a060b562SChristoph Hellwig 		ret = rdma_rw_init_mrs(qp, qp_init_attr);
1270535005caSYuval Avnery 		if (ret)
1271535005caSYuval Avnery 			goto err;
1272a060b562SChristoph Hellwig 	}
1273a060b562SChristoph Hellwig 
1274632bc3f6SBart Van Assche 	/*
1275632bc3f6SBart Van Assche 	 * Note: all hw drivers guarantee that max_send_sge is lower than
1276632bc3f6SBart Van Assche 	 * the device RDMA WRITE SGE limit but not all hw drivers ensure that
1277632bc3f6SBart Van Assche 	 * max_send_sge <= max_sge_rd.
1278632bc3f6SBart Van Assche 	 */
1279632bc3f6SBart Van Assche 	qp->max_write_sge = qp_init_attr->cap.max_send_sge;
1280632bc3f6SBart Van Assche 	qp->max_read_sge = min_t(u32, qp_init_attr->cap.max_send_sge,
1281632bc3f6SBart Van Assche 				 device->attrs.max_sge_rd);
1282185eddc4SMax Gurtovoy 	if (qp_init_attr->create_flags & IB_QP_CREATE_INTEGRITY_EN)
1283185eddc4SMax Gurtovoy 		qp->integrity_en = true;
1284632bc3f6SBart Van Assche 
12851da177e4SLinus Torvalds 	return qp;
1286535005caSYuval Avnery 
1287535005caSYuval Avnery err:
1288535005caSYuval Avnery 	ib_destroy_qp(qp);
1289535005caSYuval Avnery 	return ERR_PTR(ret);
1290535005caSYuval Avnery 
12911da177e4SLinus Torvalds }
1292b72bfc96SJason Gunthorpe EXPORT_SYMBOL(ib_create_qp);
12931da177e4SLinus Torvalds 
12948a51866fSRoland Dreier static const struct {
12958a51866fSRoland Dreier 	int			valid;
1296b42b63cfSSean Hefty 	enum ib_qp_attr_mask	req_param[IB_QPT_MAX];
1297b42b63cfSSean Hefty 	enum ib_qp_attr_mask	opt_param[IB_QPT_MAX];
12988a51866fSRoland Dreier } qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
12998a51866fSRoland Dreier 	[IB_QPS_RESET] = {
13008a51866fSRoland Dreier 		[IB_QPS_RESET] = { .valid = 1 },
13018a51866fSRoland Dreier 		[IB_QPS_INIT]  = {
13028a51866fSRoland Dreier 			.valid = 1,
13038a51866fSRoland Dreier 			.req_param = {
13048a51866fSRoland Dreier 				[IB_QPT_UD]  = (IB_QP_PKEY_INDEX		|
13058a51866fSRoland Dreier 						IB_QP_PORT			|
13068a51866fSRoland Dreier 						IB_QP_QKEY),
1307c938a616SOr Gerlitz 				[IB_QPT_RAW_PACKET] = IB_QP_PORT,
13088a51866fSRoland Dreier 				[IB_QPT_UC]  = (IB_QP_PKEY_INDEX		|
13098a51866fSRoland Dreier 						IB_QP_PORT			|
13108a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS),
13118a51866fSRoland Dreier 				[IB_QPT_RC]  = (IB_QP_PKEY_INDEX		|
13128a51866fSRoland Dreier 						IB_QP_PORT			|
13138a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS),
1314b42b63cfSSean Hefty 				[IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX		|
1315b42b63cfSSean Hefty 						IB_QP_PORT			|
1316b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS),
1317b42b63cfSSean Hefty 				[IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX		|
1318b42b63cfSSean Hefty 						IB_QP_PORT			|
1319b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS),
13208a51866fSRoland Dreier 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
13218a51866fSRoland Dreier 						IB_QP_QKEY),
13228a51866fSRoland Dreier 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
13238a51866fSRoland Dreier 						IB_QP_QKEY),
13248a51866fSRoland Dreier 			}
13258a51866fSRoland Dreier 		},
13268a51866fSRoland Dreier 	},
13278a51866fSRoland Dreier 	[IB_QPS_INIT]  = {
13288a51866fSRoland Dreier 		[IB_QPS_RESET] = { .valid = 1 },
13298a51866fSRoland Dreier 		[IB_QPS_ERR] =   { .valid = 1 },
13308a51866fSRoland Dreier 		[IB_QPS_INIT]  = {
13318a51866fSRoland Dreier 			.valid = 1,
13328a51866fSRoland Dreier 			.opt_param = {
13338a51866fSRoland Dreier 				[IB_QPT_UD]  = (IB_QP_PKEY_INDEX		|
13348a51866fSRoland Dreier 						IB_QP_PORT			|
13358a51866fSRoland Dreier 						IB_QP_QKEY),
13368a51866fSRoland Dreier 				[IB_QPT_UC]  = (IB_QP_PKEY_INDEX		|
13378a51866fSRoland Dreier 						IB_QP_PORT			|
13388a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS),
13398a51866fSRoland Dreier 				[IB_QPT_RC]  = (IB_QP_PKEY_INDEX		|
13408a51866fSRoland Dreier 						IB_QP_PORT			|
13418a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS),
1342b42b63cfSSean Hefty 				[IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX		|
1343b42b63cfSSean Hefty 						IB_QP_PORT			|
1344b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS),
1345b42b63cfSSean Hefty 				[IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX		|
1346b42b63cfSSean Hefty 						IB_QP_PORT			|
1347b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS),
13488a51866fSRoland Dreier 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
13498a51866fSRoland Dreier 						IB_QP_QKEY),
13508a51866fSRoland Dreier 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
13518a51866fSRoland Dreier 						IB_QP_QKEY),
13528a51866fSRoland Dreier 			}
13538a51866fSRoland Dreier 		},
13548a51866fSRoland Dreier 		[IB_QPS_RTR]   = {
13558a51866fSRoland Dreier 			.valid = 1,
13568a51866fSRoland Dreier 			.req_param = {
13578a51866fSRoland Dreier 				[IB_QPT_UC]  = (IB_QP_AV			|
13588a51866fSRoland Dreier 						IB_QP_PATH_MTU			|
13598a51866fSRoland Dreier 						IB_QP_DEST_QPN			|
13608a51866fSRoland Dreier 						IB_QP_RQ_PSN),
13618a51866fSRoland Dreier 				[IB_QPT_RC]  = (IB_QP_AV			|
13628a51866fSRoland Dreier 						IB_QP_PATH_MTU			|
13638a51866fSRoland Dreier 						IB_QP_DEST_QPN			|
13648a51866fSRoland Dreier 						IB_QP_RQ_PSN			|
13658a51866fSRoland Dreier 						IB_QP_MAX_DEST_RD_ATOMIC	|
13668a51866fSRoland Dreier 						IB_QP_MIN_RNR_TIMER),
1367b42b63cfSSean Hefty 				[IB_QPT_XRC_INI] = (IB_QP_AV			|
1368b42b63cfSSean Hefty 						IB_QP_PATH_MTU			|
1369b42b63cfSSean Hefty 						IB_QP_DEST_QPN			|
1370b42b63cfSSean Hefty 						IB_QP_RQ_PSN),
1371b42b63cfSSean Hefty 				[IB_QPT_XRC_TGT] = (IB_QP_AV			|
1372b42b63cfSSean Hefty 						IB_QP_PATH_MTU			|
1373b42b63cfSSean Hefty 						IB_QP_DEST_QPN			|
1374b42b63cfSSean Hefty 						IB_QP_RQ_PSN			|
1375b42b63cfSSean Hefty 						IB_QP_MAX_DEST_RD_ATOMIC	|
1376b42b63cfSSean Hefty 						IB_QP_MIN_RNR_TIMER),
13778a51866fSRoland Dreier 			},
13788a51866fSRoland Dreier 			.opt_param = {
13798a51866fSRoland Dreier 				 [IB_QPT_UD]  = (IB_QP_PKEY_INDEX		|
13808a51866fSRoland Dreier 						 IB_QP_QKEY),
13818a51866fSRoland Dreier 				 [IB_QPT_UC]  = (IB_QP_ALT_PATH			|
13828a51866fSRoland Dreier 						 IB_QP_ACCESS_FLAGS		|
13838a51866fSRoland Dreier 						 IB_QP_PKEY_INDEX),
13848a51866fSRoland Dreier 				 [IB_QPT_RC]  = (IB_QP_ALT_PATH			|
13858a51866fSRoland Dreier 						 IB_QP_ACCESS_FLAGS		|
13868a51866fSRoland Dreier 						 IB_QP_PKEY_INDEX),
1387b42b63cfSSean Hefty 				 [IB_QPT_XRC_INI] = (IB_QP_ALT_PATH		|
1388b42b63cfSSean Hefty 						 IB_QP_ACCESS_FLAGS		|
1389b42b63cfSSean Hefty 						 IB_QP_PKEY_INDEX),
1390b42b63cfSSean Hefty 				 [IB_QPT_XRC_TGT] = (IB_QP_ALT_PATH		|
1391b42b63cfSSean Hefty 						 IB_QP_ACCESS_FLAGS		|
1392b42b63cfSSean Hefty 						 IB_QP_PKEY_INDEX),
13938a51866fSRoland Dreier 				 [IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
13948a51866fSRoland Dreier 						 IB_QP_QKEY),
13958a51866fSRoland Dreier 				 [IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
13968a51866fSRoland Dreier 						 IB_QP_QKEY),
1397dd5f03beSMatan Barak 			 },
1398dbf727deSMatan Barak 		},
13998a51866fSRoland Dreier 	},
14008a51866fSRoland Dreier 	[IB_QPS_RTR]   = {
14018a51866fSRoland Dreier 		[IB_QPS_RESET] = { .valid = 1 },
14028a51866fSRoland Dreier 		[IB_QPS_ERR] =   { .valid = 1 },
14038a51866fSRoland Dreier 		[IB_QPS_RTS]   = {
14048a51866fSRoland Dreier 			.valid = 1,
14058a51866fSRoland Dreier 			.req_param = {
14068a51866fSRoland Dreier 				[IB_QPT_UD]  = IB_QP_SQ_PSN,
14078a51866fSRoland Dreier 				[IB_QPT_UC]  = IB_QP_SQ_PSN,
14088a51866fSRoland Dreier 				[IB_QPT_RC]  = (IB_QP_TIMEOUT			|
14098a51866fSRoland Dreier 						IB_QP_RETRY_CNT			|
14108a51866fSRoland Dreier 						IB_QP_RNR_RETRY			|
14118a51866fSRoland Dreier 						IB_QP_SQ_PSN			|
14128a51866fSRoland Dreier 						IB_QP_MAX_QP_RD_ATOMIC),
1413b42b63cfSSean Hefty 				[IB_QPT_XRC_INI] = (IB_QP_TIMEOUT		|
1414b42b63cfSSean Hefty 						IB_QP_RETRY_CNT			|
1415b42b63cfSSean Hefty 						IB_QP_RNR_RETRY			|
1416b42b63cfSSean Hefty 						IB_QP_SQ_PSN			|
1417b42b63cfSSean Hefty 						IB_QP_MAX_QP_RD_ATOMIC),
1418b42b63cfSSean Hefty 				[IB_QPT_XRC_TGT] = (IB_QP_TIMEOUT		|
1419b42b63cfSSean Hefty 						IB_QP_SQ_PSN),
14208a51866fSRoland Dreier 				[IB_QPT_SMI] = IB_QP_SQ_PSN,
14218a51866fSRoland Dreier 				[IB_QPT_GSI] = IB_QP_SQ_PSN,
14228a51866fSRoland Dreier 			},
14238a51866fSRoland Dreier 			.opt_param = {
14248a51866fSRoland Dreier 				 [IB_QPT_UD]  = (IB_QP_CUR_STATE		|
14258a51866fSRoland Dreier 						 IB_QP_QKEY),
14268a51866fSRoland Dreier 				 [IB_QPT_UC]  = (IB_QP_CUR_STATE		|
14278a51866fSRoland Dreier 						 IB_QP_ALT_PATH			|
14288a51866fSRoland Dreier 						 IB_QP_ACCESS_FLAGS		|
14298a51866fSRoland Dreier 						 IB_QP_PATH_MIG_STATE),
14308a51866fSRoland Dreier 				 [IB_QPT_RC]  = (IB_QP_CUR_STATE		|
14318a51866fSRoland Dreier 						 IB_QP_ALT_PATH			|
14328a51866fSRoland Dreier 						 IB_QP_ACCESS_FLAGS		|
14338a51866fSRoland Dreier 						 IB_QP_MIN_RNR_TIMER		|
14348a51866fSRoland Dreier 						 IB_QP_PATH_MIG_STATE),
1435b42b63cfSSean Hefty 				 [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE		|
1436b42b63cfSSean Hefty 						 IB_QP_ALT_PATH			|
1437b42b63cfSSean Hefty 						 IB_QP_ACCESS_FLAGS		|
1438b42b63cfSSean Hefty 						 IB_QP_PATH_MIG_STATE),
1439b42b63cfSSean Hefty 				 [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE		|
1440b42b63cfSSean Hefty 						 IB_QP_ALT_PATH			|
1441b42b63cfSSean Hefty 						 IB_QP_ACCESS_FLAGS		|
1442b42b63cfSSean Hefty 						 IB_QP_MIN_RNR_TIMER		|
1443b42b63cfSSean Hefty 						 IB_QP_PATH_MIG_STATE),
14448a51866fSRoland Dreier 				 [IB_QPT_SMI] = (IB_QP_CUR_STATE		|
14458a51866fSRoland Dreier 						 IB_QP_QKEY),
14468a51866fSRoland Dreier 				 [IB_QPT_GSI] = (IB_QP_CUR_STATE		|
14478a51866fSRoland Dreier 						 IB_QP_QKEY),
1448528e5a1bSBodong Wang 				 [IB_QPT_RAW_PACKET] = IB_QP_RATE_LIMIT,
14498a51866fSRoland Dreier 			 }
14508a51866fSRoland Dreier 		}
14518a51866fSRoland Dreier 	},
14528a51866fSRoland Dreier 	[IB_QPS_RTS]   = {
14538a51866fSRoland Dreier 		[IB_QPS_RESET] = { .valid = 1 },
14548a51866fSRoland Dreier 		[IB_QPS_ERR] =   { .valid = 1 },
14558a51866fSRoland Dreier 		[IB_QPS_RTS]   = {
14568a51866fSRoland Dreier 			.valid = 1,
14578a51866fSRoland Dreier 			.opt_param = {
14588a51866fSRoland Dreier 				[IB_QPT_UD]  = (IB_QP_CUR_STATE			|
14598a51866fSRoland Dreier 						IB_QP_QKEY),
14604546d31dSDotan Barak 				[IB_QPT_UC]  = (IB_QP_CUR_STATE			|
14614546d31dSDotan Barak 						IB_QP_ACCESS_FLAGS		|
14628a51866fSRoland Dreier 						IB_QP_ALT_PATH			|
14638a51866fSRoland Dreier 						IB_QP_PATH_MIG_STATE),
14644546d31dSDotan Barak 				[IB_QPT_RC]  = (IB_QP_CUR_STATE			|
14654546d31dSDotan Barak 						IB_QP_ACCESS_FLAGS		|
14668a51866fSRoland Dreier 						IB_QP_ALT_PATH			|
14678a51866fSRoland Dreier 						IB_QP_PATH_MIG_STATE		|
14688a51866fSRoland Dreier 						IB_QP_MIN_RNR_TIMER),
1469b42b63cfSSean Hefty 				[IB_QPT_XRC_INI] = (IB_QP_CUR_STATE		|
1470b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS		|
1471b42b63cfSSean Hefty 						IB_QP_ALT_PATH			|
1472b42b63cfSSean Hefty 						IB_QP_PATH_MIG_STATE),
1473b42b63cfSSean Hefty 				[IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE		|
1474b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS		|
1475b42b63cfSSean Hefty 						IB_QP_ALT_PATH			|
1476b42b63cfSSean Hefty 						IB_QP_PATH_MIG_STATE		|
1477b42b63cfSSean Hefty 						IB_QP_MIN_RNR_TIMER),
14788a51866fSRoland Dreier 				[IB_QPT_SMI] = (IB_QP_CUR_STATE			|
14798a51866fSRoland Dreier 						IB_QP_QKEY),
14808a51866fSRoland Dreier 				[IB_QPT_GSI] = (IB_QP_CUR_STATE			|
14818a51866fSRoland Dreier 						IB_QP_QKEY),
1482528e5a1bSBodong Wang 				[IB_QPT_RAW_PACKET] = IB_QP_RATE_LIMIT,
14838a51866fSRoland Dreier 			}
14848a51866fSRoland Dreier 		},
14858a51866fSRoland Dreier 		[IB_QPS_SQD]   = {
14868a51866fSRoland Dreier 			.valid = 1,
14878a51866fSRoland Dreier 			.opt_param = {
14888a51866fSRoland Dreier 				[IB_QPT_UD]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
14898a51866fSRoland Dreier 				[IB_QPT_UC]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
14908a51866fSRoland Dreier 				[IB_QPT_RC]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
1491b42b63cfSSean Hefty 				[IB_QPT_XRC_INI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
1492b42b63cfSSean Hefty 				[IB_QPT_XRC_TGT] = IB_QP_EN_SQD_ASYNC_NOTIFY, /* ??? */
14938a51866fSRoland Dreier 				[IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
14948a51866fSRoland Dreier 				[IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY
14958a51866fSRoland Dreier 			}
14968a51866fSRoland Dreier 		},
14978a51866fSRoland Dreier 	},
14988a51866fSRoland Dreier 	[IB_QPS_SQD]   = {
14998a51866fSRoland Dreier 		[IB_QPS_RESET] = { .valid = 1 },
15008a51866fSRoland Dreier 		[IB_QPS_ERR] =   { .valid = 1 },
15018a51866fSRoland Dreier 		[IB_QPS_RTS]   = {
15028a51866fSRoland Dreier 			.valid = 1,
15038a51866fSRoland Dreier 			.opt_param = {
15048a51866fSRoland Dreier 				[IB_QPT_UD]  = (IB_QP_CUR_STATE			|
15058a51866fSRoland Dreier 						IB_QP_QKEY),
15068a51866fSRoland Dreier 				[IB_QPT_UC]  = (IB_QP_CUR_STATE			|
15078a51866fSRoland Dreier 						IB_QP_ALT_PATH			|
15088a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS		|
15098a51866fSRoland Dreier 						IB_QP_PATH_MIG_STATE),
15108a51866fSRoland Dreier 				[IB_QPT_RC]  = (IB_QP_CUR_STATE			|
15118a51866fSRoland Dreier 						IB_QP_ALT_PATH			|
15128a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS		|
15138a51866fSRoland Dreier 						IB_QP_MIN_RNR_TIMER		|
15148a51866fSRoland Dreier 						IB_QP_PATH_MIG_STATE),
1515b42b63cfSSean Hefty 				[IB_QPT_XRC_INI] = (IB_QP_CUR_STATE		|
1516b42b63cfSSean Hefty 						IB_QP_ALT_PATH			|
1517b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS		|
1518b42b63cfSSean Hefty 						IB_QP_PATH_MIG_STATE),
1519b42b63cfSSean Hefty 				[IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE		|
1520b42b63cfSSean Hefty 						IB_QP_ALT_PATH			|
1521b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS		|
1522b42b63cfSSean Hefty 						IB_QP_MIN_RNR_TIMER		|
1523b42b63cfSSean Hefty 						IB_QP_PATH_MIG_STATE),
15248a51866fSRoland Dreier 				[IB_QPT_SMI] = (IB_QP_CUR_STATE			|
15258a51866fSRoland Dreier 						IB_QP_QKEY),
15268a51866fSRoland Dreier 				[IB_QPT_GSI] = (IB_QP_CUR_STATE			|
15278a51866fSRoland Dreier 						IB_QP_QKEY),
15288a51866fSRoland Dreier 			}
15298a51866fSRoland Dreier 		},
15308a51866fSRoland Dreier 		[IB_QPS_SQD]   = {
15318a51866fSRoland Dreier 			.valid = 1,
15328a51866fSRoland Dreier 			.opt_param = {
15338a51866fSRoland Dreier 				[IB_QPT_UD]  = (IB_QP_PKEY_INDEX		|
15348a51866fSRoland Dreier 						IB_QP_QKEY),
15358a51866fSRoland Dreier 				[IB_QPT_UC]  = (IB_QP_AV			|
15368a51866fSRoland Dreier 						IB_QP_ALT_PATH			|
15378a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS		|
15388a51866fSRoland Dreier 						IB_QP_PKEY_INDEX		|
15398a51866fSRoland Dreier 						IB_QP_PATH_MIG_STATE),
15408a51866fSRoland Dreier 				[IB_QPT_RC]  = (IB_QP_PORT			|
15418a51866fSRoland Dreier 						IB_QP_AV			|
15428a51866fSRoland Dreier 						IB_QP_TIMEOUT			|
15438a51866fSRoland Dreier 						IB_QP_RETRY_CNT			|
15448a51866fSRoland Dreier 						IB_QP_RNR_RETRY			|
15458a51866fSRoland Dreier 						IB_QP_MAX_QP_RD_ATOMIC		|
15468a51866fSRoland Dreier 						IB_QP_MAX_DEST_RD_ATOMIC	|
15478a51866fSRoland Dreier 						IB_QP_ALT_PATH			|
15488a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS		|
15498a51866fSRoland Dreier 						IB_QP_PKEY_INDEX		|
15508a51866fSRoland Dreier 						IB_QP_MIN_RNR_TIMER		|
15518a51866fSRoland Dreier 						IB_QP_PATH_MIG_STATE),
1552b42b63cfSSean Hefty 				[IB_QPT_XRC_INI] = (IB_QP_PORT			|
1553b42b63cfSSean Hefty 						IB_QP_AV			|
1554b42b63cfSSean Hefty 						IB_QP_TIMEOUT			|
1555b42b63cfSSean Hefty 						IB_QP_RETRY_CNT			|
1556b42b63cfSSean Hefty 						IB_QP_RNR_RETRY			|
1557b42b63cfSSean Hefty 						IB_QP_MAX_QP_RD_ATOMIC		|
1558b42b63cfSSean Hefty 						IB_QP_ALT_PATH			|
1559b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS		|
1560b42b63cfSSean Hefty 						IB_QP_PKEY_INDEX		|
1561b42b63cfSSean Hefty 						IB_QP_PATH_MIG_STATE),
1562b42b63cfSSean Hefty 				[IB_QPT_XRC_TGT] = (IB_QP_PORT			|
1563b42b63cfSSean Hefty 						IB_QP_AV			|
1564b42b63cfSSean Hefty 						IB_QP_TIMEOUT			|
1565b42b63cfSSean Hefty 						IB_QP_MAX_DEST_RD_ATOMIC	|
1566b42b63cfSSean Hefty 						IB_QP_ALT_PATH			|
1567b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS		|
1568b42b63cfSSean Hefty 						IB_QP_PKEY_INDEX		|
1569b42b63cfSSean Hefty 						IB_QP_MIN_RNR_TIMER		|
1570b42b63cfSSean Hefty 						IB_QP_PATH_MIG_STATE),
15718a51866fSRoland Dreier 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
15728a51866fSRoland Dreier 						IB_QP_QKEY),
15738a51866fSRoland Dreier 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
15748a51866fSRoland Dreier 						IB_QP_QKEY),
15758a51866fSRoland Dreier 			}
15768a51866fSRoland Dreier 		}
15778a51866fSRoland Dreier 	},
15788a51866fSRoland Dreier 	[IB_QPS_SQE]   = {
15798a51866fSRoland Dreier 		[IB_QPS_RESET] = { .valid = 1 },
15808a51866fSRoland Dreier 		[IB_QPS_ERR] =   { .valid = 1 },
15818a51866fSRoland Dreier 		[IB_QPS_RTS]   = {
15828a51866fSRoland Dreier 			.valid = 1,
15838a51866fSRoland Dreier 			.opt_param = {
15848a51866fSRoland Dreier 				[IB_QPT_UD]  = (IB_QP_CUR_STATE			|
15858a51866fSRoland Dreier 						IB_QP_QKEY),
15868a51866fSRoland Dreier 				[IB_QPT_UC]  = (IB_QP_CUR_STATE			|
15878a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS),
15888a51866fSRoland Dreier 				[IB_QPT_SMI] = (IB_QP_CUR_STATE			|
15898a51866fSRoland Dreier 						IB_QP_QKEY),
15908a51866fSRoland Dreier 				[IB_QPT_GSI] = (IB_QP_CUR_STATE			|
15918a51866fSRoland Dreier 						IB_QP_QKEY),
15928a51866fSRoland Dreier 			}
15938a51866fSRoland Dreier 		}
15948a51866fSRoland Dreier 	},
15958a51866fSRoland Dreier 	[IB_QPS_ERR] = {
15968a51866fSRoland Dreier 		[IB_QPS_RESET] = { .valid = 1 },
15978a51866fSRoland Dreier 		[IB_QPS_ERR] =   { .valid = 1 }
15988a51866fSRoland Dreier 	}
15998a51866fSRoland Dreier };
16008a51866fSRoland Dreier 
160119b1f540SLeon Romanovsky bool ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
1602d31131bbSKamal Heib 			enum ib_qp_type type, enum ib_qp_attr_mask mask)
16038a51866fSRoland Dreier {
16048a51866fSRoland Dreier 	enum ib_qp_attr_mask req_param, opt_param;
16058a51866fSRoland Dreier 
16068a51866fSRoland Dreier 	if (mask & IB_QP_CUR_STATE  &&
16078a51866fSRoland Dreier 	    cur_state != IB_QPS_RTR && cur_state != IB_QPS_RTS &&
16088a51866fSRoland Dreier 	    cur_state != IB_QPS_SQD && cur_state != IB_QPS_SQE)
160919b1f540SLeon Romanovsky 		return false;
16108a51866fSRoland Dreier 
16118a51866fSRoland Dreier 	if (!qp_state_table[cur_state][next_state].valid)
161219b1f540SLeon Romanovsky 		return false;
16138a51866fSRoland Dreier 
16148a51866fSRoland Dreier 	req_param = qp_state_table[cur_state][next_state].req_param[type];
16158a51866fSRoland Dreier 	opt_param = qp_state_table[cur_state][next_state].opt_param[type];
16168a51866fSRoland Dreier 
16178a51866fSRoland Dreier 	if ((mask & req_param) != req_param)
161819b1f540SLeon Romanovsky 		return false;
16198a51866fSRoland Dreier 
16208a51866fSRoland Dreier 	if (mask & ~(req_param | opt_param | IB_QP_STATE))
162119b1f540SLeon Romanovsky 		return false;
16228a51866fSRoland Dreier 
162319b1f540SLeon Romanovsky 	return true;
16248a51866fSRoland Dreier }
16258a51866fSRoland Dreier EXPORT_SYMBOL(ib_modify_qp_is_ok);
16268a51866fSRoland Dreier 
1627947c99ecSParav Pandit /**
1628947c99ecSParav Pandit  * ib_resolve_eth_dmac - Resolve destination mac address
1629947c99ecSParav Pandit  * @device:		Device to consider
1630947c99ecSParav Pandit  * @ah_attr:		address handle attribute which describes the
1631947c99ecSParav Pandit  *			source and destination parameters
1632947c99ecSParav Pandit  * ib_resolve_eth_dmac() resolves destination mac address and L3 hop limit It
1633947c99ecSParav Pandit  * returns 0 on success or appropriate error code. It initializes the
1634947c99ecSParav Pandit  * necessary ah_attr fields when call is successful.
1635947c99ecSParav Pandit  */
1636c0348eb0SParav Pandit static int ib_resolve_eth_dmac(struct ib_device *device,
163790898850SDasaratharaman Chandramouli 			       struct rdma_ah_attr *ah_attr)
1638ed4c54e5SOr Gerlitz {
1639ed4c54e5SOr Gerlitz 	int ret = 0;
1640d8966fcdSDasaratharaman Chandramouli 
16419636a56fSNoa Osherovich 	if (rdma_is_multicast_addr((struct in6_addr *)ah_attr->grh.dgid.raw)) {
16429636a56fSNoa Osherovich 		if (ipv6_addr_v4mapped((struct in6_addr *)ah_attr->grh.dgid.raw)) {
16439636a56fSNoa Osherovich 			__be32 addr = 0;
16449636a56fSNoa Osherovich 
16459636a56fSNoa Osherovich 			memcpy(&addr, ah_attr->grh.dgid.raw + 12, 4);
16469636a56fSNoa Osherovich 			ip_eth_mc_map(addr, (char *)ah_attr->roce.dmac);
16479636a56fSNoa Osherovich 		} else {
16489636a56fSNoa Osherovich 			ipv6_eth_mc_map((struct in6_addr *)ah_attr->grh.dgid.raw,
16499636a56fSNoa Osherovich 					(char *)ah_attr->roce.dmac);
16509636a56fSNoa Osherovich 		}
1651ed4c54e5SOr Gerlitz 	} else {
16521060f865SParav Pandit 		ret = ib_resolve_unicast_gid_dmac(device, ah_attr);
1653ed4c54e5SOr Gerlitz 	}
1654ed4c54e5SOr Gerlitz 	return ret;
1655ed4c54e5SOr Gerlitz }
1656ed4c54e5SOr Gerlitz 
16578d9ec9adSJason Gunthorpe static bool is_qp_type_connected(const struct ib_qp *qp)
16588d9ec9adSJason Gunthorpe {
16598d9ec9adSJason Gunthorpe 	return (qp->qp_type == IB_QPT_UC ||
16608d9ec9adSJason Gunthorpe 		qp->qp_type == IB_QPT_RC ||
16618d9ec9adSJason Gunthorpe 		qp->qp_type == IB_QPT_XRC_INI ||
16628d9ec9adSJason Gunthorpe 		qp->qp_type == IB_QPT_XRC_TGT);
16638d9ec9adSJason Gunthorpe }
16648d9ec9adSJason Gunthorpe 
1665a512c2fbSParav Pandit /**
1666b96ac05aSParav Pandit  * IB core internal function to perform QP attributes modification.
1667a512c2fbSParav Pandit  */
1668b96ac05aSParav Pandit static int _ib_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr,
1669a512c2fbSParav Pandit 			 int attr_mask, struct ib_udata *udata)
1670a512c2fbSParav Pandit {
1671727b7e9aSMajd Dibbiny 	u8 port = attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
16728d9ec9adSJason Gunthorpe 	const struct ib_gid_attr *old_sgid_attr_av;
16738d9ec9adSJason Gunthorpe 	const struct ib_gid_attr *old_sgid_attr_alt_av;
1674a512c2fbSParav Pandit 	int ret;
1675a512c2fbSParav Pandit 
167651aab126SMaor Gottlieb 	attr->xmit_slave = NULL;
16778d9ec9adSJason Gunthorpe 	if (attr_mask & IB_QP_AV) {
16788d9ec9adSJason Gunthorpe 		ret = rdma_fill_sgid_attr(qp->device, &attr->ah_attr,
16798d9ec9adSJason Gunthorpe 					  &old_sgid_attr_av);
16808d9ec9adSJason Gunthorpe 		if (ret)
16818d9ec9adSJason Gunthorpe 			return ret;
168251aab126SMaor Gottlieb 
168351aab126SMaor Gottlieb 		if (attr->ah_attr.type == RDMA_AH_ATTR_TYPE_ROCE &&
168451aab126SMaor Gottlieb 		    is_qp_type_connected(qp)) {
168551aab126SMaor Gottlieb 			struct net_device *slave;
168651aab126SMaor Gottlieb 
168751aab126SMaor Gottlieb 			/*
168851aab126SMaor Gottlieb 			 * If the user provided the qp_attr then we have to
168951aab126SMaor Gottlieb 			 * resolve it. Kerne users have to provide already
169051aab126SMaor Gottlieb 			 * resolved rdma_ah_attr's.
169151aab126SMaor Gottlieb 			 */
169251aab126SMaor Gottlieb 			if (udata) {
169351aab126SMaor Gottlieb 				ret = ib_resolve_eth_dmac(qp->device,
169451aab126SMaor Gottlieb 							  &attr->ah_attr);
169551aab126SMaor Gottlieb 				if (ret)
169651aab126SMaor Gottlieb 					goto out_av;
169751aab126SMaor Gottlieb 			}
169851aab126SMaor Gottlieb 			slave = rdma_lag_get_ah_roce_slave(qp->device,
169951aab126SMaor Gottlieb 							   &attr->ah_attr,
170051aab126SMaor Gottlieb 							   GFP_KERNEL);
170151aab126SMaor Gottlieb 			if (IS_ERR(slave))
170251aab126SMaor Gottlieb 				goto out_av;
170351aab126SMaor Gottlieb 			attr->xmit_slave = slave;
170451aab126SMaor Gottlieb 		}
17058d9ec9adSJason Gunthorpe 	}
17068d9ec9adSJason Gunthorpe 	if (attr_mask & IB_QP_ALT_PATH) {
17071a1f460fSJason Gunthorpe 		/*
17081a1f460fSJason Gunthorpe 		 * FIXME: This does not track the migration state, so if the
17091a1f460fSJason Gunthorpe 		 * user loads a new alternate path after the HW has migrated
17101a1f460fSJason Gunthorpe 		 * from primary->alternate we will keep the wrong
17111a1f460fSJason Gunthorpe 		 * references. This is OK for IB because the reference
17121a1f460fSJason Gunthorpe 		 * counting does not serve any functional purpose.
17131a1f460fSJason Gunthorpe 		 */
17148d9ec9adSJason Gunthorpe 		ret = rdma_fill_sgid_attr(qp->device, &attr->alt_ah_attr,
17158d9ec9adSJason Gunthorpe 					  &old_sgid_attr_alt_av);
17168d9ec9adSJason Gunthorpe 		if (ret)
17178d9ec9adSJason Gunthorpe 			goto out_av;
17187a5c938bSJason Gunthorpe 
17197a5c938bSJason Gunthorpe 		/*
17207a5c938bSJason Gunthorpe 		 * Today the core code can only handle alternate paths and APM
17217a5c938bSJason Gunthorpe 		 * for IB. Ban them in roce mode.
17227a5c938bSJason Gunthorpe 		 */
17237a5c938bSJason Gunthorpe 		if (!(rdma_protocol_ib(qp->device,
17247a5c938bSJason Gunthorpe 				       attr->alt_ah_attr.port_num) &&
17257a5c938bSJason Gunthorpe 		      rdma_protocol_ib(qp->device, port))) {
172647fda651SLi Heng 			ret = -EINVAL;
17277a5c938bSJason Gunthorpe 			goto out;
17287a5c938bSJason Gunthorpe 		}
17298d9ec9adSJason Gunthorpe 	}
17308d9ec9adSJason Gunthorpe 
1731727b7e9aSMajd Dibbiny 	if (rdma_ib_or_roce(qp->device, port)) {
1732727b7e9aSMajd Dibbiny 		if (attr_mask & IB_QP_RQ_PSN && attr->rq_psn & ~0xffffff) {
173343c7c851SJason Gunthorpe 			dev_warn(&qp->device->dev,
173443c7c851SJason Gunthorpe 				 "%s rq_psn overflow, masking to 24 bits\n",
173543c7c851SJason Gunthorpe 				 __func__);
1736727b7e9aSMajd Dibbiny 			attr->rq_psn &= 0xffffff;
1737727b7e9aSMajd Dibbiny 		}
1738727b7e9aSMajd Dibbiny 
1739727b7e9aSMajd Dibbiny 		if (attr_mask & IB_QP_SQ_PSN && attr->sq_psn & ~0xffffff) {
174043c7c851SJason Gunthorpe 			dev_warn(&qp->device->dev,
174143c7c851SJason Gunthorpe 				 " %s sq_psn overflow, masking to 24 bits\n",
174243c7c851SJason Gunthorpe 				 __func__);
1743727b7e9aSMajd Dibbiny 			attr->sq_psn &= 0xffffff;
1744727b7e9aSMajd Dibbiny 		}
1745727b7e9aSMajd Dibbiny 	}
1746727b7e9aSMajd Dibbiny 
174799fa331dSMark Zhang 	/*
174899fa331dSMark Zhang 	 * Bind this qp to a counter automatically based on the rdma counter
174999fa331dSMark Zhang 	 * rules. This only set in RST2INIT with port specified
175099fa331dSMark Zhang 	 */
175199fa331dSMark Zhang 	if (!qp->counter && (attr_mask & IB_QP_PORT) &&
175299fa331dSMark Zhang 	    ((attr_mask & IB_QP_STATE) && attr->qp_state == IB_QPS_INIT))
175399fa331dSMark Zhang 		rdma_counter_bind_qp_auto(qp, attr->port_num);
175499fa331dSMark Zhang 
1755498ca3c8SNoa Osherovich 	ret = ib_security_modify_qp(qp, attr, attr_mask, udata);
17561a1f460fSJason Gunthorpe 	if (ret)
17571a1f460fSJason Gunthorpe 		goto out;
17581a1f460fSJason Gunthorpe 
17591a1f460fSJason Gunthorpe 	if (attr_mask & IB_QP_PORT)
1760498ca3c8SNoa Osherovich 		qp->port = attr->port_num;
17611a1f460fSJason Gunthorpe 	if (attr_mask & IB_QP_AV)
17621a1f460fSJason Gunthorpe 		qp->av_sgid_attr =
17631a1f460fSJason Gunthorpe 			rdma_update_sgid_attr(&attr->ah_attr, qp->av_sgid_attr);
17641a1f460fSJason Gunthorpe 	if (attr_mask & IB_QP_ALT_PATH)
17651a1f460fSJason Gunthorpe 		qp->alt_path_sgid_attr = rdma_update_sgid_attr(
17661a1f460fSJason Gunthorpe 			&attr->alt_ah_attr, qp->alt_path_sgid_attr);
1767498ca3c8SNoa Osherovich 
17688d9ec9adSJason Gunthorpe out:
17698d9ec9adSJason Gunthorpe 	if (attr_mask & IB_QP_ALT_PATH)
17708d9ec9adSJason Gunthorpe 		rdma_unfill_sgid_attr(&attr->alt_ah_attr, old_sgid_attr_alt_av);
17718d9ec9adSJason Gunthorpe out_av:
177251aab126SMaor Gottlieb 	if (attr_mask & IB_QP_AV) {
177351aab126SMaor Gottlieb 		rdma_lag_put_ah_roce_slave(attr->xmit_slave);
17748d9ec9adSJason Gunthorpe 		rdma_unfill_sgid_attr(&attr->ah_attr, old_sgid_attr_av);
177551aab126SMaor Gottlieb 	}
1776498ca3c8SNoa Osherovich 	return ret;
1777a512c2fbSParav Pandit }
1778b96ac05aSParav Pandit 
1779b96ac05aSParav Pandit /**
1780b96ac05aSParav Pandit  * ib_modify_qp_with_udata - Modifies the attributes for the specified QP.
1781b96ac05aSParav Pandit  * @ib_qp: The QP to modify.
1782b96ac05aSParav Pandit  * @attr: On input, specifies the QP attributes to modify.  On output,
1783b96ac05aSParav Pandit  *   the current values of selected QP attributes are returned.
1784b96ac05aSParav Pandit  * @attr_mask: A bit-mask used to specify which attributes of the QP
1785b96ac05aSParav Pandit  *   are being modified.
1786b96ac05aSParav Pandit  * @udata: pointer to user's input output buffer information
1787b96ac05aSParav Pandit  *   are being modified.
1788b96ac05aSParav Pandit  * It returns 0 on success and returns appropriate error code on error.
1789b96ac05aSParav Pandit  */
1790b96ac05aSParav Pandit int ib_modify_qp_with_udata(struct ib_qp *ib_qp, struct ib_qp_attr *attr,
1791b96ac05aSParav Pandit 			    int attr_mask, struct ib_udata *udata)
1792b96ac05aSParav Pandit {
17938d9ec9adSJason Gunthorpe 	return _ib_modify_qp(ib_qp->real_qp, attr, attr_mask, udata);
1794b96ac05aSParav Pandit }
1795a512c2fbSParav Pandit EXPORT_SYMBOL(ib_modify_qp_with_udata);
1796a512c2fbSParav Pandit 
1797376ceb31SAharon Landau int ib_get_eth_speed(struct ib_device *dev, u8 port_num, u16 *speed, u8 *width)
1798d4186194SYuval Shaia {
1799d4186194SYuval Shaia 	int rc;
1800d4186194SYuval Shaia 	u32 netdev_speed;
1801d4186194SYuval Shaia 	struct net_device *netdev;
1802d4186194SYuval Shaia 	struct ethtool_link_ksettings lksettings;
1803d4186194SYuval Shaia 
1804d4186194SYuval Shaia 	if (rdma_port_get_link_layer(dev, port_num) != IB_LINK_LAYER_ETHERNET)
1805d4186194SYuval Shaia 		return -EINVAL;
1806d4186194SYuval Shaia 
1807c2261dd7SJason Gunthorpe 	netdev = ib_device_get_netdev(dev, port_num);
1808d4186194SYuval Shaia 	if (!netdev)
1809d4186194SYuval Shaia 		return -ENODEV;
1810d4186194SYuval Shaia 
1811d4186194SYuval Shaia 	rtnl_lock();
1812d4186194SYuval Shaia 	rc = __ethtool_get_link_ksettings(netdev, &lksettings);
1813d4186194SYuval Shaia 	rtnl_unlock();
1814d4186194SYuval Shaia 
1815d4186194SYuval Shaia 	dev_put(netdev);
1816d4186194SYuval Shaia 
181728b08657SKamal Heib 	if (!rc && lksettings.base.speed != (u32)SPEED_UNKNOWN) {
1818d4186194SYuval Shaia 		netdev_speed = lksettings.base.speed;
1819d4186194SYuval Shaia 	} else {
1820d4186194SYuval Shaia 		netdev_speed = SPEED_1000;
1821d4186194SYuval Shaia 		pr_warn("%s speed is unknown, defaulting to %d\n", netdev->name,
1822d4186194SYuval Shaia 			netdev_speed);
1823d4186194SYuval Shaia 	}
1824d4186194SYuval Shaia 
1825d4186194SYuval Shaia 	if (netdev_speed <= SPEED_1000) {
1826d4186194SYuval Shaia 		*width = IB_WIDTH_1X;
1827d4186194SYuval Shaia 		*speed = IB_SPEED_SDR;
1828d4186194SYuval Shaia 	} else if (netdev_speed <= SPEED_10000) {
1829d4186194SYuval Shaia 		*width = IB_WIDTH_1X;
1830d4186194SYuval Shaia 		*speed = IB_SPEED_FDR10;
1831d4186194SYuval Shaia 	} else if (netdev_speed <= SPEED_20000) {
1832d4186194SYuval Shaia 		*width = IB_WIDTH_4X;
1833d4186194SYuval Shaia 		*speed = IB_SPEED_DDR;
1834d4186194SYuval Shaia 	} else if (netdev_speed <= SPEED_25000) {
1835d4186194SYuval Shaia 		*width = IB_WIDTH_1X;
1836d4186194SYuval Shaia 		*speed = IB_SPEED_EDR;
1837d4186194SYuval Shaia 	} else if (netdev_speed <= SPEED_40000) {
1838d4186194SYuval Shaia 		*width = IB_WIDTH_4X;
1839d4186194SYuval Shaia 		*speed = IB_SPEED_FDR10;
1840d4186194SYuval Shaia 	} else {
1841d4186194SYuval Shaia 		*width = IB_WIDTH_4X;
1842d4186194SYuval Shaia 		*speed = IB_SPEED_EDR;
1843d4186194SYuval Shaia 	}
1844d4186194SYuval Shaia 
1845d4186194SYuval Shaia 	return 0;
1846d4186194SYuval Shaia }
1847d4186194SYuval Shaia EXPORT_SYMBOL(ib_get_eth_speed);
1848d4186194SYuval Shaia 
18491da177e4SLinus Torvalds int ib_modify_qp(struct ib_qp *qp,
18501da177e4SLinus Torvalds 		 struct ib_qp_attr *qp_attr,
18511da177e4SLinus Torvalds 		 int qp_attr_mask)
18521da177e4SLinus Torvalds {
1853b96ac05aSParav Pandit 	return _ib_modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL);
18541da177e4SLinus Torvalds }
18551da177e4SLinus Torvalds EXPORT_SYMBOL(ib_modify_qp);
18561da177e4SLinus Torvalds 
18571da177e4SLinus Torvalds int ib_query_qp(struct ib_qp *qp,
18581da177e4SLinus Torvalds 		struct ib_qp_attr *qp_attr,
18591da177e4SLinus Torvalds 		int qp_attr_mask,
18601da177e4SLinus Torvalds 		struct ib_qp_init_attr *qp_init_attr)
18611da177e4SLinus Torvalds {
18628d9ec9adSJason Gunthorpe 	qp_attr->ah_attr.grh.sgid_attr = NULL;
18638d9ec9adSJason Gunthorpe 	qp_attr->alt_ah_attr.grh.sgid_attr = NULL;
18648d9ec9adSJason Gunthorpe 
18653023a1e9SKamal Heib 	return qp->device->ops.query_qp ?
18663023a1e9SKamal Heib 		qp->device->ops.query_qp(qp->real_qp, qp_attr, qp_attr_mask,
18673023a1e9SKamal Heib 					 qp_init_attr) : -EOPNOTSUPP;
18681da177e4SLinus Torvalds }
18691da177e4SLinus Torvalds EXPORT_SYMBOL(ib_query_qp);
18701da177e4SLinus Torvalds 
18710e0ec7e0SSean Hefty int ib_close_qp(struct ib_qp *qp)
18720e0ec7e0SSean Hefty {
18730e0ec7e0SSean Hefty 	struct ib_qp *real_qp;
18740e0ec7e0SSean Hefty 	unsigned long flags;
18750e0ec7e0SSean Hefty 
18760e0ec7e0SSean Hefty 	real_qp = qp->real_qp;
18770e0ec7e0SSean Hefty 	if (real_qp == qp)
18780e0ec7e0SSean Hefty 		return -EINVAL;
18790e0ec7e0SSean Hefty 
188040adf686SParav Pandit 	spin_lock_irqsave(&real_qp->device->qp_open_list_lock, flags);
18810e0ec7e0SSean Hefty 	list_del(&qp->open_list);
188240adf686SParav Pandit 	spin_unlock_irqrestore(&real_qp->device->qp_open_list_lock, flags);
18830e0ec7e0SSean Hefty 
18840e0ec7e0SSean Hefty 	atomic_dec(&real_qp->usecnt);
18854a50881bSMoni Shoua 	if (qp->qp_sec)
1886d291f1a6SDaniel Jurgens 		ib_close_shared_qp_security(qp->qp_sec);
18870e0ec7e0SSean Hefty 	kfree(qp);
18880e0ec7e0SSean Hefty 
18890e0ec7e0SSean Hefty 	return 0;
18900e0ec7e0SSean Hefty }
18910e0ec7e0SSean Hefty EXPORT_SYMBOL(ib_close_qp);
18920e0ec7e0SSean Hefty 
18930e0ec7e0SSean Hefty static int __ib_destroy_shared_qp(struct ib_qp *qp)
18940e0ec7e0SSean Hefty {
18950e0ec7e0SSean Hefty 	struct ib_xrcd *xrcd;
18960e0ec7e0SSean Hefty 	struct ib_qp *real_qp;
18970e0ec7e0SSean Hefty 	int ret;
18980e0ec7e0SSean Hefty 
18990e0ec7e0SSean Hefty 	real_qp = qp->real_qp;
19000e0ec7e0SSean Hefty 	xrcd = real_qp->xrcd;
19016f3ca6f4SMaor Gottlieb 	down_write(&xrcd->tgt_qps_rwsem);
19020e0ec7e0SSean Hefty 	ib_close_qp(qp);
19030e0ec7e0SSean Hefty 	if (atomic_read(&real_qp->usecnt) == 0)
19046f3ca6f4SMaor Gottlieb 		xa_erase(&xrcd->tgt_qps, real_qp->qp_num);
19050e0ec7e0SSean Hefty 	else
19060e0ec7e0SSean Hefty 		real_qp = NULL;
19076f3ca6f4SMaor Gottlieb 	up_write(&xrcd->tgt_qps_rwsem);
19080e0ec7e0SSean Hefty 
19090e0ec7e0SSean Hefty 	if (real_qp) {
19100e0ec7e0SSean Hefty 		ret = ib_destroy_qp(real_qp);
19110e0ec7e0SSean Hefty 		if (!ret)
19120e0ec7e0SSean Hefty 			atomic_dec(&xrcd->usecnt);
19130e0ec7e0SSean Hefty 	}
19140e0ec7e0SSean Hefty 
19150e0ec7e0SSean Hefty 	return 0;
19160e0ec7e0SSean Hefty }
19170e0ec7e0SSean Hefty 
1918c4367a26SShamir Rabinovitch int ib_destroy_qp_user(struct ib_qp *qp, struct ib_udata *udata)
19191da177e4SLinus Torvalds {
19201a1f460fSJason Gunthorpe 	const struct ib_gid_attr *alt_path_sgid_attr = qp->alt_path_sgid_attr;
19211a1f460fSJason Gunthorpe 	const struct ib_gid_attr *av_sgid_attr = qp->av_sgid_attr;
19221da177e4SLinus Torvalds 	struct ib_pd *pd;
19231da177e4SLinus Torvalds 	struct ib_cq *scq, *rcq;
19241da177e4SLinus Torvalds 	struct ib_srq *srq;
1925a9017e23SYishai Hadas 	struct ib_rwq_ind_table *ind_tbl;
1926d291f1a6SDaniel Jurgens 	struct ib_qp_security *sec;
19271da177e4SLinus Torvalds 	int ret;
19281da177e4SLinus Torvalds 
1929fffb0383SChristoph Hellwig 	WARN_ON_ONCE(qp->mrs_used > 0);
1930fffb0383SChristoph Hellwig 
19310e0ec7e0SSean Hefty 	if (atomic_read(&qp->usecnt))
19320e0ec7e0SSean Hefty 		return -EBUSY;
19330e0ec7e0SSean Hefty 
19340e0ec7e0SSean Hefty 	if (qp->real_qp != qp)
19350e0ec7e0SSean Hefty 		return __ib_destroy_shared_qp(qp);
19360e0ec7e0SSean Hefty 
19371da177e4SLinus Torvalds 	pd   = qp->pd;
19381da177e4SLinus Torvalds 	scq  = qp->send_cq;
19391da177e4SLinus Torvalds 	rcq  = qp->recv_cq;
19401da177e4SLinus Torvalds 	srq  = qp->srq;
1941a9017e23SYishai Hadas 	ind_tbl = qp->rwq_ind_tbl;
1942d291f1a6SDaniel Jurgens 	sec  = qp->qp_sec;
1943d291f1a6SDaniel Jurgens 	if (sec)
1944d291f1a6SDaniel Jurgens 		ib_destroy_qp_security_begin(sec);
19451da177e4SLinus Torvalds 
1946a060b562SChristoph Hellwig 	if (!qp->uobject)
1947a060b562SChristoph Hellwig 		rdma_rw_cleanup_mrs(qp);
1948a060b562SChristoph Hellwig 
194999fa331dSMark Zhang 	rdma_counter_unbind_qp(qp, true);
195078a0cd64SLeon Romanovsky 	rdma_restrack_del(&qp->res);
1951c4367a26SShamir Rabinovitch 	ret = qp->device->ops.destroy_qp(qp, udata);
19521da177e4SLinus Torvalds 	if (!ret) {
19531a1f460fSJason Gunthorpe 		if (alt_path_sgid_attr)
19541a1f460fSJason Gunthorpe 			rdma_put_gid_attr(alt_path_sgid_attr);
19551a1f460fSJason Gunthorpe 		if (av_sgid_attr)
19561a1f460fSJason Gunthorpe 			rdma_put_gid_attr(av_sgid_attr);
1957b42b63cfSSean Hefty 		if (pd)
19581da177e4SLinus Torvalds 			atomic_dec(&pd->usecnt);
1959b42b63cfSSean Hefty 		if (scq)
19601da177e4SLinus Torvalds 			atomic_dec(&scq->usecnt);
1961b42b63cfSSean Hefty 		if (rcq)
19621da177e4SLinus Torvalds 			atomic_dec(&rcq->usecnt);
19631da177e4SLinus Torvalds 		if (srq)
19641da177e4SLinus Torvalds 			atomic_dec(&srq->usecnt);
1965a9017e23SYishai Hadas 		if (ind_tbl)
1966a9017e23SYishai Hadas 			atomic_dec(&ind_tbl->usecnt);
1967d291f1a6SDaniel Jurgens 		if (sec)
1968d291f1a6SDaniel Jurgens 			ib_destroy_qp_security_end(sec);
1969d291f1a6SDaniel Jurgens 	} else {
1970d291f1a6SDaniel Jurgens 		if (sec)
1971d291f1a6SDaniel Jurgens 			ib_destroy_qp_security_abort(sec);
19721da177e4SLinus Torvalds 	}
19731da177e4SLinus Torvalds 
19741da177e4SLinus Torvalds 	return ret;
19751da177e4SLinus Torvalds }
1976c4367a26SShamir Rabinovitch EXPORT_SYMBOL(ib_destroy_qp_user);
19771da177e4SLinus Torvalds 
19781da177e4SLinus Torvalds /* Completion queues */
19791da177e4SLinus Torvalds 
19807350cdd0SBharat Potnuri struct ib_cq *__ib_create_cq(struct ib_device *device,
19811da177e4SLinus Torvalds 			     ib_comp_handler comp_handler,
19821da177e4SLinus Torvalds 			     void (*event_handler)(struct ib_event *, void *),
19838e37210bSMatan Barak 			     void *cq_context,
19847350cdd0SBharat Potnuri 			     const struct ib_cq_init_attr *cq_attr,
19857350cdd0SBharat Potnuri 			     const char *caller)
19861da177e4SLinus Torvalds {
19871da177e4SLinus Torvalds 	struct ib_cq *cq;
1988e39afe3dSLeon Romanovsky 	int ret;
19891da177e4SLinus Torvalds 
1990e39afe3dSLeon Romanovsky 	cq = rdma_zalloc_drv_obj(device, ib_cq);
1991e39afe3dSLeon Romanovsky 	if (!cq)
1992e39afe3dSLeon Romanovsky 		return ERR_PTR(-ENOMEM);
19931da177e4SLinus Torvalds 
19941da177e4SLinus Torvalds 	cq->device = device;
1995b5e81bf5SRoland Dreier 	cq->uobject = NULL;
19961da177e4SLinus Torvalds 	cq->comp_handler = comp_handler;
19971da177e4SLinus Torvalds 	cq->event_handler = event_handler;
19981da177e4SLinus Torvalds 	cq->cq_context = cq_context;
19991da177e4SLinus Torvalds 	atomic_set(&cq->usecnt, 0);
200013ef5539SLeon Romanovsky 
200113ef5539SLeon Romanovsky 	rdma_restrack_new(&cq->res, RDMA_RESTRACK_CQ);
20022165fc26SLeon Romanovsky 	rdma_restrack_set_task(&cq->res, caller);
2003e39afe3dSLeon Romanovsky 
2004e39afe3dSLeon Romanovsky 	ret = device->ops.create_cq(cq, cq_attr, NULL);
2005e39afe3dSLeon Romanovsky 	if (ret) {
200613ef5539SLeon Romanovsky 		rdma_restrack_put(&cq->res);
2007e39afe3dSLeon Romanovsky 		kfree(cq);
2008e39afe3dSLeon Romanovsky 		return ERR_PTR(ret);
20091da177e4SLinus Torvalds 	}
20101da177e4SLinus Torvalds 
2011e39afe3dSLeon Romanovsky 	rdma_restrack_kadd(&cq->res);
20121da177e4SLinus Torvalds 	return cq;
20131da177e4SLinus Torvalds }
20147350cdd0SBharat Potnuri EXPORT_SYMBOL(__ib_create_cq);
20151da177e4SLinus Torvalds 
20164190b4e9SLeon Romanovsky int rdma_set_cq_moderation(struct ib_cq *cq, u16 cq_count, u16 cq_period)
20172dd57162SEli Cohen {
20183446cbd2SYamin Friedman 	if (cq->shared)
20193446cbd2SYamin Friedman 		return -EOPNOTSUPP;
20203446cbd2SYamin Friedman 
20213023a1e9SKamal Heib 	return cq->device->ops.modify_cq ?
20223023a1e9SKamal Heib 		cq->device->ops.modify_cq(cq, cq_count,
20233023a1e9SKamal Heib 					  cq_period) : -EOPNOTSUPP;
20242dd57162SEli Cohen }
20254190b4e9SLeon Romanovsky EXPORT_SYMBOL(rdma_set_cq_moderation);
20262dd57162SEli Cohen 
2027c4367a26SShamir Rabinovitch int ib_destroy_cq_user(struct ib_cq *cq, struct ib_udata *udata)
20281da177e4SLinus Torvalds {
202943d781b9SLeon Romanovsky 	int ret;
203043d781b9SLeon Romanovsky 
20313446cbd2SYamin Friedman 	if (WARN_ON_ONCE(cq->shared))
20323446cbd2SYamin Friedman 		return -EOPNOTSUPP;
20333446cbd2SYamin Friedman 
20341da177e4SLinus Torvalds 	if (atomic_read(&cq->usecnt))
20351da177e4SLinus Torvalds 		return -EBUSY;
20361da177e4SLinus Torvalds 
203743d781b9SLeon Romanovsky 	ret = cq->device->ops.destroy_cq(cq, udata);
203843d781b9SLeon Romanovsky 	if (ret)
203943d781b9SLeon Romanovsky 		return ret;
204043d781b9SLeon Romanovsky 
204108f294a1SLeon Romanovsky 	rdma_restrack_del(&cq->res);
2042e39afe3dSLeon Romanovsky 	kfree(cq);
204343d781b9SLeon Romanovsky 	return ret;
20441da177e4SLinus Torvalds }
2045c4367a26SShamir Rabinovitch EXPORT_SYMBOL(ib_destroy_cq_user);
20461da177e4SLinus Torvalds 
2047a74cd4afSRoland Dreier int ib_resize_cq(struct ib_cq *cq, int cqe)
20481da177e4SLinus Torvalds {
20493446cbd2SYamin Friedman 	if (cq->shared)
20503446cbd2SYamin Friedman 		return -EOPNOTSUPP;
20513446cbd2SYamin Friedman 
20523023a1e9SKamal Heib 	return cq->device->ops.resize_cq ?
20533023a1e9SKamal Heib 		cq->device->ops.resize_cq(cq, cqe, NULL) : -EOPNOTSUPP;
20541da177e4SLinus Torvalds }
20551da177e4SLinus Torvalds EXPORT_SYMBOL(ib_resize_cq);
20561da177e4SLinus Torvalds 
20571da177e4SLinus Torvalds /* Memory regions */
20581da177e4SLinus Torvalds 
205933006bd4SMoni Shoua struct ib_mr *ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
206033006bd4SMoni Shoua 			     u64 virt_addr, int access_flags)
206133006bd4SMoni Shoua {
206233006bd4SMoni Shoua 	struct ib_mr *mr;
206333006bd4SMoni Shoua 
206433006bd4SMoni Shoua 	if (access_flags & IB_ACCESS_ON_DEMAND) {
206533006bd4SMoni Shoua 		if (!(pd->device->attrs.device_cap_flags &
206633006bd4SMoni Shoua 		      IB_DEVICE_ON_DEMAND_PAGING)) {
206733006bd4SMoni Shoua 			pr_debug("ODP support not available\n");
206833006bd4SMoni Shoua 			return ERR_PTR(-EINVAL);
206933006bd4SMoni Shoua 		}
207033006bd4SMoni Shoua 	}
207133006bd4SMoni Shoua 
207233006bd4SMoni Shoua 	mr = pd->device->ops.reg_user_mr(pd, start, length, virt_addr,
207333006bd4SMoni Shoua 					 access_flags, NULL);
207433006bd4SMoni Shoua 
207533006bd4SMoni Shoua 	if (IS_ERR(mr))
207633006bd4SMoni Shoua 		return mr;
207733006bd4SMoni Shoua 
207833006bd4SMoni Shoua 	mr->device = pd->device;
207933006bd4SMoni Shoua 	mr->pd = pd;
208033006bd4SMoni Shoua 	mr->dm = NULL;
208133006bd4SMoni Shoua 	atomic_inc(&pd->usecnt);
208213ef5539SLeon Romanovsky 
208313ef5539SLeon Romanovsky 	rdma_restrack_new(&mr->res, RDMA_RESTRACK_MR);
208433006bd4SMoni Shoua 	rdma_restrack_kadd(&mr->res);
208533006bd4SMoni Shoua 
208633006bd4SMoni Shoua 	return mr;
208733006bd4SMoni Shoua }
208833006bd4SMoni Shoua EXPORT_SYMBOL(ib_reg_user_mr);
208933006bd4SMoni Shoua 
209087d8069fSMoni Shoua int ib_advise_mr(struct ib_pd *pd, enum ib_uverbs_advise_mr_advice advice,
209187d8069fSMoni Shoua 		 u32 flags, struct ib_sge *sg_list, u32 num_sge)
209287d8069fSMoni Shoua {
209387d8069fSMoni Shoua 	if (!pd->device->ops.advise_mr)
209487d8069fSMoni Shoua 		return -EOPNOTSUPP;
209587d8069fSMoni Shoua 
2096d4d7f596SMaor Gottlieb 	if (!num_sge)
2097d4d7f596SMaor Gottlieb 		return 0;
2098d4d7f596SMaor Gottlieb 
209987d8069fSMoni Shoua 	return pd->device->ops.advise_mr(pd, advice, flags, sg_list, num_sge,
210087d8069fSMoni Shoua 					 NULL);
210187d8069fSMoni Shoua }
210287d8069fSMoni Shoua EXPORT_SYMBOL(ib_advise_mr);
210387d8069fSMoni Shoua 
2104c4367a26SShamir Rabinovitch int ib_dereg_mr_user(struct ib_mr *mr, struct ib_udata *udata)
21051da177e4SLinus Torvalds {
2106ab67ed8dSChristoph Hellwig 	struct ib_pd *pd = mr->pd;
2107be934ccaSAriel Levkovich 	struct ib_dm *dm = mr->dm;
21087c717d3aSMax Gurtovoy 	struct ib_sig_attrs *sig_attrs = mr->sig_attrs;
21091da177e4SLinus Torvalds 	int ret;
21101da177e4SLinus Torvalds 
2111622db5b6SChuck Lever 	trace_mr_dereg(mr);
2112fccec5b8SSteve Wise 	rdma_restrack_del(&mr->res);
2113c4367a26SShamir Rabinovitch 	ret = mr->device->ops.dereg_mr(mr, udata);
2114be934ccaSAriel Levkovich 	if (!ret) {
21151da177e4SLinus Torvalds 		atomic_dec(&pd->usecnt);
2116be934ccaSAriel Levkovich 		if (dm)
2117be934ccaSAriel Levkovich 			atomic_dec(&dm->usecnt);
21187c717d3aSMax Gurtovoy 		kfree(sig_attrs);
2119be934ccaSAriel Levkovich 	}
21201da177e4SLinus Torvalds 
21211da177e4SLinus Torvalds 	return ret;
21221da177e4SLinus Torvalds }
2123c4367a26SShamir Rabinovitch EXPORT_SYMBOL(ib_dereg_mr_user);
21241da177e4SLinus Torvalds 
21259bee178bSSagi Grimberg /**
2126b64b74b1SGal Pressman  * ib_alloc_mr() - Allocates a memory region
21279bee178bSSagi Grimberg  * @pd:            protection domain associated with the region
21289bee178bSSagi Grimberg  * @mr_type:       memory region type
21299bee178bSSagi Grimberg  * @max_num_sg:    maximum sg entries available for registration.
21309bee178bSSagi Grimberg  *
21319bee178bSSagi Grimberg  * Notes:
21329bee178bSSagi Grimberg  * Memory registeration page/sg lists must not exceed max_num_sg.
21339bee178bSSagi Grimberg  * For mr_type IB_MR_TYPE_MEM_REG, the total length cannot exceed
21349bee178bSSagi Grimberg  * max_num_sg * used_page_size.
21359bee178bSSagi Grimberg  *
21369bee178bSSagi Grimberg  */
2137b64b74b1SGal Pressman struct ib_mr *ib_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type,
2138b64b74b1SGal Pressman 			  u32 max_num_sg)
213917cd3a2dSSagi Grimberg {
214017cd3a2dSSagi Grimberg 	struct ib_mr *mr;
214117cd3a2dSSagi Grimberg 
2142622db5b6SChuck Lever 	if (!pd->device->ops.alloc_mr) {
2143622db5b6SChuck Lever 		mr = ERR_PTR(-EOPNOTSUPP);
2144622db5b6SChuck Lever 		goto out;
2145622db5b6SChuck Lever 	}
214617cd3a2dSSagi Grimberg 
2147622db5b6SChuck Lever 	if (mr_type == IB_MR_TYPE_INTEGRITY) {
2148622db5b6SChuck Lever 		WARN_ON_ONCE(1);
2149622db5b6SChuck Lever 		mr = ERR_PTR(-EINVAL);
2150622db5b6SChuck Lever 		goto out;
2151622db5b6SChuck Lever 	}
215226bc7eaeSIsrael Rukshin 
215342a3b153SGal Pressman 	mr = pd->device->ops.alloc_mr(pd, mr_type, max_num_sg);
2154c5f42b21SGal Pressman 	if (IS_ERR(mr))
2155c5f42b21SGal Pressman 		goto out;
2156c5f42b21SGal Pressman 
215717cd3a2dSSagi Grimberg 	mr->device = pd->device;
215817cd3a2dSSagi Grimberg 	mr->pd = pd;
215954e7e48bSAriel Levkovich 	mr->dm = NULL;
216017cd3a2dSSagi Grimberg 	mr->uobject = NULL;
216117cd3a2dSSagi Grimberg 	atomic_inc(&pd->usecnt);
2162d4a85c30SSteve Wise 	mr->need_inval = false;
2163a0bc099aSMax Gurtovoy 	mr->type = mr_type;
21647c717d3aSMax Gurtovoy 	mr->sig_attrs = NULL;
216517cd3a2dSSagi Grimberg 
216613ef5539SLeon Romanovsky 	rdma_restrack_new(&mr->res, RDMA_RESTRACK_MR);
216713ef5539SLeon Romanovsky 	rdma_restrack_kadd(&mr->res);
2168622db5b6SChuck Lever out:
2169622db5b6SChuck Lever 	trace_mr_alloc(pd, mr_type, max_num_sg, mr);
217017cd3a2dSSagi Grimberg 	return mr;
217117cd3a2dSSagi Grimberg }
2172b64b74b1SGal Pressman EXPORT_SYMBOL(ib_alloc_mr);
217300f7ec36SSteve Wise 
217426bc7eaeSIsrael Rukshin /**
217526bc7eaeSIsrael Rukshin  * ib_alloc_mr_integrity() - Allocates an integrity memory region
217626bc7eaeSIsrael Rukshin  * @pd:                      protection domain associated with the region
217726bc7eaeSIsrael Rukshin  * @max_num_data_sg:         maximum data sg entries available for registration
217826bc7eaeSIsrael Rukshin  * @max_num_meta_sg:         maximum metadata sg entries available for
217926bc7eaeSIsrael Rukshin  *                           registration
218026bc7eaeSIsrael Rukshin  *
218126bc7eaeSIsrael Rukshin  * Notes:
218226bc7eaeSIsrael Rukshin  * Memory registration page/sg lists must not exceed max_num_sg,
218326bc7eaeSIsrael Rukshin  * also the integrity page/sg lists must not exceed max_num_meta_sg.
218426bc7eaeSIsrael Rukshin  *
218526bc7eaeSIsrael Rukshin  */
218626bc7eaeSIsrael Rukshin struct ib_mr *ib_alloc_mr_integrity(struct ib_pd *pd,
218726bc7eaeSIsrael Rukshin 				    u32 max_num_data_sg,
218826bc7eaeSIsrael Rukshin 				    u32 max_num_meta_sg)
218926bc7eaeSIsrael Rukshin {
219026bc7eaeSIsrael Rukshin 	struct ib_mr *mr;
21917c717d3aSMax Gurtovoy 	struct ib_sig_attrs *sig_attrs;
219226bc7eaeSIsrael Rukshin 
21932cdfcdd8SMax Gurtovoy 	if (!pd->device->ops.alloc_mr_integrity ||
2194622db5b6SChuck Lever 	    !pd->device->ops.map_mr_sg_pi) {
2195622db5b6SChuck Lever 		mr = ERR_PTR(-EOPNOTSUPP);
2196622db5b6SChuck Lever 		goto out;
2197622db5b6SChuck Lever 	}
219826bc7eaeSIsrael Rukshin 
2199622db5b6SChuck Lever 	if (!max_num_meta_sg) {
2200622db5b6SChuck Lever 		mr = ERR_PTR(-EINVAL);
2201622db5b6SChuck Lever 		goto out;
2202622db5b6SChuck Lever 	}
220326bc7eaeSIsrael Rukshin 
22047c717d3aSMax Gurtovoy 	sig_attrs = kzalloc(sizeof(struct ib_sig_attrs), GFP_KERNEL);
2205622db5b6SChuck Lever 	if (!sig_attrs) {
2206622db5b6SChuck Lever 		mr = ERR_PTR(-ENOMEM);
2207622db5b6SChuck Lever 		goto out;
2208622db5b6SChuck Lever 	}
22097c717d3aSMax Gurtovoy 
221026bc7eaeSIsrael Rukshin 	mr = pd->device->ops.alloc_mr_integrity(pd, max_num_data_sg,
221126bc7eaeSIsrael Rukshin 						max_num_meta_sg);
22127c717d3aSMax Gurtovoy 	if (IS_ERR(mr)) {
22137c717d3aSMax Gurtovoy 		kfree(sig_attrs);
2214622db5b6SChuck Lever 		goto out;
22157c717d3aSMax Gurtovoy 	}
221626bc7eaeSIsrael Rukshin 
221726bc7eaeSIsrael Rukshin 	mr->device = pd->device;
221826bc7eaeSIsrael Rukshin 	mr->pd = pd;
221926bc7eaeSIsrael Rukshin 	mr->dm = NULL;
222026bc7eaeSIsrael Rukshin 	mr->uobject = NULL;
222126bc7eaeSIsrael Rukshin 	atomic_inc(&pd->usecnt);
222226bc7eaeSIsrael Rukshin 	mr->need_inval = false;
222326bc7eaeSIsrael Rukshin 	mr->type = IB_MR_TYPE_INTEGRITY;
22247c717d3aSMax Gurtovoy 	mr->sig_attrs = sig_attrs;
222526bc7eaeSIsrael Rukshin 
222613ef5539SLeon Romanovsky 	rdma_restrack_new(&mr->res, RDMA_RESTRACK_MR);
222713ef5539SLeon Romanovsky 	rdma_restrack_kadd(&mr->res);
2228622db5b6SChuck Lever out:
2229622db5b6SChuck Lever 	trace_mr_integ_alloc(pd, max_num_data_sg, max_num_meta_sg, mr);
223026bc7eaeSIsrael Rukshin 	return mr;
223126bc7eaeSIsrael Rukshin }
223226bc7eaeSIsrael Rukshin EXPORT_SYMBOL(ib_alloc_mr_integrity);
223326bc7eaeSIsrael Rukshin 
22341da177e4SLinus Torvalds /* Multicast groups */
22351da177e4SLinus Torvalds 
223652363335SNoa Osherovich static bool is_valid_mcast_lid(struct ib_qp *qp, u16 lid)
223752363335SNoa Osherovich {
223852363335SNoa Osherovich 	struct ib_qp_init_attr init_attr = {};
223952363335SNoa Osherovich 	struct ib_qp_attr attr = {};
224052363335SNoa Osherovich 	int num_eth_ports = 0;
224152363335SNoa Osherovich 	int port;
224252363335SNoa Osherovich 
224352363335SNoa Osherovich 	/* If QP state >= init, it is assigned to a port and we can check this
224452363335SNoa Osherovich 	 * port only.
224552363335SNoa Osherovich 	 */
224652363335SNoa Osherovich 	if (!ib_query_qp(qp, &attr, IB_QP_STATE | IB_QP_PORT, &init_attr)) {
224752363335SNoa Osherovich 		if (attr.qp_state >= IB_QPS_INIT) {
2248e6f9bc34SAlex Estrin 			if (rdma_port_get_link_layer(qp->device, attr.port_num) !=
224952363335SNoa Osherovich 			    IB_LINK_LAYER_INFINIBAND)
225052363335SNoa Osherovich 				return true;
225152363335SNoa Osherovich 			goto lid_check;
225252363335SNoa Osherovich 		}
225352363335SNoa Osherovich 	}
225452363335SNoa Osherovich 
225552363335SNoa Osherovich 	/* Can't get a quick answer, iterate over all ports */
225652363335SNoa Osherovich 	for (port = 0; port < qp->device->phys_port_cnt; port++)
2257e6f9bc34SAlex Estrin 		if (rdma_port_get_link_layer(qp->device, port) !=
225852363335SNoa Osherovich 		    IB_LINK_LAYER_INFINIBAND)
225952363335SNoa Osherovich 			num_eth_ports++;
226052363335SNoa Osherovich 
226152363335SNoa Osherovich 	/* If we have at lease one Ethernet port, RoCE annex declares that
226252363335SNoa Osherovich 	 * multicast LID should be ignored. We can't tell at this step if the
226352363335SNoa Osherovich 	 * QP belongs to an IB or Ethernet port.
226452363335SNoa Osherovich 	 */
226552363335SNoa Osherovich 	if (num_eth_ports)
226652363335SNoa Osherovich 		return true;
226752363335SNoa Osherovich 
226852363335SNoa Osherovich 	/* If all the ports are IB, we can check according to IB spec. */
226952363335SNoa Osherovich lid_check:
227052363335SNoa Osherovich 	return !(lid < be16_to_cpu(IB_MULTICAST_LID_BASE) ||
227152363335SNoa Osherovich 		 lid == be16_to_cpu(IB_LID_PERMISSIVE));
227252363335SNoa Osherovich }
227352363335SNoa Osherovich 
22741da177e4SLinus Torvalds int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
22751da177e4SLinus Torvalds {
2276c3bccbfbSOr Gerlitz 	int ret;
2277c3bccbfbSOr Gerlitz 
22783023a1e9SKamal Heib 	if (!qp->device->ops.attach_mcast)
227987915bf8SLeon Romanovsky 		return -EOPNOTSUPP;
2280be1d325aSNoa Osherovich 
2281be1d325aSNoa Osherovich 	if (!rdma_is_multicast_addr((struct in6_addr *)gid->raw) ||
2282be1d325aSNoa Osherovich 	    qp->qp_type != IB_QPT_UD || !is_valid_mcast_lid(qp, lid))
22830c33aeedSJack Morgenstein 		return -EINVAL;
22840c33aeedSJack Morgenstein 
22853023a1e9SKamal Heib 	ret = qp->device->ops.attach_mcast(qp, gid, lid);
2286c3bccbfbSOr Gerlitz 	if (!ret)
2287c3bccbfbSOr Gerlitz 		atomic_inc(&qp->usecnt);
2288c3bccbfbSOr Gerlitz 	return ret;
22891da177e4SLinus Torvalds }
22901da177e4SLinus Torvalds EXPORT_SYMBOL(ib_attach_mcast);
22911da177e4SLinus Torvalds 
22921da177e4SLinus Torvalds int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
22931da177e4SLinus Torvalds {
2294c3bccbfbSOr Gerlitz 	int ret;
2295c3bccbfbSOr Gerlitz 
22963023a1e9SKamal Heib 	if (!qp->device->ops.detach_mcast)
229787915bf8SLeon Romanovsky 		return -EOPNOTSUPP;
2298be1d325aSNoa Osherovich 
2299be1d325aSNoa Osherovich 	if (!rdma_is_multicast_addr((struct in6_addr *)gid->raw) ||
2300be1d325aSNoa Osherovich 	    qp->qp_type != IB_QPT_UD || !is_valid_mcast_lid(qp, lid))
23010c33aeedSJack Morgenstein 		return -EINVAL;
23020c33aeedSJack Morgenstein 
23033023a1e9SKamal Heib 	ret = qp->device->ops.detach_mcast(qp, gid, lid);
2304c3bccbfbSOr Gerlitz 	if (!ret)
2305c3bccbfbSOr Gerlitz 		atomic_dec(&qp->usecnt);
2306c3bccbfbSOr Gerlitz 	return ret;
23071da177e4SLinus Torvalds }
23081da177e4SLinus Torvalds EXPORT_SYMBOL(ib_detach_mcast);
230959991f94SSean Hefty 
2310b73efcb2SMaor Gottlieb /**
2311b73efcb2SMaor Gottlieb  * ib_alloc_xrcd_user - Allocates an XRC domain.
2312b73efcb2SMaor Gottlieb  * @device: The device on which to allocate the XRC domain.
2313b73efcb2SMaor Gottlieb  * @inode: inode to connect XRCD
2314b73efcb2SMaor Gottlieb  * @udata: Valid user data or NULL for kernel object
2315b73efcb2SMaor Gottlieb  */
2316b73efcb2SMaor Gottlieb struct ib_xrcd *ib_alloc_xrcd_user(struct ib_device *device,
2317b73efcb2SMaor Gottlieb 				   struct inode *inode, struct ib_udata *udata)
231859991f94SSean Hefty {
231959991f94SSean Hefty 	struct ib_xrcd *xrcd;
232028ad5f65SLeon Romanovsky 	int ret;
232159991f94SSean Hefty 
23223023a1e9SKamal Heib 	if (!device->ops.alloc_xrcd)
232387915bf8SLeon Romanovsky 		return ERR_PTR(-EOPNOTSUPP);
232459991f94SSean Hefty 
232528ad5f65SLeon Romanovsky 	xrcd = rdma_zalloc_drv_obj(device, ib_xrcd);
232628ad5f65SLeon Romanovsky 	if (!xrcd)
232728ad5f65SLeon Romanovsky 		return ERR_PTR(-ENOMEM);
232828ad5f65SLeon Romanovsky 
232959991f94SSean Hefty 	xrcd->device = device;
2330b73efcb2SMaor Gottlieb 	xrcd->inode = inode;
233159991f94SSean Hefty 	atomic_set(&xrcd->usecnt, 0);
23326f3ca6f4SMaor Gottlieb 	init_rwsem(&xrcd->tgt_qps_rwsem);
23336f3ca6f4SMaor Gottlieb 	xa_init(&xrcd->tgt_qps);
233459991f94SSean Hefty 
233528ad5f65SLeon Romanovsky 	ret = device->ops.alloc_xrcd(xrcd, udata);
233628ad5f65SLeon Romanovsky 	if (ret)
233728ad5f65SLeon Romanovsky 		goto err;
233859991f94SSean Hefty 	return xrcd;
233928ad5f65SLeon Romanovsky err:
234028ad5f65SLeon Romanovsky 	kfree(xrcd);
234128ad5f65SLeon Romanovsky 	return ERR_PTR(ret);
234259991f94SSean Hefty }
2343b73efcb2SMaor Gottlieb EXPORT_SYMBOL(ib_alloc_xrcd_user);
234459991f94SSean Hefty 
2345b73efcb2SMaor Gottlieb /**
2346b73efcb2SMaor Gottlieb  * ib_dealloc_xrcd_user - Deallocates an XRC domain.
2347b73efcb2SMaor Gottlieb  * @xrcd: The XRC domain to deallocate.
2348b73efcb2SMaor Gottlieb  * @udata: Valid user data or NULL for kernel object
2349b73efcb2SMaor Gottlieb  */
2350b73efcb2SMaor Gottlieb int ib_dealloc_xrcd_user(struct ib_xrcd *xrcd, struct ib_udata *udata)
235159991f94SSean Hefty {
2352d0c45c85SLeon Romanovsky 	int ret;
2353d0c45c85SLeon Romanovsky 
235459991f94SSean Hefty 	if (atomic_read(&xrcd->usecnt))
235559991f94SSean Hefty 		return -EBUSY;
235659991f94SSean Hefty 
23576f3ca6f4SMaor Gottlieb 	WARN_ON(!xa_empty(&xrcd->tgt_qps));
2358d0c45c85SLeon Romanovsky 	ret = xrcd->device->ops.dealloc_xrcd(xrcd, udata);
2359d0c45c85SLeon Romanovsky 	if (ret)
2360d0c45c85SLeon Romanovsky 		return ret;
236128ad5f65SLeon Romanovsky 	kfree(xrcd);
2362d0c45c85SLeon Romanovsky 	return ret;
236359991f94SSean Hefty }
2364b73efcb2SMaor Gottlieb EXPORT_SYMBOL(ib_dealloc_xrcd_user);
2365319a441dSHadar Hen Zion 
23665fd251c8SYishai Hadas /**
23675fd251c8SYishai Hadas  * ib_create_wq - Creates a WQ associated with the specified protection
23685fd251c8SYishai Hadas  * domain.
23695fd251c8SYishai Hadas  * @pd: The protection domain associated with the WQ.
23701f58621eSRandy Dunlap  * @wq_attr: A list of initial attributes required to create the
23715fd251c8SYishai Hadas  * WQ. If WQ creation succeeds, then the attributes are updated to
23725fd251c8SYishai Hadas  * the actual capabilities of the created WQ.
23735fd251c8SYishai Hadas  *
23741f58621eSRandy Dunlap  * wq_attr->max_wr and wq_attr->max_sge determine
23755fd251c8SYishai Hadas  * the requested size of the WQ, and set to the actual values allocated
23765fd251c8SYishai Hadas  * on return.
23775fd251c8SYishai Hadas  * If ib_create_wq() succeeds, then max_wr and max_sge will always be
23785fd251c8SYishai Hadas  * at least as large as the requested values.
23795fd251c8SYishai Hadas  */
23805fd251c8SYishai Hadas struct ib_wq *ib_create_wq(struct ib_pd *pd,
23815fd251c8SYishai Hadas 			   struct ib_wq_init_attr *wq_attr)
23825fd251c8SYishai Hadas {
23835fd251c8SYishai Hadas 	struct ib_wq *wq;
23845fd251c8SYishai Hadas 
23853023a1e9SKamal Heib 	if (!pd->device->ops.create_wq)
238687915bf8SLeon Romanovsky 		return ERR_PTR(-EOPNOTSUPP);
23875fd251c8SYishai Hadas 
23883023a1e9SKamal Heib 	wq = pd->device->ops.create_wq(pd, wq_attr, NULL);
23895fd251c8SYishai Hadas 	if (!IS_ERR(wq)) {
23905fd251c8SYishai Hadas 		wq->event_handler = wq_attr->event_handler;
23915fd251c8SYishai Hadas 		wq->wq_context = wq_attr->wq_context;
23925fd251c8SYishai Hadas 		wq->wq_type = wq_attr->wq_type;
23935fd251c8SYishai Hadas 		wq->cq = wq_attr->cq;
23945fd251c8SYishai Hadas 		wq->device = pd->device;
23955fd251c8SYishai Hadas 		wq->pd = pd;
23965fd251c8SYishai Hadas 		wq->uobject = NULL;
23975fd251c8SYishai Hadas 		atomic_inc(&pd->usecnt);
23985fd251c8SYishai Hadas 		atomic_inc(&wq_attr->cq->usecnt);
23995fd251c8SYishai Hadas 		atomic_set(&wq->usecnt, 0);
24005fd251c8SYishai Hadas 	}
24015fd251c8SYishai Hadas 	return wq;
24025fd251c8SYishai Hadas }
24035fd251c8SYishai Hadas EXPORT_SYMBOL(ib_create_wq);
24045fd251c8SYishai Hadas 
24055fd251c8SYishai Hadas /**
2406add53535SLeon Romanovsky  * ib_destroy_wq_user - Destroys the specified user WQ.
24075fd251c8SYishai Hadas  * @wq: The WQ to destroy.
2408c4367a26SShamir Rabinovitch  * @udata: Valid user data
24095fd251c8SYishai Hadas  */
2410add53535SLeon Romanovsky int ib_destroy_wq_user(struct ib_wq *wq, struct ib_udata *udata)
24115fd251c8SYishai Hadas {
24125fd251c8SYishai Hadas 	struct ib_cq *cq = wq->cq;
24135fd251c8SYishai Hadas 	struct ib_pd *pd = wq->pd;
2414add53535SLeon Romanovsky 	int ret;
24155fd251c8SYishai Hadas 
24165fd251c8SYishai Hadas 	if (atomic_read(&wq->usecnt))
24175fd251c8SYishai Hadas 		return -EBUSY;
24185fd251c8SYishai Hadas 
2419add53535SLeon Romanovsky 	ret = wq->device->ops.destroy_wq(wq, udata);
2420add53535SLeon Romanovsky 	if (ret)
2421add53535SLeon Romanovsky 		return ret;
2422add53535SLeon Romanovsky 
24235fd251c8SYishai Hadas 	atomic_dec(&pd->usecnt);
24245fd251c8SYishai Hadas 	atomic_dec(&cq->usecnt);
2425add53535SLeon Romanovsky 	return ret;
24265fd251c8SYishai Hadas }
2427add53535SLeon Romanovsky EXPORT_SYMBOL(ib_destroy_wq_user);
24285fd251c8SYishai Hadas 
24295fd251c8SYishai Hadas /**
24305fd251c8SYishai Hadas  * ib_modify_wq - Modifies the specified WQ.
24315fd251c8SYishai Hadas  * @wq: The WQ to modify.
24325fd251c8SYishai Hadas  * @wq_attr: On input, specifies the WQ attributes to modify.
24335fd251c8SYishai Hadas  * @wq_attr_mask: A bit-mask used to specify which attributes of the WQ
24345fd251c8SYishai Hadas  *   are being modified.
24355fd251c8SYishai Hadas  * On output, the current values of selected WQ attributes are returned.
24365fd251c8SYishai Hadas  */
24375fd251c8SYishai Hadas int ib_modify_wq(struct ib_wq *wq, struct ib_wq_attr *wq_attr,
24385fd251c8SYishai Hadas 		 u32 wq_attr_mask)
24395fd251c8SYishai Hadas {
24405fd251c8SYishai Hadas 	int err;
24415fd251c8SYishai Hadas 
24423023a1e9SKamal Heib 	if (!wq->device->ops.modify_wq)
244387915bf8SLeon Romanovsky 		return -EOPNOTSUPP;
24445fd251c8SYishai Hadas 
24453023a1e9SKamal Heib 	err = wq->device->ops.modify_wq(wq, wq_attr, wq_attr_mask, NULL);
24465fd251c8SYishai Hadas 	return err;
24475fd251c8SYishai Hadas }
24485fd251c8SYishai Hadas EXPORT_SYMBOL(ib_modify_wq);
24495fd251c8SYishai Hadas 
24501b01d335SSagi Grimberg int ib_check_mr_status(struct ib_mr *mr, u32 check_mask,
24511b01d335SSagi Grimberg 		       struct ib_mr_status *mr_status)
24521b01d335SSagi Grimberg {
24533023a1e9SKamal Heib 	if (!mr->device->ops.check_mr_status)
24543023a1e9SKamal Heib 		return -EOPNOTSUPP;
24553023a1e9SKamal Heib 
24563023a1e9SKamal Heib 	return mr->device->ops.check_mr_status(mr, check_mask, mr_status);
24571b01d335SSagi Grimberg }
24581b01d335SSagi Grimberg EXPORT_SYMBOL(ib_check_mr_status);
24594c67e2bfSSagi Grimberg 
246050174a7fSEli Cohen int ib_set_vf_link_state(struct ib_device *device, int vf, u8 port,
246150174a7fSEli Cohen 			 int state)
246250174a7fSEli Cohen {
24633023a1e9SKamal Heib 	if (!device->ops.set_vf_link_state)
246487915bf8SLeon Romanovsky 		return -EOPNOTSUPP;
246550174a7fSEli Cohen 
24663023a1e9SKamal Heib 	return device->ops.set_vf_link_state(device, vf, port, state);
246750174a7fSEli Cohen }
246850174a7fSEli Cohen EXPORT_SYMBOL(ib_set_vf_link_state);
246950174a7fSEli Cohen 
247050174a7fSEli Cohen int ib_get_vf_config(struct ib_device *device, int vf, u8 port,
247150174a7fSEli Cohen 		     struct ifla_vf_info *info)
247250174a7fSEli Cohen {
24733023a1e9SKamal Heib 	if (!device->ops.get_vf_config)
247487915bf8SLeon Romanovsky 		return -EOPNOTSUPP;
247550174a7fSEli Cohen 
24763023a1e9SKamal Heib 	return device->ops.get_vf_config(device, vf, port, info);
247750174a7fSEli Cohen }
247850174a7fSEli Cohen EXPORT_SYMBOL(ib_get_vf_config);
247950174a7fSEli Cohen 
248050174a7fSEli Cohen int ib_get_vf_stats(struct ib_device *device, int vf, u8 port,
248150174a7fSEli Cohen 		    struct ifla_vf_stats *stats)
248250174a7fSEli Cohen {
24833023a1e9SKamal Heib 	if (!device->ops.get_vf_stats)
248487915bf8SLeon Romanovsky 		return -EOPNOTSUPP;
248550174a7fSEli Cohen 
24863023a1e9SKamal Heib 	return device->ops.get_vf_stats(device, vf, port, stats);
248750174a7fSEli Cohen }
248850174a7fSEli Cohen EXPORT_SYMBOL(ib_get_vf_stats);
248950174a7fSEli Cohen 
249050174a7fSEli Cohen int ib_set_vf_guid(struct ib_device *device, int vf, u8 port, u64 guid,
249150174a7fSEli Cohen 		   int type)
249250174a7fSEli Cohen {
24933023a1e9SKamal Heib 	if (!device->ops.set_vf_guid)
249487915bf8SLeon Romanovsky 		return -EOPNOTSUPP;
249550174a7fSEli Cohen 
24963023a1e9SKamal Heib 	return device->ops.set_vf_guid(device, vf, port, guid, type);
249750174a7fSEli Cohen }
249850174a7fSEli Cohen EXPORT_SYMBOL(ib_set_vf_guid);
249950174a7fSEli Cohen 
2500bfcb3c5dSDanit Goldberg int ib_get_vf_guid(struct ib_device *device, int vf, u8 port,
2501bfcb3c5dSDanit Goldberg 		   struct ifla_vf_guid *node_guid,
2502bfcb3c5dSDanit Goldberg 		   struct ifla_vf_guid *port_guid)
2503bfcb3c5dSDanit Goldberg {
2504bfcb3c5dSDanit Goldberg 	if (!device->ops.get_vf_guid)
2505bfcb3c5dSDanit Goldberg 		return -EOPNOTSUPP;
2506bfcb3c5dSDanit Goldberg 
2507bfcb3c5dSDanit Goldberg 	return device->ops.get_vf_guid(device, vf, port, node_guid, port_guid);
2508bfcb3c5dSDanit Goldberg }
2509bfcb3c5dSDanit Goldberg EXPORT_SYMBOL(ib_get_vf_guid);
25104c67e2bfSSagi Grimberg /**
25112cdfcdd8SMax Gurtovoy  * ib_map_mr_sg_pi() - Map the dma mapped SG lists for PI (protection
25122cdfcdd8SMax Gurtovoy  *     information) and set an appropriate memory region for registration.
25132cdfcdd8SMax Gurtovoy  * @mr:             memory region
25142cdfcdd8SMax Gurtovoy  * @data_sg:        dma mapped scatterlist for data
25152cdfcdd8SMax Gurtovoy  * @data_sg_nents:  number of entries in data_sg
25162cdfcdd8SMax Gurtovoy  * @data_sg_offset: offset in bytes into data_sg
25172cdfcdd8SMax Gurtovoy  * @meta_sg:        dma mapped scatterlist for metadata
25182cdfcdd8SMax Gurtovoy  * @meta_sg_nents:  number of entries in meta_sg
25192cdfcdd8SMax Gurtovoy  * @meta_sg_offset: offset in bytes into meta_sg
25202cdfcdd8SMax Gurtovoy  * @page_size:      page vector desired page size
25212cdfcdd8SMax Gurtovoy  *
25222cdfcdd8SMax Gurtovoy  * Constraints:
25232cdfcdd8SMax Gurtovoy  * - The MR must be allocated with type IB_MR_TYPE_INTEGRITY.
25242cdfcdd8SMax Gurtovoy  *
25252cdfcdd8SMax Gurtovoy  * Return: 0 on success.
25262cdfcdd8SMax Gurtovoy  *
25272cdfcdd8SMax Gurtovoy  * After this completes successfully, the  memory region
25282cdfcdd8SMax Gurtovoy  * is ready for registration.
25292cdfcdd8SMax Gurtovoy  */
25302cdfcdd8SMax Gurtovoy int ib_map_mr_sg_pi(struct ib_mr *mr, struct scatterlist *data_sg,
25312cdfcdd8SMax Gurtovoy 		    int data_sg_nents, unsigned int *data_sg_offset,
25322cdfcdd8SMax Gurtovoy 		    struct scatterlist *meta_sg, int meta_sg_nents,
25332cdfcdd8SMax Gurtovoy 		    unsigned int *meta_sg_offset, unsigned int page_size)
25342cdfcdd8SMax Gurtovoy {
25352cdfcdd8SMax Gurtovoy 	if (unlikely(!mr->device->ops.map_mr_sg_pi ||
25362cdfcdd8SMax Gurtovoy 		     WARN_ON_ONCE(mr->type != IB_MR_TYPE_INTEGRITY)))
25372cdfcdd8SMax Gurtovoy 		return -EOPNOTSUPP;
25382cdfcdd8SMax Gurtovoy 
25392cdfcdd8SMax Gurtovoy 	mr->page_size = page_size;
25402cdfcdd8SMax Gurtovoy 
25412cdfcdd8SMax Gurtovoy 	return mr->device->ops.map_mr_sg_pi(mr, data_sg, data_sg_nents,
25422cdfcdd8SMax Gurtovoy 					    data_sg_offset, meta_sg,
25432cdfcdd8SMax Gurtovoy 					    meta_sg_nents, meta_sg_offset);
25442cdfcdd8SMax Gurtovoy }
25452cdfcdd8SMax Gurtovoy EXPORT_SYMBOL(ib_map_mr_sg_pi);
25462cdfcdd8SMax Gurtovoy 
25472cdfcdd8SMax Gurtovoy /**
25484c67e2bfSSagi Grimberg  * ib_map_mr_sg() - Map the largest prefix of a dma mapped SG list
25494c67e2bfSSagi Grimberg  *     and set it the memory region.
25504c67e2bfSSagi Grimberg  * @mr:            memory region
25514c67e2bfSSagi Grimberg  * @sg:            dma mapped scatterlist
25524c67e2bfSSagi Grimberg  * @sg_nents:      number of entries in sg
2553ff2ba993SChristoph Hellwig  * @sg_offset:     offset in bytes into sg
25544c67e2bfSSagi Grimberg  * @page_size:     page vector desired page size
25554c67e2bfSSagi Grimberg  *
25564c67e2bfSSagi Grimberg  * Constraints:
2557255e636dSMauro Carvalho Chehab  *
25584c67e2bfSSagi Grimberg  * - The first sg element is allowed to have an offset.
255952746129SBart Van Assche  * - Each sg element must either be aligned to page_size or virtually
256052746129SBart Van Assche  *   contiguous to the previous element. In case an sg element has a
256152746129SBart Van Assche  *   non-contiguous offset, the mapping prefix will not include it.
25624c67e2bfSSagi Grimberg  * - The last sg element is allowed to have length less than page_size.
25634c67e2bfSSagi Grimberg  * - If sg_nents total byte length exceeds the mr max_num_sge * page_size
25644c67e2bfSSagi Grimberg  *   then only max_num_sg entries will be mapped.
256552746129SBart Van Assche  * - If the MR was allocated with type IB_MR_TYPE_SG_GAPS, none of these
2566f5aa9159SSagi Grimberg  *   constraints holds and the page_size argument is ignored.
25674c67e2bfSSagi Grimberg  *
25684c67e2bfSSagi Grimberg  * Returns the number of sg elements that were mapped to the memory region.
25694c67e2bfSSagi Grimberg  *
25704c67e2bfSSagi Grimberg  * After this completes successfully, the  memory region
25714c67e2bfSSagi Grimberg  * is ready for registration.
25724c67e2bfSSagi Grimberg  */
2573ff2ba993SChristoph Hellwig int ib_map_mr_sg(struct ib_mr *mr, struct scatterlist *sg, int sg_nents,
25749aa8b321SBart Van Assche 		 unsigned int *sg_offset, unsigned int page_size)
25754c67e2bfSSagi Grimberg {
25763023a1e9SKamal Heib 	if (unlikely(!mr->device->ops.map_mr_sg))
257787915bf8SLeon Romanovsky 		return -EOPNOTSUPP;
25784c67e2bfSSagi Grimberg 
25794c67e2bfSSagi Grimberg 	mr->page_size = page_size;
25804c67e2bfSSagi Grimberg 
25813023a1e9SKamal Heib 	return mr->device->ops.map_mr_sg(mr, sg, sg_nents, sg_offset);
25824c67e2bfSSagi Grimberg }
25834c67e2bfSSagi Grimberg EXPORT_SYMBOL(ib_map_mr_sg);
25844c67e2bfSSagi Grimberg 
25854c67e2bfSSagi Grimberg /**
25864c67e2bfSSagi Grimberg  * ib_sg_to_pages() - Convert the largest prefix of a sg list
25874c67e2bfSSagi Grimberg  *     to a page vector
25884c67e2bfSSagi Grimberg  * @mr:            memory region
25894c67e2bfSSagi Grimberg  * @sgl:           dma mapped scatterlist
25904c67e2bfSSagi Grimberg  * @sg_nents:      number of entries in sg
2591255e636dSMauro Carvalho Chehab  * @sg_offset_p:   ==== =======================================================
2592255e636dSMauro Carvalho Chehab  *                 IN   start offset in bytes into sg
2593255e636dSMauro Carvalho Chehab  *                 OUT  offset in bytes for element n of the sg of the first
25949aa8b321SBart Van Assche  *                      byte that has not been processed where n is the return
25959aa8b321SBart Van Assche  *                      value of this function.
2596255e636dSMauro Carvalho Chehab  *                 ==== =======================================================
25974c67e2bfSSagi Grimberg  * @set_page:      driver page assignment function pointer
25984c67e2bfSSagi Grimberg  *
25998f5ba10eSBart Van Assche  * Core service helper for drivers to convert the largest
26004c67e2bfSSagi Grimberg  * prefix of given sg list to a page vector. The sg list
26014c67e2bfSSagi Grimberg  * prefix converted is the prefix that meet the requirements
26024c67e2bfSSagi Grimberg  * of ib_map_mr_sg.
26034c67e2bfSSagi Grimberg  *
26044c67e2bfSSagi Grimberg  * Returns the number of sg elements that were assigned to
26054c67e2bfSSagi Grimberg  * a page vector.
26064c67e2bfSSagi Grimberg  */
2607ff2ba993SChristoph Hellwig int ib_sg_to_pages(struct ib_mr *mr, struct scatterlist *sgl, int sg_nents,
26089aa8b321SBart Van Assche 		unsigned int *sg_offset_p, int (*set_page)(struct ib_mr *, u64))
26094c67e2bfSSagi Grimberg {
26104c67e2bfSSagi Grimberg 	struct scatterlist *sg;
2611b6aeb980SBart Van Assche 	u64 last_end_dma_addr = 0;
26129aa8b321SBart Van Assche 	unsigned int sg_offset = sg_offset_p ? *sg_offset_p : 0;
26134c67e2bfSSagi Grimberg 	unsigned int last_page_off = 0;
26144c67e2bfSSagi Grimberg 	u64 page_mask = ~((u64)mr->page_size - 1);
26158f5ba10eSBart Van Assche 	int i, ret;
26164c67e2bfSSagi Grimberg 
26179aa8b321SBart Van Assche 	if (unlikely(sg_nents <= 0 || sg_offset > sg_dma_len(&sgl[0])))
26189aa8b321SBart Van Assche 		return -EINVAL;
26199aa8b321SBart Van Assche 
2620ff2ba993SChristoph Hellwig 	mr->iova = sg_dma_address(&sgl[0]) + sg_offset;
26214c67e2bfSSagi Grimberg 	mr->length = 0;
26224c67e2bfSSagi Grimberg 
26234c67e2bfSSagi Grimberg 	for_each_sg(sgl, sg, sg_nents, i) {
2624ff2ba993SChristoph Hellwig 		u64 dma_addr = sg_dma_address(sg) + sg_offset;
26259aa8b321SBart Van Assche 		u64 prev_addr = dma_addr;
2626ff2ba993SChristoph Hellwig 		unsigned int dma_len = sg_dma_len(sg) - sg_offset;
26274c67e2bfSSagi Grimberg 		u64 end_dma_addr = dma_addr + dma_len;
26284c67e2bfSSagi Grimberg 		u64 page_addr = dma_addr & page_mask;
26294c67e2bfSSagi Grimberg 
26308f5ba10eSBart Van Assche 		/*
26318f5ba10eSBart Van Assche 		 * For the second and later elements, check whether either the
26328f5ba10eSBart Van Assche 		 * end of element i-1 or the start of element i is not aligned
26338f5ba10eSBart Van Assche 		 * on a page boundary.
26348f5ba10eSBart Van Assche 		 */
26358f5ba10eSBart Van Assche 		if (i && (last_page_off != 0 || page_addr != dma_addr)) {
26368f5ba10eSBart Van Assche 			/* Stop mapping if there is a gap. */
26378f5ba10eSBart Van Assche 			if (last_end_dma_addr != dma_addr)
26388f5ba10eSBart Van Assche 				break;
26394c67e2bfSSagi Grimberg 
26408f5ba10eSBart Van Assche 			/*
26418f5ba10eSBart Van Assche 			 * Coalesce this element with the last. If it is small
26428f5ba10eSBart Van Assche 			 * enough just update mr->length. Otherwise start
26438f5ba10eSBart Van Assche 			 * mapping from the next page.
26448f5ba10eSBart Van Assche 			 */
26458f5ba10eSBart Van Assche 			goto next_page;
26464c67e2bfSSagi Grimberg 		}
26474c67e2bfSSagi Grimberg 
26484c67e2bfSSagi Grimberg 		do {
26498f5ba10eSBart Van Assche 			ret = set_page(mr, page_addr);
26509aa8b321SBart Van Assche 			if (unlikely(ret < 0)) {
26519aa8b321SBart Van Assche 				sg_offset = prev_addr - sg_dma_address(sg);
26529aa8b321SBart Van Assche 				mr->length += prev_addr - dma_addr;
26539aa8b321SBart Van Assche 				if (sg_offset_p)
26549aa8b321SBart Van Assche 					*sg_offset_p = sg_offset;
26559aa8b321SBart Van Assche 				return i || sg_offset ? i : ret;
26569aa8b321SBart Van Assche 			}
26579aa8b321SBart Van Assche 			prev_addr = page_addr;
26588f5ba10eSBart Van Assche next_page:
26594c67e2bfSSagi Grimberg 			page_addr += mr->page_size;
26604c67e2bfSSagi Grimberg 		} while (page_addr < end_dma_addr);
26614c67e2bfSSagi Grimberg 
26624c67e2bfSSagi Grimberg 		mr->length += dma_len;
26634c67e2bfSSagi Grimberg 		last_end_dma_addr = end_dma_addr;
26644c67e2bfSSagi Grimberg 		last_page_off = end_dma_addr & ~page_mask;
2665ff2ba993SChristoph Hellwig 
2666ff2ba993SChristoph Hellwig 		sg_offset = 0;
26674c67e2bfSSagi Grimberg 	}
26684c67e2bfSSagi Grimberg 
26699aa8b321SBart Van Assche 	if (sg_offset_p)
26709aa8b321SBart Van Assche 		*sg_offset_p = 0;
26714c67e2bfSSagi Grimberg 	return i;
26724c67e2bfSSagi Grimberg }
26734c67e2bfSSagi Grimberg EXPORT_SYMBOL(ib_sg_to_pages);
2674765d6774SSteve Wise 
2675765d6774SSteve Wise struct ib_drain_cqe {
2676765d6774SSteve Wise 	struct ib_cqe cqe;
2677765d6774SSteve Wise 	struct completion done;
2678765d6774SSteve Wise };
2679765d6774SSteve Wise 
2680765d6774SSteve Wise static void ib_drain_qp_done(struct ib_cq *cq, struct ib_wc *wc)
2681765d6774SSteve Wise {
2682765d6774SSteve Wise 	struct ib_drain_cqe *cqe = container_of(wc->wr_cqe, struct ib_drain_cqe,
2683765d6774SSteve Wise 						cqe);
2684765d6774SSteve Wise 
2685765d6774SSteve Wise 	complete(&cqe->done);
2686765d6774SSteve Wise }
2687765d6774SSteve Wise 
2688765d6774SSteve Wise /*
2689765d6774SSteve Wise  * Post a WR and block until its completion is reaped for the SQ.
2690765d6774SSteve Wise  */
2691765d6774SSteve Wise static void __ib_drain_sq(struct ib_qp *qp)
2692765d6774SSteve Wise {
2693f039f44fSBart Van Assche 	struct ib_cq *cq = qp->send_cq;
2694765d6774SSteve Wise 	struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
2695765d6774SSteve Wise 	struct ib_drain_cqe sdrain;
2696a1ae7d03SBart Van Assche 	struct ib_rdma_wr swr = {
2697a1ae7d03SBart Van Assche 		.wr = {
26986ee68773SAndrew Morton 			.next = NULL,
26996ee68773SAndrew Morton 			{ .wr_cqe	= &sdrain.cqe, },
2700a1ae7d03SBart Van Assche 			.opcode	= IB_WR_RDMA_WRITE,
2701a1ae7d03SBart Van Assche 		},
2702a1ae7d03SBart Van Assche 	};
2703765d6774SSteve Wise 	int ret;
2704765d6774SSteve Wise 
2705765d6774SSteve Wise 	ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
2706765d6774SSteve Wise 	if (ret) {
2707765d6774SSteve Wise 		WARN_ONCE(ret, "failed to drain send queue: %d\n", ret);
2708765d6774SSteve Wise 		return;
2709765d6774SSteve Wise 	}
2710765d6774SSteve Wise 
2711aaebd377SMax Gurtovoy 	sdrain.cqe.done = ib_drain_qp_done;
2712aaebd377SMax Gurtovoy 	init_completion(&sdrain.done);
2713aaebd377SMax Gurtovoy 
27141fec77bfSBart Van Assche 	ret = ib_post_send(qp, &swr.wr, NULL);
2715765d6774SSteve Wise 	if (ret) {
2716765d6774SSteve Wise 		WARN_ONCE(ret, "failed to drain send queue: %d\n", ret);
2717765d6774SSteve Wise 		return;
2718765d6774SSteve Wise 	}
2719765d6774SSteve Wise 
2720f039f44fSBart Van Assche 	if (cq->poll_ctx == IB_POLL_DIRECT)
2721f039f44fSBart Van Assche 		while (wait_for_completion_timeout(&sdrain.done, HZ / 10) <= 0)
2722f039f44fSBart Van Assche 			ib_process_cq_direct(cq, -1);
2723f039f44fSBart Van Assche 	else
2724765d6774SSteve Wise 		wait_for_completion(&sdrain.done);
2725765d6774SSteve Wise }
2726765d6774SSteve Wise 
2727765d6774SSteve Wise /*
2728765d6774SSteve Wise  * Post a WR and block until its completion is reaped for the RQ.
2729765d6774SSteve Wise  */
2730765d6774SSteve Wise static void __ib_drain_rq(struct ib_qp *qp)
2731765d6774SSteve Wise {
2732f039f44fSBart Van Assche 	struct ib_cq *cq = qp->recv_cq;
2733765d6774SSteve Wise 	struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
2734765d6774SSteve Wise 	struct ib_drain_cqe rdrain;
27351fec77bfSBart Van Assche 	struct ib_recv_wr rwr = {};
2736765d6774SSteve Wise 	int ret;
2737765d6774SSteve Wise 
2738765d6774SSteve Wise 	ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
2739765d6774SSteve Wise 	if (ret) {
2740765d6774SSteve Wise 		WARN_ONCE(ret, "failed to drain recv queue: %d\n", ret);
2741765d6774SSteve Wise 		return;
2742765d6774SSteve Wise 	}
2743765d6774SSteve Wise 
2744aaebd377SMax Gurtovoy 	rwr.wr_cqe = &rdrain.cqe;
2745aaebd377SMax Gurtovoy 	rdrain.cqe.done = ib_drain_qp_done;
2746aaebd377SMax Gurtovoy 	init_completion(&rdrain.done);
2747aaebd377SMax Gurtovoy 
27481fec77bfSBart Van Assche 	ret = ib_post_recv(qp, &rwr, NULL);
2749765d6774SSteve Wise 	if (ret) {
2750765d6774SSteve Wise 		WARN_ONCE(ret, "failed to drain recv queue: %d\n", ret);
2751765d6774SSteve Wise 		return;
2752765d6774SSteve Wise 	}
2753765d6774SSteve Wise 
2754f039f44fSBart Van Assche 	if (cq->poll_ctx == IB_POLL_DIRECT)
2755f039f44fSBart Van Assche 		while (wait_for_completion_timeout(&rdrain.done, HZ / 10) <= 0)
2756f039f44fSBart Van Assche 			ib_process_cq_direct(cq, -1);
2757f039f44fSBart Van Assche 	else
2758765d6774SSteve Wise 		wait_for_completion(&rdrain.done);
2759765d6774SSteve Wise }
2760765d6774SSteve Wise 
2761765d6774SSteve Wise /**
2762765d6774SSteve Wise  * ib_drain_sq() - Block until all SQ CQEs have been consumed by the
2763765d6774SSteve Wise  *		   application.
2764765d6774SSteve Wise  * @qp:            queue pair to drain
2765765d6774SSteve Wise  *
2766765d6774SSteve Wise  * If the device has a provider-specific drain function, then
2767765d6774SSteve Wise  * call that.  Otherwise call the generic drain function
2768765d6774SSteve Wise  * __ib_drain_sq().
2769765d6774SSteve Wise  *
2770765d6774SSteve Wise  * The caller must:
2771765d6774SSteve Wise  *
2772765d6774SSteve Wise  * ensure there is room in the CQ and SQ for the drain work request and
2773765d6774SSteve Wise  * completion.
2774765d6774SSteve Wise  *
2775f039f44fSBart Van Assche  * allocate the CQ using ib_alloc_cq().
2776765d6774SSteve Wise  *
2777765d6774SSteve Wise  * ensure that there are no other contexts that are posting WRs concurrently.
2778765d6774SSteve Wise  * Otherwise the drain is not guaranteed.
2779765d6774SSteve Wise  */
2780765d6774SSteve Wise void ib_drain_sq(struct ib_qp *qp)
2781765d6774SSteve Wise {
27823023a1e9SKamal Heib 	if (qp->device->ops.drain_sq)
27833023a1e9SKamal Heib 		qp->device->ops.drain_sq(qp);
2784765d6774SSteve Wise 	else
2785765d6774SSteve Wise 		__ib_drain_sq(qp);
27863e5901cbSChuck Lever 	trace_cq_drain_complete(qp->send_cq);
2787765d6774SSteve Wise }
2788765d6774SSteve Wise EXPORT_SYMBOL(ib_drain_sq);
2789765d6774SSteve Wise 
2790765d6774SSteve Wise /**
2791765d6774SSteve Wise  * ib_drain_rq() - Block until all RQ CQEs have been consumed by the
2792765d6774SSteve Wise  *		   application.
2793765d6774SSteve Wise  * @qp:            queue pair to drain
2794765d6774SSteve Wise  *
2795765d6774SSteve Wise  * If the device has a provider-specific drain function, then
2796765d6774SSteve Wise  * call that.  Otherwise call the generic drain function
2797765d6774SSteve Wise  * __ib_drain_rq().
2798765d6774SSteve Wise  *
2799765d6774SSteve Wise  * The caller must:
2800765d6774SSteve Wise  *
2801765d6774SSteve Wise  * ensure there is room in the CQ and RQ for the drain work request and
2802765d6774SSteve Wise  * completion.
2803765d6774SSteve Wise  *
2804f039f44fSBart Van Assche  * allocate the CQ using ib_alloc_cq().
2805765d6774SSteve Wise  *
2806765d6774SSteve Wise  * ensure that there are no other contexts that are posting WRs concurrently.
2807765d6774SSteve Wise  * Otherwise the drain is not guaranteed.
2808765d6774SSteve Wise  */
2809765d6774SSteve Wise void ib_drain_rq(struct ib_qp *qp)
2810765d6774SSteve Wise {
28113023a1e9SKamal Heib 	if (qp->device->ops.drain_rq)
28123023a1e9SKamal Heib 		qp->device->ops.drain_rq(qp);
2813765d6774SSteve Wise 	else
2814765d6774SSteve Wise 		__ib_drain_rq(qp);
28153e5901cbSChuck Lever 	trace_cq_drain_complete(qp->recv_cq);
2816765d6774SSteve Wise }
2817765d6774SSteve Wise EXPORT_SYMBOL(ib_drain_rq);
2818765d6774SSteve Wise 
2819765d6774SSteve Wise /**
2820765d6774SSteve Wise  * ib_drain_qp() - Block until all CQEs have been consumed by the
2821765d6774SSteve Wise  *		   application on both the RQ and SQ.
2822765d6774SSteve Wise  * @qp:            queue pair to drain
2823765d6774SSteve Wise  *
2824765d6774SSteve Wise  * The caller must:
2825765d6774SSteve Wise  *
2826765d6774SSteve Wise  * ensure there is room in the CQ(s), SQ, and RQ for drain work requests
2827765d6774SSteve Wise  * and completions.
2828765d6774SSteve Wise  *
2829f039f44fSBart Van Assche  * allocate the CQs using ib_alloc_cq().
2830765d6774SSteve Wise  *
2831765d6774SSteve Wise  * ensure that there are no other contexts that are posting WRs concurrently.
2832765d6774SSteve Wise  * Otherwise the drain is not guaranteed.
2833765d6774SSteve Wise  */
2834765d6774SSteve Wise void ib_drain_qp(struct ib_qp *qp)
2835765d6774SSteve Wise {
2836765d6774SSteve Wise 	ib_drain_sq(qp);
283742235f80SSagi Grimberg 	if (!qp->srq)
2838765d6774SSteve Wise 		ib_drain_rq(qp);
2839765d6774SSteve Wise }
2840765d6774SSteve Wise EXPORT_SYMBOL(ib_drain_qp);
2841f6a8a19bSDenis Drozdov 
2842f6a8a19bSDenis Drozdov struct net_device *rdma_alloc_netdev(struct ib_device *device, u8 port_num,
2843f6a8a19bSDenis Drozdov 				     enum rdma_netdev_t type, const char *name,
2844f6a8a19bSDenis Drozdov 				     unsigned char name_assign_type,
2845f6a8a19bSDenis Drozdov 				     void (*setup)(struct net_device *))
2846f6a8a19bSDenis Drozdov {
2847f6a8a19bSDenis Drozdov 	struct rdma_netdev_alloc_params params;
2848f6a8a19bSDenis Drozdov 	struct net_device *netdev;
2849f6a8a19bSDenis Drozdov 	int rc;
2850f6a8a19bSDenis Drozdov 
28513023a1e9SKamal Heib 	if (!device->ops.rdma_netdev_get_params)
2852f6a8a19bSDenis Drozdov 		return ERR_PTR(-EOPNOTSUPP);
2853f6a8a19bSDenis Drozdov 
28543023a1e9SKamal Heib 	rc = device->ops.rdma_netdev_get_params(device, port_num, type,
28553023a1e9SKamal Heib 						&params);
2856f6a8a19bSDenis Drozdov 	if (rc)
2857f6a8a19bSDenis Drozdov 		return ERR_PTR(rc);
2858f6a8a19bSDenis Drozdov 
2859f6a8a19bSDenis Drozdov 	netdev = alloc_netdev_mqs(params.sizeof_priv, name, name_assign_type,
2860f6a8a19bSDenis Drozdov 				  setup, params.txqs, params.rxqs);
2861f6a8a19bSDenis Drozdov 	if (!netdev)
2862f6a8a19bSDenis Drozdov 		return ERR_PTR(-ENOMEM);
2863f6a8a19bSDenis Drozdov 
2864f6a8a19bSDenis Drozdov 	return netdev;
2865f6a8a19bSDenis Drozdov }
2866f6a8a19bSDenis Drozdov EXPORT_SYMBOL(rdma_alloc_netdev);
28675d6b0cb3SDenis Drozdov 
28685d6b0cb3SDenis Drozdov int rdma_init_netdev(struct ib_device *device, u8 port_num,
28695d6b0cb3SDenis Drozdov 		     enum rdma_netdev_t type, const char *name,
28705d6b0cb3SDenis Drozdov 		     unsigned char name_assign_type,
28715d6b0cb3SDenis Drozdov 		     void (*setup)(struct net_device *),
28725d6b0cb3SDenis Drozdov 		     struct net_device *netdev)
28735d6b0cb3SDenis Drozdov {
28745d6b0cb3SDenis Drozdov 	struct rdma_netdev_alloc_params params;
28755d6b0cb3SDenis Drozdov 	int rc;
28765d6b0cb3SDenis Drozdov 
28773023a1e9SKamal Heib 	if (!device->ops.rdma_netdev_get_params)
28785d6b0cb3SDenis Drozdov 		return -EOPNOTSUPP;
28795d6b0cb3SDenis Drozdov 
28803023a1e9SKamal Heib 	rc = device->ops.rdma_netdev_get_params(device, port_num, type,
28813023a1e9SKamal Heib 						&params);
28825d6b0cb3SDenis Drozdov 	if (rc)
28835d6b0cb3SDenis Drozdov 		return rc;
28845d6b0cb3SDenis Drozdov 
28855d6b0cb3SDenis Drozdov 	return params.initialize_rdma_netdev(device, port_num,
28865d6b0cb3SDenis Drozdov 					     netdev, params.param);
28875d6b0cb3SDenis Drozdov }
28885d6b0cb3SDenis Drozdov EXPORT_SYMBOL(rdma_init_netdev);
2889a808273aSShiraz Saleem 
2890a808273aSShiraz Saleem void __rdma_block_iter_start(struct ib_block_iter *biter,
2891a808273aSShiraz Saleem 			     struct scatterlist *sglist, unsigned int nents,
2892a808273aSShiraz Saleem 			     unsigned long pgsz)
2893a808273aSShiraz Saleem {
2894a808273aSShiraz Saleem 	memset(biter, 0, sizeof(struct ib_block_iter));
2895a808273aSShiraz Saleem 	biter->__sg = sglist;
2896a808273aSShiraz Saleem 	biter->__sg_nents = nents;
2897a808273aSShiraz Saleem 
2898a808273aSShiraz Saleem 	/* Driver provides best block size to use */
2899a808273aSShiraz Saleem 	biter->__pg_bit = __fls(pgsz);
2900a808273aSShiraz Saleem }
2901a808273aSShiraz Saleem EXPORT_SYMBOL(__rdma_block_iter_start);
2902a808273aSShiraz Saleem 
2903a808273aSShiraz Saleem bool __rdma_block_iter_next(struct ib_block_iter *biter)
2904a808273aSShiraz Saleem {
2905a808273aSShiraz Saleem 	unsigned int block_offset;
2906a808273aSShiraz Saleem 
2907a808273aSShiraz Saleem 	if (!biter->__sg_nents || !biter->__sg)
2908a808273aSShiraz Saleem 		return false;
2909a808273aSShiraz Saleem 
2910a808273aSShiraz Saleem 	biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance;
2911a808273aSShiraz Saleem 	block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1);
2912a808273aSShiraz Saleem 	biter->__sg_advance += BIT_ULL(biter->__pg_bit) - block_offset;
2913a808273aSShiraz Saleem 
2914a808273aSShiraz Saleem 	if (biter->__sg_advance >= sg_dma_len(biter->__sg)) {
2915a808273aSShiraz Saleem 		biter->__sg_advance = 0;
2916a808273aSShiraz Saleem 		biter->__sg = sg_next(biter->__sg);
2917a808273aSShiraz Saleem 		biter->__sg_nents--;
2918a808273aSShiraz Saleem 	}
2919a808273aSShiraz Saleem 
2920a808273aSShiraz Saleem 	return true;
2921a808273aSShiraz Saleem }
2922a808273aSShiraz Saleem EXPORT_SYMBOL(__rdma_block_iter_next);
2923