xref: /openbmc/linux/drivers/infiniband/core/verbs.c (revision 24436fe7)
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 
ib_event_msg(enum ib_event_type event)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",
997d8f3465SYixian Liu 	[IB_WC_MW_BIND_ERR]		= "memory bind operation error",
1002b1b5b60SSagi Grimberg 	[IB_WC_BAD_RESP_ERR]		= "bad response error",
1012b1b5b60SSagi Grimberg 	[IB_WC_LOC_ACCESS_ERR]		= "local access error",
1027d8f3465SYixian Liu 	[IB_WC_REM_INV_REQ_ERR]		= "remote 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 
ib_wc_status_msg(enum ib_wc_status status)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 
ib_rate_to_mult(enum ib_rate rate)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 
mult_to_ib_rate(int mult)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 
ib_rate_to_mbps(enum ib_rate rate)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
rdma_node_get_transport(unsigned int node_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 
rdma_port_get_link_layer(struct ib_device * device,u32 port_num)2301fb7f897SMark Bloch enum rdma_link_layer rdma_port_get_link_layer(struct ib_device *device,
2311fb7f897SMark Bloch 					      u32 port_num)
232a3f5adafSEli Cohen {
23382901e3eSLeon Romanovsky 	enum rdma_transport_type lt;
2343023a1e9SKamal Heib 	if (device->ops.get_link_layer)
2353023a1e9SKamal Heib 		return device->ops.get_link_layer(device, port_num);
236a3f5adafSEli Cohen 
23782901e3eSLeon Romanovsky 	lt = rdma_node_get_transport(device->node_type);
23882901e3eSLeon Romanovsky 	if (lt == RDMA_TRANSPORT_IB)
239a3f5adafSEli Cohen 		return IB_LINK_LAYER_INFINIBAND;
24082901e3eSLeon Romanovsky 
241a3f5adafSEli Cohen 	return IB_LINK_LAYER_ETHERNET;
242a3f5adafSEli Cohen }
243a3f5adafSEli Cohen EXPORT_SYMBOL(rdma_port_get_link_layer);
244a3f5adafSEli Cohen 
2451da177e4SLinus Torvalds /* Protection domains */
2461da177e4SLinus Torvalds 
24796249d70SJason Gunthorpe /**
2482988ca08SMauro Carvalho Chehab  * __ib_alloc_pd - Allocates an unused protection domain.
24996249d70SJason Gunthorpe  * @device: The device on which to allocate the protection domain.
250094c88f3Srd.dunlab@gmail.com  * @flags: protection domain flags
251094c88f3Srd.dunlab@gmail.com  * @caller: caller's build-time module name
25296249d70SJason Gunthorpe  *
25396249d70SJason Gunthorpe  * A protection domain object provides an association between QPs, shared
25496249d70SJason Gunthorpe  * receive queues, address handles, memory regions, and memory windows.
25596249d70SJason Gunthorpe  *
25696249d70SJason Gunthorpe  * Every PD has a local_dma_lkey which can be used as the lkey value for local
25796249d70SJason Gunthorpe  * memory operations.
25896249d70SJason Gunthorpe  */
__ib_alloc_pd(struct ib_device * device,unsigned int flags,const char * caller)259ed082d36SChristoph Hellwig struct ib_pd *__ib_alloc_pd(struct ib_device *device, unsigned int flags,
260ed082d36SChristoph Hellwig 		const char *caller)
2611da177e4SLinus Torvalds {
2621da177e4SLinus Torvalds 	struct ib_pd *pd;
263ed082d36SChristoph Hellwig 	int mr_access_flags = 0;
26421a428a0SLeon Romanovsky 	int ret;
2651da177e4SLinus Torvalds 
26621a428a0SLeon Romanovsky 	pd = rdma_zalloc_drv_obj(device, ib_pd);
26721a428a0SLeon Romanovsky 	if (!pd)
26821a428a0SLeon Romanovsky 		return ERR_PTR(-ENOMEM);
2691da177e4SLinus Torvalds 
2701da177e4SLinus Torvalds 	pd->device = device;
271ed082d36SChristoph Hellwig 	pd->flags = flags;
27296249d70SJason Gunthorpe 
27313ef5539SLeon Romanovsky 	rdma_restrack_new(&pd->res, RDMA_RESTRACK_PD);
274b09c4d70SLeon Romanovsky 	rdma_restrack_set_name(&pd->res, caller);
27521a428a0SLeon Romanovsky 
276ff23dfa1SShamir Rabinovitch 	ret = device->ops.alloc_pd(pd, NULL);
27721a428a0SLeon Romanovsky 	if (ret) {
27813ef5539SLeon Romanovsky 		rdma_restrack_put(&pd->res);
27921a428a0SLeon Romanovsky 		kfree(pd);
28021a428a0SLeon Romanovsky 		return ERR_PTR(ret);
28121a428a0SLeon Romanovsky 	}
282c34a23c2SLeon Romanovsky 	rdma_restrack_add(&pd->res);
28321a428a0SLeon Romanovsky 
284e945c653SJason Gunthorpe 	if (device->attrs.kernel_cap_flags & IBK_LOCAL_DMA_LKEY)
28596249d70SJason Gunthorpe 		pd->local_dma_lkey = device->local_dma_lkey;
286ed082d36SChristoph Hellwig 	else
287ed082d36SChristoph Hellwig 		mr_access_flags |= IB_ACCESS_LOCAL_WRITE;
288ed082d36SChristoph Hellwig 
289ed082d36SChristoph Hellwig 	if (flags & IB_PD_UNSAFE_GLOBAL_RKEY) {
290ed082d36SChristoph Hellwig 		pr_warn("%s: enabling unsafe global rkey\n", caller);
291ed082d36SChristoph Hellwig 		mr_access_flags |= IB_ACCESS_REMOTE_READ | IB_ACCESS_REMOTE_WRITE;
292ed082d36SChristoph Hellwig 	}
293ed082d36SChristoph Hellwig 
294ed082d36SChristoph Hellwig 	if (mr_access_flags) {
29596249d70SJason Gunthorpe 		struct ib_mr *mr;
29696249d70SJason Gunthorpe 
2973023a1e9SKamal Heib 		mr = pd->device->ops.get_dma_mr(pd, mr_access_flags);
29896249d70SJason Gunthorpe 		if (IS_ERR(mr)) {
29996249d70SJason Gunthorpe 			ib_dealloc_pd(pd);
3005ef990f0SChristoph Hellwig 			return ERR_CAST(mr);
3011da177e4SLinus Torvalds 		}
3021da177e4SLinus Torvalds 
3035ef990f0SChristoph Hellwig 		mr->device	= pd->device;
3045ef990f0SChristoph Hellwig 		mr->pd		= pd;
305a0bc099aSMax Gurtovoy 		mr->type        = IB_MR_TYPE_DMA;
3065ef990f0SChristoph Hellwig 		mr->uobject	= NULL;
3075ef990f0SChristoph Hellwig 		mr->need_inval	= false;
3085ef990f0SChristoph Hellwig 
30950d46335SChristoph Hellwig 		pd->__internal_mr = mr;
310ed082d36SChristoph Hellwig 
311e945c653SJason Gunthorpe 		if (!(device->attrs.kernel_cap_flags & IBK_LOCAL_DMA_LKEY))
31250d46335SChristoph Hellwig 			pd->local_dma_lkey = pd->__internal_mr->lkey;
313ed082d36SChristoph Hellwig 
314ed082d36SChristoph Hellwig 		if (flags & IB_PD_UNSAFE_GLOBAL_RKEY)
315ed082d36SChristoph Hellwig 			pd->unsafe_global_rkey = pd->__internal_mr->rkey;
31696249d70SJason Gunthorpe 	}
317ed082d36SChristoph Hellwig 
3181da177e4SLinus Torvalds 	return pd;
3191da177e4SLinus Torvalds }
320ed082d36SChristoph Hellwig EXPORT_SYMBOL(__ib_alloc_pd);
3211da177e4SLinus Torvalds 
3227dd78647SJason Gunthorpe /**
32391f57129SIsrael Rukshin  * ib_dealloc_pd_user - Deallocates a protection domain.
3247dd78647SJason Gunthorpe  * @pd: The protection domain to deallocate.
325c4367a26SShamir Rabinovitch  * @udata: Valid user data or NULL for kernel object
3267dd78647SJason Gunthorpe  *
3277dd78647SJason Gunthorpe  * It is an error to call this function while any resources in the pd still
3287dd78647SJason Gunthorpe  * exist.  The caller is responsible to synchronously destroy them and
3297dd78647SJason Gunthorpe  * guarantee no new allocations will happen.
3307dd78647SJason Gunthorpe  */
ib_dealloc_pd_user(struct ib_pd * pd,struct ib_udata * udata)33191a7c58fSLeon Romanovsky int ib_dealloc_pd_user(struct ib_pd *pd, struct ib_udata *udata)
3321da177e4SLinus Torvalds {
3337dd78647SJason Gunthorpe 	int ret;
3341da177e4SLinus Torvalds 
33550d46335SChristoph Hellwig 	if (pd->__internal_mr) {
336c4367a26SShamir Rabinovitch 		ret = pd->device->ops.dereg_mr(pd->__internal_mr, NULL);
3377dd78647SJason Gunthorpe 		WARN_ON(ret);
33850d46335SChristoph Hellwig 		pd->__internal_mr = NULL;
33996249d70SJason Gunthorpe 	}
34096249d70SJason Gunthorpe 
34191a7c58fSLeon Romanovsky 	ret = pd->device->ops.dealloc_pd(pd, udata);
34291a7c58fSLeon Romanovsky 	if (ret)
34391a7c58fSLeon Romanovsky 		return ret;
34491a7c58fSLeon Romanovsky 
3459d5f8c20SLeon Romanovsky 	rdma_restrack_del(&pd->res);
34621a428a0SLeon Romanovsky 	kfree(pd);
34791a7c58fSLeon Romanovsky 	return ret;
3481da177e4SLinus Torvalds }
349c4367a26SShamir Rabinovitch EXPORT_SYMBOL(ib_dealloc_pd_user);
3501da177e4SLinus Torvalds 
3511da177e4SLinus Torvalds /* Address handles */
3521da177e4SLinus Torvalds 
353d97099feSJason Gunthorpe /**
354d97099feSJason Gunthorpe  * rdma_copy_ah_attr - Copy rdma ah attribute from source to destination.
355d97099feSJason Gunthorpe  * @dest:       Pointer to destination ah_attr. Contents of the destination
356d97099feSJason Gunthorpe  *              pointer is assumed to be invalid and attribute are overwritten.
357d97099feSJason Gunthorpe  * @src:        Pointer to source ah_attr.
358d97099feSJason Gunthorpe  */
rdma_copy_ah_attr(struct rdma_ah_attr * dest,const struct rdma_ah_attr * src)359d97099feSJason Gunthorpe void rdma_copy_ah_attr(struct rdma_ah_attr *dest,
360d97099feSJason Gunthorpe 		       const struct rdma_ah_attr *src)
361d97099feSJason Gunthorpe {
362d97099feSJason Gunthorpe 	*dest = *src;
363d97099feSJason Gunthorpe 	if (dest->grh.sgid_attr)
364d97099feSJason Gunthorpe 		rdma_hold_gid_attr(dest->grh.sgid_attr);
365d97099feSJason Gunthorpe }
366d97099feSJason Gunthorpe EXPORT_SYMBOL(rdma_copy_ah_attr);
367d97099feSJason Gunthorpe 
368d97099feSJason Gunthorpe /**
369d97099feSJason Gunthorpe  * rdma_replace_ah_attr - Replace valid ah_attr with new new one.
370d97099feSJason Gunthorpe  * @old:        Pointer to existing ah_attr which needs to be replaced.
371d97099feSJason Gunthorpe  *              old is assumed to be valid or zero'd
372d97099feSJason Gunthorpe  * @new:        Pointer to the new ah_attr.
373d97099feSJason Gunthorpe  *
374d97099feSJason Gunthorpe  * rdma_replace_ah_attr() first releases any reference in the old ah_attr if
375d97099feSJason Gunthorpe  * old the ah_attr is valid; after that it copies the new attribute and holds
376d97099feSJason Gunthorpe  * the reference to the replaced ah_attr.
377d97099feSJason Gunthorpe  */
rdma_replace_ah_attr(struct rdma_ah_attr * old,const struct rdma_ah_attr * new)378d97099feSJason Gunthorpe void rdma_replace_ah_attr(struct rdma_ah_attr *old,
379d97099feSJason Gunthorpe 			  const struct rdma_ah_attr *new)
380d97099feSJason Gunthorpe {
381d97099feSJason Gunthorpe 	rdma_destroy_ah_attr(old);
382d97099feSJason Gunthorpe 	*old = *new;
383d97099feSJason Gunthorpe 	if (old->grh.sgid_attr)
384d97099feSJason Gunthorpe 		rdma_hold_gid_attr(old->grh.sgid_attr);
385d97099feSJason Gunthorpe }
386d97099feSJason Gunthorpe EXPORT_SYMBOL(rdma_replace_ah_attr);
387d97099feSJason Gunthorpe 
388d97099feSJason Gunthorpe /**
389d97099feSJason Gunthorpe  * rdma_move_ah_attr - Move ah_attr pointed by source to destination.
390d97099feSJason Gunthorpe  * @dest:       Pointer to destination ah_attr to copy to.
391d97099feSJason Gunthorpe  *              dest is assumed to be valid or zero'd
392d97099feSJason Gunthorpe  * @src:        Pointer to the new ah_attr.
393d97099feSJason Gunthorpe  *
394d97099feSJason Gunthorpe  * rdma_move_ah_attr() first releases any reference in the destination ah_attr
395d97099feSJason Gunthorpe  * if it is valid. This also transfers ownership of internal references from
396d97099feSJason Gunthorpe  * src to dest, making src invalid in the process. No new reference of the src
397d97099feSJason Gunthorpe  * ah_attr is taken.
398d97099feSJason Gunthorpe  */
rdma_move_ah_attr(struct rdma_ah_attr * dest,struct rdma_ah_attr * src)399d97099feSJason Gunthorpe void rdma_move_ah_attr(struct rdma_ah_attr *dest, struct rdma_ah_attr *src)
400d97099feSJason Gunthorpe {
401d97099feSJason Gunthorpe 	rdma_destroy_ah_attr(dest);
402d97099feSJason Gunthorpe 	*dest = *src;
403d97099feSJason Gunthorpe 	src->grh.sgid_attr = NULL;
404d97099feSJason Gunthorpe }
405d97099feSJason Gunthorpe EXPORT_SYMBOL(rdma_move_ah_attr);
406d97099feSJason Gunthorpe 
4078d9ec9adSJason Gunthorpe /*
4088d9ec9adSJason Gunthorpe  * Validate that the rdma_ah_attr is valid for the device before passing it
4098d9ec9adSJason Gunthorpe  * off to the driver.
4108d9ec9adSJason Gunthorpe  */
rdma_check_ah_attr(struct ib_device * device,struct rdma_ah_attr * ah_attr)4118d9ec9adSJason Gunthorpe static int rdma_check_ah_attr(struct ib_device *device,
4128d9ec9adSJason Gunthorpe 			      struct rdma_ah_attr *ah_attr)
4138d9ec9adSJason Gunthorpe {
4148d9ec9adSJason Gunthorpe 	if (!rdma_is_port_valid(device, ah_attr->port_num))
4158d9ec9adSJason Gunthorpe 		return -EINVAL;
4168d9ec9adSJason Gunthorpe 
417b02289b3SArtemy Kovalyov 	if ((rdma_is_grh_required(device, ah_attr->port_num) ||
418b02289b3SArtemy Kovalyov 	     ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) &&
4198d9ec9adSJason Gunthorpe 	    !(ah_attr->ah_flags & IB_AH_GRH))
4208d9ec9adSJason Gunthorpe 		return -EINVAL;
4218d9ec9adSJason Gunthorpe 
4228d9ec9adSJason Gunthorpe 	if (ah_attr->grh.sgid_attr) {
4238d9ec9adSJason Gunthorpe 		/*
4248d9ec9adSJason Gunthorpe 		 * Make sure the passed sgid_attr is consistent with the
4258d9ec9adSJason Gunthorpe 		 * parameters
4268d9ec9adSJason Gunthorpe 		 */
4278d9ec9adSJason Gunthorpe 		if (ah_attr->grh.sgid_attr->index != ah_attr->grh.sgid_index ||
4288d9ec9adSJason Gunthorpe 		    ah_attr->grh.sgid_attr->port_num != ah_attr->port_num)
4298d9ec9adSJason Gunthorpe 			return -EINVAL;
4308d9ec9adSJason Gunthorpe 	}
4318d9ec9adSJason Gunthorpe 	return 0;
4328d9ec9adSJason Gunthorpe }
4338d9ec9adSJason Gunthorpe 
4348d9ec9adSJason Gunthorpe /*
4358d9ec9adSJason Gunthorpe  * If the ah requires a GRH then ensure that sgid_attr pointer is filled in.
4368d9ec9adSJason Gunthorpe  * On success the caller is responsible to call rdma_unfill_sgid_attr().
4378d9ec9adSJason Gunthorpe  */
rdma_fill_sgid_attr(struct ib_device * device,struct rdma_ah_attr * ah_attr,const struct ib_gid_attr ** old_sgid_attr)4388d9ec9adSJason Gunthorpe static int rdma_fill_sgid_attr(struct ib_device *device,
4398d9ec9adSJason Gunthorpe 			       struct rdma_ah_attr *ah_attr,
4408d9ec9adSJason Gunthorpe 			       const struct ib_gid_attr **old_sgid_attr)
4418d9ec9adSJason Gunthorpe {
4428d9ec9adSJason Gunthorpe 	const struct ib_gid_attr *sgid_attr;
4438d9ec9adSJason Gunthorpe 	struct ib_global_route *grh;
4448d9ec9adSJason Gunthorpe 	int ret;
4458d9ec9adSJason Gunthorpe 
4468d9ec9adSJason Gunthorpe 	*old_sgid_attr = ah_attr->grh.sgid_attr;
4478d9ec9adSJason Gunthorpe 
4488d9ec9adSJason Gunthorpe 	ret = rdma_check_ah_attr(device, ah_attr);
4498d9ec9adSJason Gunthorpe 	if (ret)
4508d9ec9adSJason Gunthorpe 		return ret;
4518d9ec9adSJason Gunthorpe 
4528d9ec9adSJason Gunthorpe 	if (!(ah_attr->ah_flags & IB_AH_GRH))
4538d9ec9adSJason Gunthorpe 		return 0;
4548d9ec9adSJason Gunthorpe 
4558d9ec9adSJason Gunthorpe 	grh = rdma_ah_retrieve_grh(ah_attr);
4568d9ec9adSJason Gunthorpe 	if (grh->sgid_attr)
4578d9ec9adSJason Gunthorpe 		return 0;
4588d9ec9adSJason Gunthorpe 
4598d9ec9adSJason Gunthorpe 	sgid_attr =
4608d9ec9adSJason Gunthorpe 		rdma_get_gid_attr(device, ah_attr->port_num, grh->sgid_index);
4618d9ec9adSJason Gunthorpe 	if (IS_ERR(sgid_attr))
4628d9ec9adSJason Gunthorpe 		return PTR_ERR(sgid_attr);
4638d9ec9adSJason Gunthorpe 
4648d9ec9adSJason Gunthorpe 	/* Move ownerhip of the kref into the ah_attr */
4658d9ec9adSJason Gunthorpe 	grh->sgid_attr = sgid_attr;
4668d9ec9adSJason Gunthorpe 	return 0;
4678d9ec9adSJason Gunthorpe }
4688d9ec9adSJason Gunthorpe 
rdma_unfill_sgid_attr(struct rdma_ah_attr * ah_attr,const struct ib_gid_attr * old_sgid_attr)4698d9ec9adSJason Gunthorpe static void rdma_unfill_sgid_attr(struct rdma_ah_attr *ah_attr,
4708d9ec9adSJason Gunthorpe 				  const struct ib_gid_attr *old_sgid_attr)
4718d9ec9adSJason Gunthorpe {
4728d9ec9adSJason Gunthorpe 	/*
4738d9ec9adSJason Gunthorpe 	 * Fill didn't change anything, the caller retains ownership of
4748d9ec9adSJason Gunthorpe 	 * whatever it passed
4758d9ec9adSJason Gunthorpe 	 */
4768d9ec9adSJason Gunthorpe 	if (ah_attr->grh.sgid_attr == old_sgid_attr)
4778d9ec9adSJason Gunthorpe 		return;
4788d9ec9adSJason Gunthorpe 
4798d9ec9adSJason Gunthorpe 	/*
4808d9ec9adSJason Gunthorpe 	 * Otherwise, we need to undo what rdma_fill_sgid_attr so the caller
4818d9ec9adSJason Gunthorpe 	 * doesn't see any change in the rdma_ah_attr. If we get here
4828d9ec9adSJason Gunthorpe 	 * old_sgid_attr is NULL.
4838d9ec9adSJason Gunthorpe 	 */
4848d9ec9adSJason Gunthorpe 	rdma_destroy_ah_attr(ah_attr);
4858d9ec9adSJason Gunthorpe }
4868d9ec9adSJason Gunthorpe 
4871a1f460fSJason Gunthorpe static const struct ib_gid_attr *
rdma_update_sgid_attr(struct rdma_ah_attr * ah_attr,const struct ib_gid_attr * old_attr)4881a1f460fSJason Gunthorpe rdma_update_sgid_attr(struct rdma_ah_attr *ah_attr,
4891a1f460fSJason Gunthorpe 		      const struct ib_gid_attr *old_attr)
4901a1f460fSJason Gunthorpe {
4911a1f460fSJason Gunthorpe 	if (old_attr)
4921a1f460fSJason Gunthorpe 		rdma_put_gid_attr(old_attr);
4931a1f460fSJason Gunthorpe 	if (ah_attr->ah_flags & IB_AH_GRH) {
4941a1f460fSJason Gunthorpe 		rdma_hold_gid_attr(ah_attr->grh.sgid_attr);
4951a1f460fSJason Gunthorpe 		return ah_attr->grh.sgid_attr;
4961a1f460fSJason Gunthorpe 	}
4971a1f460fSJason Gunthorpe 	return NULL;
4981a1f460fSJason Gunthorpe }
4991a1f460fSJason Gunthorpe 
_rdma_create_ah(struct ib_pd * pd,struct rdma_ah_attr * ah_attr,u32 flags,struct ib_udata * udata,struct net_device * xmit_slave)5005cda6587SParav Pandit static struct ib_ah *_rdma_create_ah(struct ib_pd *pd,
5015cda6587SParav Pandit 				     struct rdma_ah_attr *ah_attr,
502b090c4e3SGal Pressman 				     u32 flags,
50351aab126SMaor Gottlieb 				     struct ib_udata *udata,
50451aab126SMaor Gottlieb 				     struct net_device *xmit_slave)
5051da177e4SLinus Torvalds {
506fa5d010cSMaor Gottlieb 	struct rdma_ah_init_attr init_attr = {};
507d3456914SLeon Romanovsky 	struct ib_device *device = pd->device;
5081da177e4SLinus Torvalds 	struct ib_ah *ah;
509d3456914SLeon Romanovsky 	int ret;
5101da177e4SLinus Torvalds 
511b090c4e3SGal Pressman 	might_sleep_if(flags & RDMA_CREATE_AH_SLEEPABLE);
512b090c4e3SGal Pressman 
5138c030d78SGal Pressman 	if (!udata && !device->ops.create_ah)
5140584c47bSKamal Heib 		return ERR_PTR(-EOPNOTSUPP);
5150584c47bSKamal Heib 
516d3456914SLeon Romanovsky 	ah = rdma_zalloc_drv_obj_gfp(
517d3456914SLeon Romanovsky 		device, ib_ah,
518d3456914SLeon Romanovsky 		(flags & RDMA_CREATE_AH_SLEEPABLE) ? GFP_KERNEL : GFP_ATOMIC);
519d3456914SLeon Romanovsky 	if (!ah)
520d3456914SLeon Romanovsky 		return ERR_PTR(-ENOMEM);
5211da177e4SLinus Torvalds 
522d3456914SLeon Romanovsky 	ah->device = device;
5231da177e4SLinus Torvalds 	ah->pd = pd;
52444c58487SDasaratharaman Chandramouli 	ah->type = ah_attr->type;
5251a1f460fSJason Gunthorpe 	ah->sgid_attr = rdma_update_sgid_attr(ah_attr, NULL);
526fa5d010cSMaor Gottlieb 	init_attr.ah_attr = ah_attr;
527fa5d010cSMaor Gottlieb 	init_attr.flags = flags;
52851aab126SMaor Gottlieb 	init_attr.xmit_slave = xmit_slave;
5291a1f460fSJason Gunthorpe 
530676a80adSJason Gunthorpe 	if (udata)
531676a80adSJason Gunthorpe 		ret = device->ops.create_user_ah(ah, &init_attr, udata);
532676a80adSJason Gunthorpe 	else
533676a80adSJason Gunthorpe 		ret = device->ops.create_ah(ah, &init_attr, NULL);
534d3456914SLeon Romanovsky 	if (ret) {
535aca3b0faSSaravanan Vajravel 		if (ah->sgid_attr)
536aca3b0faSSaravanan Vajravel 			rdma_put_gid_attr(ah->sgid_attr);
537d3456914SLeon Romanovsky 		kfree(ah);
538d3456914SLeon Romanovsky 		return ERR_PTR(ret);
5391da177e4SLinus Torvalds 	}
5401da177e4SLinus Torvalds 
541d3456914SLeon Romanovsky 	atomic_inc(&pd->usecnt);
5421da177e4SLinus Torvalds 	return ah;
5431da177e4SLinus Torvalds }
5445cda6587SParav Pandit 
5458d9ec9adSJason Gunthorpe /**
5468d9ec9adSJason Gunthorpe  * rdma_create_ah - Creates an address handle for the
5478d9ec9adSJason Gunthorpe  * given address vector.
5488d9ec9adSJason Gunthorpe  * @pd: The protection domain associated with the address handle.
5498d9ec9adSJason Gunthorpe  * @ah_attr: The attributes of the address vector.
550b090c4e3SGal Pressman  * @flags: Create address handle flags (see enum rdma_create_ah_flags).
5518d9ec9adSJason Gunthorpe  *
5528d9ec9adSJason Gunthorpe  * It returns 0 on success and returns appropriate error code on error.
5538d9ec9adSJason Gunthorpe  * The address handle is used to reference a local or global destination
5548d9ec9adSJason Gunthorpe  * in all UD QP post sends.
5558d9ec9adSJason Gunthorpe  */
rdma_create_ah(struct ib_pd * pd,struct rdma_ah_attr * ah_attr,u32 flags)556b090c4e3SGal Pressman struct ib_ah *rdma_create_ah(struct ib_pd *pd, struct rdma_ah_attr *ah_attr,
557b090c4e3SGal Pressman 			     u32 flags)
5585cda6587SParav Pandit {
5598d9ec9adSJason Gunthorpe 	const struct ib_gid_attr *old_sgid_attr;
56051aab126SMaor Gottlieb 	struct net_device *slave;
5618d9ec9adSJason Gunthorpe 	struct ib_ah *ah;
5628d9ec9adSJason Gunthorpe 	int ret;
5638d9ec9adSJason Gunthorpe 
5648d9ec9adSJason Gunthorpe 	ret = rdma_fill_sgid_attr(pd->device, ah_attr, &old_sgid_attr);
5658d9ec9adSJason Gunthorpe 	if (ret)
5668d9ec9adSJason Gunthorpe 		return ERR_PTR(ret);
56751aab126SMaor Gottlieb 	slave = rdma_lag_get_ah_roce_slave(pd->device, ah_attr,
56851aab126SMaor Gottlieb 					   (flags & RDMA_CREATE_AH_SLEEPABLE) ?
56951aab126SMaor Gottlieb 					   GFP_KERNEL : GFP_ATOMIC);
57051aab126SMaor Gottlieb 	if (IS_ERR(slave)) {
57151aab126SMaor Gottlieb 		rdma_unfill_sgid_attr(ah_attr, old_sgid_attr);
57251aab126SMaor Gottlieb 		return (void *)slave;
57351aab126SMaor Gottlieb 	}
57451aab126SMaor Gottlieb 	ah = _rdma_create_ah(pd, ah_attr, flags, NULL, slave);
57551aab126SMaor Gottlieb 	rdma_lag_put_ah_roce_slave(slave);
5768d9ec9adSJason Gunthorpe 	rdma_unfill_sgid_attr(ah_attr, old_sgid_attr);
5778d9ec9adSJason Gunthorpe 	return ah;
5785cda6587SParav Pandit }
5790a18cfe4SDasaratharaman Chandramouli EXPORT_SYMBOL(rdma_create_ah);
5801da177e4SLinus Torvalds 
5815cda6587SParav Pandit /**
5825cda6587SParav Pandit  * rdma_create_user_ah - Creates an address handle for the
5835cda6587SParav Pandit  * given address vector.
5845cda6587SParav Pandit  * It resolves destination mac address for ah attribute of RoCE type.
5855cda6587SParav Pandit  * @pd: The protection domain associated with the address handle.
5865cda6587SParav Pandit  * @ah_attr: The attributes of the address vector.
5875cda6587SParav Pandit  * @udata: pointer to user's input output buffer information need by
5885cda6587SParav Pandit  *         provider driver.
5895cda6587SParav Pandit  *
5905cda6587SParav Pandit  * It returns 0 on success and returns appropriate error code on error.
5915cda6587SParav Pandit  * The address handle is used to reference a local or global destination
5925cda6587SParav Pandit  * in all UD QP post sends.
5935cda6587SParav Pandit  */
rdma_create_user_ah(struct ib_pd * pd,struct rdma_ah_attr * ah_attr,struct ib_udata * udata)5945cda6587SParav Pandit struct ib_ah *rdma_create_user_ah(struct ib_pd *pd,
5955cda6587SParav Pandit 				  struct rdma_ah_attr *ah_attr,
5965cda6587SParav Pandit 				  struct ib_udata *udata)
5975cda6587SParav Pandit {
5988d9ec9adSJason Gunthorpe 	const struct ib_gid_attr *old_sgid_attr;
5998d9ec9adSJason Gunthorpe 	struct ib_ah *ah;
6005cda6587SParav Pandit 	int err;
6015cda6587SParav Pandit 
6028d9ec9adSJason Gunthorpe 	err = rdma_fill_sgid_attr(pd->device, ah_attr, &old_sgid_attr);
6038d9ec9adSJason Gunthorpe 	if (err)
6048d9ec9adSJason Gunthorpe 		return ERR_PTR(err);
6058d9ec9adSJason Gunthorpe 
6065cda6587SParav Pandit 	if (ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) {
6075cda6587SParav Pandit 		err = ib_resolve_eth_dmac(pd->device, ah_attr);
6088d9ec9adSJason Gunthorpe 		if (err) {
6098d9ec9adSJason Gunthorpe 			ah = ERR_PTR(err);
6108d9ec9adSJason Gunthorpe 			goto out;
6118d9ec9adSJason Gunthorpe 		}
6125cda6587SParav Pandit 	}
6135cda6587SParav Pandit 
61451aab126SMaor Gottlieb 	ah = _rdma_create_ah(pd, ah_attr, RDMA_CREATE_AH_SLEEPABLE,
61551aab126SMaor Gottlieb 			     udata, NULL);
6168d9ec9adSJason Gunthorpe 
6178d9ec9adSJason Gunthorpe out:
6188d9ec9adSJason Gunthorpe 	rdma_unfill_sgid_attr(ah_attr, old_sgid_attr);
6198d9ec9adSJason Gunthorpe 	return ah;
6205cda6587SParav Pandit }
6215cda6587SParav Pandit EXPORT_SYMBOL(rdma_create_user_ah);
6225cda6587SParav Pandit 
ib_get_rdma_header_version(const union rdma_network_hdr * hdr)623850d8fd7SMoni Shoua int ib_get_rdma_header_version(const union rdma_network_hdr *hdr)
624c865f246SSomnath Kotur {
625c865f246SSomnath Kotur 	const struct iphdr *ip4h = (struct iphdr *)&hdr->roce4grh;
626c865f246SSomnath Kotur 	struct iphdr ip4h_checked;
627c865f246SSomnath Kotur 	const struct ipv6hdr *ip6h = (struct ipv6hdr *)&hdr->ibgrh;
628c865f246SSomnath Kotur 
629c865f246SSomnath Kotur 	/* If it's IPv6, the version must be 6, otherwise, the first
630c865f246SSomnath Kotur 	 * 20 bytes (before the IPv4 header) are garbled.
631c865f246SSomnath Kotur 	 */
632c865f246SSomnath Kotur 	if (ip6h->version != 6)
633c865f246SSomnath Kotur 		return (ip4h->version == 4) ? 4 : 0;
634c865f246SSomnath Kotur 	/* version may be 6 or 4 because the first 20 bytes could be garbled */
635c865f246SSomnath Kotur 
636c865f246SSomnath Kotur 	/* RoCE v2 requires no options, thus header length
637c865f246SSomnath Kotur 	 * must be 5 words
638c865f246SSomnath Kotur 	 */
639c865f246SSomnath Kotur 	if (ip4h->ihl != 5)
640c865f246SSomnath Kotur 		return 6;
641c865f246SSomnath Kotur 
642c865f246SSomnath Kotur 	/* Verify checksum.
643c865f246SSomnath Kotur 	 * We can't write on scattered buffers so we need to copy to
644c865f246SSomnath Kotur 	 * temp buffer.
645c865f246SSomnath Kotur 	 */
646c865f246SSomnath Kotur 	memcpy(&ip4h_checked, ip4h, sizeof(ip4h_checked));
647c865f246SSomnath Kotur 	ip4h_checked.check = 0;
648c865f246SSomnath Kotur 	ip4h_checked.check = ip_fast_csum((u8 *)&ip4h_checked, 5);
649c865f246SSomnath Kotur 	/* if IPv4 header checksum is OK, believe it */
650c865f246SSomnath Kotur 	if (ip4h->check == ip4h_checked.check)
651c865f246SSomnath Kotur 		return 4;
652c865f246SSomnath Kotur 	return 6;
653c865f246SSomnath Kotur }
654850d8fd7SMoni Shoua EXPORT_SYMBOL(ib_get_rdma_header_version);
655c865f246SSomnath Kotur 
ib_get_net_type_by_grh(struct ib_device * device,u32 port_num,const struct ib_grh * grh)656c865f246SSomnath Kotur static enum rdma_network_type ib_get_net_type_by_grh(struct ib_device *device,
6571fb7f897SMark Bloch 						     u32 port_num,
658c865f246SSomnath Kotur 						     const struct ib_grh *grh)
659c865f246SSomnath Kotur {
660c865f246SSomnath Kotur 	int grh_version;
661c865f246SSomnath Kotur 
662c865f246SSomnath Kotur 	if (rdma_protocol_ib(device, port_num))
663c865f246SSomnath Kotur 		return RDMA_NETWORK_IB;
664c865f246SSomnath Kotur 
665850d8fd7SMoni Shoua 	grh_version = ib_get_rdma_header_version((union rdma_network_hdr *)grh);
666c865f246SSomnath Kotur 
667c865f246SSomnath Kotur 	if (grh_version == 4)
668c865f246SSomnath Kotur 		return RDMA_NETWORK_IPV4;
669c865f246SSomnath Kotur 
670c865f246SSomnath Kotur 	if (grh->next_hdr == IPPROTO_UDP)
671c865f246SSomnath Kotur 		return RDMA_NETWORK_IPV6;
672c865f246SSomnath Kotur 
673c865f246SSomnath Kotur 	return RDMA_NETWORK_ROCE_V1;
674c865f246SSomnath Kotur }
675c865f246SSomnath Kotur 
676dbf727deSMatan Barak struct find_gid_index_context {
677dbf727deSMatan Barak 	u16 vlan_id;
678c865f246SSomnath Kotur 	enum ib_gid_type gid_type;
679dbf727deSMatan Barak };
680dbf727deSMatan Barak 
find_gid_index(const union ib_gid * gid,const struct ib_gid_attr * gid_attr,void * context)681dbf727deSMatan Barak static bool find_gid_index(const union ib_gid *gid,
682dbf727deSMatan Barak 			   const struct ib_gid_attr *gid_attr,
683dbf727deSMatan Barak 			   void *context)
684dbf727deSMatan Barak {
685b0dd0d33SParav Pandit 	struct find_gid_index_context *ctx = context;
686777a8b32SParav Pandit 	u16 vlan_id = 0xffff;
687777a8b32SParav Pandit 	int ret;
688dbf727deSMatan Barak 
689c865f246SSomnath Kotur 	if (ctx->gid_type != gid_attr->gid_type)
690c865f246SSomnath Kotur 		return false;
691c865f246SSomnath Kotur 
692777a8b32SParav Pandit 	ret = rdma_read_gid_l2_fields(gid_attr, &vlan_id, NULL);
693777a8b32SParav Pandit 	if (ret)
694dbf727deSMatan Barak 		return false;
695dbf727deSMatan Barak 
696777a8b32SParav Pandit 	return ctx->vlan_id == vlan_id;
697dbf727deSMatan Barak }
698dbf727deSMatan Barak 
699b7403217SParav Pandit static const struct ib_gid_attr *
get_sgid_attr_from_eth(struct ib_device * device,u32 port_num,u16 vlan_id,const union ib_gid * sgid,enum ib_gid_type gid_type)7001fb7f897SMark Bloch get_sgid_attr_from_eth(struct ib_device *device, u32 port_num,
701dbf727deSMatan Barak 		       u16 vlan_id, const union ib_gid *sgid,
702b7403217SParav Pandit 		       enum ib_gid_type gid_type)
703dbf727deSMatan Barak {
704c865f246SSomnath Kotur 	struct find_gid_index_context context = {.vlan_id = vlan_id,
705c865f246SSomnath Kotur 						 .gid_type = gid_type};
706dbf727deSMatan Barak 
707b7403217SParav Pandit 	return rdma_find_gid_by_filter(device, sgid, port_num, find_gid_index,
708b7403217SParav Pandit 				       &context);
709dbf727deSMatan Barak }
710dbf727deSMatan Barak 
ib_get_gids_from_rdma_hdr(const union rdma_network_hdr * hdr,enum rdma_network_type net_type,union ib_gid * sgid,union ib_gid * dgid)711850d8fd7SMoni Shoua int ib_get_gids_from_rdma_hdr(const union rdma_network_hdr *hdr,
712c865f246SSomnath Kotur 			      enum rdma_network_type net_type,
713c865f246SSomnath Kotur 			      union ib_gid *sgid, union ib_gid *dgid)
714c865f246SSomnath Kotur {
715c865f246SSomnath Kotur 	struct sockaddr_in  src_in;
716c865f246SSomnath Kotur 	struct sockaddr_in  dst_in;
717c865f246SSomnath Kotur 	__be32 src_saddr, dst_saddr;
718c865f246SSomnath Kotur 
719c865f246SSomnath Kotur 	if (!sgid || !dgid)
720c865f246SSomnath Kotur 		return -EINVAL;
721c865f246SSomnath Kotur 
722c865f246SSomnath Kotur 	if (net_type == RDMA_NETWORK_IPV4) {
723c865f246SSomnath Kotur 		memcpy(&src_in.sin_addr.s_addr,
724c865f246SSomnath Kotur 		       &hdr->roce4grh.saddr, 4);
725c865f246SSomnath Kotur 		memcpy(&dst_in.sin_addr.s_addr,
726c865f246SSomnath Kotur 		       &hdr->roce4grh.daddr, 4);
727c865f246SSomnath Kotur 		src_saddr = src_in.sin_addr.s_addr;
728c865f246SSomnath Kotur 		dst_saddr = dst_in.sin_addr.s_addr;
729c865f246SSomnath Kotur 		ipv6_addr_set_v4mapped(src_saddr,
730c865f246SSomnath Kotur 				       (struct in6_addr *)sgid);
731c865f246SSomnath Kotur 		ipv6_addr_set_v4mapped(dst_saddr,
732c865f246SSomnath Kotur 				       (struct in6_addr *)dgid);
733c865f246SSomnath Kotur 		return 0;
734c865f246SSomnath Kotur 	} else if (net_type == RDMA_NETWORK_IPV6 ||
7351c15b4f2SAvihai Horon 		   net_type == RDMA_NETWORK_IB || RDMA_NETWORK_ROCE_V1) {
736c865f246SSomnath Kotur 		*dgid = hdr->ibgrh.dgid;
737c865f246SSomnath Kotur 		*sgid = hdr->ibgrh.sgid;
738c865f246SSomnath Kotur 		return 0;
739c865f246SSomnath Kotur 	} else {
740c865f246SSomnath Kotur 		return -EINVAL;
741c865f246SSomnath Kotur 	}
742c865f246SSomnath Kotur }
743850d8fd7SMoni Shoua EXPORT_SYMBOL(ib_get_gids_from_rdma_hdr);
744c865f246SSomnath Kotur 
7451060f865SParav Pandit /* Resolve destination mac address and hop limit for unicast destination
7461060f865SParav Pandit  * GID entry, considering the source GID entry as well.
7471060f865SParav Pandit  * ah_attribute must have have valid port_num, sgid_index.
7481060f865SParav Pandit  */
ib_resolve_unicast_gid_dmac(struct ib_device * device,struct rdma_ah_attr * ah_attr)7491060f865SParav Pandit static int ib_resolve_unicast_gid_dmac(struct ib_device *device,
7501060f865SParav Pandit 				       struct rdma_ah_attr *ah_attr)
7511060f865SParav Pandit {
752b7403217SParav Pandit 	struct ib_global_route *grh = rdma_ah_retrieve_grh(ah_attr);
753b7403217SParav Pandit 	const struct ib_gid_attr *sgid_attr = grh->sgid_attr;
7541060f865SParav Pandit 	int hop_limit = 0xff;
755b7403217SParav Pandit 	int ret = 0;
7561060f865SParav Pandit 
75756d0a7d9SParav Pandit 	/* If destination is link local and source GID is RoCEv1,
75856d0a7d9SParav Pandit 	 * IP stack is not used.
75956d0a7d9SParav Pandit 	 */
76056d0a7d9SParav Pandit 	if (rdma_link_local_addr((struct in6_addr *)grh->dgid.raw) &&
761b7403217SParav Pandit 	    sgid_attr->gid_type == IB_GID_TYPE_ROCE) {
76256d0a7d9SParav Pandit 		rdma_get_ll_mac((struct in6_addr *)grh->dgid.raw,
76356d0a7d9SParav Pandit 				ah_attr->roce.dmac);
764b7403217SParav Pandit 		return ret;
76556d0a7d9SParav Pandit 	}
76656d0a7d9SParav Pandit 
767b7403217SParav Pandit 	ret = rdma_addr_find_l2_eth_by_grh(&sgid_attr->gid, &grh->dgid,
7681060f865SParav Pandit 					   ah_attr->roce.dmac,
7690e9d2c19SParav Pandit 					   sgid_attr, &hop_limit);
7701060f865SParav Pandit 
7711060f865SParav Pandit 	grh->hop_limit = hop_limit;
7721060f865SParav Pandit 	return ret;
7731060f865SParav Pandit }
7741060f865SParav Pandit 
77528b5b3a2SGustavo A. R. Silva /*
776f6bdb142SParav Pandit  * This function initializes address handle attributes from the incoming packet.
77728b5b3a2SGustavo A. R. Silva  * Incoming packet has dgid of the receiver node on which this code is
77828b5b3a2SGustavo A. R. Silva  * getting executed and, sgid contains the GID of the sender.
77928b5b3a2SGustavo A. R. Silva  *
78028b5b3a2SGustavo A. R. Silva  * When resolving mac address of destination, the arrived dgid is used
78128b5b3a2SGustavo A. R. Silva  * as sgid and, sgid is used as dgid because sgid contains destinations
78228b5b3a2SGustavo A. R. Silva  * GID whom to respond to.
78328b5b3a2SGustavo A. R. Silva  *
784b7403217SParav Pandit  * On success the caller is responsible to call rdma_destroy_ah_attr on the
785b7403217SParav Pandit  * attr.
78628b5b3a2SGustavo A. R. Silva  */
ib_init_ah_attr_from_wc(struct ib_device * device,u32 port_num,const struct ib_wc * wc,const struct ib_grh * grh,struct rdma_ah_attr * ah_attr)7871fb7f897SMark Bloch int ib_init_ah_attr_from_wc(struct ib_device *device, u32 port_num,
78873cdaaeeSIra Weiny 			    const struct ib_wc *wc, const struct ib_grh *grh,
78990898850SDasaratharaman Chandramouli 			    struct rdma_ah_attr *ah_attr)
790513789edSHal Rosenstock {
791513789edSHal Rosenstock 	u32 flow_class;
792513789edSHal Rosenstock 	int ret;
793c865f246SSomnath Kotur 	enum rdma_network_type net_type = RDMA_NETWORK_IB;
794c865f246SSomnath Kotur 	enum ib_gid_type gid_type = IB_GID_TYPE_IB;
795b7403217SParav Pandit 	const struct ib_gid_attr *sgid_attr;
796c3efe750SMatan Barak 	int hoplimit = 0xff;
797c865f246SSomnath Kotur 	union ib_gid dgid;
798c865f246SSomnath Kotur 	union ib_gid sgid;
799513789edSHal Rosenstock 
80079364227SRoland Dreier 	might_sleep();
80179364227SRoland Dreier 
8024e00d694SSean Hefty 	memset(ah_attr, 0, sizeof *ah_attr);
80344c58487SDasaratharaman Chandramouli 	ah_attr->type = rdma_ah_find_type(device, port_num);
804227128fcSMichael Wang 	if (rdma_cap_eth_ah(device, port_num)) {
805c865f246SSomnath Kotur 		if (wc->wc_flags & IB_WC_WITH_NETWORK_HDR_TYPE)
806c865f246SSomnath Kotur 			net_type = wc->network_hdr_type;
807c865f246SSomnath Kotur 		else
808c865f246SSomnath Kotur 			net_type = ib_get_net_type_by_grh(device, port_num, grh);
809c865f246SSomnath Kotur 		gid_type = ib_network_to_gid_type(net_type);
810c865f246SSomnath Kotur 	}
811850d8fd7SMoni Shoua 	ret = ib_get_gids_from_rdma_hdr((union rdma_network_hdr *)grh, net_type,
812c865f246SSomnath Kotur 					&sgid, &dgid);
813c865f246SSomnath Kotur 	if (ret)
814c865f246SSomnath Kotur 		return ret;
815c865f246SSomnath Kotur 
8161060f865SParav Pandit 	rdma_ah_set_sl(ah_attr, wc->sl);
8171060f865SParav Pandit 	rdma_ah_set_port_num(ah_attr, port_num);
8181060f865SParav Pandit 
819c865f246SSomnath Kotur 	if (rdma_protocol_roce(device, port_num)) {
820dbf727deSMatan Barak 		u16 vlan_id = wc->wc_flags & IB_WC_WITH_VLAN ?
821dbf727deSMatan Barak 				wc->vlan_id : 0xffff;
822dbf727deSMatan Barak 
823dd5f03beSMatan Barak 		if (!(wc->wc_flags & IB_WC_GRH))
824dd5f03beSMatan Barak 			return -EPROTOTYPE;
825dd5f03beSMatan Barak 
826b7403217SParav Pandit 		sgid_attr = get_sgid_attr_from_eth(device, port_num,
8271060f865SParav Pandit 						   vlan_id, &dgid,
828b7403217SParav Pandit 						   gid_type);
829b7403217SParav Pandit 		if (IS_ERR(sgid_attr))
830b7403217SParav Pandit 			return PTR_ERR(sgid_attr);
83120029832SMatan Barak 
8321060f865SParav Pandit 		flow_class = be32_to_cpu(grh->version_tclass_flow);
833b7403217SParav Pandit 		rdma_move_grh_sgid_attr(ah_attr,
834b7403217SParav Pandit 					&sgid,
8351060f865SParav Pandit 					flow_class & 0xFFFFF,
836b7403217SParav Pandit 					hoplimit,
837b7403217SParav Pandit 					(flow_class >> 20) & 0xFF,
838b7403217SParav Pandit 					sgid_attr);
839b7403217SParav Pandit 
840b7403217SParav Pandit 		ret = ib_resolve_unicast_gid_dmac(device, ah_attr);
841b7403217SParav Pandit 		if (ret)
842b7403217SParav Pandit 			rdma_destroy_ah_attr(ah_attr);
843b7403217SParav Pandit 
844b7403217SParav Pandit 		return ret;
8451060f865SParav Pandit 	} else {
846d8966fcdSDasaratharaman Chandramouli 		rdma_ah_set_dlid(ah_attr, wc->slid);
847d8966fcdSDasaratharaman Chandramouli 		rdma_ah_set_path_bits(ah_attr, wc->dlid_path_bits);
848513789edSHal Rosenstock 
849b7403217SParav Pandit 		if ((wc->wc_flags & IB_WC_GRH) == 0)
850b7403217SParav Pandit 			return 0;
851513789edSHal Rosenstock 
852b7403217SParav Pandit 		if (dgid.global.interface_id !=
853b7403217SParav Pandit 					cpu_to_be64(IB_SA_WELL_KNOWN_GUID)) {
854b7403217SParav Pandit 			sgid_attr = rdma_find_gid_by_port(
855b7403217SParav Pandit 				device, &dgid, IB_GID_TYPE_IB, port_num, NULL);
856b7403217SParav Pandit 		} else
857b7403217SParav Pandit 			sgid_attr = rdma_get_gid_attr(device, port_num, 0);
858b7403217SParav Pandit 
859b7403217SParav Pandit 		if (IS_ERR(sgid_attr))
860b7403217SParav Pandit 			return PTR_ERR(sgid_attr);
861497677abSHal Rosenstock 		flow_class = be32_to_cpu(grh->version_tclass_flow);
862b7403217SParav Pandit 		rdma_move_grh_sgid_attr(ah_attr,
863b7403217SParav Pandit 					&sgid,
864d8966fcdSDasaratharaman Chandramouli 					flow_class & 0xFFFFF,
865b7403217SParav Pandit 					hoplimit,
866b7403217SParav Pandit 					(flow_class >> 20) & 0xFF,
867b7403217SParav Pandit 					sgid_attr);
868b7403217SParav Pandit 
8694e00d694SSean Hefty 		return 0;
8704e00d694SSean Hefty 	}
8711060f865SParav Pandit }
872f6bdb142SParav Pandit EXPORT_SYMBOL(ib_init_ah_attr_from_wc);
8734e00d694SSean Hefty 
8748d9ec9adSJason Gunthorpe /**
8758d9ec9adSJason Gunthorpe  * rdma_move_grh_sgid_attr - Sets the sgid attribute of GRH, taking ownership
8768d9ec9adSJason Gunthorpe  * of the reference
8778d9ec9adSJason Gunthorpe  *
8788d9ec9adSJason Gunthorpe  * @attr:	Pointer to AH attribute structure
8798d9ec9adSJason Gunthorpe  * @dgid:	Destination GID
8808d9ec9adSJason Gunthorpe  * @flow_label:	Flow label
8818d9ec9adSJason Gunthorpe  * @hop_limit:	Hop limit
8828d9ec9adSJason Gunthorpe  * @traffic_class: traffic class
8838d9ec9adSJason Gunthorpe  * @sgid_attr:	Pointer to SGID attribute
8848d9ec9adSJason Gunthorpe  *
8858d9ec9adSJason Gunthorpe  * This takes ownership of the sgid_attr reference. The caller must ensure
8868d9ec9adSJason Gunthorpe  * rdma_destroy_ah_attr() is called before destroying the rdma_ah_attr after
8878d9ec9adSJason Gunthorpe  * calling this function.
8888d9ec9adSJason Gunthorpe  */
rdma_move_grh_sgid_attr(struct rdma_ah_attr * attr,union ib_gid * dgid,u32 flow_label,u8 hop_limit,u8 traffic_class,const struct ib_gid_attr * sgid_attr)8898d9ec9adSJason Gunthorpe void rdma_move_grh_sgid_attr(struct rdma_ah_attr *attr, union ib_gid *dgid,
8908d9ec9adSJason Gunthorpe 			     u32 flow_label, u8 hop_limit, u8 traffic_class,
8918d9ec9adSJason Gunthorpe 			     const struct ib_gid_attr *sgid_attr)
8928d9ec9adSJason Gunthorpe {
8938d9ec9adSJason Gunthorpe 	rdma_ah_set_grh(attr, dgid, flow_label, sgid_attr->index, hop_limit,
8948d9ec9adSJason Gunthorpe 			traffic_class);
8958d9ec9adSJason Gunthorpe 	attr->grh.sgid_attr = sgid_attr;
8968d9ec9adSJason Gunthorpe }
8978d9ec9adSJason Gunthorpe EXPORT_SYMBOL(rdma_move_grh_sgid_attr);
8988d9ec9adSJason Gunthorpe 
8998d9ec9adSJason Gunthorpe /**
9008d9ec9adSJason Gunthorpe  * rdma_destroy_ah_attr - Release reference to SGID attribute of
9018d9ec9adSJason Gunthorpe  * ah attribute.
9028d9ec9adSJason Gunthorpe  * @ah_attr: Pointer to ah attribute
9038d9ec9adSJason Gunthorpe  *
9048d9ec9adSJason Gunthorpe  * Release reference to the SGID attribute of the ah attribute if it is
9058d9ec9adSJason Gunthorpe  * non NULL. It is safe to call this multiple times, and safe to call it on
9068d9ec9adSJason Gunthorpe  * a zero initialized ah_attr.
9078d9ec9adSJason Gunthorpe  */
rdma_destroy_ah_attr(struct rdma_ah_attr * ah_attr)9088d9ec9adSJason Gunthorpe void rdma_destroy_ah_attr(struct rdma_ah_attr *ah_attr)
9098d9ec9adSJason Gunthorpe {
9108d9ec9adSJason Gunthorpe 	if (ah_attr->grh.sgid_attr) {
9118d9ec9adSJason Gunthorpe 		rdma_put_gid_attr(ah_attr->grh.sgid_attr);
9128d9ec9adSJason Gunthorpe 		ah_attr->grh.sgid_attr = NULL;
9138d9ec9adSJason Gunthorpe 	}
9148d9ec9adSJason Gunthorpe }
9158d9ec9adSJason Gunthorpe EXPORT_SYMBOL(rdma_destroy_ah_attr);
9168d9ec9adSJason Gunthorpe 
ib_create_ah_from_wc(struct ib_pd * pd,const struct ib_wc * wc,const struct ib_grh * grh,u32 port_num)91773cdaaeeSIra Weiny struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, const struct ib_wc *wc,
9181fb7f897SMark Bloch 				   const struct ib_grh *grh, u32 port_num)
9194e00d694SSean Hefty {
92090898850SDasaratharaman Chandramouli 	struct rdma_ah_attr ah_attr;
921b7403217SParav Pandit 	struct ib_ah *ah;
9224e00d694SSean Hefty 	int ret;
9234e00d694SSean Hefty 
924f6bdb142SParav Pandit 	ret = ib_init_ah_attr_from_wc(pd->device, port_num, wc, grh, &ah_attr);
9254e00d694SSean Hefty 	if (ret)
9264e00d694SSean Hefty 		return ERR_PTR(ret);
927513789edSHal Rosenstock 
928b090c4e3SGal Pressman 	ah = rdma_create_ah(pd, &ah_attr, RDMA_CREATE_AH_SLEEPABLE);
929b7403217SParav Pandit 
930b7403217SParav Pandit 	rdma_destroy_ah_attr(&ah_attr);
931b7403217SParav Pandit 	return ah;
932513789edSHal Rosenstock }
933513789edSHal Rosenstock EXPORT_SYMBOL(ib_create_ah_from_wc);
934513789edSHal Rosenstock 
rdma_modify_ah(struct ib_ah * ah,struct rdma_ah_attr * ah_attr)93567b985b6SDasaratharaman Chandramouli int rdma_modify_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr)
9361da177e4SLinus Torvalds {
9378d9ec9adSJason Gunthorpe 	const struct ib_gid_attr *old_sgid_attr;
9388d9ec9adSJason Gunthorpe 	int ret;
9398d9ec9adSJason Gunthorpe 
94044c58487SDasaratharaman Chandramouli 	if (ah->type != ah_attr->type)
94144c58487SDasaratharaman Chandramouli 		return -EINVAL;
94244c58487SDasaratharaman Chandramouli 
9438d9ec9adSJason Gunthorpe 	ret = rdma_fill_sgid_attr(ah->device, ah_attr, &old_sgid_attr);
9448d9ec9adSJason Gunthorpe 	if (ret)
9458d9ec9adSJason Gunthorpe 		return ret;
9468d9ec9adSJason Gunthorpe 
9473023a1e9SKamal Heib 	ret = ah->device->ops.modify_ah ?
9483023a1e9SKamal Heib 		ah->device->ops.modify_ah(ah, ah_attr) :
94987915bf8SLeon Romanovsky 		-EOPNOTSUPP;
9508d9ec9adSJason Gunthorpe 
9511a1f460fSJason Gunthorpe 	ah->sgid_attr = rdma_update_sgid_attr(ah_attr, ah->sgid_attr);
9528d9ec9adSJason Gunthorpe 	rdma_unfill_sgid_attr(ah_attr, old_sgid_attr);
9538d9ec9adSJason Gunthorpe 	return ret;
9541da177e4SLinus Torvalds }
95567b985b6SDasaratharaman Chandramouli EXPORT_SYMBOL(rdma_modify_ah);
9561da177e4SLinus Torvalds 
rdma_query_ah(struct ib_ah * ah,struct rdma_ah_attr * ah_attr)957bfbfd661SDasaratharaman Chandramouli int rdma_query_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr)
9581da177e4SLinus Torvalds {
9598d9ec9adSJason Gunthorpe 	ah_attr->grh.sgid_attr = NULL;
9608d9ec9adSJason Gunthorpe 
9613023a1e9SKamal Heib 	return ah->device->ops.query_ah ?
9623023a1e9SKamal Heib 		ah->device->ops.query_ah(ah, ah_attr) :
96387915bf8SLeon Romanovsky 		-EOPNOTSUPP;
9641da177e4SLinus Torvalds }
965bfbfd661SDasaratharaman Chandramouli EXPORT_SYMBOL(rdma_query_ah);
9661da177e4SLinus Torvalds 
rdma_destroy_ah_user(struct ib_ah * ah,u32 flags,struct ib_udata * udata)967c4367a26SShamir Rabinovitch int rdma_destroy_ah_user(struct ib_ah *ah, u32 flags, struct ib_udata *udata)
9681da177e4SLinus Torvalds {
9691a1f460fSJason Gunthorpe 	const struct ib_gid_attr *sgid_attr = ah->sgid_attr;
9701da177e4SLinus Torvalds 	struct ib_pd *pd;
9719a9ebf8cSLeon Romanovsky 	int ret;
9721da177e4SLinus Torvalds 
9732553ba21SGal Pressman 	might_sleep_if(flags & RDMA_DESTROY_AH_SLEEPABLE);
9742553ba21SGal Pressman 
9751da177e4SLinus Torvalds 	pd = ah->pd;
976d3456914SLeon Romanovsky 
9779a9ebf8cSLeon Romanovsky 	ret = ah->device->ops.destroy_ah(ah, flags);
9789a9ebf8cSLeon Romanovsky 	if (ret)
9799a9ebf8cSLeon Romanovsky 		return ret;
9809a9ebf8cSLeon Romanovsky 
9811da177e4SLinus Torvalds 	atomic_dec(&pd->usecnt);
9821a1f460fSJason Gunthorpe 	if (sgid_attr)
9831a1f460fSJason Gunthorpe 		rdma_put_gid_attr(sgid_attr);
9841da177e4SLinus Torvalds 
985d3456914SLeon Romanovsky 	kfree(ah);
9869a9ebf8cSLeon Romanovsky 	return ret;
9871da177e4SLinus Torvalds }
988c4367a26SShamir Rabinovitch EXPORT_SYMBOL(rdma_destroy_ah_user);
9891da177e4SLinus Torvalds 
990d41fcc67SRoland Dreier /* Shared receive queues */
991d41fcc67SRoland Dreier 
992b0810b03SJason Gunthorpe /**
993b0810b03SJason Gunthorpe  * ib_create_srq_user - Creates a SRQ associated with the specified protection
994b0810b03SJason Gunthorpe  *   domain.
995b0810b03SJason Gunthorpe  * @pd: The protection domain associated with the SRQ.
996b0810b03SJason Gunthorpe  * @srq_init_attr: A list of initial attributes required to create the
997b0810b03SJason Gunthorpe  *   SRQ.  If SRQ creation succeeds, then the attributes are updated to
998b0810b03SJason Gunthorpe  *   the actual capabilities of the created SRQ.
99911708142SColton Lewis  * @uobject: uobject pointer if this is not a kernel SRQ
100011708142SColton Lewis  * @udata: udata pointer if this is not a kernel SRQ
1001b0810b03SJason Gunthorpe  *
1002b0810b03SJason Gunthorpe  * srq_attr->max_wr and srq_attr->max_sge are read the determine the
1003b0810b03SJason Gunthorpe  * requested size of the SRQ, and set to the actual values allocated
1004b0810b03SJason Gunthorpe  * on return.  If ib_create_srq() succeeds, then max_wr and max_sge
1005b0810b03SJason Gunthorpe  * will always be at least as large as the requested values.
1006b0810b03SJason Gunthorpe  */
ib_create_srq_user(struct ib_pd * pd,struct ib_srq_init_attr * srq_init_attr,struct ib_usrq_object * uobject,struct ib_udata * udata)1007b0810b03SJason Gunthorpe struct ib_srq *ib_create_srq_user(struct ib_pd *pd,
1008b0810b03SJason Gunthorpe 				  struct ib_srq_init_attr *srq_init_attr,
1009b0810b03SJason Gunthorpe 				  struct ib_usrq_object *uobject,
1010b0810b03SJason Gunthorpe 				  struct ib_udata *udata)
1011d41fcc67SRoland Dreier {
1012d41fcc67SRoland Dreier 	struct ib_srq *srq;
101368e326deSLeon Romanovsky 	int ret;
1014d41fcc67SRoland Dreier 
101568e326deSLeon Romanovsky 	srq = rdma_zalloc_drv_obj(pd->device, ib_srq);
101668e326deSLeon Romanovsky 	if (!srq)
101768e326deSLeon Romanovsky 		return ERR_PTR(-ENOMEM);
1018d41fcc67SRoland Dreier 
1019d41fcc67SRoland Dreier 	srq->device = pd->device;
1020d41fcc67SRoland Dreier 	srq->pd = pd;
1021d41fcc67SRoland Dreier 	srq->event_handler = srq_init_attr->event_handler;
1022d41fcc67SRoland Dreier 	srq->srq_context = srq_init_attr->srq_context;
102396104edaSSean Hefty 	srq->srq_type = srq_init_attr->srq_type;
1024b0810b03SJason Gunthorpe 	srq->uobject = uobject;
102568e326deSLeon Romanovsky 
10261a56ff6dSArtemy Kovalyov 	if (ib_srq_has_cq(srq->srq_type)) {
10271a56ff6dSArtemy Kovalyov 		srq->ext.cq = srq_init_attr->ext.cq;
10281a56ff6dSArtemy Kovalyov 		atomic_inc(&srq->ext.cq->usecnt);
10291a56ff6dSArtemy Kovalyov 	}
1030418d5130SSean Hefty 	if (srq->srq_type == IB_SRQT_XRC) {
1031418d5130SSean Hefty 		srq->ext.xrc.xrcd = srq_init_attr->ext.xrc.xrcd;
103220da44dfSLeon Romanovsky 		if (srq->ext.xrc.xrcd)
1033418d5130SSean Hefty 			atomic_inc(&srq->ext.xrc.xrcd->usecnt);
1034418d5130SSean Hefty 	}
1035d41fcc67SRoland Dreier 	atomic_inc(&pd->usecnt);
103668e326deSLeon Romanovsky 
103748f8a70eSNeta Ostrovsky 	rdma_restrack_new(&srq->res, RDMA_RESTRACK_SRQ);
103848f8a70eSNeta Ostrovsky 	rdma_restrack_parent_name(&srq->res, &pd->res);
103948f8a70eSNeta Ostrovsky 
1040b0810b03SJason Gunthorpe 	ret = pd->device->ops.create_srq(srq, srq_init_attr, udata);
104168e326deSLeon Romanovsky 	if (ret) {
104248f8a70eSNeta Ostrovsky 		rdma_restrack_put(&srq->res);
1043b300729bSDan Carpenter 		atomic_dec(&pd->usecnt);
104420da44dfSLeon Romanovsky 		if (srq->srq_type == IB_SRQT_XRC && srq->ext.xrc.xrcd)
104568e326deSLeon Romanovsky 			atomic_dec(&srq->ext.xrc.xrcd->usecnt);
104668e326deSLeon Romanovsky 		if (ib_srq_has_cq(srq->srq_type))
104768e326deSLeon Romanovsky 			atomic_dec(&srq->ext.cq->usecnt);
104868e326deSLeon Romanovsky 		kfree(srq);
104968e326deSLeon Romanovsky 		return ERR_PTR(ret);
1050d41fcc67SRoland Dreier 	}
1051d41fcc67SRoland Dreier 
105248f8a70eSNeta Ostrovsky 	rdma_restrack_add(&srq->res);
105348f8a70eSNeta Ostrovsky 
1054d41fcc67SRoland Dreier 	return srq;
1055d41fcc67SRoland Dreier }
1056b0810b03SJason Gunthorpe EXPORT_SYMBOL(ib_create_srq_user);
1057d41fcc67SRoland Dreier 
ib_modify_srq(struct ib_srq * srq,struct ib_srq_attr * srq_attr,enum ib_srq_attr_mask srq_attr_mask)1058d41fcc67SRoland Dreier int ib_modify_srq(struct ib_srq *srq,
1059d41fcc67SRoland Dreier 		  struct ib_srq_attr *srq_attr,
1060d41fcc67SRoland Dreier 		  enum ib_srq_attr_mask srq_attr_mask)
1061d41fcc67SRoland Dreier {
10623023a1e9SKamal Heib 	return srq->device->ops.modify_srq ?
10633023a1e9SKamal Heib 		srq->device->ops.modify_srq(srq, srq_attr, srq_attr_mask,
10643023a1e9SKamal Heib 					    NULL) : -EOPNOTSUPP;
1065d41fcc67SRoland Dreier }
1066d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_modify_srq);
1067d41fcc67SRoland Dreier 
ib_query_srq(struct ib_srq * srq,struct ib_srq_attr * srq_attr)1068d41fcc67SRoland Dreier int ib_query_srq(struct ib_srq *srq,
1069d41fcc67SRoland Dreier 		 struct ib_srq_attr *srq_attr)
1070d41fcc67SRoland Dreier {
10713023a1e9SKamal Heib 	return srq->device->ops.query_srq ?
10723023a1e9SKamal Heib 		srq->device->ops.query_srq(srq, srq_attr) : -EOPNOTSUPP;
1073d41fcc67SRoland Dreier }
1074d41fcc67SRoland Dreier EXPORT_SYMBOL(ib_query_srq);
1075d41fcc67SRoland Dreier 
ib_destroy_srq_user(struct ib_srq * srq,struct ib_udata * udata)1076c4367a26SShamir Rabinovitch int ib_destroy_srq_user(struct ib_srq *srq, struct ib_udata *udata)
1077d41fcc67SRoland Dreier {
1078119181d1SLeon Romanovsky 	int ret;
1079119181d1SLeon Romanovsky 
1080d41fcc67SRoland Dreier 	if (atomic_read(&srq->usecnt))
1081d41fcc67SRoland Dreier 		return -EBUSY;
1082d41fcc67SRoland Dreier 
1083119181d1SLeon Romanovsky 	ret = srq->device->ops.destroy_srq(srq, udata);
1084119181d1SLeon Romanovsky 	if (ret)
1085119181d1SLeon Romanovsky 		return ret;
1086d41fcc67SRoland Dreier 
108768e326deSLeon Romanovsky 	atomic_dec(&srq->pd->usecnt);
108820da44dfSLeon Romanovsky 	if (srq->srq_type == IB_SRQT_XRC && srq->ext.xrc.xrcd)
108968e326deSLeon Romanovsky 		atomic_dec(&srq->ext.xrc.xrcd->usecnt);
109068e326deSLeon Romanovsky 	if (ib_srq_has_cq(srq->srq_type))
109168e326deSLeon Romanovsky 		atomic_dec(&srq->ext.cq->usecnt);
109248f8a70eSNeta Ostrovsky 	rdma_restrack_del(&srq->res);
109368e326deSLeon Romanovsky 	kfree(srq);
1094d41fcc67SRoland Dreier 
1095119181d1SLeon Romanovsky 	return ret;
1096d41fcc67SRoland Dreier }
1097c4367a26SShamir Rabinovitch EXPORT_SYMBOL(ib_destroy_srq_user);
1098d41fcc67SRoland Dreier 
10991da177e4SLinus Torvalds /* Queue pairs */
11001da177e4SLinus Torvalds 
__ib_shared_qp_event_handler(struct ib_event * event,void * context)11010e0ec7e0SSean Hefty static void __ib_shared_qp_event_handler(struct ib_event *event, void *context)
11020e0ec7e0SSean Hefty {
11030e0ec7e0SSean Hefty 	struct ib_qp *qp = context;
110473c40c61SYishai Hadas 	unsigned long flags;
11050e0ec7e0SSean Hefty 
110640adf686SParav Pandit 	spin_lock_irqsave(&qp->device->qp_open_list_lock, flags);
11070e0ec7e0SSean Hefty 	list_for_each_entry(event->element.qp, &qp->open_list, open_list)
1108eec9e29fSShlomo Pongratz 		if (event->element.qp->event_handler)
11090e0ec7e0SSean Hefty 			event->element.qp->event_handler(event, event->element.qp->qp_context);
111040adf686SParav Pandit 	spin_unlock_irqrestore(&qp->device->qp_open_list_lock, flags);
11110e0ec7e0SSean Hefty }
11120e0ec7e0SSean Hefty 
__ib_open_qp(struct ib_qp * real_qp,void (* event_handler)(struct ib_event *,void *),void * qp_context)11130e0ec7e0SSean Hefty static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp,
11140e0ec7e0SSean Hefty 				  void (*event_handler)(struct ib_event *, void *),
11150e0ec7e0SSean Hefty 				  void *qp_context)
1116d3d72d90SSean Hefty {
11170e0ec7e0SSean Hefty 	struct ib_qp *qp;
11180e0ec7e0SSean Hefty 	unsigned long flags;
1119d291f1a6SDaniel Jurgens 	int err;
11200e0ec7e0SSean Hefty 
11210e0ec7e0SSean Hefty 	qp = kzalloc(sizeof *qp, GFP_KERNEL);
11220e0ec7e0SSean Hefty 	if (!qp)
11230e0ec7e0SSean Hefty 		return ERR_PTR(-ENOMEM);
11240e0ec7e0SSean Hefty 
11250e0ec7e0SSean Hefty 	qp->real_qp = real_qp;
1126d291f1a6SDaniel Jurgens 	err = ib_open_shared_qp_security(qp, real_qp->device);
1127d291f1a6SDaniel Jurgens 	if (err) {
1128d291f1a6SDaniel Jurgens 		kfree(qp);
1129d291f1a6SDaniel Jurgens 		return ERR_PTR(err);
1130d291f1a6SDaniel Jurgens 	}
1131d291f1a6SDaniel Jurgens 
1132d291f1a6SDaniel Jurgens 	qp->real_qp = real_qp;
11330e0ec7e0SSean Hefty 	atomic_inc(&real_qp->usecnt);
11340e0ec7e0SSean Hefty 	qp->device = real_qp->device;
11350e0ec7e0SSean Hefty 	qp->event_handler = event_handler;
11360e0ec7e0SSean Hefty 	qp->qp_context = qp_context;
11370e0ec7e0SSean Hefty 	qp->qp_num = real_qp->qp_num;
11380e0ec7e0SSean Hefty 	qp->qp_type = real_qp->qp_type;
11390e0ec7e0SSean Hefty 
114040adf686SParav Pandit 	spin_lock_irqsave(&real_qp->device->qp_open_list_lock, flags);
11410e0ec7e0SSean Hefty 	list_add(&qp->open_list, &real_qp->open_list);
114240adf686SParav Pandit 	spin_unlock_irqrestore(&real_qp->device->qp_open_list_lock, flags);
11430e0ec7e0SSean Hefty 
11440e0ec7e0SSean Hefty 	return qp;
1145d3d72d90SSean Hefty }
1146d3d72d90SSean Hefty 
ib_open_qp(struct ib_xrcd * xrcd,struct ib_qp_open_attr * qp_open_attr)11470e0ec7e0SSean Hefty struct ib_qp *ib_open_qp(struct ib_xrcd *xrcd,
11480e0ec7e0SSean Hefty 			 struct ib_qp_open_attr *qp_open_attr)
11490e0ec7e0SSean Hefty {
11500e0ec7e0SSean Hefty 	struct ib_qp *qp, *real_qp;
11510e0ec7e0SSean Hefty 
11520e0ec7e0SSean Hefty 	if (qp_open_attr->qp_type != IB_QPT_XRC_TGT)
11530e0ec7e0SSean Hefty 		return ERR_PTR(-EINVAL);
11540e0ec7e0SSean Hefty 
11556f3ca6f4SMaor Gottlieb 	down_read(&xrcd->tgt_qps_rwsem);
11566f3ca6f4SMaor Gottlieb 	real_qp = xa_load(&xrcd->tgt_qps, qp_open_attr->qp_num);
11576f3ca6f4SMaor Gottlieb 	if (!real_qp) {
11586f3ca6f4SMaor Gottlieb 		up_read(&xrcd->tgt_qps_rwsem);
11596f3ca6f4SMaor Gottlieb 		return ERR_PTR(-EINVAL);
11606f3ca6f4SMaor Gottlieb 	}
11610e0ec7e0SSean Hefty 	qp = __ib_open_qp(real_qp, qp_open_attr->event_handler,
11620e0ec7e0SSean Hefty 			  qp_open_attr->qp_context);
11636f3ca6f4SMaor Gottlieb 	up_read(&xrcd->tgt_qps_rwsem);
11640e0ec7e0SSean Hefty 	return qp;
11650e0ec7e0SSean Hefty }
11660e0ec7e0SSean Hefty EXPORT_SYMBOL(ib_open_qp);
11670e0ec7e0SSean Hefty 
create_xrc_qp_user(struct ib_qp * qp,struct ib_qp_init_attr * qp_init_attr)1168c4367a26SShamir Rabinovitch static struct ib_qp *create_xrc_qp_user(struct ib_qp *qp,
1169b72bfc96SJason Gunthorpe 					struct ib_qp_init_attr *qp_init_attr)
11701da177e4SLinus Torvalds {
117104c41bf3SChristoph Hellwig 	struct ib_qp *real_qp = qp;
11726f3ca6f4SMaor Gottlieb 	int err;
11731da177e4SLinus Torvalds 
11740e0ec7e0SSean Hefty 	qp->event_handler = __ib_shared_qp_event_handler;
11750e0ec7e0SSean Hefty 	qp->qp_context = qp;
1176b42b63cfSSean Hefty 	qp->pd = NULL;
1177b42b63cfSSean Hefty 	qp->send_cq = qp->recv_cq = NULL;
1178b42b63cfSSean Hefty 	qp->srq = NULL;
1179b42b63cfSSean Hefty 	qp->xrcd = qp_init_attr->xrcd;
1180b42b63cfSSean Hefty 	atomic_inc(&qp_init_attr->xrcd->usecnt);
11810e0ec7e0SSean Hefty 	INIT_LIST_HEAD(&qp->open_list);
11820e0ec7e0SSean Hefty 
11830e0ec7e0SSean Hefty 	qp = __ib_open_qp(real_qp, qp_init_attr->event_handler,
11840e0ec7e0SSean Hefty 			  qp_init_attr->qp_context);
1185535005caSYuval Avnery 	if (IS_ERR(qp))
1186535005caSYuval Avnery 		return qp;
1187535005caSYuval Avnery 
11886f3ca6f4SMaor Gottlieb 	err = xa_err(xa_store(&qp_init_attr->xrcd->tgt_qps, real_qp->qp_num,
11896f3ca6f4SMaor Gottlieb 			      real_qp, GFP_KERNEL));
11906f3ca6f4SMaor Gottlieb 	if (err) {
11916f3ca6f4SMaor Gottlieb 		ib_close_qp(qp);
11926f3ca6f4SMaor Gottlieb 		return ERR_PTR(err);
11936f3ca6f4SMaor Gottlieb 	}
119404c41bf3SChristoph Hellwig 	return qp;
119504c41bf3SChristoph Hellwig }
119604c41bf3SChristoph Hellwig 
create_qp(struct ib_device * dev,struct ib_pd * pd,struct ib_qp_init_attr * attr,struct ib_udata * udata,struct ib_uqp_object * uobj,const char * caller)1197d2b10794SLeon Romanovsky static struct ib_qp *create_qp(struct ib_device *dev, struct ib_pd *pd,
11988da9fe4eSLeon Romanovsky 			       struct ib_qp_init_attr *attr,
1199d2b10794SLeon Romanovsky 			       struct ib_udata *udata,
1200d2b10794SLeon Romanovsky 			       struct ib_uqp_object *uobj, const char *caller)
12018da9fe4eSLeon Romanovsky {
120200a79d6bSLeon Romanovsky 	struct ib_udata dummy = {};
12038da9fe4eSLeon Romanovsky 	struct ib_qp *qp;
12048da9fe4eSLeon Romanovsky 	int ret;
12058da9fe4eSLeon Romanovsky 
12068da9fe4eSLeon Romanovsky 	if (!dev->ops.create_qp)
12078da9fe4eSLeon Romanovsky 		return ERR_PTR(-EOPNOTSUPP);
12088da9fe4eSLeon Romanovsky 
12098da9fe4eSLeon Romanovsky 	qp = rdma_zalloc_drv_obj_numa(dev, ib_qp);
12108da9fe4eSLeon Romanovsky 	if (!qp)
12118da9fe4eSLeon Romanovsky 		return ERR_PTR(-ENOMEM);
12128da9fe4eSLeon Romanovsky 
12138da9fe4eSLeon Romanovsky 	qp->device = dev;
12148da9fe4eSLeon Romanovsky 	qp->pd = pd;
12158da9fe4eSLeon Romanovsky 	qp->uobject = uobj;
12168da9fe4eSLeon Romanovsky 	qp->real_qp = qp;
12178da9fe4eSLeon Romanovsky 
12188da9fe4eSLeon Romanovsky 	qp->qp_type = attr->qp_type;
12198da9fe4eSLeon Romanovsky 	qp->rwq_ind_tbl = attr->rwq_ind_tbl;
12208da9fe4eSLeon Romanovsky 	qp->srq = attr->srq;
12218da9fe4eSLeon Romanovsky 	qp->event_handler = attr->event_handler;
12228da9fe4eSLeon Romanovsky 	qp->port = attr->port_num;
12238da9fe4eSLeon Romanovsky 	qp->qp_context = attr->qp_context;
12248da9fe4eSLeon Romanovsky 
12258da9fe4eSLeon Romanovsky 	spin_lock_init(&qp->mr_lock);
12268da9fe4eSLeon Romanovsky 	INIT_LIST_HEAD(&qp->rdma_mrs);
12278da9fe4eSLeon Romanovsky 	INIT_LIST_HEAD(&qp->sig_mrs);
12288da9fe4eSLeon Romanovsky 
12296cd7397dSLeon Romanovsky 	qp->send_cq = attr->send_cq;
12306cd7397dSLeon Romanovsky 	qp->recv_cq = attr->recv_cq;
12316cd7397dSLeon Romanovsky 
12328da9fe4eSLeon Romanovsky 	rdma_restrack_new(&qp->res, RDMA_RESTRACK_QP);
12338da9fe4eSLeon Romanovsky 	WARN_ONCE(!udata && !caller, "Missing kernel QP owner");
12348da9fe4eSLeon Romanovsky 	rdma_restrack_set_name(&qp->res, udata ? NULL : caller);
12358da9fe4eSLeon Romanovsky 	ret = dev->ops.create_qp(qp, attr, udata);
12368da9fe4eSLeon Romanovsky 	if (ret)
12378da9fe4eSLeon Romanovsky 		goto err_create;
12388da9fe4eSLeon Romanovsky 
12398da9fe4eSLeon Romanovsky 	/*
12408da9fe4eSLeon Romanovsky 	 * TODO: The mlx4 internally overwrites send_cq and recv_cq.
12418da9fe4eSLeon Romanovsky 	 * Unfortunately, it is not an easy task to fix that driver.
12428da9fe4eSLeon Romanovsky 	 */
12438da9fe4eSLeon Romanovsky 	qp->send_cq = attr->send_cq;
12448da9fe4eSLeon Romanovsky 	qp->recv_cq = attr->recv_cq;
12458da9fe4eSLeon Romanovsky 
124600a79d6bSLeon Romanovsky 	ret = ib_create_qp_security(qp, dev);
124700a79d6bSLeon Romanovsky 	if (ret)
124800a79d6bSLeon Romanovsky 		goto err_security;
124900a79d6bSLeon Romanovsky 
12508da9fe4eSLeon Romanovsky 	rdma_restrack_add(&qp->res);
12518da9fe4eSLeon Romanovsky 	return qp;
12528da9fe4eSLeon Romanovsky 
125300a79d6bSLeon Romanovsky err_security:
125400a79d6bSLeon Romanovsky 	qp->device->ops.destroy_qp(qp, udata ? &dummy : NULL);
12558da9fe4eSLeon Romanovsky err_create:
12568da9fe4eSLeon Romanovsky 	rdma_restrack_put(&qp->res);
12578da9fe4eSLeon Romanovsky 	kfree(qp);
12588da9fe4eSLeon Romanovsky 	return ERR_PTR(ret);
12598da9fe4eSLeon Romanovsky 
12608da9fe4eSLeon Romanovsky }
1261d2b10794SLeon Romanovsky 
1262d2b10794SLeon Romanovsky /**
1263d2b10794SLeon Romanovsky  * ib_create_qp_user - Creates a QP associated with the specified protection
1264d2b10794SLeon Romanovsky  *   domain.
1265d2b10794SLeon Romanovsky  * @dev: IB device
1266d2b10794SLeon Romanovsky  * @pd: The protection domain associated with the QP.
1267d2b10794SLeon Romanovsky  * @attr: A list of initial attributes required to create the
1268d2b10794SLeon Romanovsky  *   QP.  If QP creation succeeds, then the attributes are updated to
1269d2b10794SLeon Romanovsky  *   the actual capabilities of the created QP.
1270d2b10794SLeon Romanovsky  * @udata: User data
1271d2b10794SLeon Romanovsky  * @uobj: uverbs obect
1272d2b10794SLeon Romanovsky  * @caller: caller's build-time module name
1273d2b10794SLeon Romanovsky  */
ib_create_qp_user(struct ib_device * dev,struct ib_pd * pd,struct ib_qp_init_attr * attr,struct ib_udata * udata,struct ib_uqp_object * uobj,const char * caller)1274d2b10794SLeon Romanovsky struct ib_qp *ib_create_qp_user(struct ib_device *dev, struct ib_pd *pd,
1275d2b10794SLeon Romanovsky 				struct ib_qp_init_attr *attr,
1276d2b10794SLeon Romanovsky 				struct ib_udata *udata,
1277d2b10794SLeon Romanovsky 				struct ib_uqp_object *uobj, const char *caller)
1278d2b10794SLeon Romanovsky {
1279d2b10794SLeon Romanovsky 	struct ib_qp *qp, *xrc_qp;
1280d2b10794SLeon Romanovsky 
1281d2b10794SLeon Romanovsky 	if (attr->qp_type == IB_QPT_XRC_TGT)
1282d2b10794SLeon Romanovsky 		qp = create_qp(dev, pd, attr, NULL, NULL, caller);
1283d2b10794SLeon Romanovsky 	else
1284d2b10794SLeon Romanovsky 		qp = create_qp(dev, pd, attr, udata, uobj, NULL);
1285d2b10794SLeon Romanovsky 	if (attr->qp_type != IB_QPT_XRC_TGT || IS_ERR(qp))
1286d2b10794SLeon Romanovsky 		return qp;
1287d2b10794SLeon Romanovsky 
1288d2b10794SLeon Romanovsky 	xrc_qp = create_xrc_qp_user(qp, attr);
1289d2b10794SLeon Romanovsky 	if (IS_ERR(xrc_qp)) {
1290d2b10794SLeon Romanovsky 		ib_destroy_qp(qp);
1291d2b10794SLeon Romanovsky 		return xrc_qp;
1292d2b10794SLeon Romanovsky 	}
1293d2b10794SLeon Romanovsky 
1294d2b10794SLeon Romanovsky 	xrc_qp->uobject = uobj;
1295d2b10794SLeon Romanovsky 	return xrc_qp;
1296d2b10794SLeon Romanovsky }
1297d2b10794SLeon Romanovsky EXPORT_SYMBOL(ib_create_qp_user);
12988da9fe4eSLeon Romanovsky 
ib_qp_usecnt_inc(struct ib_qp * qp)12995507f67dSLeon Romanovsky void ib_qp_usecnt_inc(struct ib_qp *qp)
13005507f67dSLeon Romanovsky {
13015507f67dSLeon Romanovsky 	if (qp->pd)
13025507f67dSLeon Romanovsky 		atomic_inc(&qp->pd->usecnt);
13035507f67dSLeon Romanovsky 	if (qp->send_cq)
13045507f67dSLeon Romanovsky 		atomic_inc(&qp->send_cq->usecnt);
13055507f67dSLeon Romanovsky 	if (qp->recv_cq)
13065507f67dSLeon Romanovsky 		atomic_inc(&qp->recv_cq->usecnt);
13075507f67dSLeon Romanovsky 	if (qp->srq)
13085507f67dSLeon Romanovsky 		atomic_inc(&qp->srq->usecnt);
13095507f67dSLeon Romanovsky 	if (qp->rwq_ind_tbl)
13105507f67dSLeon Romanovsky 		atomic_inc(&qp->rwq_ind_tbl->usecnt);
13115507f67dSLeon Romanovsky }
13125507f67dSLeon Romanovsky EXPORT_SYMBOL(ib_qp_usecnt_inc);
13135507f67dSLeon Romanovsky 
ib_qp_usecnt_dec(struct ib_qp * qp)13145507f67dSLeon Romanovsky void ib_qp_usecnt_dec(struct ib_qp *qp)
13155507f67dSLeon Romanovsky {
13165507f67dSLeon Romanovsky 	if (qp->rwq_ind_tbl)
13175507f67dSLeon Romanovsky 		atomic_dec(&qp->rwq_ind_tbl->usecnt);
13185507f67dSLeon Romanovsky 	if (qp->srq)
13195507f67dSLeon Romanovsky 		atomic_dec(&qp->srq->usecnt);
13205507f67dSLeon Romanovsky 	if (qp->recv_cq)
13215507f67dSLeon Romanovsky 		atomic_dec(&qp->recv_cq->usecnt);
13225507f67dSLeon Romanovsky 	if (qp->send_cq)
13235507f67dSLeon Romanovsky 		atomic_dec(&qp->send_cq->usecnt);
13245507f67dSLeon Romanovsky 	if (qp->pd)
13255507f67dSLeon Romanovsky 		atomic_dec(&qp->pd->usecnt);
13265507f67dSLeon Romanovsky }
13275507f67dSLeon Romanovsky EXPORT_SYMBOL(ib_qp_usecnt_dec);
13285507f67dSLeon Romanovsky 
ib_create_qp_kernel(struct ib_pd * pd,struct ib_qp_init_attr * qp_init_attr,const char * caller)13298da9fe4eSLeon Romanovsky struct ib_qp *ib_create_qp_kernel(struct ib_pd *pd,
133066f57b87SLeon Romanovsky 				  struct ib_qp_init_attr *qp_init_attr,
133166f57b87SLeon Romanovsky 				  const char *caller)
133204c41bf3SChristoph Hellwig {
1333d2b10794SLeon Romanovsky 	struct ib_device *device = pd->device;
133404c41bf3SChristoph Hellwig 	struct ib_qp *qp;
1335a060b562SChristoph Hellwig 	int ret;
1336a060b562SChristoph Hellwig 
1337a060b562SChristoph Hellwig 	/*
1338a060b562SChristoph Hellwig 	 * If the callers is using the RDMA API calculate the resources
1339a060b562SChristoph Hellwig 	 * needed for the RDMA READ/WRITE operations.
1340a060b562SChristoph Hellwig 	 *
1341a060b562SChristoph Hellwig 	 * Note that these callers need to pass in a port number.
1342a060b562SChristoph Hellwig 	 */
1343a060b562SChristoph Hellwig 	if (qp_init_attr->cap.max_rdma_ctxs)
1344a060b562SChristoph Hellwig 		rdma_rw_init_qp(device, qp_init_attr);
134504c41bf3SChristoph Hellwig 
1346d2b10794SLeon Romanovsky 	qp = create_qp(device, pd, qp_init_attr, NULL, NULL, caller);
134704c41bf3SChristoph Hellwig 	if (IS_ERR(qp))
134804c41bf3SChristoph Hellwig 		return qp;
134904c41bf3SChristoph Hellwig 
13507922d3deSLeon Romanovsky 	ib_qp_usecnt_inc(qp);
13517922d3deSLeon Romanovsky 
1352a060b562SChristoph Hellwig 	if (qp_init_attr->cap.max_rdma_ctxs) {
1353a060b562SChristoph Hellwig 		ret = rdma_rw_init_mrs(qp, qp_init_attr);
1354535005caSYuval Avnery 		if (ret)
1355535005caSYuval Avnery 			goto err;
1356a060b562SChristoph Hellwig 	}
1357a060b562SChristoph Hellwig 
1358632bc3f6SBart Van Assche 	/*
1359632bc3f6SBart Van Assche 	 * Note: all hw drivers guarantee that max_send_sge is lower than
1360632bc3f6SBart Van Assche 	 * the device RDMA WRITE SGE limit but not all hw drivers ensure that
1361632bc3f6SBart Van Assche 	 * max_send_sge <= max_sge_rd.
1362632bc3f6SBart Van Assche 	 */
1363632bc3f6SBart Van Assche 	qp->max_write_sge = qp_init_attr->cap.max_send_sge;
1364632bc3f6SBart Van Assche 	qp->max_read_sge = min_t(u32, qp_init_attr->cap.max_send_sge,
1365632bc3f6SBart Van Assche 				 device->attrs.max_sge_rd);
1366185eddc4SMax Gurtovoy 	if (qp_init_attr->create_flags & IB_QP_CREATE_INTEGRITY_EN)
1367185eddc4SMax Gurtovoy 		qp->integrity_en = true;
1368632bc3f6SBart Van Assche 
13691da177e4SLinus Torvalds 	return qp;
1370535005caSYuval Avnery 
1371535005caSYuval Avnery err:
1372535005caSYuval Avnery 	ib_destroy_qp(qp);
1373535005caSYuval Avnery 	return ERR_PTR(ret);
1374535005caSYuval Avnery 
13751da177e4SLinus Torvalds }
13768da9fe4eSLeon Romanovsky EXPORT_SYMBOL(ib_create_qp_kernel);
13771da177e4SLinus Torvalds 
13788a51866fSRoland Dreier static const struct {
13798a51866fSRoland Dreier 	int			valid;
1380b42b63cfSSean Hefty 	enum ib_qp_attr_mask	req_param[IB_QPT_MAX];
1381b42b63cfSSean Hefty 	enum ib_qp_attr_mask	opt_param[IB_QPT_MAX];
13828a51866fSRoland Dreier } qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
13838a51866fSRoland Dreier 	[IB_QPS_RESET] = {
13848a51866fSRoland Dreier 		[IB_QPS_RESET] = { .valid = 1 },
13858a51866fSRoland Dreier 		[IB_QPS_INIT]  = {
13868a51866fSRoland Dreier 			.valid = 1,
13878a51866fSRoland Dreier 			.req_param = {
13888a51866fSRoland Dreier 				[IB_QPT_UD]  = (IB_QP_PKEY_INDEX		|
13898a51866fSRoland Dreier 						IB_QP_PORT			|
13908a51866fSRoland Dreier 						IB_QP_QKEY),
1391c938a616SOr Gerlitz 				[IB_QPT_RAW_PACKET] = IB_QP_PORT,
13928a51866fSRoland Dreier 				[IB_QPT_UC]  = (IB_QP_PKEY_INDEX		|
13938a51866fSRoland Dreier 						IB_QP_PORT			|
13948a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS),
13958a51866fSRoland Dreier 				[IB_QPT_RC]  = (IB_QP_PKEY_INDEX		|
13968a51866fSRoland Dreier 						IB_QP_PORT			|
13978a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS),
1398b42b63cfSSean Hefty 				[IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX		|
1399b42b63cfSSean Hefty 						IB_QP_PORT			|
1400b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS),
1401b42b63cfSSean Hefty 				[IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX		|
1402b42b63cfSSean Hefty 						IB_QP_PORT			|
1403b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS),
14048a51866fSRoland Dreier 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
14058a51866fSRoland Dreier 						IB_QP_QKEY),
14068a51866fSRoland Dreier 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
14078a51866fSRoland Dreier 						IB_QP_QKEY),
14088a51866fSRoland Dreier 			}
14098a51866fSRoland Dreier 		},
14108a51866fSRoland Dreier 	},
14118a51866fSRoland Dreier 	[IB_QPS_INIT]  = {
14128a51866fSRoland Dreier 		[IB_QPS_RESET] = { .valid = 1 },
14138a51866fSRoland Dreier 		[IB_QPS_ERR] =   { .valid = 1 },
14148a51866fSRoland Dreier 		[IB_QPS_INIT]  = {
14158a51866fSRoland Dreier 			.valid = 1,
14168a51866fSRoland Dreier 			.opt_param = {
14178a51866fSRoland Dreier 				[IB_QPT_UD]  = (IB_QP_PKEY_INDEX		|
14188a51866fSRoland Dreier 						IB_QP_PORT			|
14198a51866fSRoland Dreier 						IB_QP_QKEY),
14208a51866fSRoland Dreier 				[IB_QPT_UC]  = (IB_QP_PKEY_INDEX		|
14218a51866fSRoland Dreier 						IB_QP_PORT			|
14228a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS),
14238a51866fSRoland Dreier 				[IB_QPT_RC]  = (IB_QP_PKEY_INDEX		|
14248a51866fSRoland Dreier 						IB_QP_PORT			|
14258a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS),
1426b42b63cfSSean Hefty 				[IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX		|
1427b42b63cfSSean Hefty 						IB_QP_PORT			|
1428b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS),
1429b42b63cfSSean Hefty 				[IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX		|
1430b42b63cfSSean Hefty 						IB_QP_PORT			|
1431b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS),
14328a51866fSRoland Dreier 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
14338a51866fSRoland Dreier 						IB_QP_QKEY),
14348a51866fSRoland Dreier 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
14358a51866fSRoland Dreier 						IB_QP_QKEY),
14368a51866fSRoland Dreier 			}
14378a51866fSRoland Dreier 		},
14388a51866fSRoland Dreier 		[IB_QPS_RTR]   = {
14398a51866fSRoland Dreier 			.valid = 1,
14408a51866fSRoland Dreier 			.req_param = {
14418a51866fSRoland Dreier 				[IB_QPT_UC]  = (IB_QP_AV			|
14428a51866fSRoland Dreier 						IB_QP_PATH_MTU			|
14438a51866fSRoland Dreier 						IB_QP_DEST_QPN			|
14448a51866fSRoland Dreier 						IB_QP_RQ_PSN),
14458a51866fSRoland Dreier 				[IB_QPT_RC]  = (IB_QP_AV			|
14468a51866fSRoland Dreier 						IB_QP_PATH_MTU			|
14478a51866fSRoland Dreier 						IB_QP_DEST_QPN			|
14488a51866fSRoland Dreier 						IB_QP_RQ_PSN			|
14498a51866fSRoland Dreier 						IB_QP_MAX_DEST_RD_ATOMIC	|
14508a51866fSRoland Dreier 						IB_QP_MIN_RNR_TIMER),
1451b42b63cfSSean Hefty 				[IB_QPT_XRC_INI] = (IB_QP_AV			|
1452b42b63cfSSean Hefty 						IB_QP_PATH_MTU			|
1453b42b63cfSSean Hefty 						IB_QP_DEST_QPN			|
1454b42b63cfSSean Hefty 						IB_QP_RQ_PSN),
1455b42b63cfSSean Hefty 				[IB_QPT_XRC_TGT] = (IB_QP_AV			|
1456b42b63cfSSean Hefty 						IB_QP_PATH_MTU			|
1457b42b63cfSSean Hefty 						IB_QP_DEST_QPN			|
1458b42b63cfSSean Hefty 						IB_QP_RQ_PSN			|
1459b42b63cfSSean Hefty 						IB_QP_MAX_DEST_RD_ATOMIC	|
1460b42b63cfSSean Hefty 						IB_QP_MIN_RNR_TIMER),
14618a51866fSRoland Dreier 			},
14628a51866fSRoland Dreier 			.opt_param = {
14638a51866fSRoland Dreier 				 [IB_QPT_UD]  = (IB_QP_PKEY_INDEX		|
14648a51866fSRoland Dreier 						 IB_QP_QKEY),
14658a51866fSRoland Dreier 				 [IB_QPT_UC]  = (IB_QP_ALT_PATH			|
14668a51866fSRoland Dreier 						 IB_QP_ACCESS_FLAGS		|
14678a51866fSRoland Dreier 						 IB_QP_PKEY_INDEX),
14688a51866fSRoland Dreier 				 [IB_QPT_RC]  = (IB_QP_ALT_PATH			|
14698a51866fSRoland Dreier 						 IB_QP_ACCESS_FLAGS		|
14708a51866fSRoland Dreier 						 IB_QP_PKEY_INDEX),
1471b42b63cfSSean Hefty 				 [IB_QPT_XRC_INI] = (IB_QP_ALT_PATH		|
1472b42b63cfSSean Hefty 						 IB_QP_ACCESS_FLAGS		|
1473b42b63cfSSean Hefty 						 IB_QP_PKEY_INDEX),
1474b42b63cfSSean Hefty 				 [IB_QPT_XRC_TGT] = (IB_QP_ALT_PATH		|
1475b42b63cfSSean Hefty 						 IB_QP_ACCESS_FLAGS		|
1476b42b63cfSSean Hefty 						 IB_QP_PKEY_INDEX),
14778a51866fSRoland Dreier 				 [IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
14788a51866fSRoland Dreier 						 IB_QP_QKEY),
14798a51866fSRoland Dreier 				 [IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
14808a51866fSRoland Dreier 						 IB_QP_QKEY),
1481dd5f03beSMatan Barak 			 },
1482dbf727deSMatan Barak 		},
14838a51866fSRoland Dreier 	},
14848a51866fSRoland Dreier 	[IB_QPS_RTR]   = {
14858a51866fSRoland Dreier 		[IB_QPS_RESET] = { .valid = 1 },
14868a51866fSRoland Dreier 		[IB_QPS_ERR] =   { .valid = 1 },
14878a51866fSRoland Dreier 		[IB_QPS_RTS]   = {
14888a51866fSRoland Dreier 			.valid = 1,
14898a51866fSRoland Dreier 			.req_param = {
14908a51866fSRoland Dreier 				[IB_QPT_UD]  = IB_QP_SQ_PSN,
14918a51866fSRoland Dreier 				[IB_QPT_UC]  = IB_QP_SQ_PSN,
14928a51866fSRoland Dreier 				[IB_QPT_RC]  = (IB_QP_TIMEOUT			|
14938a51866fSRoland Dreier 						IB_QP_RETRY_CNT			|
14948a51866fSRoland Dreier 						IB_QP_RNR_RETRY			|
14958a51866fSRoland Dreier 						IB_QP_SQ_PSN			|
14968a51866fSRoland Dreier 						IB_QP_MAX_QP_RD_ATOMIC),
1497b42b63cfSSean Hefty 				[IB_QPT_XRC_INI] = (IB_QP_TIMEOUT		|
1498b42b63cfSSean Hefty 						IB_QP_RETRY_CNT			|
1499b42b63cfSSean Hefty 						IB_QP_RNR_RETRY			|
1500b42b63cfSSean Hefty 						IB_QP_SQ_PSN			|
1501b42b63cfSSean Hefty 						IB_QP_MAX_QP_RD_ATOMIC),
1502b42b63cfSSean Hefty 				[IB_QPT_XRC_TGT] = (IB_QP_TIMEOUT		|
1503b42b63cfSSean Hefty 						IB_QP_SQ_PSN),
15048a51866fSRoland Dreier 				[IB_QPT_SMI] = IB_QP_SQ_PSN,
15058a51866fSRoland Dreier 				[IB_QPT_GSI] = IB_QP_SQ_PSN,
15068a51866fSRoland Dreier 			},
15078a51866fSRoland Dreier 			.opt_param = {
15088a51866fSRoland Dreier 				 [IB_QPT_UD]  = (IB_QP_CUR_STATE		|
15098a51866fSRoland Dreier 						 IB_QP_QKEY),
15108a51866fSRoland Dreier 				 [IB_QPT_UC]  = (IB_QP_CUR_STATE		|
15118a51866fSRoland Dreier 						 IB_QP_ALT_PATH			|
15128a51866fSRoland Dreier 						 IB_QP_ACCESS_FLAGS		|
15138a51866fSRoland Dreier 						 IB_QP_PATH_MIG_STATE),
15148a51866fSRoland Dreier 				 [IB_QPT_RC]  = (IB_QP_CUR_STATE		|
15158a51866fSRoland Dreier 						 IB_QP_ALT_PATH			|
15168a51866fSRoland Dreier 						 IB_QP_ACCESS_FLAGS		|
15178a51866fSRoland Dreier 						 IB_QP_MIN_RNR_TIMER		|
15188a51866fSRoland Dreier 						 IB_QP_PATH_MIG_STATE),
1519b42b63cfSSean Hefty 				 [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE		|
1520b42b63cfSSean Hefty 						 IB_QP_ALT_PATH			|
1521b42b63cfSSean Hefty 						 IB_QP_ACCESS_FLAGS		|
1522b42b63cfSSean Hefty 						 IB_QP_PATH_MIG_STATE),
1523b42b63cfSSean Hefty 				 [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE		|
1524b42b63cfSSean Hefty 						 IB_QP_ALT_PATH			|
1525b42b63cfSSean Hefty 						 IB_QP_ACCESS_FLAGS		|
1526b42b63cfSSean Hefty 						 IB_QP_MIN_RNR_TIMER		|
1527b42b63cfSSean Hefty 						 IB_QP_PATH_MIG_STATE),
15288a51866fSRoland Dreier 				 [IB_QPT_SMI] = (IB_QP_CUR_STATE		|
15298a51866fSRoland Dreier 						 IB_QP_QKEY),
15308a51866fSRoland Dreier 				 [IB_QPT_GSI] = (IB_QP_CUR_STATE		|
15318a51866fSRoland Dreier 						 IB_QP_QKEY),
1532528e5a1bSBodong Wang 				 [IB_QPT_RAW_PACKET] = IB_QP_RATE_LIMIT,
15338a51866fSRoland Dreier 			 }
15348a51866fSRoland Dreier 		}
15358a51866fSRoland Dreier 	},
15368a51866fSRoland Dreier 	[IB_QPS_RTS]   = {
15378a51866fSRoland Dreier 		[IB_QPS_RESET] = { .valid = 1 },
15388a51866fSRoland Dreier 		[IB_QPS_ERR] =   { .valid = 1 },
15398a51866fSRoland Dreier 		[IB_QPS_RTS]   = {
15408a51866fSRoland Dreier 			.valid = 1,
15418a51866fSRoland Dreier 			.opt_param = {
15428a51866fSRoland Dreier 				[IB_QPT_UD]  = (IB_QP_CUR_STATE			|
15438a51866fSRoland Dreier 						IB_QP_QKEY),
15444546d31dSDotan Barak 				[IB_QPT_UC]  = (IB_QP_CUR_STATE			|
15454546d31dSDotan Barak 						IB_QP_ACCESS_FLAGS		|
15468a51866fSRoland Dreier 						IB_QP_ALT_PATH			|
15478a51866fSRoland Dreier 						IB_QP_PATH_MIG_STATE),
15484546d31dSDotan Barak 				[IB_QPT_RC]  = (IB_QP_CUR_STATE			|
15494546d31dSDotan Barak 						IB_QP_ACCESS_FLAGS		|
15508a51866fSRoland Dreier 						IB_QP_ALT_PATH			|
15518a51866fSRoland Dreier 						IB_QP_PATH_MIG_STATE		|
15528a51866fSRoland Dreier 						IB_QP_MIN_RNR_TIMER),
1553b42b63cfSSean Hefty 				[IB_QPT_XRC_INI] = (IB_QP_CUR_STATE		|
1554b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS		|
1555b42b63cfSSean Hefty 						IB_QP_ALT_PATH			|
1556b42b63cfSSean Hefty 						IB_QP_PATH_MIG_STATE),
1557b42b63cfSSean Hefty 				[IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE		|
1558b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS		|
1559b42b63cfSSean Hefty 						IB_QP_ALT_PATH			|
1560b42b63cfSSean Hefty 						IB_QP_PATH_MIG_STATE		|
1561b42b63cfSSean Hefty 						IB_QP_MIN_RNR_TIMER),
15628a51866fSRoland Dreier 				[IB_QPT_SMI] = (IB_QP_CUR_STATE			|
15638a51866fSRoland Dreier 						IB_QP_QKEY),
15648a51866fSRoland Dreier 				[IB_QPT_GSI] = (IB_QP_CUR_STATE			|
15658a51866fSRoland Dreier 						IB_QP_QKEY),
1566528e5a1bSBodong Wang 				[IB_QPT_RAW_PACKET] = IB_QP_RATE_LIMIT,
15678a51866fSRoland Dreier 			}
15688a51866fSRoland Dreier 		},
15698a51866fSRoland Dreier 		[IB_QPS_SQD]   = {
15708a51866fSRoland Dreier 			.valid = 1,
15718a51866fSRoland Dreier 			.opt_param = {
15728a51866fSRoland Dreier 				[IB_QPT_UD]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
15738a51866fSRoland Dreier 				[IB_QPT_UC]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
15748a51866fSRoland Dreier 				[IB_QPT_RC]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
1575b42b63cfSSean Hefty 				[IB_QPT_XRC_INI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
1576b42b63cfSSean Hefty 				[IB_QPT_XRC_TGT] = IB_QP_EN_SQD_ASYNC_NOTIFY, /* ??? */
15778a51866fSRoland Dreier 				[IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
15788a51866fSRoland Dreier 				[IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY
15798a51866fSRoland Dreier 			}
15808a51866fSRoland Dreier 		},
15818a51866fSRoland Dreier 	},
15828a51866fSRoland Dreier 	[IB_QPS_SQD]   = {
15838a51866fSRoland Dreier 		[IB_QPS_RESET] = { .valid = 1 },
15848a51866fSRoland Dreier 		[IB_QPS_ERR] =   { .valid = 1 },
15858a51866fSRoland Dreier 		[IB_QPS_RTS]   = {
15868a51866fSRoland Dreier 			.valid = 1,
15878a51866fSRoland Dreier 			.opt_param = {
15888a51866fSRoland Dreier 				[IB_QPT_UD]  = (IB_QP_CUR_STATE			|
15898a51866fSRoland Dreier 						IB_QP_QKEY),
15908a51866fSRoland Dreier 				[IB_QPT_UC]  = (IB_QP_CUR_STATE			|
15918a51866fSRoland Dreier 						IB_QP_ALT_PATH			|
15928a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS		|
15938a51866fSRoland Dreier 						IB_QP_PATH_MIG_STATE),
15948a51866fSRoland Dreier 				[IB_QPT_RC]  = (IB_QP_CUR_STATE			|
15958a51866fSRoland Dreier 						IB_QP_ALT_PATH			|
15968a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS		|
15978a51866fSRoland Dreier 						IB_QP_MIN_RNR_TIMER		|
15988a51866fSRoland Dreier 						IB_QP_PATH_MIG_STATE),
1599b42b63cfSSean Hefty 				[IB_QPT_XRC_INI] = (IB_QP_CUR_STATE		|
1600b42b63cfSSean Hefty 						IB_QP_ALT_PATH			|
1601b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS		|
1602b42b63cfSSean Hefty 						IB_QP_PATH_MIG_STATE),
1603b42b63cfSSean Hefty 				[IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE		|
1604b42b63cfSSean Hefty 						IB_QP_ALT_PATH			|
1605b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS		|
1606b42b63cfSSean Hefty 						IB_QP_MIN_RNR_TIMER		|
1607b42b63cfSSean Hefty 						IB_QP_PATH_MIG_STATE),
16088a51866fSRoland Dreier 				[IB_QPT_SMI] = (IB_QP_CUR_STATE			|
16098a51866fSRoland Dreier 						IB_QP_QKEY),
16108a51866fSRoland Dreier 				[IB_QPT_GSI] = (IB_QP_CUR_STATE			|
16118a51866fSRoland Dreier 						IB_QP_QKEY),
16128a51866fSRoland Dreier 			}
16138a51866fSRoland Dreier 		},
16148a51866fSRoland Dreier 		[IB_QPS_SQD]   = {
16158a51866fSRoland Dreier 			.valid = 1,
16168a51866fSRoland Dreier 			.opt_param = {
16178a51866fSRoland Dreier 				[IB_QPT_UD]  = (IB_QP_PKEY_INDEX		|
16188a51866fSRoland Dreier 						IB_QP_QKEY),
16198a51866fSRoland Dreier 				[IB_QPT_UC]  = (IB_QP_AV			|
16208a51866fSRoland Dreier 						IB_QP_ALT_PATH			|
16218a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS		|
16228a51866fSRoland Dreier 						IB_QP_PKEY_INDEX		|
16238a51866fSRoland Dreier 						IB_QP_PATH_MIG_STATE),
16248a51866fSRoland Dreier 				[IB_QPT_RC]  = (IB_QP_PORT			|
16258a51866fSRoland Dreier 						IB_QP_AV			|
16268a51866fSRoland Dreier 						IB_QP_TIMEOUT			|
16278a51866fSRoland Dreier 						IB_QP_RETRY_CNT			|
16288a51866fSRoland Dreier 						IB_QP_RNR_RETRY			|
16298a51866fSRoland Dreier 						IB_QP_MAX_QP_RD_ATOMIC		|
16308a51866fSRoland Dreier 						IB_QP_MAX_DEST_RD_ATOMIC	|
16318a51866fSRoland Dreier 						IB_QP_ALT_PATH			|
16328a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS		|
16338a51866fSRoland Dreier 						IB_QP_PKEY_INDEX		|
16348a51866fSRoland Dreier 						IB_QP_MIN_RNR_TIMER		|
16358a51866fSRoland Dreier 						IB_QP_PATH_MIG_STATE),
1636b42b63cfSSean Hefty 				[IB_QPT_XRC_INI] = (IB_QP_PORT			|
1637b42b63cfSSean Hefty 						IB_QP_AV			|
1638b42b63cfSSean Hefty 						IB_QP_TIMEOUT			|
1639b42b63cfSSean Hefty 						IB_QP_RETRY_CNT			|
1640b42b63cfSSean Hefty 						IB_QP_RNR_RETRY			|
1641b42b63cfSSean Hefty 						IB_QP_MAX_QP_RD_ATOMIC		|
1642b42b63cfSSean Hefty 						IB_QP_ALT_PATH			|
1643b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS		|
1644b42b63cfSSean Hefty 						IB_QP_PKEY_INDEX		|
1645b42b63cfSSean Hefty 						IB_QP_PATH_MIG_STATE),
1646b42b63cfSSean Hefty 				[IB_QPT_XRC_TGT] = (IB_QP_PORT			|
1647b42b63cfSSean Hefty 						IB_QP_AV			|
1648b42b63cfSSean Hefty 						IB_QP_TIMEOUT			|
1649b42b63cfSSean Hefty 						IB_QP_MAX_DEST_RD_ATOMIC	|
1650b42b63cfSSean Hefty 						IB_QP_ALT_PATH			|
1651b42b63cfSSean Hefty 						IB_QP_ACCESS_FLAGS		|
1652b42b63cfSSean Hefty 						IB_QP_PKEY_INDEX		|
1653b42b63cfSSean Hefty 						IB_QP_MIN_RNR_TIMER		|
1654b42b63cfSSean Hefty 						IB_QP_PATH_MIG_STATE),
16558a51866fSRoland Dreier 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
16568a51866fSRoland Dreier 						IB_QP_QKEY),
16578a51866fSRoland Dreier 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
16588a51866fSRoland Dreier 						IB_QP_QKEY),
16598a51866fSRoland Dreier 			}
16608a51866fSRoland Dreier 		}
16618a51866fSRoland Dreier 	},
16628a51866fSRoland Dreier 	[IB_QPS_SQE]   = {
16638a51866fSRoland Dreier 		[IB_QPS_RESET] = { .valid = 1 },
16648a51866fSRoland Dreier 		[IB_QPS_ERR] =   { .valid = 1 },
16658a51866fSRoland Dreier 		[IB_QPS_RTS]   = {
16668a51866fSRoland Dreier 			.valid = 1,
16678a51866fSRoland Dreier 			.opt_param = {
16688a51866fSRoland Dreier 				[IB_QPT_UD]  = (IB_QP_CUR_STATE			|
16698a51866fSRoland Dreier 						IB_QP_QKEY),
16708a51866fSRoland Dreier 				[IB_QPT_UC]  = (IB_QP_CUR_STATE			|
16718a51866fSRoland Dreier 						IB_QP_ACCESS_FLAGS),
16728a51866fSRoland Dreier 				[IB_QPT_SMI] = (IB_QP_CUR_STATE			|
16738a51866fSRoland Dreier 						IB_QP_QKEY),
16748a51866fSRoland Dreier 				[IB_QPT_GSI] = (IB_QP_CUR_STATE			|
16758a51866fSRoland Dreier 						IB_QP_QKEY),
16768a51866fSRoland Dreier 			}
16778a51866fSRoland Dreier 		}
16788a51866fSRoland Dreier 	},
16798a51866fSRoland Dreier 	[IB_QPS_ERR] = {
16808a51866fSRoland Dreier 		[IB_QPS_RESET] = { .valid = 1 },
16818a51866fSRoland Dreier 		[IB_QPS_ERR] =   { .valid = 1 }
16828a51866fSRoland Dreier 	}
16838a51866fSRoland Dreier };
16848a51866fSRoland Dreier 
ib_modify_qp_is_ok(enum ib_qp_state cur_state,enum ib_qp_state next_state,enum ib_qp_type type,enum ib_qp_attr_mask mask)168519b1f540SLeon Romanovsky bool ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
1686d31131bbSKamal Heib 			enum ib_qp_type type, enum ib_qp_attr_mask mask)
16878a51866fSRoland Dreier {
16888a51866fSRoland Dreier 	enum ib_qp_attr_mask req_param, opt_param;
16898a51866fSRoland Dreier 
16908a51866fSRoland Dreier 	if (mask & IB_QP_CUR_STATE  &&
16918a51866fSRoland Dreier 	    cur_state != IB_QPS_RTR && cur_state != IB_QPS_RTS &&
16928a51866fSRoland Dreier 	    cur_state != IB_QPS_SQD && cur_state != IB_QPS_SQE)
169319b1f540SLeon Romanovsky 		return false;
16948a51866fSRoland Dreier 
16958a51866fSRoland Dreier 	if (!qp_state_table[cur_state][next_state].valid)
169619b1f540SLeon Romanovsky 		return false;
16978a51866fSRoland Dreier 
16988a51866fSRoland Dreier 	req_param = qp_state_table[cur_state][next_state].req_param[type];
16998a51866fSRoland Dreier 	opt_param = qp_state_table[cur_state][next_state].opt_param[type];
17008a51866fSRoland Dreier 
17018a51866fSRoland Dreier 	if ((mask & req_param) != req_param)
170219b1f540SLeon Romanovsky 		return false;
17038a51866fSRoland Dreier 
17048a51866fSRoland Dreier 	if (mask & ~(req_param | opt_param | IB_QP_STATE))
170519b1f540SLeon Romanovsky 		return false;
17068a51866fSRoland Dreier 
170719b1f540SLeon Romanovsky 	return true;
17088a51866fSRoland Dreier }
17098a51866fSRoland Dreier EXPORT_SYMBOL(ib_modify_qp_is_ok);
17108a51866fSRoland Dreier 
1711947c99ecSParav Pandit /**
1712947c99ecSParav Pandit  * ib_resolve_eth_dmac - Resolve destination mac address
1713947c99ecSParav Pandit  * @device:		Device to consider
1714947c99ecSParav Pandit  * @ah_attr:		address handle attribute which describes the
1715947c99ecSParav Pandit  *			source and destination parameters
1716947c99ecSParav Pandit  * ib_resolve_eth_dmac() resolves destination mac address and L3 hop limit It
1717947c99ecSParav Pandit  * returns 0 on success or appropriate error code. It initializes the
1718947c99ecSParav Pandit  * necessary ah_attr fields when call is successful.
1719947c99ecSParav Pandit  */
ib_resolve_eth_dmac(struct ib_device * device,struct rdma_ah_attr * ah_attr)1720c0348eb0SParav Pandit static int ib_resolve_eth_dmac(struct ib_device *device,
172190898850SDasaratharaman Chandramouli 			       struct rdma_ah_attr *ah_attr)
1722ed4c54e5SOr Gerlitz {
1723ed4c54e5SOr Gerlitz 	int ret = 0;
1724d8966fcdSDasaratharaman Chandramouli 
17259636a56fSNoa Osherovich 	if (rdma_is_multicast_addr((struct in6_addr *)ah_attr->grh.dgid.raw)) {
17269636a56fSNoa Osherovich 		if (ipv6_addr_v4mapped((struct in6_addr *)ah_attr->grh.dgid.raw)) {
17279636a56fSNoa Osherovich 			__be32 addr = 0;
17289636a56fSNoa Osherovich 
17299636a56fSNoa Osherovich 			memcpy(&addr, ah_attr->grh.dgid.raw + 12, 4);
17309636a56fSNoa Osherovich 			ip_eth_mc_map(addr, (char *)ah_attr->roce.dmac);
17319636a56fSNoa Osherovich 		} else {
17329636a56fSNoa Osherovich 			ipv6_eth_mc_map((struct in6_addr *)ah_attr->grh.dgid.raw,
17339636a56fSNoa Osherovich 					(char *)ah_attr->roce.dmac);
17349636a56fSNoa Osherovich 		}
1735ed4c54e5SOr Gerlitz 	} else {
17361060f865SParav Pandit 		ret = ib_resolve_unicast_gid_dmac(device, ah_attr);
1737ed4c54e5SOr Gerlitz 	}
1738ed4c54e5SOr Gerlitz 	return ret;
1739ed4c54e5SOr Gerlitz }
1740ed4c54e5SOr Gerlitz 
is_qp_type_connected(const struct ib_qp * qp)17418d9ec9adSJason Gunthorpe static bool is_qp_type_connected(const struct ib_qp *qp)
17428d9ec9adSJason Gunthorpe {
17438d9ec9adSJason Gunthorpe 	return (qp->qp_type == IB_QPT_UC ||
17448d9ec9adSJason Gunthorpe 		qp->qp_type == IB_QPT_RC ||
17458d9ec9adSJason Gunthorpe 		qp->qp_type == IB_QPT_XRC_INI ||
17468d9ec9adSJason Gunthorpe 		qp->qp_type == IB_QPT_XRC_TGT);
17478d9ec9adSJason Gunthorpe }
17488d9ec9adSJason Gunthorpe 
17492988ca08SMauro Carvalho Chehab /*
1750b96ac05aSParav Pandit  * IB core internal function to perform QP attributes modification.
1751a512c2fbSParav Pandit  */
_ib_modify_qp(struct ib_qp * qp,struct ib_qp_attr * attr,int attr_mask,struct ib_udata * udata)1752b96ac05aSParav Pandit static int _ib_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr,
1753a512c2fbSParav Pandit 			 int attr_mask, struct ib_udata *udata)
1754a512c2fbSParav Pandit {
17551fb7f897SMark Bloch 	u32 port = attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
17568d9ec9adSJason Gunthorpe 	const struct ib_gid_attr *old_sgid_attr_av;
17578d9ec9adSJason Gunthorpe 	const struct ib_gid_attr *old_sgid_attr_alt_av;
1758a512c2fbSParav Pandit 	int ret;
1759a512c2fbSParav Pandit 
176051aab126SMaor Gottlieb 	attr->xmit_slave = NULL;
17618d9ec9adSJason Gunthorpe 	if (attr_mask & IB_QP_AV) {
17628d9ec9adSJason Gunthorpe 		ret = rdma_fill_sgid_attr(qp->device, &attr->ah_attr,
17638d9ec9adSJason Gunthorpe 					  &old_sgid_attr_av);
17648d9ec9adSJason Gunthorpe 		if (ret)
17658d9ec9adSJason Gunthorpe 			return ret;
176651aab126SMaor Gottlieb 
176751aab126SMaor Gottlieb 		if (attr->ah_attr.type == RDMA_AH_ATTR_TYPE_ROCE &&
176851aab126SMaor Gottlieb 		    is_qp_type_connected(qp)) {
176951aab126SMaor Gottlieb 			struct net_device *slave;
177051aab126SMaor Gottlieb 
177151aab126SMaor Gottlieb 			/*
177251aab126SMaor Gottlieb 			 * If the user provided the qp_attr then we have to
177351aab126SMaor Gottlieb 			 * resolve it. Kerne users have to provide already
177451aab126SMaor Gottlieb 			 * resolved rdma_ah_attr's.
177551aab126SMaor Gottlieb 			 */
177651aab126SMaor Gottlieb 			if (udata) {
177751aab126SMaor Gottlieb 				ret = ib_resolve_eth_dmac(qp->device,
177851aab126SMaor Gottlieb 							  &attr->ah_attr);
177951aab126SMaor Gottlieb 				if (ret)
178051aab126SMaor Gottlieb 					goto out_av;
178151aab126SMaor Gottlieb 			}
178251aab126SMaor Gottlieb 			slave = rdma_lag_get_ah_roce_slave(qp->device,
178351aab126SMaor Gottlieb 							   &attr->ah_attr,
178451aab126SMaor Gottlieb 							   GFP_KERNEL);
17855333499cSJing Xiangfeng 			if (IS_ERR(slave)) {
17865333499cSJing Xiangfeng 				ret = PTR_ERR(slave);
178751aab126SMaor Gottlieb 				goto out_av;
17885333499cSJing Xiangfeng 			}
178951aab126SMaor Gottlieb 			attr->xmit_slave = slave;
179051aab126SMaor Gottlieb 		}
17918d9ec9adSJason Gunthorpe 	}
17928d9ec9adSJason Gunthorpe 	if (attr_mask & IB_QP_ALT_PATH) {
17931a1f460fSJason Gunthorpe 		/*
17941a1f460fSJason Gunthorpe 		 * FIXME: This does not track the migration state, so if the
17951a1f460fSJason Gunthorpe 		 * user loads a new alternate path after the HW has migrated
17961a1f460fSJason Gunthorpe 		 * from primary->alternate we will keep the wrong
17971a1f460fSJason Gunthorpe 		 * references. This is OK for IB because the reference
17981a1f460fSJason Gunthorpe 		 * counting does not serve any functional purpose.
17991a1f460fSJason Gunthorpe 		 */
18008d9ec9adSJason Gunthorpe 		ret = rdma_fill_sgid_attr(qp->device, &attr->alt_ah_attr,
18018d9ec9adSJason Gunthorpe 					  &old_sgid_attr_alt_av);
18028d9ec9adSJason Gunthorpe 		if (ret)
18038d9ec9adSJason Gunthorpe 			goto out_av;
18047a5c938bSJason Gunthorpe 
18057a5c938bSJason Gunthorpe 		/*
18067a5c938bSJason Gunthorpe 		 * Today the core code can only handle alternate paths and APM
18077a5c938bSJason Gunthorpe 		 * for IB. Ban them in roce mode.
18087a5c938bSJason Gunthorpe 		 */
18097a5c938bSJason Gunthorpe 		if (!(rdma_protocol_ib(qp->device,
18107a5c938bSJason Gunthorpe 				       attr->alt_ah_attr.port_num) &&
18117a5c938bSJason Gunthorpe 		      rdma_protocol_ib(qp->device, port))) {
181247fda651SLi Heng 			ret = -EINVAL;
18137a5c938bSJason Gunthorpe 			goto out;
18147a5c938bSJason Gunthorpe 		}
18158d9ec9adSJason Gunthorpe 	}
18168d9ec9adSJason Gunthorpe 
1817727b7e9aSMajd Dibbiny 	if (rdma_ib_or_roce(qp->device, port)) {
1818727b7e9aSMajd Dibbiny 		if (attr_mask & IB_QP_RQ_PSN && attr->rq_psn & ~0xffffff) {
181943c7c851SJason Gunthorpe 			dev_warn(&qp->device->dev,
182043c7c851SJason Gunthorpe 				 "%s rq_psn overflow, masking to 24 bits\n",
182143c7c851SJason Gunthorpe 				 __func__);
1822727b7e9aSMajd Dibbiny 			attr->rq_psn &= 0xffffff;
1823727b7e9aSMajd Dibbiny 		}
1824727b7e9aSMajd Dibbiny 
1825727b7e9aSMajd Dibbiny 		if (attr_mask & IB_QP_SQ_PSN && attr->sq_psn & ~0xffffff) {
182643c7c851SJason Gunthorpe 			dev_warn(&qp->device->dev,
182743c7c851SJason Gunthorpe 				 " %s sq_psn overflow, masking to 24 bits\n",
182843c7c851SJason Gunthorpe 				 __func__);
1829727b7e9aSMajd Dibbiny 			attr->sq_psn &= 0xffffff;
1830727b7e9aSMajd Dibbiny 		}
1831727b7e9aSMajd Dibbiny 	}
1832727b7e9aSMajd Dibbiny 
183399fa331dSMark Zhang 	/*
183499fa331dSMark Zhang 	 * Bind this qp to a counter automatically based on the rdma counter
183599fa331dSMark Zhang 	 * rules. This only set in RST2INIT with port specified
183699fa331dSMark Zhang 	 */
183799fa331dSMark Zhang 	if (!qp->counter && (attr_mask & IB_QP_PORT) &&
183899fa331dSMark Zhang 	    ((attr_mask & IB_QP_STATE) && attr->qp_state == IB_QPS_INIT))
183999fa331dSMark Zhang 		rdma_counter_bind_qp_auto(qp, attr->port_num);
184099fa331dSMark Zhang 
1841498ca3c8SNoa Osherovich 	ret = ib_security_modify_qp(qp, attr, attr_mask, udata);
18421a1f460fSJason Gunthorpe 	if (ret)
18431a1f460fSJason Gunthorpe 		goto out;
18441a1f460fSJason Gunthorpe 
18451a1f460fSJason Gunthorpe 	if (attr_mask & IB_QP_PORT)
1846498ca3c8SNoa Osherovich 		qp->port = attr->port_num;
18471a1f460fSJason Gunthorpe 	if (attr_mask & IB_QP_AV)
18481a1f460fSJason Gunthorpe 		qp->av_sgid_attr =
18491a1f460fSJason Gunthorpe 			rdma_update_sgid_attr(&attr->ah_attr, qp->av_sgid_attr);
18501a1f460fSJason Gunthorpe 	if (attr_mask & IB_QP_ALT_PATH)
18511a1f460fSJason Gunthorpe 		qp->alt_path_sgid_attr = rdma_update_sgid_attr(
18521a1f460fSJason Gunthorpe 			&attr->alt_ah_attr, qp->alt_path_sgid_attr);
1853498ca3c8SNoa Osherovich 
18548d9ec9adSJason Gunthorpe out:
18558d9ec9adSJason Gunthorpe 	if (attr_mask & IB_QP_ALT_PATH)
18568d9ec9adSJason Gunthorpe 		rdma_unfill_sgid_attr(&attr->alt_ah_attr, old_sgid_attr_alt_av);
18578d9ec9adSJason Gunthorpe out_av:
185851aab126SMaor Gottlieb 	if (attr_mask & IB_QP_AV) {
185951aab126SMaor Gottlieb 		rdma_lag_put_ah_roce_slave(attr->xmit_slave);
18608d9ec9adSJason Gunthorpe 		rdma_unfill_sgid_attr(&attr->ah_attr, old_sgid_attr_av);
186151aab126SMaor Gottlieb 	}
1862498ca3c8SNoa Osherovich 	return ret;
1863a512c2fbSParav Pandit }
1864b96ac05aSParav Pandit 
1865b96ac05aSParav Pandit /**
1866b96ac05aSParav Pandit  * ib_modify_qp_with_udata - Modifies the attributes for the specified QP.
1867b96ac05aSParav Pandit  * @ib_qp: The QP to modify.
1868b96ac05aSParav Pandit  * @attr: On input, specifies the QP attributes to modify.  On output,
1869b96ac05aSParav Pandit  *   the current values of selected QP attributes are returned.
1870b96ac05aSParav Pandit  * @attr_mask: A bit-mask used to specify which attributes of the QP
1871b96ac05aSParav Pandit  *   are being modified.
1872b96ac05aSParav Pandit  * @udata: pointer to user's input output buffer information
1873b96ac05aSParav Pandit  *   are being modified.
1874b96ac05aSParav Pandit  * It returns 0 on success and returns appropriate error code on error.
1875b96ac05aSParav Pandit  */
ib_modify_qp_with_udata(struct ib_qp * ib_qp,struct ib_qp_attr * attr,int attr_mask,struct ib_udata * udata)1876b96ac05aSParav Pandit int ib_modify_qp_with_udata(struct ib_qp *ib_qp, struct ib_qp_attr *attr,
1877b96ac05aSParav Pandit 			    int attr_mask, struct ib_udata *udata)
1878b96ac05aSParav Pandit {
18798d9ec9adSJason Gunthorpe 	return _ib_modify_qp(ib_qp->real_qp, attr, attr_mask, udata);
1880b96ac05aSParav Pandit }
1881a512c2fbSParav Pandit EXPORT_SYMBOL(ib_modify_qp_with_udata);
1882a512c2fbSParav Pandit 
ib_get_width_and_speed(u32 netdev_speed,u32 lanes,u16 * speed,u8 * width)1883cb06b6b3SHaoyue Xu static void ib_get_width_and_speed(u32 netdev_speed, u32 lanes,
1884cb06b6b3SHaoyue Xu 				   u16 *speed, u8 *width)
1885cb06b6b3SHaoyue Xu {
1886cb06b6b3SHaoyue Xu 	if (!lanes) {
1887cb06b6b3SHaoyue Xu 		if (netdev_speed <= SPEED_1000) {
1888cb06b6b3SHaoyue Xu 			*width = IB_WIDTH_1X;
1889cb06b6b3SHaoyue Xu 			*speed = IB_SPEED_SDR;
1890cb06b6b3SHaoyue Xu 		} else if (netdev_speed <= SPEED_10000) {
1891cb06b6b3SHaoyue Xu 			*width = IB_WIDTH_1X;
1892cb06b6b3SHaoyue Xu 			*speed = IB_SPEED_FDR10;
1893cb06b6b3SHaoyue Xu 		} else if (netdev_speed <= SPEED_20000) {
1894cb06b6b3SHaoyue Xu 			*width = IB_WIDTH_4X;
1895cb06b6b3SHaoyue Xu 			*speed = IB_SPEED_DDR;
1896cb06b6b3SHaoyue Xu 		} else if (netdev_speed <= SPEED_25000) {
1897cb06b6b3SHaoyue Xu 			*width = IB_WIDTH_1X;
1898cb06b6b3SHaoyue Xu 			*speed = IB_SPEED_EDR;
1899cb06b6b3SHaoyue Xu 		} else if (netdev_speed <= SPEED_40000) {
1900cb06b6b3SHaoyue Xu 			*width = IB_WIDTH_4X;
1901cb06b6b3SHaoyue Xu 			*speed = IB_SPEED_FDR10;
1902ca60fd11SKalesh AP 		} else if (netdev_speed <= SPEED_50000) {
1903ca60fd11SKalesh AP 			*width = IB_WIDTH_2X;
1904ca60fd11SKalesh AP 			*speed = IB_SPEED_EDR;
1905ca60fd11SKalesh AP 		} else if (netdev_speed <= SPEED_100000) {
1906cb06b6b3SHaoyue Xu 			*width = IB_WIDTH_4X;
1907cb06b6b3SHaoyue Xu 			*speed = IB_SPEED_EDR;
1908ca60fd11SKalesh AP 		} else if (netdev_speed <= SPEED_200000) {
1909ca60fd11SKalesh AP 			*width = IB_WIDTH_4X;
1910ca60fd11SKalesh AP 			*speed = IB_SPEED_HDR;
1911ca60fd11SKalesh AP 		} else {
1912ca60fd11SKalesh AP 			*width = IB_WIDTH_4X;
1913ca60fd11SKalesh AP 			*speed = IB_SPEED_NDR;
1914cb06b6b3SHaoyue Xu 		}
1915cb06b6b3SHaoyue Xu 
1916cb06b6b3SHaoyue Xu 		return;
1917cb06b6b3SHaoyue Xu 	}
1918cb06b6b3SHaoyue Xu 
1919cb06b6b3SHaoyue Xu 	switch (lanes) {
1920cb06b6b3SHaoyue Xu 	case 1:
1921cb06b6b3SHaoyue Xu 		*width = IB_WIDTH_1X;
1922cb06b6b3SHaoyue Xu 		break;
1923cb06b6b3SHaoyue Xu 	case 2:
1924cb06b6b3SHaoyue Xu 		*width = IB_WIDTH_2X;
1925cb06b6b3SHaoyue Xu 		break;
1926cb06b6b3SHaoyue Xu 	case 4:
1927cb06b6b3SHaoyue Xu 		*width = IB_WIDTH_4X;
1928cb06b6b3SHaoyue Xu 		break;
1929cb06b6b3SHaoyue Xu 	case 8:
1930cb06b6b3SHaoyue Xu 		*width = IB_WIDTH_8X;
1931cb06b6b3SHaoyue Xu 		break;
1932cb06b6b3SHaoyue Xu 	case 12:
1933cb06b6b3SHaoyue Xu 		*width = IB_WIDTH_12X;
1934cb06b6b3SHaoyue Xu 		break;
1935cb06b6b3SHaoyue Xu 	default:
1936cb06b6b3SHaoyue Xu 		*width = IB_WIDTH_1X;
1937cb06b6b3SHaoyue Xu 	}
1938cb06b6b3SHaoyue Xu 
1939cb06b6b3SHaoyue Xu 	switch (netdev_speed / lanes) {
1940cb06b6b3SHaoyue Xu 	case SPEED_2500:
1941cb06b6b3SHaoyue Xu 		*speed = IB_SPEED_SDR;
1942cb06b6b3SHaoyue Xu 		break;
1943cb06b6b3SHaoyue Xu 	case SPEED_5000:
1944cb06b6b3SHaoyue Xu 		*speed = IB_SPEED_DDR;
1945cb06b6b3SHaoyue Xu 		break;
1946cb06b6b3SHaoyue Xu 	case SPEED_10000:
1947cb06b6b3SHaoyue Xu 		*speed = IB_SPEED_FDR10;
1948cb06b6b3SHaoyue Xu 		break;
1949cb06b6b3SHaoyue Xu 	case SPEED_14000:
1950cb06b6b3SHaoyue Xu 		*speed = IB_SPEED_FDR;
1951cb06b6b3SHaoyue Xu 		break;
1952cb06b6b3SHaoyue Xu 	case SPEED_25000:
1953cb06b6b3SHaoyue Xu 		*speed = IB_SPEED_EDR;
1954cb06b6b3SHaoyue Xu 		break;
1955cb06b6b3SHaoyue Xu 	case SPEED_50000:
1956cb06b6b3SHaoyue Xu 		*speed = IB_SPEED_HDR;
1957cb06b6b3SHaoyue Xu 		break;
1958cb06b6b3SHaoyue Xu 	case SPEED_100000:
1959cb06b6b3SHaoyue Xu 		*speed = IB_SPEED_NDR;
1960cb06b6b3SHaoyue Xu 		break;
1961cb06b6b3SHaoyue Xu 	default:
1962cb06b6b3SHaoyue Xu 		*speed = IB_SPEED_SDR;
1963cb06b6b3SHaoyue Xu 	}
1964cb06b6b3SHaoyue Xu }
1965cb06b6b3SHaoyue Xu 
ib_get_eth_speed(struct ib_device * dev,u32 port_num,u16 * speed,u8 * width)19661fb7f897SMark Bloch int ib_get_eth_speed(struct ib_device *dev, u32 port_num, u16 *speed, u8 *width)
1967d4186194SYuval Shaia {
1968d4186194SYuval Shaia 	int rc;
1969d4186194SYuval Shaia 	u32 netdev_speed;
1970d4186194SYuval Shaia 	struct net_device *netdev;
1971*24436fe7SShigeru Yoshida 	struct ethtool_link_ksettings lksettings = {};
1972d4186194SYuval Shaia 
1973d4186194SYuval Shaia 	if (rdma_port_get_link_layer(dev, port_num) != IB_LINK_LAYER_ETHERNET)
1974d4186194SYuval Shaia 		return -EINVAL;
1975d4186194SYuval Shaia 
1976c2261dd7SJason Gunthorpe 	netdev = ib_device_get_netdev(dev, port_num);
1977d4186194SYuval Shaia 	if (!netdev)
1978d4186194SYuval Shaia 		return -ENODEV;
1979d4186194SYuval Shaia 
1980d4186194SYuval Shaia 	rtnl_lock();
1981d4186194SYuval Shaia 	rc = __ethtool_get_link_ksettings(netdev, &lksettings);
1982d4186194SYuval Shaia 	rtnl_unlock();
1983d4186194SYuval Shaia 
1984d4186194SYuval Shaia 	dev_put(netdev);
1985d4186194SYuval Shaia 
198628b08657SKamal Heib 	if (!rc && lksettings.base.speed != (u32)SPEED_UNKNOWN) {
1987d4186194SYuval Shaia 		netdev_speed = lksettings.base.speed;
1988d4186194SYuval Shaia 	} else {
1989d4186194SYuval Shaia 		netdev_speed = SPEED_1000;
1990cb06b6b3SHaoyue Xu 		if (rc)
1991cb06b6b3SHaoyue Xu 			pr_warn("%s speed is unknown, defaulting to %u\n",
1992cb06b6b3SHaoyue Xu 				netdev->name, netdev_speed);
1993d4186194SYuval Shaia 	}
1994d4186194SYuval Shaia 
1995cb06b6b3SHaoyue Xu 	ib_get_width_and_speed(netdev_speed, lksettings.lanes,
1996cb06b6b3SHaoyue Xu 			       speed, width);
1997d4186194SYuval Shaia 
1998d4186194SYuval Shaia 	return 0;
1999d4186194SYuval Shaia }
2000d4186194SYuval Shaia EXPORT_SYMBOL(ib_get_eth_speed);
2001d4186194SYuval Shaia 
ib_modify_qp(struct ib_qp * qp,struct ib_qp_attr * qp_attr,int qp_attr_mask)20021da177e4SLinus Torvalds int ib_modify_qp(struct ib_qp *qp,
20031da177e4SLinus Torvalds 		 struct ib_qp_attr *qp_attr,
20041da177e4SLinus Torvalds 		 int qp_attr_mask)
20051da177e4SLinus Torvalds {
2006b96ac05aSParav Pandit 	return _ib_modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL);
20071da177e4SLinus Torvalds }
20081da177e4SLinus Torvalds EXPORT_SYMBOL(ib_modify_qp);
20091da177e4SLinus Torvalds 
ib_query_qp(struct ib_qp * qp,struct ib_qp_attr * qp_attr,int qp_attr_mask,struct ib_qp_init_attr * qp_init_attr)20101da177e4SLinus Torvalds int ib_query_qp(struct ib_qp *qp,
20111da177e4SLinus Torvalds 		struct ib_qp_attr *qp_attr,
20121da177e4SLinus Torvalds 		int qp_attr_mask,
20131da177e4SLinus Torvalds 		struct ib_qp_init_attr *qp_init_attr)
20141da177e4SLinus Torvalds {
20158d9ec9adSJason Gunthorpe 	qp_attr->ah_attr.grh.sgid_attr = NULL;
20168d9ec9adSJason Gunthorpe 	qp_attr->alt_ah_attr.grh.sgid_attr = NULL;
20178d9ec9adSJason Gunthorpe 
20183023a1e9SKamal Heib 	return qp->device->ops.query_qp ?
20193023a1e9SKamal Heib 		qp->device->ops.query_qp(qp->real_qp, qp_attr, qp_attr_mask,
20203023a1e9SKamal Heib 					 qp_init_attr) : -EOPNOTSUPP;
20211da177e4SLinus Torvalds }
20221da177e4SLinus Torvalds EXPORT_SYMBOL(ib_query_qp);
20231da177e4SLinus Torvalds 
ib_close_qp(struct ib_qp * qp)20240e0ec7e0SSean Hefty int ib_close_qp(struct ib_qp *qp)
20250e0ec7e0SSean Hefty {
20260e0ec7e0SSean Hefty 	struct ib_qp *real_qp;
20270e0ec7e0SSean Hefty 	unsigned long flags;
20280e0ec7e0SSean Hefty 
20290e0ec7e0SSean Hefty 	real_qp = qp->real_qp;
20300e0ec7e0SSean Hefty 	if (real_qp == qp)
20310e0ec7e0SSean Hefty 		return -EINVAL;
20320e0ec7e0SSean Hefty 
203340adf686SParav Pandit 	spin_lock_irqsave(&real_qp->device->qp_open_list_lock, flags);
20340e0ec7e0SSean Hefty 	list_del(&qp->open_list);
203540adf686SParav Pandit 	spin_unlock_irqrestore(&real_qp->device->qp_open_list_lock, flags);
20360e0ec7e0SSean Hefty 
20370e0ec7e0SSean Hefty 	atomic_dec(&real_qp->usecnt);
20384a50881bSMoni Shoua 	if (qp->qp_sec)
2039d291f1a6SDaniel Jurgens 		ib_close_shared_qp_security(qp->qp_sec);
20400e0ec7e0SSean Hefty 	kfree(qp);
20410e0ec7e0SSean Hefty 
20420e0ec7e0SSean Hefty 	return 0;
20430e0ec7e0SSean Hefty }
20440e0ec7e0SSean Hefty EXPORT_SYMBOL(ib_close_qp);
20450e0ec7e0SSean Hefty 
__ib_destroy_shared_qp(struct ib_qp * qp)20460e0ec7e0SSean Hefty static int __ib_destroy_shared_qp(struct ib_qp *qp)
20470e0ec7e0SSean Hefty {
20480e0ec7e0SSean Hefty 	struct ib_xrcd *xrcd;
20490e0ec7e0SSean Hefty 	struct ib_qp *real_qp;
20500e0ec7e0SSean Hefty 	int ret;
20510e0ec7e0SSean Hefty 
20520e0ec7e0SSean Hefty 	real_qp = qp->real_qp;
20530e0ec7e0SSean Hefty 	xrcd = real_qp->xrcd;
20546f3ca6f4SMaor Gottlieb 	down_write(&xrcd->tgt_qps_rwsem);
20550e0ec7e0SSean Hefty 	ib_close_qp(qp);
20560e0ec7e0SSean Hefty 	if (atomic_read(&real_qp->usecnt) == 0)
20576f3ca6f4SMaor Gottlieb 		xa_erase(&xrcd->tgt_qps, real_qp->qp_num);
20580e0ec7e0SSean Hefty 	else
20590e0ec7e0SSean Hefty 		real_qp = NULL;
20606f3ca6f4SMaor Gottlieb 	up_write(&xrcd->tgt_qps_rwsem);
20610e0ec7e0SSean Hefty 
20620e0ec7e0SSean Hefty 	if (real_qp) {
20630e0ec7e0SSean Hefty 		ret = ib_destroy_qp(real_qp);
20640e0ec7e0SSean Hefty 		if (!ret)
20650e0ec7e0SSean Hefty 			atomic_dec(&xrcd->usecnt);
20660e0ec7e0SSean Hefty 	}
20670e0ec7e0SSean Hefty 
20680e0ec7e0SSean Hefty 	return 0;
20690e0ec7e0SSean Hefty }
20700e0ec7e0SSean Hefty 
ib_destroy_qp_user(struct ib_qp * qp,struct ib_udata * udata)2071c4367a26SShamir Rabinovitch int ib_destroy_qp_user(struct ib_qp *qp, struct ib_udata *udata)
20721da177e4SLinus Torvalds {
20731a1f460fSJason Gunthorpe 	const struct ib_gid_attr *alt_path_sgid_attr = qp->alt_path_sgid_attr;
20741a1f460fSJason Gunthorpe 	const struct ib_gid_attr *av_sgid_attr = qp->av_sgid_attr;
2075d291f1a6SDaniel Jurgens 	struct ib_qp_security *sec;
20761da177e4SLinus Torvalds 	int ret;
20771da177e4SLinus Torvalds 
2078fffb0383SChristoph Hellwig 	WARN_ON_ONCE(qp->mrs_used > 0);
2079fffb0383SChristoph Hellwig 
20800e0ec7e0SSean Hefty 	if (atomic_read(&qp->usecnt))
20810e0ec7e0SSean Hefty 		return -EBUSY;
20820e0ec7e0SSean Hefty 
20830e0ec7e0SSean Hefty 	if (qp->real_qp != qp)
20840e0ec7e0SSean Hefty 		return __ib_destroy_shared_qp(qp);
20850e0ec7e0SSean Hefty 
2086d291f1a6SDaniel Jurgens 	sec  = qp->qp_sec;
2087d291f1a6SDaniel Jurgens 	if (sec)
2088d291f1a6SDaniel Jurgens 		ib_destroy_qp_security_begin(sec);
20891da177e4SLinus Torvalds 
2090a060b562SChristoph Hellwig 	if (!qp->uobject)
2091a060b562SChristoph Hellwig 		rdma_rw_cleanup_mrs(qp);
2092a060b562SChristoph Hellwig 
209399fa331dSMark Zhang 	rdma_counter_unbind_qp(qp, true);
2094c4367a26SShamir Rabinovitch 	ret = qp->device->ops.destroy_qp(qp, udata);
2095514aee66SLeon Romanovsky 	if (ret) {
2096514aee66SLeon Romanovsky 		if (sec)
2097514aee66SLeon Romanovsky 			ib_destroy_qp_security_abort(sec);
2098514aee66SLeon Romanovsky 		return ret;
2099514aee66SLeon Romanovsky 	}
2100514aee66SLeon Romanovsky 
21011a1f460fSJason Gunthorpe 	if (alt_path_sgid_attr)
21021a1f460fSJason Gunthorpe 		rdma_put_gid_attr(alt_path_sgid_attr);
21031a1f460fSJason Gunthorpe 	if (av_sgid_attr)
21041a1f460fSJason Gunthorpe 		rdma_put_gid_attr(av_sgid_attr);
21055507f67dSLeon Romanovsky 
21065507f67dSLeon Romanovsky 	ib_qp_usecnt_dec(qp);
2107d291f1a6SDaniel Jurgens 	if (sec)
2108d291f1a6SDaniel Jurgens 		ib_destroy_qp_security_end(sec);
21091da177e4SLinus Torvalds 
2110514aee66SLeon Romanovsky 	rdma_restrack_del(&qp->res);
2111514aee66SLeon Romanovsky 	kfree(qp);
21121da177e4SLinus Torvalds 	return ret;
21131da177e4SLinus Torvalds }
2114c4367a26SShamir Rabinovitch EXPORT_SYMBOL(ib_destroy_qp_user);
21151da177e4SLinus Torvalds 
21161da177e4SLinus Torvalds /* Completion queues */
21171da177e4SLinus Torvalds 
__ib_create_cq(struct ib_device * device,ib_comp_handler comp_handler,void (* event_handler)(struct ib_event *,void *),void * cq_context,const struct ib_cq_init_attr * cq_attr,const char * caller)21187350cdd0SBharat Potnuri struct ib_cq *__ib_create_cq(struct ib_device *device,
21191da177e4SLinus Torvalds 			     ib_comp_handler comp_handler,
21201da177e4SLinus Torvalds 			     void (*event_handler)(struct ib_event *, void *),
21218e37210bSMatan Barak 			     void *cq_context,
21227350cdd0SBharat Potnuri 			     const struct ib_cq_init_attr *cq_attr,
21237350cdd0SBharat Potnuri 			     const char *caller)
21241da177e4SLinus Torvalds {
21251da177e4SLinus Torvalds 	struct ib_cq *cq;
2126e39afe3dSLeon Romanovsky 	int ret;
21271da177e4SLinus Torvalds 
2128e39afe3dSLeon Romanovsky 	cq = rdma_zalloc_drv_obj(device, ib_cq);
2129e39afe3dSLeon Romanovsky 	if (!cq)
2130e39afe3dSLeon Romanovsky 		return ERR_PTR(-ENOMEM);
21311da177e4SLinus Torvalds 
21321da177e4SLinus Torvalds 	cq->device = device;
2133b5e81bf5SRoland Dreier 	cq->uobject = NULL;
21341da177e4SLinus Torvalds 	cq->comp_handler = comp_handler;
21351da177e4SLinus Torvalds 	cq->event_handler = event_handler;
21361da177e4SLinus Torvalds 	cq->cq_context = cq_context;
21371da177e4SLinus Torvalds 	atomic_set(&cq->usecnt, 0);
213813ef5539SLeon Romanovsky 
213913ef5539SLeon Romanovsky 	rdma_restrack_new(&cq->res, RDMA_RESTRACK_CQ);
2140b09c4d70SLeon Romanovsky 	rdma_restrack_set_name(&cq->res, caller);
2141e39afe3dSLeon Romanovsky 
2142e39afe3dSLeon Romanovsky 	ret = device->ops.create_cq(cq, cq_attr, NULL);
2143e39afe3dSLeon Romanovsky 	if (ret) {
214413ef5539SLeon Romanovsky 		rdma_restrack_put(&cq->res);
2145e39afe3dSLeon Romanovsky 		kfree(cq);
2146e39afe3dSLeon Romanovsky 		return ERR_PTR(ret);
21471da177e4SLinus Torvalds 	}
21481da177e4SLinus Torvalds 
2149c34a23c2SLeon Romanovsky 	rdma_restrack_add(&cq->res);
21501da177e4SLinus Torvalds 	return cq;
21511da177e4SLinus Torvalds }
21527350cdd0SBharat Potnuri EXPORT_SYMBOL(__ib_create_cq);
21531da177e4SLinus Torvalds 
rdma_set_cq_moderation(struct ib_cq * cq,u16 cq_count,u16 cq_period)21544190b4e9SLeon Romanovsky int rdma_set_cq_moderation(struct ib_cq *cq, u16 cq_count, u16 cq_period)
21552dd57162SEli Cohen {
21563446cbd2SYamin Friedman 	if (cq->shared)
21573446cbd2SYamin Friedman 		return -EOPNOTSUPP;
21583446cbd2SYamin Friedman 
21593023a1e9SKamal Heib 	return cq->device->ops.modify_cq ?
21603023a1e9SKamal Heib 		cq->device->ops.modify_cq(cq, cq_count,
21613023a1e9SKamal Heib 					  cq_period) : -EOPNOTSUPP;
21622dd57162SEli Cohen }
21634190b4e9SLeon Romanovsky EXPORT_SYMBOL(rdma_set_cq_moderation);
21642dd57162SEli Cohen 
ib_destroy_cq_user(struct ib_cq * cq,struct ib_udata * udata)2165c4367a26SShamir Rabinovitch int ib_destroy_cq_user(struct ib_cq *cq, struct ib_udata *udata)
21661da177e4SLinus Torvalds {
216743d781b9SLeon Romanovsky 	int ret;
216843d781b9SLeon Romanovsky 
21693446cbd2SYamin Friedman 	if (WARN_ON_ONCE(cq->shared))
21703446cbd2SYamin Friedman 		return -EOPNOTSUPP;
21713446cbd2SYamin Friedman 
21721da177e4SLinus Torvalds 	if (atomic_read(&cq->usecnt))
21731da177e4SLinus Torvalds 		return -EBUSY;
21741da177e4SLinus Torvalds 
217543d781b9SLeon Romanovsky 	ret = cq->device->ops.destroy_cq(cq, udata);
217643d781b9SLeon Romanovsky 	if (ret)
217743d781b9SLeon Romanovsky 		return ret;
217843d781b9SLeon Romanovsky 
217908f294a1SLeon Romanovsky 	rdma_restrack_del(&cq->res);
2180e39afe3dSLeon Romanovsky 	kfree(cq);
218143d781b9SLeon Romanovsky 	return ret;
21821da177e4SLinus Torvalds }
2183c4367a26SShamir Rabinovitch EXPORT_SYMBOL(ib_destroy_cq_user);
21841da177e4SLinus Torvalds 
ib_resize_cq(struct ib_cq * cq,int cqe)2185a74cd4afSRoland Dreier int ib_resize_cq(struct ib_cq *cq, int cqe)
21861da177e4SLinus Torvalds {
21873446cbd2SYamin Friedman 	if (cq->shared)
21883446cbd2SYamin Friedman 		return -EOPNOTSUPP;
21893446cbd2SYamin Friedman 
21903023a1e9SKamal Heib 	return cq->device->ops.resize_cq ?
21913023a1e9SKamal Heib 		cq->device->ops.resize_cq(cq, cqe, NULL) : -EOPNOTSUPP;
21921da177e4SLinus Torvalds }
21931da177e4SLinus Torvalds EXPORT_SYMBOL(ib_resize_cq);
21941da177e4SLinus Torvalds 
21951da177e4SLinus Torvalds /* Memory regions */
21961da177e4SLinus Torvalds 
ib_reg_user_mr(struct ib_pd * pd,u64 start,u64 length,u64 virt_addr,int access_flags)219733006bd4SMoni Shoua struct ib_mr *ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
219833006bd4SMoni Shoua 			     u64 virt_addr, int access_flags)
219933006bd4SMoni Shoua {
220033006bd4SMoni Shoua 	struct ib_mr *mr;
220133006bd4SMoni Shoua 
220233006bd4SMoni Shoua 	if (access_flags & IB_ACCESS_ON_DEMAND) {
2203e945c653SJason Gunthorpe 		if (!(pd->device->attrs.kernel_cap_flags &
2204e945c653SJason Gunthorpe 		      IBK_ON_DEMAND_PAGING)) {
220533006bd4SMoni Shoua 			pr_debug("ODP support not available\n");
220633006bd4SMoni Shoua 			return ERR_PTR(-EINVAL);
220733006bd4SMoni Shoua 		}
220833006bd4SMoni Shoua 	}
220933006bd4SMoni Shoua 
221033006bd4SMoni Shoua 	mr = pd->device->ops.reg_user_mr(pd, start, length, virt_addr,
221133006bd4SMoni Shoua 					 access_flags, NULL);
221233006bd4SMoni Shoua 
221333006bd4SMoni Shoua 	if (IS_ERR(mr))
221433006bd4SMoni Shoua 		return mr;
221533006bd4SMoni Shoua 
221633006bd4SMoni Shoua 	mr->device = pd->device;
221732a88d16SMaor Gottlieb 	mr->type = IB_MR_TYPE_USER;
221833006bd4SMoni Shoua 	mr->pd = pd;
221933006bd4SMoni Shoua 	mr->dm = NULL;
222033006bd4SMoni Shoua 	atomic_inc(&pd->usecnt);
2221241f9a27SDaisuke Matsuda 	mr->iova =  virt_addr;
2222241f9a27SDaisuke Matsuda 	mr->length = length;
222313ef5539SLeon Romanovsky 
222413ef5539SLeon Romanovsky 	rdma_restrack_new(&mr->res, RDMA_RESTRACK_MR);
2225b09c4d70SLeon Romanovsky 	rdma_restrack_parent_name(&mr->res, &pd->res);
2226c34a23c2SLeon Romanovsky 	rdma_restrack_add(&mr->res);
222733006bd4SMoni Shoua 
222833006bd4SMoni Shoua 	return mr;
222933006bd4SMoni Shoua }
223033006bd4SMoni Shoua EXPORT_SYMBOL(ib_reg_user_mr);
223133006bd4SMoni Shoua 
ib_advise_mr(struct ib_pd * pd,enum ib_uverbs_advise_mr_advice advice,u32 flags,struct ib_sge * sg_list,u32 num_sge)223287d8069fSMoni Shoua int ib_advise_mr(struct ib_pd *pd, enum ib_uverbs_advise_mr_advice advice,
223387d8069fSMoni Shoua 		 u32 flags, struct ib_sge *sg_list, u32 num_sge)
223487d8069fSMoni Shoua {
223587d8069fSMoni Shoua 	if (!pd->device->ops.advise_mr)
223687d8069fSMoni Shoua 		return -EOPNOTSUPP;
223787d8069fSMoni Shoua 
2238d4d7f596SMaor Gottlieb 	if (!num_sge)
2239d4d7f596SMaor Gottlieb 		return 0;
2240d4d7f596SMaor Gottlieb 
224187d8069fSMoni Shoua 	return pd->device->ops.advise_mr(pd, advice, flags, sg_list, num_sge,
224287d8069fSMoni Shoua 					 NULL);
224387d8069fSMoni Shoua }
224487d8069fSMoni Shoua EXPORT_SYMBOL(ib_advise_mr);
224587d8069fSMoni Shoua 
ib_dereg_mr_user(struct ib_mr * mr,struct ib_udata * udata)2246c4367a26SShamir Rabinovitch int ib_dereg_mr_user(struct ib_mr *mr, struct ib_udata *udata)
22471da177e4SLinus Torvalds {
2248ab67ed8dSChristoph Hellwig 	struct ib_pd *pd = mr->pd;
2249be934ccaSAriel Levkovich 	struct ib_dm *dm = mr->dm;
22507c717d3aSMax Gurtovoy 	struct ib_sig_attrs *sig_attrs = mr->sig_attrs;
22511da177e4SLinus Torvalds 	int ret;
22521da177e4SLinus Torvalds 
2253622db5b6SChuck Lever 	trace_mr_dereg(mr);
2254fccec5b8SSteve Wise 	rdma_restrack_del(&mr->res);
2255c4367a26SShamir Rabinovitch 	ret = mr->device->ops.dereg_mr(mr, udata);
2256be934ccaSAriel Levkovich 	if (!ret) {
22571da177e4SLinus Torvalds 		atomic_dec(&pd->usecnt);
2258be934ccaSAriel Levkovich 		if (dm)
2259be934ccaSAriel Levkovich 			atomic_dec(&dm->usecnt);
22607c717d3aSMax Gurtovoy 		kfree(sig_attrs);
2261be934ccaSAriel Levkovich 	}
22621da177e4SLinus Torvalds 
22631da177e4SLinus Torvalds 	return ret;
22641da177e4SLinus Torvalds }
2265c4367a26SShamir Rabinovitch EXPORT_SYMBOL(ib_dereg_mr_user);
22661da177e4SLinus Torvalds 
22679bee178bSSagi Grimberg /**
2268b64b74b1SGal Pressman  * ib_alloc_mr() - Allocates a memory region
22699bee178bSSagi Grimberg  * @pd:            protection domain associated with the region
22709bee178bSSagi Grimberg  * @mr_type:       memory region type
22719bee178bSSagi Grimberg  * @max_num_sg:    maximum sg entries available for registration.
22729bee178bSSagi Grimberg  *
22739bee178bSSagi Grimberg  * Notes:
22749bee178bSSagi Grimberg  * Memory registeration page/sg lists must not exceed max_num_sg.
22759bee178bSSagi Grimberg  * For mr_type IB_MR_TYPE_MEM_REG, the total length cannot exceed
22769bee178bSSagi Grimberg  * max_num_sg * used_page_size.
22779bee178bSSagi Grimberg  *
22789bee178bSSagi Grimberg  */
ib_alloc_mr(struct ib_pd * pd,enum ib_mr_type mr_type,u32 max_num_sg)2279b64b74b1SGal Pressman struct ib_mr *ib_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type,
2280b64b74b1SGal Pressman 			  u32 max_num_sg)
228117cd3a2dSSagi Grimberg {
228217cd3a2dSSagi Grimberg 	struct ib_mr *mr;
228317cd3a2dSSagi Grimberg 
2284622db5b6SChuck Lever 	if (!pd->device->ops.alloc_mr) {
2285622db5b6SChuck Lever 		mr = ERR_PTR(-EOPNOTSUPP);
2286622db5b6SChuck Lever 		goto out;
2287622db5b6SChuck Lever 	}
228817cd3a2dSSagi Grimberg 
2289622db5b6SChuck Lever 	if (mr_type == IB_MR_TYPE_INTEGRITY) {
2290622db5b6SChuck Lever 		WARN_ON_ONCE(1);
2291622db5b6SChuck Lever 		mr = ERR_PTR(-EINVAL);
2292622db5b6SChuck Lever 		goto out;
2293622db5b6SChuck Lever 	}
229426bc7eaeSIsrael Rukshin 
229542a3b153SGal Pressman 	mr = pd->device->ops.alloc_mr(pd, mr_type, max_num_sg);
2296c5f42b21SGal Pressman 	if (IS_ERR(mr))
2297c5f42b21SGal Pressman 		goto out;
2298c5f42b21SGal Pressman 
229917cd3a2dSSagi Grimberg 	mr->device = pd->device;
230017cd3a2dSSagi Grimberg 	mr->pd = pd;
230154e7e48bSAriel Levkovich 	mr->dm = NULL;
230217cd3a2dSSagi Grimberg 	mr->uobject = NULL;
230317cd3a2dSSagi Grimberg 	atomic_inc(&pd->usecnt);
2304d4a85c30SSteve Wise 	mr->need_inval = false;
2305a0bc099aSMax Gurtovoy 	mr->type = mr_type;
23067c717d3aSMax Gurtovoy 	mr->sig_attrs = NULL;
230717cd3a2dSSagi Grimberg 
230813ef5539SLeon Romanovsky 	rdma_restrack_new(&mr->res, RDMA_RESTRACK_MR);
2309b09c4d70SLeon Romanovsky 	rdma_restrack_parent_name(&mr->res, &pd->res);
2310c34a23c2SLeon Romanovsky 	rdma_restrack_add(&mr->res);
2311622db5b6SChuck Lever out:
2312622db5b6SChuck Lever 	trace_mr_alloc(pd, mr_type, max_num_sg, mr);
231317cd3a2dSSagi Grimberg 	return mr;
231417cd3a2dSSagi Grimberg }
2315b64b74b1SGal Pressman EXPORT_SYMBOL(ib_alloc_mr);
231600f7ec36SSteve Wise 
231726bc7eaeSIsrael Rukshin /**
231826bc7eaeSIsrael Rukshin  * ib_alloc_mr_integrity() - Allocates an integrity memory region
231926bc7eaeSIsrael Rukshin  * @pd:                      protection domain associated with the region
232026bc7eaeSIsrael Rukshin  * @max_num_data_sg:         maximum data sg entries available for registration
232126bc7eaeSIsrael Rukshin  * @max_num_meta_sg:         maximum metadata sg entries available for
232226bc7eaeSIsrael Rukshin  *                           registration
232326bc7eaeSIsrael Rukshin  *
232426bc7eaeSIsrael Rukshin  * Notes:
232526bc7eaeSIsrael Rukshin  * Memory registration page/sg lists must not exceed max_num_sg,
232626bc7eaeSIsrael Rukshin  * also the integrity page/sg lists must not exceed max_num_meta_sg.
232726bc7eaeSIsrael Rukshin  *
232826bc7eaeSIsrael Rukshin  */
ib_alloc_mr_integrity(struct ib_pd * pd,u32 max_num_data_sg,u32 max_num_meta_sg)232926bc7eaeSIsrael Rukshin struct ib_mr *ib_alloc_mr_integrity(struct ib_pd *pd,
233026bc7eaeSIsrael Rukshin 				    u32 max_num_data_sg,
233126bc7eaeSIsrael Rukshin 				    u32 max_num_meta_sg)
233226bc7eaeSIsrael Rukshin {
233326bc7eaeSIsrael Rukshin 	struct ib_mr *mr;
23347c717d3aSMax Gurtovoy 	struct ib_sig_attrs *sig_attrs;
233526bc7eaeSIsrael Rukshin 
23362cdfcdd8SMax Gurtovoy 	if (!pd->device->ops.alloc_mr_integrity ||
2337622db5b6SChuck Lever 	    !pd->device->ops.map_mr_sg_pi) {
2338622db5b6SChuck Lever 		mr = ERR_PTR(-EOPNOTSUPP);
2339622db5b6SChuck Lever 		goto out;
2340622db5b6SChuck Lever 	}
234126bc7eaeSIsrael Rukshin 
2342622db5b6SChuck Lever 	if (!max_num_meta_sg) {
2343622db5b6SChuck Lever 		mr = ERR_PTR(-EINVAL);
2344622db5b6SChuck Lever 		goto out;
2345622db5b6SChuck Lever 	}
234626bc7eaeSIsrael Rukshin 
23477c717d3aSMax Gurtovoy 	sig_attrs = kzalloc(sizeof(struct ib_sig_attrs), GFP_KERNEL);
2348622db5b6SChuck Lever 	if (!sig_attrs) {
2349622db5b6SChuck Lever 		mr = ERR_PTR(-ENOMEM);
2350622db5b6SChuck Lever 		goto out;
2351622db5b6SChuck Lever 	}
23527c717d3aSMax Gurtovoy 
235326bc7eaeSIsrael Rukshin 	mr = pd->device->ops.alloc_mr_integrity(pd, max_num_data_sg,
235426bc7eaeSIsrael Rukshin 						max_num_meta_sg);
23557c717d3aSMax Gurtovoy 	if (IS_ERR(mr)) {
23567c717d3aSMax Gurtovoy 		kfree(sig_attrs);
2357622db5b6SChuck Lever 		goto out;
23587c717d3aSMax Gurtovoy 	}
235926bc7eaeSIsrael Rukshin 
236026bc7eaeSIsrael Rukshin 	mr->device = pd->device;
236126bc7eaeSIsrael Rukshin 	mr->pd = pd;
236226bc7eaeSIsrael Rukshin 	mr->dm = NULL;
236326bc7eaeSIsrael Rukshin 	mr->uobject = NULL;
236426bc7eaeSIsrael Rukshin 	atomic_inc(&pd->usecnt);
236526bc7eaeSIsrael Rukshin 	mr->need_inval = false;
236626bc7eaeSIsrael Rukshin 	mr->type = IB_MR_TYPE_INTEGRITY;
23677c717d3aSMax Gurtovoy 	mr->sig_attrs = sig_attrs;
236826bc7eaeSIsrael Rukshin 
236913ef5539SLeon Romanovsky 	rdma_restrack_new(&mr->res, RDMA_RESTRACK_MR);
2370b09c4d70SLeon Romanovsky 	rdma_restrack_parent_name(&mr->res, &pd->res);
2371c34a23c2SLeon Romanovsky 	rdma_restrack_add(&mr->res);
2372622db5b6SChuck Lever out:
2373622db5b6SChuck Lever 	trace_mr_integ_alloc(pd, max_num_data_sg, max_num_meta_sg, mr);
237426bc7eaeSIsrael Rukshin 	return mr;
237526bc7eaeSIsrael Rukshin }
237626bc7eaeSIsrael Rukshin EXPORT_SYMBOL(ib_alloc_mr_integrity);
237726bc7eaeSIsrael Rukshin 
23781da177e4SLinus Torvalds /* Multicast groups */
23791da177e4SLinus Torvalds 
is_valid_mcast_lid(struct ib_qp * qp,u16 lid)238052363335SNoa Osherovich static bool is_valid_mcast_lid(struct ib_qp *qp, u16 lid)
238152363335SNoa Osherovich {
238252363335SNoa Osherovich 	struct ib_qp_init_attr init_attr = {};
238352363335SNoa Osherovich 	struct ib_qp_attr attr = {};
238452363335SNoa Osherovich 	int num_eth_ports = 0;
2385904f4f64SParav Pandit 	unsigned int port;
238652363335SNoa Osherovich 
238752363335SNoa Osherovich 	/* If QP state >= init, it is assigned to a port and we can check this
238852363335SNoa Osherovich 	 * port only.
238952363335SNoa Osherovich 	 */
239052363335SNoa Osherovich 	if (!ib_query_qp(qp, &attr, IB_QP_STATE | IB_QP_PORT, &init_attr)) {
239152363335SNoa Osherovich 		if (attr.qp_state >= IB_QPS_INIT) {
2392e6f9bc34SAlex Estrin 			if (rdma_port_get_link_layer(qp->device, attr.port_num) !=
239352363335SNoa Osherovich 			    IB_LINK_LAYER_INFINIBAND)
239452363335SNoa Osherovich 				return true;
239552363335SNoa Osherovich 			goto lid_check;
239652363335SNoa Osherovich 		}
239752363335SNoa Osherovich 	}
239852363335SNoa Osherovich 
239952363335SNoa Osherovich 	/* Can't get a quick answer, iterate over all ports */
2400904f4f64SParav Pandit 	rdma_for_each_port(qp->device, port)
2401e6f9bc34SAlex Estrin 		if (rdma_port_get_link_layer(qp->device, port) !=
240252363335SNoa Osherovich 		    IB_LINK_LAYER_INFINIBAND)
240352363335SNoa Osherovich 			num_eth_ports++;
240452363335SNoa Osherovich 
240552363335SNoa Osherovich 	/* If we have at lease one Ethernet port, RoCE annex declares that
240652363335SNoa Osherovich 	 * multicast LID should be ignored. We can't tell at this step if the
240752363335SNoa Osherovich 	 * QP belongs to an IB or Ethernet port.
240852363335SNoa Osherovich 	 */
240952363335SNoa Osherovich 	if (num_eth_ports)
241052363335SNoa Osherovich 		return true;
241152363335SNoa Osherovich 
241252363335SNoa Osherovich 	/* If all the ports are IB, we can check according to IB spec. */
241352363335SNoa Osherovich lid_check:
241452363335SNoa Osherovich 	return !(lid < be16_to_cpu(IB_MULTICAST_LID_BASE) ||
241552363335SNoa Osherovich 		 lid == be16_to_cpu(IB_LID_PERMISSIVE));
241652363335SNoa Osherovich }
241752363335SNoa Osherovich 
ib_attach_mcast(struct ib_qp * qp,union ib_gid * gid,u16 lid)24181da177e4SLinus Torvalds int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
24191da177e4SLinus Torvalds {
2420c3bccbfbSOr Gerlitz 	int ret;
2421c3bccbfbSOr Gerlitz 
24223023a1e9SKamal Heib 	if (!qp->device->ops.attach_mcast)
242387915bf8SLeon Romanovsky 		return -EOPNOTSUPP;
2424be1d325aSNoa Osherovich 
2425be1d325aSNoa Osherovich 	if (!rdma_is_multicast_addr((struct in6_addr *)gid->raw) ||
2426be1d325aSNoa Osherovich 	    qp->qp_type != IB_QPT_UD || !is_valid_mcast_lid(qp, lid))
24270c33aeedSJack Morgenstein 		return -EINVAL;
24280c33aeedSJack Morgenstein 
24293023a1e9SKamal Heib 	ret = qp->device->ops.attach_mcast(qp, gid, lid);
2430c3bccbfbSOr Gerlitz 	if (!ret)
2431c3bccbfbSOr Gerlitz 		atomic_inc(&qp->usecnt);
2432c3bccbfbSOr Gerlitz 	return ret;
24331da177e4SLinus Torvalds }
24341da177e4SLinus Torvalds EXPORT_SYMBOL(ib_attach_mcast);
24351da177e4SLinus Torvalds 
ib_detach_mcast(struct ib_qp * qp,union ib_gid * gid,u16 lid)24361da177e4SLinus Torvalds int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
24371da177e4SLinus Torvalds {
2438c3bccbfbSOr Gerlitz 	int ret;
2439c3bccbfbSOr Gerlitz 
24403023a1e9SKamal Heib 	if (!qp->device->ops.detach_mcast)
244187915bf8SLeon Romanovsky 		return -EOPNOTSUPP;
2442be1d325aSNoa Osherovich 
2443be1d325aSNoa Osherovich 	if (!rdma_is_multicast_addr((struct in6_addr *)gid->raw) ||
2444be1d325aSNoa Osherovich 	    qp->qp_type != IB_QPT_UD || !is_valid_mcast_lid(qp, lid))
24450c33aeedSJack Morgenstein 		return -EINVAL;
24460c33aeedSJack Morgenstein 
24473023a1e9SKamal Heib 	ret = qp->device->ops.detach_mcast(qp, gid, lid);
2448c3bccbfbSOr Gerlitz 	if (!ret)
2449c3bccbfbSOr Gerlitz 		atomic_dec(&qp->usecnt);
2450c3bccbfbSOr Gerlitz 	return ret;
24511da177e4SLinus Torvalds }
24521da177e4SLinus Torvalds EXPORT_SYMBOL(ib_detach_mcast);
245359991f94SSean Hefty 
2454b73efcb2SMaor Gottlieb /**
2455b73efcb2SMaor Gottlieb  * ib_alloc_xrcd_user - Allocates an XRC domain.
2456b73efcb2SMaor Gottlieb  * @device: The device on which to allocate the XRC domain.
2457b73efcb2SMaor Gottlieb  * @inode: inode to connect XRCD
2458b73efcb2SMaor Gottlieb  * @udata: Valid user data or NULL for kernel object
2459b73efcb2SMaor Gottlieb  */
ib_alloc_xrcd_user(struct ib_device * device,struct inode * inode,struct ib_udata * udata)2460b73efcb2SMaor Gottlieb struct ib_xrcd *ib_alloc_xrcd_user(struct ib_device *device,
2461b73efcb2SMaor Gottlieb 				   struct inode *inode, struct ib_udata *udata)
246259991f94SSean Hefty {
246359991f94SSean Hefty 	struct ib_xrcd *xrcd;
246428ad5f65SLeon Romanovsky 	int ret;
246559991f94SSean Hefty 
24663023a1e9SKamal Heib 	if (!device->ops.alloc_xrcd)
246787915bf8SLeon Romanovsky 		return ERR_PTR(-EOPNOTSUPP);
246859991f94SSean Hefty 
246928ad5f65SLeon Romanovsky 	xrcd = rdma_zalloc_drv_obj(device, ib_xrcd);
247028ad5f65SLeon Romanovsky 	if (!xrcd)
247128ad5f65SLeon Romanovsky 		return ERR_PTR(-ENOMEM);
247228ad5f65SLeon Romanovsky 
247359991f94SSean Hefty 	xrcd->device = device;
2474b73efcb2SMaor Gottlieb 	xrcd->inode = inode;
247559991f94SSean Hefty 	atomic_set(&xrcd->usecnt, 0);
24766f3ca6f4SMaor Gottlieb 	init_rwsem(&xrcd->tgt_qps_rwsem);
24776f3ca6f4SMaor Gottlieb 	xa_init(&xrcd->tgt_qps);
247859991f94SSean Hefty 
247928ad5f65SLeon Romanovsky 	ret = device->ops.alloc_xrcd(xrcd, udata);
248028ad5f65SLeon Romanovsky 	if (ret)
248128ad5f65SLeon Romanovsky 		goto err;
248259991f94SSean Hefty 	return xrcd;
248328ad5f65SLeon Romanovsky err:
248428ad5f65SLeon Romanovsky 	kfree(xrcd);
248528ad5f65SLeon Romanovsky 	return ERR_PTR(ret);
248659991f94SSean Hefty }
2487b73efcb2SMaor Gottlieb EXPORT_SYMBOL(ib_alloc_xrcd_user);
248859991f94SSean Hefty 
2489b73efcb2SMaor Gottlieb /**
2490b73efcb2SMaor Gottlieb  * ib_dealloc_xrcd_user - Deallocates an XRC domain.
2491b73efcb2SMaor Gottlieb  * @xrcd: The XRC domain to deallocate.
2492b73efcb2SMaor Gottlieb  * @udata: Valid user data or NULL for kernel object
2493b73efcb2SMaor Gottlieb  */
ib_dealloc_xrcd_user(struct ib_xrcd * xrcd,struct ib_udata * udata)2494b73efcb2SMaor Gottlieb int ib_dealloc_xrcd_user(struct ib_xrcd *xrcd, struct ib_udata *udata)
249559991f94SSean Hefty {
2496d0c45c85SLeon Romanovsky 	int ret;
2497d0c45c85SLeon Romanovsky 
249859991f94SSean Hefty 	if (atomic_read(&xrcd->usecnt))
249959991f94SSean Hefty 		return -EBUSY;
250059991f94SSean Hefty 
25016f3ca6f4SMaor Gottlieb 	WARN_ON(!xa_empty(&xrcd->tgt_qps));
2502d0c45c85SLeon Romanovsky 	ret = xrcd->device->ops.dealloc_xrcd(xrcd, udata);
2503d0c45c85SLeon Romanovsky 	if (ret)
2504d0c45c85SLeon Romanovsky 		return ret;
250528ad5f65SLeon Romanovsky 	kfree(xrcd);
2506d0c45c85SLeon Romanovsky 	return ret;
250759991f94SSean Hefty }
2508b73efcb2SMaor Gottlieb EXPORT_SYMBOL(ib_dealloc_xrcd_user);
2509319a441dSHadar Hen Zion 
25105fd251c8SYishai Hadas /**
25115fd251c8SYishai Hadas  * ib_create_wq - Creates a WQ associated with the specified protection
25125fd251c8SYishai Hadas  * domain.
25135fd251c8SYishai Hadas  * @pd: The protection domain associated with the WQ.
25141f58621eSRandy Dunlap  * @wq_attr: A list of initial attributes required to create the
25155fd251c8SYishai Hadas  * WQ. If WQ creation succeeds, then the attributes are updated to
25165fd251c8SYishai Hadas  * the actual capabilities of the created WQ.
25175fd251c8SYishai Hadas  *
25181f58621eSRandy Dunlap  * wq_attr->max_wr and wq_attr->max_sge determine
25195fd251c8SYishai Hadas  * the requested size of the WQ, and set to the actual values allocated
25205fd251c8SYishai Hadas  * on return.
25215fd251c8SYishai Hadas  * If ib_create_wq() succeeds, then max_wr and max_sge will always be
25225fd251c8SYishai Hadas  * at least as large as the requested values.
25235fd251c8SYishai Hadas  */
ib_create_wq(struct ib_pd * pd,struct ib_wq_init_attr * wq_attr)25245fd251c8SYishai Hadas struct ib_wq *ib_create_wq(struct ib_pd *pd,
25255fd251c8SYishai Hadas 			   struct ib_wq_init_attr *wq_attr)
25265fd251c8SYishai Hadas {
25275fd251c8SYishai Hadas 	struct ib_wq *wq;
25285fd251c8SYishai Hadas 
25293023a1e9SKamal Heib 	if (!pd->device->ops.create_wq)
253087915bf8SLeon Romanovsky 		return ERR_PTR(-EOPNOTSUPP);
25315fd251c8SYishai Hadas 
25323023a1e9SKamal Heib 	wq = pd->device->ops.create_wq(pd, wq_attr, NULL);
25335fd251c8SYishai Hadas 	if (!IS_ERR(wq)) {
25345fd251c8SYishai Hadas 		wq->event_handler = wq_attr->event_handler;
25355fd251c8SYishai Hadas 		wq->wq_context = wq_attr->wq_context;
25365fd251c8SYishai Hadas 		wq->wq_type = wq_attr->wq_type;
25375fd251c8SYishai Hadas 		wq->cq = wq_attr->cq;
25385fd251c8SYishai Hadas 		wq->device = pd->device;
25395fd251c8SYishai Hadas 		wq->pd = pd;
25405fd251c8SYishai Hadas 		wq->uobject = NULL;
25415fd251c8SYishai Hadas 		atomic_inc(&pd->usecnt);
25425fd251c8SYishai Hadas 		atomic_inc(&wq_attr->cq->usecnt);
25435fd251c8SYishai Hadas 		atomic_set(&wq->usecnt, 0);
25445fd251c8SYishai Hadas 	}
25455fd251c8SYishai Hadas 	return wq;
25465fd251c8SYishai Hadas }
25475fd251c8SYishai Hadas EXPORT_SYMBOL(ib_create_wq);
25485fd251c8SYishai Hadas 
25495fd251c8SYishai Hadas /**
2550add53535SLeon Romanovsky  * ib_destroy_wq_user - Destroys the specified user WQ.
25515fd251c8SYishai Hadas  * @wq: The WQ to destroy.
2552c4367a26SShamir Rabinovitch  * @udata: Valid user data
25535fd251c8SYishai Hadas  */
ib_destroy_wq_user(struct ib_wq * wq,struct ib_udata * udata)2554add53535SLeon Romanovsky int ib_destroy_wq_user(struct ib_wq *wq, struct ib_udata *udata)
25555fd251c8SYishai Hadas {
25565fd251c8SYishai Hadas 	struct ib_cq *cq = wq->cq;
25575fd251c8SYishai Hadas 	struct ib_pd *pd = wq->pd;
2558add53535SLeon Romanovsky 	int ret;
25595fd251c8SYishai Hadas 
25605fd251c8SYishai Hadas 	if (atomic_read(&wq->usecnt))
25615fd251c8SYishai Hadas 		return -EBUSY;
25625fd251c8SYishai Hadas 
2563add53535SLeon Romanovsky 	ret = wq->device->ops.destroy_wq(wq, udata);
2564add53535SLeon Romanovsky 	if (ret)
2565add53535SLeon Romanovsky 		return ret;
2566add53535SLeon Romanovsky 
25675fd251c8SYishai Hadas 	atomic_dec(&pd->usecnt);
25685fd251c8SYishai Hadas 	atomic_dec(&cq->usecnt);
2569add53535SLeon Romanovsky 	return ret;
25705fd251c8SYishai Hadas }
2571add53535SLeon Romanovsky EXPORT_SYMBOL(ib_destroy_wq_user);
25725fd251c8SYishai Hadas 
ib_check_mr_status(struct ib_mr * mr,u32 check_mask,struct ib_mr_status * mr_status)25731b01d335SSagi Grimberg int ib_check_mr_status(struct ib_mr *mr, u32 check_mask,
25741b01d335SSagi Grimberg 		       struct ib_mr_status *mr_status)
25751b01d335SSagi Grimberg {
25763023a1e9SKamal Heib 	if (!mr->device->ops.check_mr_status)
25773023a1e9SKamal Heib 		return -EOPNOTSUPP;
25783023a1e9SKamal Heib 
25793023a1e9SKamal Heib 	return mr->device->ops.check_mr_status(mr, check_mask, mr_status);
25801b01d335SSagi Grimberg }
25811b01d335SSagi Grimberg EXPORT_SYMBOL(ib_check_mr_status);
25824c67e2bfSSagi Grimberg 
ib_set_vf_link_state(struct ib_device * device,int vf,u32 port,int state)25831fb7f897SMark Bloch int ib_set_vf_link_state(struct ib_device *device, int vf, u32 port,
258450174a7fSEli Cohen 			 int state)
258550174a7fSEli Cohen {
25863023a1e9SKamal Heib 	if (!device->ops.set_vf_link_state)
258787915bf8SLeon Romanovsky 		return -EOPNOTSUPP;
258850174a7fSEli Cohen 
25893023a1e9SKamal Heib 	return device->ops.set_vf_link_state(device, vf, port, state);
259050174a7fSEli Cohen }
259150174a7fSEli Cohen EXPORT_SYMBOL(ib_set_vf_link_state);
259250174a7fSEli Cohen 
ib_get_vf_config(struct ib_device * device,int vf,u32 port,struct ifla_vf_info * info)25931fb7f897SMark Bloch int ib_get_vf_config(struct ib_device *device, int vf, u32 port,
259450174a7fSEli Cohen 		     struct ifla_vf_info *info)
259550174a7fSEli Cohen {
25963023a1e9SKamal Heib 	if (!device->ops.get_vf_config)
259787915bf8SLeon Romanovsky 		return -EOPNOTSUPP;
259850174a7fSEli Cohen 
25993023a1e9SKamal Heib 	return device->ops.get_vf_config(device, vf, port, info);
260050174a7fSEli Cohen }
260150174a7fSEli Cohen EXPORT_SYMBOL(ib_get_vf_config);
260250174a7fSEli Cohen 
ib_get_vf_stats(struct ib_device * device,int vf,u32 port,struct ifla_vf_stats * stats)26031fb7f897SMark Bloch int ib_get_vf_stats(struct ib_device *device, int vf, u32 port,
260450174a7fSEli Cohen 		    struct ifla_vf_stats *stats)
260550174a7fSEli Cohen {
26063023a1e9SKamal Heib 	if (!device->ops.get_vf_stats)
260787915bf8SLeon Romanovsky 		return -EOPNOTSUPP;
260850174a7fSEli Cohen 
26093023a1e9SKamal Heib 	return device->ops.get_vf_stats(device, vf, port, stats);
261050174a7fSEli Cohen }
261150174a7fSEli Cohen EXPORT_SYMBOL(ib_get_vf_stats);
261250174a7fSEli Cohen 
ib_set_vf_guid(struct ib_device * device,int vf,u32 port,u64 guid,int type)26131fb7f897SMark Bloch int ib_set_vf_guid(struct ib_device *device, int vf, u32 port, u64 guid,
261450174a7fSEli Cohen 		   int type)
261550174a7fSEli Cohen {
26163023a1e9SKamal Heib 	if (!device->ops.set_vf_guid)
261787915bf8SLeon Romanovsky 		return -EOPNOTSUPP;
261850174a7fSEli Cohen 
26193023a1e9SKamal Heib 	return device->ops.set_vf_guid(device, vf, port, guid, type);
262050174a7fSEli Cohen }
262150174a7fSEli Cohen EXPORT_SYMBOL(ib_set_vf_guid);
262250174a7fSEli Cohen 
ib_get_vf_guid(struct ib_device * device,int vf,u32 port,struct ifla_vf_guid * node_guid,struct ifla_vf_guid * port_guid)26231fb7f897SMark Bloch int ib_get_vf_guid(struct ib_device *device, int vf, u32 port,
2624bfcb3c5dSDanit Goldberg 		   struct ifla_vf_guid *node_guid,
2625bfcb3c5dSDanit Goldberg 		   struct ifla_vf_guid *port_guid)
2626bfcb3c5dSDanit Goldberg {
2627bfcb3c5dSDanit Goldberg 	if (!device->ops.get_vf_guid)
2628bfcb3c5dSDanit Goldberg 		return -EOPNOTSUPP;
2629bfcb3c5dSDanit Goldberg 
2630bfcb3c5dSDanit Goldberg 	return device->ops.get_vf_guid(device, vf, port, node_guid, port_guid);
2631bfcb3c5dSDanit Goldberg }
2632bfcb3c5dSDanit Goldberg EXPORT_SYMBOL(ib_get_vf_guid);
26334c67e2bfSSagi Grimberg /**
26342cdfcdd8SMax Gurtovoy  * ib_map_mr_sg_pi() - Map the dma mapped SG lists for PI (protection
26352cdfcdd8SMax Gurtovoy  *     information) and set an appropriate memory region for registration.
26362cdfcdd8SMax Gurtovoy  * @mr:             memory region
26372cdfcdd8SMax Gurtovoy  * @data_sg:        dma mapped scatterlist for data
26382cdfcdd8SMax Gurtovoy  * @data_sg_nents:  number of entries in data_sg
26392cdfcdd8SMax Gurtovoy  * @data_sg_offset: offset in bytes into data_sg
26402cdfcdd8SMax Gurtovoy  * @meta_sg:        dma mapped scatterlist for metadata
26412cdfcdd8SMax Gurtovoy  * @meta_sg_nents:  number of entries in meta_sg
26422cdfcdd8SMax Gurtovoy  * @meta_sg_offset: offset in bytes into meta_sg
26432cdfcdd8SMax Gurtovoy  * @page_size:      page vector desired page size
26442cdfcdd8SMax Gurtovoy  *
26452cdfcdd8SMax Gurtovoy  * Constraints:
26462cdfcdd8SMax Gurtovoy  * - The MR must be allocated with type IB_MR_TYPE_INTEGRITY.
26472cdfcdd8SMax Gurtovoy  *
26482cdfcdd8SMax Gurtovoy  * Return: 0 on success.
26492cdfcdd8SMax Gurtovoy  *
26502cdfcdd8SMax Gurtovoy  * After this completes successfully, the  memory region
26512cdfcdd8SMax Gurtovoy  * is ready for registration.
26522cdfcdd8SMax Gurtovoy  */
ib_map_mr_sg_pi(struct ib_mr * mr,struct scatterlist * data_sg,int data_sg_nents,unsigned int * data_sg_offset,struct scatterlist * meta_sg,int meta_sg_nents,unsigned int * meta_sg_offset,unsigned int page_size)26532cdfcdd8SMax Gurtovoy int ib_map_mr_sg_pi(struct ib_mr *mr, struct scatterlist *data_sg,
26542cdfcdd8SMax Gurtovoy 		    int data_sg_nents, unsigned int *data_sg_offset,
26552cdfcdd8SMax Gurtovoy 		    struct scatterlist *meta_sg, int meta_sg_nents,
26562cdfcdd8SMax Gurtovoy 		    unsigned int *meta_sg_offset, unsigned int page_size)
26572cdfcdd8SMax Gurtovoy {
26582cdfcdd8SMax Gurtovoy 	if (unlikely(!mr->device->ops.map_mr_sg_pi ||
26592cdfcdd8SMax Gurtovoy 		     WARN_ON_ONCE(mr->type != IB_MR_TYPE_INTEGRITY)))
26602cdfcdd8SMax Gurtovoy 		return -EOPNOTSUPP;
26612cdfcdd8SMax Gurtovoy 
26622cdfcdd8SMax Gurtovoy 	mr->page_size = page_size;
26632cdfcdd8SMax Gurtovoy 
26642cdfcdd8SMax Gurtovoy 	return mr->device->ops.map_mr_sg_pi(mr, data_sg, data_sg_nents,
26652cdfcdd8SMax Gurtovoy 					    data_sg_offset, meta_sg,
26662cdfcdd8SMax Gurtovoy 					    meta_sg_nents, meta_sg_offset);
26672cdfcdd8SMax Gurtovoy }
26682cdfcdd8SMax Gurtovoy EXPORT_SYMBOL(ib_map_mr_sg_pi);
26692cdfcdd8SMax Gurtovoy 
26702cdfcdd8SMax Gurtovoy /**
26714c67e2bfSSagi Grimberg  * ib_map_mr_sg() - Map the largest prefix of a dma mapped SG list
26724c67e2bfSSagi Grimberg  *     and set it the memory region.
26734c67e2bfSSagi Grimberg  * @mr:            memory region
26744c67e2bfSSagi Grimberg  * @sg:            dma mapped scatterlist
26754c67e2bfSSagi Grimberg  * @sg_nents:      number of entries in sg
2676ff2ba993SChristoph Hellwig  * @sg_offset:     offset in bytes into sg
26774c67e2bfSSagi Grimberg  * @page_size:     page vector desired page size
26784c67e2bfSSagi Grimberg  *
26794c67e2bfSSagi Grimberg  * Constraints:
2680255e636dSMauro Carvalho Chehab  *
26814c67e2bfSSagi Grimberg  * - The first sg element is allowed to have an offset.
268252746129SBart Van Assche  * - Each sg element must either be aligned to page_size or virtually
268352746129SBart Van Assche  *   contiguous to the previous element. In case an sg element has a
268452746129SBart Van Assche  *   non-contiguous offset, the mapping prefix will not include it.
26854c67e2bfSSagi Grimberg  * - The last sg element is allowed to have length less than page_size.
26864c67e2bfSSagi Grimberg  * - If sg_nents total byte length exceeds the mr max_num_sge * page_size
26874c67e2bfSSagi Grimberg  *   then only max_num_sg entries will be mapped.
268852746129SBart Van Assche  * - If the MR was allocated with type IB_MR_TYPE_SG_GAPS, none of these
2689f5aa9159SSagi Grimberg  *   constraints holds and the page_size argument is ignored.
26904c67e2bfSSagi Grimberg  *
26914c67e2bfSSagi Grimberg  * Returns the number of sg elements that were mapped to the memory region.
26924c67e2bfSSagi Grimberg  *
26934c67e2bfSSagi Grimberg  * After this completes successfully, the  memory region
26944c67e2bfSSagi Grimberg  * is ready for registration.
26954c67e2bfSSagi Grimberg  */
ib_map_mr_sg(struct ib_mr * mr,struct scatterlist * sg,int sg_nents,unsigned int * sg_offset,unsigned int page_size)2696ff2ba993SChristoph Hellwig int ib_map_mr_sg(struct ib_mr *mr, struct scatterlist *sg, int sg_nents,
26979aa8b321SBart Van Assche 		 unsigned int *sg_offset, unsigned int page_size)
26984c67e2bfSSagi Grimberg {
26993023a1e9SKamal Heib 	if (unlikely(!mr->device->ops.map_mr_sg))
270087915bf8SLeon Romanovsky 		return -EOPNOTSUPP;
27014c67e2bfSSagi Grimberg 
27024c67e2bfSSagi Grimberg 	mr->page_size = page_size;
27034c67e2bfSSagi Grimberg 
27043023a1e9SKamal Heib 	return mr->device->ops.map_mr_sg(mr, sg, sg_nents, sg_offset);
27054c67e2bfSSagi Grimberg }
27064c67e2bfSSagi Grimberg EXPORT_SYMBOL(ib_map_mr_sg);
27074c67e2bfSSagi Grimberg 
27084c67e2bfSSagi Grimberg /**
27094c67e2bfSSagi Grimberg  * ib_sg_to_pages() - Convert the largest prefix of a sg list
27104c67e2bfSSagi Grimberg  *     to a page vector
27114c67e2bfSSagi Grimberg  * @mr:            memory region
27124c67e2bfSSagi Grimberg  * @sgl:           dma mapped scatterlist
27134c67e2bfSSagi Grimberg  * @sg_nents:      number of entries in sg
2714255e636dSMauro Carvalho Chehab  * @sg_offset_p:   ==== =======================================================
2715255e636dSMauro Carvalho Chehab  *                 IN   start offset in bytes into sg
2716255e636dSMauro Carvalho Chehab  *                 OUT  offset in bytes for element n of the sg of the first
27179aa8b321SBart Van Assche  *                      byte that has not been processed where n is the return
27189aa8b321SBart Van Assche  *                      value of this function.
2719255e636dSMauro Carvalho Chehab  *                 ==== =======================================================
27204c67e2bfSSagi Grimberg  * @set_page:      driver page assignment function pointer
27214c67e2bfSSagi Grimberg  *
27228f5ba10eSBart Van Assche  * Core service helper for drivers to convert the largest
27234c67e2bfSSagi Grimberg  * prefix of given sg list to a page vector. The sg list
27244c67e2bfSSagi Grimberg  * prefix converted is the prefix that meet the requirements
27254c67e2bfSSagi Grimberg  * of ib_map_mr_sg.
27264c67e2bfSSagi Grimberg  *
27274c67e2bfSSagi Grimberg  * Returns the number of sg elements that were assigned to
27284c67e2bfSSagi Grimberg  * a page vector.
27294c67e2bfSSagi Grimberg  */
ib_sg_to_pages(struct ib_mr * mr,struct scatterlist * sgl,int sg_nents,unsigned int * sg_offset_p,int (* set_page)(struct ib_mr *,u64))2730ff2ba993SChristoph Hellwig int ib_sg_to_pages(struct ib_mr *mr, struct scatterlist *sgl, int sg_nents,
27319aa8b321SBart Van Assche 		unsigned int *sg_offset_p, int (*set_page)(struct ib_mr *, u64))
27324c67e2bfSSagi Grimberg {
27334c67e2bfSSagi Grimberg 	struct scatterlist *sg;
2734b6aeb980SBart Van Assche 	u64 last_end_dma_addr = 0;
27359aa8b321SBart Van Assche 	unsigned int sg_offset = sg_offset_p ? *sg_offset_p : 0;
27364c67e2bfSSagi Grimberg 	unsigned int last_page_off = 0;
27374c67e2bfSSagi Grimberg 	u64 page_mask = ~((u64)mr->page_size - 1);
27388f5ba10eSBart Van Assche 	int i, ret;
27394c67e2bfSSagi Grimberg 
27409aa8b321SBart Van Assche 	if (unlikely(sg_nents <= 0 || sg_offset > sg_dma_len(&sgl[0])))
27419aa8b321SBart Van Assche 		return -EINVAL;
27429aa8b321SBart Van Assche 
2743ff2ba993SChristoph Hellwig 	mr->iova = sg_dma_address(&sgl[0]) + sg_offset;
27444c67e2bfSSagi Grimberg 	mr->length = 0;
27454c67e2bfSSagi Grimberg 
27464c67e2bfSSagi Grimberg 	for_each_sg(sgl, sg, sg_nents, i) {
2747ff2ba993SChristoph Hellwig 		u64 dma_addr = sg_dma_address(sg) + sg_offset;
27489aa8b321SBart Van Assche 		u64 prev_addr = dma_addr;
2749ff2ba993SChristoph Hellwig 		unsigned int dma_len = sg_dma_len(sg) - sg_offset;
27504c67e2bfSSagi Grimberg 		u64 end_dma_addr = dma_addr + dma_len;
27514c67e2bfSSagi Grimberg 		u64 page_addr = dma_addr & page_mask;
27524c67e2bfSSagi Grimberg 
27538f5ba10eSBart Van Assche 		/*
27548f5ba10eSBart Van Assche 		 * For the second and later elements, check whether either the
27558f5ba10eSBart Van Assche 		 * end of element i-1 or the start of element i is not aligned
27568f5ba10eSBart Van Assche 		 * on a page boundary.
27578f5ba10eSBart Van Assche 		 */
27588f5ba10eSBart Van Assche 		if (i && (last_page_off != 0 || page_addr != dma_addr)) {
27598f5ba10eSBart Van Assche 			/* Stop mapping if there is a gap. */
27608f5ba10eSBart Van Assche 			if (last_end_dma_addr != dma_addr)
27618f5ba10eSBart Van Assche 				break;
27624c67e2bfSSagi Grimberg 
27638f5ba10eSBart Van Assche 			/*
27648f5ba10eSBart Van Assche 			 * Coalesce this element with the last. If it is small
27658f5ba10eSBart Van Assche 			 * enough just update mr->length. Otherwise start
27668f5ba10eSBart Van Assche 			 * mapping from the next page.
27678f5ba10eSBart Van Assche 			 */
27688f5ba10eSBart Van Assche 			goto next_page;
27694c67e2bfSSagi Grimberg 		}
27704c67e2bfSSagi Grimberg 
27714c67e2bfSSagi Grimberg 		do {
27728f5ba10eSBart Van Assche 			ret = set_page(mr, page_addr);
27739aa8b321SBart Van Assche 			if (unlikely(ret < 0)) {
27749aa8b321SBart Van Assche 				sg_offset = prev_addr - sg_dma_address(sg);
27759aa8b321SBart Van Assche 				mr->length += prev_addr - dma_addr;
27769aa8b321SBart Van Assche 				if (sg_offset_p)
27779aa8b321SBart Van Assche 					*sg_offset_p = sg_offset;
27789aa8b321SBart Van Assche 				return i || sg_offset ? i : ret;
27799aa8b321SBart Van Assche 			}
27809aa8b321SBart Van Assche 			prev_addr = page_addr;
27818f5ba10eSBart Van Assche next_page:
27824c67e2bfSSagi Grimberg 			page_addr += mr->page_size;
27834c67e2bfSSagi Grimberg 		} while (page_addr < end_dma_addr);
27844c67e2bfSSagi Grimberg 
27854c67e2bfSSagi Grimberg 		mr->length += dma_len;
27864c67e2bfSSagi Grimberg 		last_end_dma_addr = end_dma_addr;
27874c67e2bfSSagi Grimberg 		last_page_off = end_dma_addr & ~page_mask;
2788ff2ba993SChristoph Hellwig 
2789ff2ba993SChristoph Hellwig 		sg_offset = 0;
27904c67e2bfSSagi Grimberg 	}
27914c67e2bfSSagi Grimberg 
27929aa8b321SBart Van Assche 	if (sg_offset_p)
27939aa8b321SBart Van Assche 		*sg_offset_p = 0;
27944c67e2bfSSagi Grimberg 	return i;
27954c67e2bfSSagi Grimberg }
27964c67e2bfSSagi Grimberg EXPORT_SYMBOL(ib_sg_to_pages);
2797765d6774SSteve Wise 
2798765d6774SSteve Wise struct ib_drain_cqe {
2799765d6774SSteve Wise 	struct ib_cqe cqe;
2800765d6774SSteve Wise 	struct completion done;
2801765d6774SSteve Wise };
2802765d6774SSteve Wise 
ib_drain_qp_done(struct ib_cq * cq,struct ib_wc * wc)2803765d6774SSteve Wise static void ib_drain_qp_done(struct ib_cq *cq, struct ib_wc *wc)
2804765d6774SSteve Wise {
2805765d6774SSteve Wise 	struct ib_drain_cqe *cqe = container_of(wc->wr_cqe, struct ib_drain_cqe,
2806765d6774SSteve Wise 						cqe);
2807765d6774SSteve Wise 
2808765d6774SSteve Wise 	complete(&cqe->done);
2809765d6774SSteve Wise }
2810765d6774SSteve Wise 
2811765d6774SSteve Wise /*
2812765d6774SSteve Wise  * Post a WR and block until its completion is reaped for the SQ.
2813765d6774SSteve Wise  */
__ib_drain_sq(struct ib_qp * qp)2814765d6774SSteve Wise static void __ib_drain_sq(struct ib_qp *qp)
2815765d6774SSteve Wise {
2816f039f44fSBart Van Assche 	struct ib_cq *cq = qp->send_cq;
2817765d6774SSteve Wise 	struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
2818765d6774SSteve Wise 	struct ib_drain_cqe sdrain;
2819a1ae7d03SBart Van Assche 	struct ib_rdma_wr swr = {
2820a1ae7d03SBart Van Assche 		.wr = {
28216ee68773SAndrew Morton 			.next = NULL,
28226ee68773SAndrew Morton 			{ .wr_cqe	= &sdrain.cqe, },
2823a1ae7d03SBart Van Assche 			.opcode	= IB_WR_RDMA_WRITE,
2824a1ae7d03SBart Van Assche 		},
2825a1ae7d03SBart Van Assche 	};
2826765d6774SSteve Wise 	int ret;
2827765d6774SSteve Wise 
2828765d6774SSteve Wise 	ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
2829765d6774SSteve Wise 	if (ret) {
2830765d6774SSteve Wise 		WARN_ONCE(ret, "failed to drain send queue: %d\n", ret);
2831765d6774SSteve Wise 		return;
2832765d6774SSteve Wise 	}
2833765d6774SSteve Wise 
2834aaebd377SMax Gurtovoy 	sdrain.cqe.done = ib_drain_qp_done;
2835aaebd377SMax Gurtovoy 	init_completion(&sdrain.done);
2836aaebd377SMax Gurtovoy 
28371fec77bfSBart Van Assche 	ret = ib_post_send(qp, &swr.wr, NULL);
2838765d6774SSteve Wise 	if (ret) {
2839765d6774SSteve Wise 		WARN_ONCE(ret, "failed to drain send queue: %d\n", ret);
2840765d6774SSteve Wise 		return;
2841765d6774SSteve Wise 	}
2842765d6774SSteve Wise 
2843f039f44fSBart Van Assche 	if (cq->poll_ctx == IB_POLL_DIRECT)
2844f039f44fSBart Van Assche 		while (wait_for_completion_timeout(&sdrain.done, HZ / 10) <= 0)
2845f039f44fSBart Van Assche 			ib_process_cq_direct(cq, -1);
2846f039f44fSBart Van Assche 	else
2847765d6774SSteve Wise 		wait_for_completion(&sdrain.done);
2848765d6774SSteve Wise }
2849765d6774SSteve Wise 
2850765d6774SSteve Wise /*
2851765d6774SSteve Wise  * Post a WR and block until its completion is reaped for the RQ.
2852765d6774SSteve Wise  */
__ib_drain_rq(struct ib_qp * qp)2853765d6774SSteve Wise static void __ib_drain_rq(struct ib_qp *qp)
2854765d6774SSteve Wise {
2855f039f44fSBart Van Assche 	struct ib_cq *cq = qp->recv_cq;
2856765d6774SSteve Wise 	struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
2857765d6774SSteve Wise 	struct ib_drain_cqe rdrain;
28581fec77bfSBart Van Assche 	struct ib_recv_wr rwr = {};
2859765d6774SSteve Wise 	int ret;
2860765d6774SSteve Wise 
2861765d6774SSteve Wise 	ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
2862765d6774SSteve Wise 	if (ret) {
2863765d6774SSteve Wise 		WARN_ONCE(ret, "failed to drain recv queue: %d\n", ret);
2864765d6774SSteve Wise 		return;
2865765d6774SSteve Wise 	}
2866765d6774SSteve Wise 
2867aaebd377SMax Gurtovoy 	rwr.wr_cqe = &rdrain.cqe;
2868aaebd377SMax Gurtovoy 	rdrain.cqe.done = ib_drain_qp_done;
2869aaebd377SMax Gurtovoy 	init_completion(&rdrain.done);
2870aaebd377SMax Gurtovoy 
28711fec77bfSBart Van Assche 	ret = ib_post_recv(qp, &rwr, NULL);
2872765d6774SSteve Wise 	if (ret) {
2873765d6774SSteve Wise 		WARN_ONCE(ret, "failed to drain recv queue: %d\n", ret);
2874765d6774SSteve Wise 		return;
2875765d6774SSteve Wise 	}
2876765d6774SSteve Wise 
2877f039f44fSBart Van Assche 	if (cq->poll_ctx == IB_POLL_DIRECT)
2878f039f44fSBart Van Assche 		while (wait_for_completion_timeout(&rdrain.done, HZ / 10) <= 0)
2879f039f44fSBart Van Assche 			ib_process_cq_direct(cq, -1);
2880f039f44fSBart Van Assche 	else
2881765d6774SSteve Wise 		wait_for_completion(&rdrain.done);
2882765d6774SSteve Wise }
2883765d6774SSteve Wise 
2884765d6774SSteve Wise /**
2885765d6774SSteve Wise  * ib_drain_sq() - Block until all SQ CQEs have been consumed by the
2886765d6774SSteve Wise  *		   application.
2887765d6774SSteve Wise  * @qp:            queue pair to drain
2888765d6774SSteve Wise  *
2889765d6774SSteve Wise  * If the device has a provider-specific drain function, then
2890765d6774SSteve Wise  * call that.  Otherwise call the generic drain function
2891765d6774SSteve Wise  * __ib_drain_sq().
2892765d6774SSteve Wise  *
2893765d6774SSteve Wise  * The caller must:
2894765d6774SSteve Wise  *
2895765d6774SSteve Wise  * ensure there is room in the CQ and SQ for the drain work request and
2896765d6774SSteve Wise  * completion.
2897765d6774SSteve Wise  *
2898f039f44fSBart Van Assche  * allocate the CQ using ib_alloc_cq().
2899765d6774SSteve Wise  *
2900765d6774SSteve Wise  * ensure that there are no other contexts that are posting WRs concurrently.
2901765d6774SSteve Wise  * Otherwise the drain is not guaranteed.
2902765d6774SSteve Wise  */
ib_drain_sq(struct ib_qp * qp)2903765d6774SSteve Wise void ib_drain_sq(struct ib_qp *qp)
2904765d6774SSteve Wise {
29053023a1e9SKamal Heib 	if (qp->device->ops.drain_sq)
29063023a1e9SKamal Heib 		qp->device->ops.drain_sq(qp);
2907765d6774SSteve Wise 	else
2908765d6774SSteve Wise 		__ib_drain_sq(qp);
29093e5901cbSChuck Lever 	trace_cq_drain_complete(qp->send_cq);
2910765d6774SSteve Wise }
2911765d6774SSteve Wise EXPORT_SYMBOL(ib_drain_sq);
2912765d6774SSteve Wise 
2913765d6774SSteve Wise /**
2914765d6774SSteve Wise  * ib_drain_rq() - Block until all RQ CQEs have been consumed by the
2915765d6774SSteve Wise  *		   application.
2916765d6774SSteve Wise  * @qp:            queue pair to drain
2917765d6774SSteve Wise  *
2918765d6774SSteve Wise  * If the device has a provider-specific drain function, then
2919765d6774SSteve Wise  * call that.  Otherwise call the generic drain function
2920765d6774SSteve Wise  * __ib_drain_rq().
2921765d6774SSteve Wise  *
2922765d6774SSteve Wise  * The caller must:
2923765d6774SSteve Wise  *
2924765d6774SSteve Wise  * ensure there is room in the CQ and RQ for the drain work request and
2925765d6774SSteve Wise  * completion.
2926765d6774SSteve Wise  *
2927f039f44fSBart Van Assche  * allocate the CQ using ib_alloc_cq().
2928765d6774SSteve Wise  *
2929765d6774SSteve Wise  * ensure that there are no other contexts that are posting WRs concurrently.
2930765d6774SSteve Wise  * Otherwise the drain is not guaranteed.
2931765d6774SSteve Wise  */
ib_drain_rq(struct ib_qp * qp)2932765d6774SSteve Wise void ib_drain_rq(struct ib_qp *qp)
2933765d6774SSteve Wise {
29343023a1e9SKamal Heib 	if (qp->device->ops.drain_rq)
29353023a1e9SKamal Heib 		qp->device->ops.drain_rq(qp);
2936765d6774SSteve Wise 	else
2937765d6774SSteve Wise 		__ib_drain_rq(qp);
29383e5901cbSChuck Lever 	trace_cq_drain_complete(qp->recv_cq);
2939765d6774SSteve Wise }
2940765d6774SSteve Wise EXPORT_SYMBOL(ib_drain_rq);
2941765d6774SSteve Wise 
2942765d6774SSteve Wise /**
2943765d6774SSteve Wise  * ib_drain_qp() - Block until all CQEs have been consumed by the
2944765d6774SSteve Wise  *		   application on both the RQ and SQ.
2945765d6774SSteve Wise  * @qp:            queue pair to drain
2946765d6774SSteve Wise  *
2947765d6774SSteve Wise  * The caller must:
2948765d6774SSteve Wise  *
2949765d6774SSteve Wise  * ensure there is room in the CQ(s), SQ, and RQ for drain work requests
2950765d6774SSteve Wise  * and completions.
2951765d6774SSteve Wise  *
2952f039f44fSBart Van Assche  * allocate the CQs using ib_alloc_cq().
2953765d6774SSteve Wise  *
2954765d6774SSteve Wise  * ensure that there are no other contexts that are posting WRs concurrently.
2955765d6774SSteve Wise  * Otherwise the drain is not guaranteed.
2956765d6774SSteve Wise  */
ib_drain_qp(struct ib_qp * qp)2957765d6774SSteve Wise void ib_drain_qp(struct ib_qp *qp)
2958765d6774SSteve Wise {
2959765d6774SSteve Wise 	ib_drain_sq(qp);
296042235f80SSagi Grimberg 	if (!qp->srq)
2961765d6774SSteve Wise 		ib_drain_rq(qp);
2962765d6774SSteve Wise }
2963765d6774SSteve Wise EXPORT_SYMBOL(ib_drain_qp);
2964f6a8a19bSDenis Drozdov 
rdma_alloc_netdev(struct ib_device * device,u32 port_num,enum rdma_netdev_t type,const char * name,unsigned char name_assign_type,void (* setup)(struct net_device *))29651fb7f897SMark Bloch struct net_device *rdma_alloc_netdev(struct ib_device *device, u32 port_num,
2966f6a8a19bSDenis Drozdov 				     enum rdma_netdev_t type, const char *name,
2967f6a8a19bSDenis Drozdov 				     unsigned char name_assign_type,
2968f6a8a19bSDenis Drozdov 				     void (*setup)(struct net_device *))
2969f6a8a19bSDenis Drozdov {
2970f6a8a19bSDenis Drozdov 	struct rdma_netdev_alloc_params params;
2971f6a8a19bSDenis Drozdov 	struct net_device *netdev;
2972f6a8a19bSDenis Drozdov 	int rc;
2973f6a8a19bSDenis Drozdov 
29743023a1e9SKamal Heib 	if (!device->ops.rdma_netdev_get_params)
2975f6a8a19bSDenis Drozdov 		return ERR_PTR(-EOPNOTSUPP);
2976f6a8a19bSDenis Drozdov 
29773023a1e9SKamal Heib 	rc = device->ops.rdma_netdev_get_params(device, port_num, type,
29783023a1e9SKamal Heib 						&params);
2979f6a8a19bSDenis Drozdov 	if (rc)
2980f6a8a19bSDenis Drozdov 		return ERR_PTR(rc);
2981f6a8a19bSDenis Drozdov 
2982f6a8a19bSDenis Drozdov 	netdev = alloc_netdev_mqs(params.sizeof_priv, name, name_assign_type,
2983f6a8a19bSDenis Drozdov 				  setup, params.txqs, params.rxqs);
2984f6a8a19bSDenis Drozdov 	if (!netdev)
2985f6a8a19bSDenis Drozdov 		return ERR_PTR(-ENOMEM);
2986f6a8a19bSDenis Drozdov 
2987f6a8a19bSDenis Drozdov 	return netdev;
2988f6a8a19bSDenis Drozdov }
2989f6a8a19bSDenis Drozdov EXPORT_SYMBOL(rdma_alloc_netdev);
29905d6b0cb3SDenis Drozdov 
rdma_init_netdev(struct ib_device * device,u32 port_num,enum rdma_netdev_t type,const char * name,unsigned char name_assign_type,void (* setup)(struct net_device *),struct net_device * netdev)29911fb7f897SMark Bloch int rdma_init_netdev(struct ib_device *device, u32 port_num,
29925d6b0cb3SDenis Drozdov 		     enum rdma_netdev_t type, const char *name,
29935d6b0cb3SDenis Drozdov 		     unsigned char name_assign_type,
29945d6b0cb3SDenis Drozdov 		     void (*setup)(struct net_device *),
29955d6b0cb3SDenis Drozdov 		     struct net_device *netdev)
29965d6b0cb3SDenis Drozdov {
29975d6b0cb3SDenis Drozdov 	struct rdma_netdev_alloc_params params;
29985d6b0cb3SDenis Drozdov 	int rc;
29995d6b0cb3SDenis Drozdov 
30003023a1e9SKamal Heib 	if (!device->ops.rdma_netdev_get_params)
30015d6b0cb3SDenis Drozdov 		return -EOPNOTSUPP;
30025d6b0cb3SDenis Drozdov 
30033023a1e9SKamal Heib 	rc = device->ops.rdma_netdev_get_params(device, port_num, type,
30043023a1e9SKamal Heib 						&params);
30055d6b0cb3SDenis Drozdov 	if (rc)
30065d6b0cb3SDenis Drozdov 		return rc;
30075d6b0cb3SDenis Drozdov 
30085d6b0cb3SDenis Drozdov 	return params.initialize_rdma_netdev(device, port_num,
30095d6b0cb3SDenis Drozdov 					     netdev, params.param);
30105d6b0cb3SDenis Drozdov }
30115d6b0cb3SDenis Drozdov EXPORT_SYMBOL(rdma_init_netdev);
3012a808273aSShiraz Saleem 
__rdma_block_iter_start(struct ib_block_iter * biter,struct scatterlist * sglist,unsigned int nents,unsigned long pgsz)3013a808273aSShiraz Saleem void __rdma_block_iter_start(struct ib_block_iter *biter,
3014a808273aSShiraz Saleem 			     struct scatterlist *sglist, unsigned int nents,
3015a808273aSShiraz Saleem 			     unsigned long pgsz)
3016a808273aSShiraz Saleem {
3017a808273aSShiraz Saleem 	memset(biter, 0, sizeof(struct ib_block_iter));
3018a808273aSShiraz Saleem 	biter->__sg = sglist;
3019a808273aSShiraz Saleem 	biter->__sg_nents = nents;
3020a808273aSShiraz Saleem 
3021a808273aSShiraz Saleem 	/* Driver provides best block size to use */
3022a808273aSShiraz Saleem 	biter->__pg_bit = __fls(pgsz);
3023a808273aSShiraz Saleem }
3024a808273aSShiraz Saleem EXPORT_SYMBOL(__rdma_block_iter_start);
3025a808273aSShiraz Saleem 
__rdma_block_iter_next(struct ib_block_iter * biter)3026a808273aSShiraz Saleem bool __rdma_block_iter_next(struct ib_block_iter *biter)
3027a808273aSShiraz Saleem {
3028a808273aSShiraz Saleem 	unsigned int block_offset;
30290afec5e9SYonatan Nachum 	unsigned int sg_delta;
3030a808273aSShiraz Saleem 
3031a808273aSShiraz Saleem 	if (!biter->__sg_nents || !biter->__sg)
3032a808273aSShiraz Saleem 		return false;
3033a808273aSShiraz Saleem 
3034a808273aSShiraz Saleem 	biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance;
3035a808273aSShiraz Saleem 	block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1);
30360afec5e9SYonatan Nachum 	sg_delta = BIT_ULL(biter->__pg_bit) - block_offset;
3037a808273aSShiraz Saleem 
30380afec5e9SYonatan Nachum 	if (sg_dma_len(biter->__sg) - biter->__sg_advance > sg_delta) {
30390afec5e9SYonatan Nachum 		biter->__sg_advance += sg_delta;
30400afec5e9SYonatan Nachum 	} else {
3041a808273aSShiraz Saleem 		biter->__sg_advance = 0;
3042a808273aSShiraz Saleem 		biter->__sg = sg_next(biter->__sg);
3043a808273aSShiraz Saleem 		biter->__sg_nents--;
3044a808273aSShiraz Saleem 	}
3045a808273aSShiraz Saleem 
3046a808273aSShiraz Saleem 	return true;
3047a808273aSShiraz Saleem }
3048a808273aSShiraz Saleem EXPORT_SYMBOL(__rdma_block_iter_next);
30490a0800ceSMark Zhang 
30500a0800ceSMark Zhang /**
30510a0800ceSMark Zhang  * rdma_alloc_hw_stats_struct - Helper function to allocate dynamic struct
30520a0800ceSMark Zhang  *   for the drivers.
30530a0800ceSMark Zhang  * @descs: array of static descriptors
30540a0800ceSMark Zhang  * @num_counters: number of elements in array
30550a0800ceSMark Zhang  * @lifespan: milliseconds between updates
30560a0800ceSMark Zhang  */
rdma_alloc_hw_stats_struct(const struct rdma_stat_desc * descs,int num_counters,unsigned long lifespan)30570a0800ceSMark Zhang struct rdma_hw_stats *rdma_alloc_hw_stats_struct(
30580a0800ceSMark Zhang 	const struct rdma_stat_desc *descs, int num_counters,
30590a0800ceSMark Zhang 	unsigned long lifespan)
30600a0800ceSMark Zhang {
30610a0800ceSMark Zhang 	struct rdma_hw_stats *stats;
30620a0800ceSMark Zhang 
30630a0800ceSMark Zhang 	stats = kzalloc(struct_size(stats, value, num_counters), GFP_KERNEL);
30640a0800ceSMark Zhang 	if (!stats)
30650a0800ceSMark Zhang 		return NULL;
30660a0800ceSMark Zhang 
30670dc89684SAharon Landau 	stats->is_disabled = kcalloc(BITS_TO_LONGS(num_counters),
30680dc89684SAharon Landau 				     sizeof(*stats->is_disabled), GFP_KERNEL);
30690dc89684SAharon Landau 	if (!stats->is_disabled)
30700dc89684SAharon Landau 		goto err;
30710dc89684SAharon Landau 
30720a0800ceSMark Zhang 	stats->descs = descs;
30730a0800ceSMark Zhang 	stats->num_counters = num_counters;
30740a0800ceSMark Zhang 	stats->lifespan = msecs_to_jiffies(lifespan);
3075067113d9SMark Zhang 	mutex_init(&stats->lock);
30760a0800ceSMark Zhang 
30770a0800ceSMark Zhang 	return stats;
30780dc89684SAharon Landau 
30790dc89684SAharon Landau err:
30800dc89684SAharon Landau 	kfree(stats);
30810dc89684SAharon Landau 	return NULL;
30820a0800ceSMark Zhang }
30830a0800ceSMark Zhang EXPORT_SYMBOL(rdma_alloc_hw_stats_struct);
30840a0800ceSMark Zhang 
30850a0800ceSMark Zhang /**
30860a0800ceSMark Zhang  * rdma_free_hw_stats_struct - Helper function to release rdma_hw_stats
30870a0800ceSMark Zhang  * @stats: statistics to release
30880a0800ceSMark Zhang  */
rdma_free_hw_stats_struct(struct rdma_hw_stats * stats)30890a0800ceSMark Zhang void rdma_free_hw_stats_struct(struct rdma_hw_stats *stats)
30900a0800ceSMark Zhang {
30910dc89684SAharon Landau 	if (!stats)
30920dc89684SAharon Landau 		return;
30930dc89684SAharon Landau 
30940dc89684SAharon Landau 	kfree(stats->is_disabled);
30950a0800ceSMark Zhang 	kfree(stats);
30960a0800ceSMark Zhang }
30970a0800ceSMark Zhang EXPORT_SYMBOL(rdma_free_hw_stats_struct);
3098