1c39526b7SPramod Gunjikar /*
2c39526b7SPramod Gunjikar  * CDDL HEADER START
3c39526b7SPramod Gunjikar  *
4c39526b7SPramod Gunjikar  * The contents of this file are subject to the terms of the
5c39526b7SPramod Gunjikar  * Common Development and Distribution License (the "License").
6c39526b7SPramod Gunjikar  * You may not use this file except in compliance with the License.
7c39526b7SPramod Gunjikar  *
8c39526b7SPramod Gunjikar  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c39526b7SPramod Gunjikar  * or http://www.opensolaris.org/os/licensing.
10c39526b7SPramod Gunjikar  * See the License for the specific language governing permissions
11c39526b7SPramod Gunjikar  * and limitations under the License.
12c39526b7SPramod Gunjikar  *
13c39526b7SPramod Gunjikar  * When distributing Covered Code, include this CDDL HEADER in each
14c39526b7SPramod Gunjikar  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c39526b7SPramod Gunjikar  * If applicable, add the following below this CDDL HEADER, with the
16c39526b7SPramod Gunjikar  * fields enclosed by brackets "[]" replaced with your own identifying
17c39526b7SPramod Gunjikar  * information: Portions Copyright [yyyy] [name of copyright owner]
18c39526b7SPramod Gunjikar  *
19c39526b7SPramod Gunjikar  * CDDL HEADER END
20c39526b7SPramod Gunjikar  */
21c39526b7SPramod Gunjikar 
22c39526b7SPramod Gunjikar /*
23c39526b7SPramod Gunjikar  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24c39526b7SPramod Gunjikar  */
25c39526b7SPramod Gunjikar 
26c39526b7SPramod Gunjikar /*
27c39526b7SPramod Gunjikar  * IB specific routines for RDMA CM functionality
28c39526b7SPramod Gunjikar  */
29c39526b7SPramod Gunjikar /* Standard driver includes */
30c39526b7SPramod Gunjikar #include <sys/types.h>
31c39526b7SPramod Gunjikar #include <sys/modctl.h>
32c39526b7SPramod Gunjikar #include <sys/errno.h>
33c39526b7SPramod Gunjikar #include <sys/stat.h>
34c39526b7SPramod Gunjikar 
35c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_ofs/sol_ofs_common.h>
36c39526b7SPramod Gunjikar #include <sys/ib/clients/of/ofed_kernel.h>
37c39526b7SPramod Gunjikar #include <sys/ib/clients/of/rdma/ib_addr.h>
38c39526b7SPramod Gunjikar #include <sys/ib/clients/of/rdma/rdma_cm.h>
39c39526b7SPramod Gunjikar 
40c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_ofs/sol_cma.h>
41c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_ofs/sol_ib_cma.h>
42c39526b7SPramod Gunjikar 
43c39526b7SPramod Gunjikar extern char 	*sol_rdmacm_dbg_str;
44c39526b7SPramod Gunjikar 
45c39526b7SPramod Gunjikar /* Delay of 5 secs */
46c39526b7SPramod Gunjikar #define	SOL_OFS_REQ_DELAY	5000000
47c39526b7SPramod Gunjikar 
48fffafeb2SJohnny Cheung /* Default Qkey used for IPoIB. */
49fffafeb2SJohnny Cheung #define	SOL_IPOIB_DEFAULT_QKEY	0xB1B
50fffafeb2SJohnny Cheung 
51c39526b7SPramod Gunjikar /*	Solaris CM Event Callbacks 	*/
52c39526b7SPramod Gunjikar static ibt_cm_status_t ibcma_rc_hdlr(void *, ibt_cm_event_t *,
53c39526b7SPramod Gunjikar     ibt_cm_return_args_t *, void *, ibt_priv_data_len_t);
54c39526b7SPramod Gunjikar static ibt_cm_status_t ibcma_ud_hdlr(void *, ibt_cm_ud_event_t *,
55c39526b7SPramod Gunjikar     ibt_cm_ud_return_args_t *, void *, ibt_priv_data_len_t);
56c39526b7SPramod Gunjikar static void ibcma_multicast_hdlr(void *, ibt_status_t, ibt_mcg_info_t *);
57c39526b7SPramod Gunjikar 
58c39526b7SPramod Gunjikar /*	Local functions 	*/
59c39526b7SPramod Gunjikar static int ibcma_tcp_connect(struct rdma_cm_id *, ibcma_chan_t *,
60c39526b7SPramod Gunjikar     struct rdma_conn_param *);
61c39526b7SPramod Gunjikar static int ibcma_udp_connect(struct rdma_cm_id *, ibcma_chan_t *,
62c39526b7SPramod Gunjikar     struct rdma_conn_param *);
63c39526b7SPramod Gunjikar static struct rdma_cm_id *ibcma_create_new_id(struct rdma_cm_id *);
64c39526b7SPramod Gunjikar static int ibcma_query_local_ip(struct rdma_cm_id *, sol_cma_chan_t *,
65c39526b7SPramod Gunjikar     ibcma_chan_t *);
66c39526b7SPramod Gunjikar static int ibcma_get_paths(struct rdma_cm_id *, sol_cma_chan_t *,
67c39526b7SPramod Gunjikar     ibcma_chan_t *);
68c39526b7SPramod Gunjikar static void ibcma_get_devlist(sol_cma_chan_t *, ib_guid_t *, int,
69a3077325SPramod Gunjikar     genlist_t *, boolean_t);
70c39526b7SPramod Gunjikar static int ibcma_any_addr(ibt_ip_addr_t *);
71c39526b7SPramod Gunjikar static int ibcma_get_first_ib_ipaddr(struct rdma_cm_id *);
72c39526b7SPramod Gunjikar 
73c39526b7SPramod Gunjikar /* Utility Conversion Routines */
74c39526b7SPramod Gunjikar static void 	ipaddr2mgid(struct sockaddr *, ib_gid_t *, ib_pkey_t);
75c39526b7SPramod Gunjikar static void 	ibt_path2ah(ibt_path_info_t *, struct ib_ah_attr *);
76c39526b7SPramod Gunjikar static void	ibt_addsvect2ah(ibt_adds_vect_t *, struct ib_ah_attr *);
77c39526b7SPramod Gunjikar static void	ibt_addsvect2sa_path(ibt_adds_vect_t *,
78c39526b7SPramod Gunjikar     struct ib_sa_path_rec *, ib_lid_t);
79c39526b7SPramod Gunjikar static void	ibt_path2sa_path(ibt_path_info_t *, struct ib_sa_path_rec *,
80c39526b7SPramod Gunjikar     ib_lid_t);
81c39526b7SPramod Gunjikar static void 	mcginfo2ah(ibt_mcg_info_t *, struct ib_ah_attr *);
82c39526b7SPramod Gunjikar static void	sockaddr2ibtaddr_port(struct rdma_cm_id *, struct sockaddr *,
83c39526b7SPramod Gunjikar     ibt_ip_addr_t *, in_port_t *);
84c39526b7SPramod Gunjikar static void ipaddr2sockaddr(ibt_ip_addr_t *, struct sockaddr *,
85c39526b7SPramod Gunjikar     in_port_t *);
86c39526b7SPramod Gunjikar 
87c39526b7SPramod Gunjikar #ifdef	QP_DEBUG
88c39526b7SPramod Gunjikar static void 	dump_qp_info(ibt_qp_hdl_t);
89c39526b7SPramod Gunjikar #endif
90c39526b7SPramod Gunjikar static void	dump_priv_data(void *, ibt_priv_data_len_t,
91c39526b7SPramod Gunjikar     ibt_priv_data_len_t, char *);
92c39526b7SPramod Gunjikar 
93c39526b7SPramod Gunjikar extern cma_chan_state_t cma_get_chan_state(sol_cma_chan_t *);
94c39526b7SPramod Gunjikar 
95c39526b7SPramod Gunjikar /*
96c39526b7SPramod Gunjikar  * RDMA CM API - Transport specific functions
97c39526b7SPramod Gunjikar  */
98c39526b7SPramod Gunjikar void
rdma_ib_destroy_id(struct rdma_cm_id * idp)99c39526b7SPramod Gunjikar rdma_ib_destroy_id(struct rdma_cm_id *idp)
100c39526b7SPramod Gunjikar {
101c39526b7SPramod Gunjikar 	sol_cma_chan_t		*chanp = (sol_cma_chan_t *)idp;
102c39526b7SPramod Gunjikar 	ibcma_chan_t		*ibchanp;
103c39526b7SPramod Gunjikar 	ibt_status_t		status;
104c39526b7SPramod Gunjikar 
105c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_ib_destroy_id(%p)", idp);
106c39526b7SPramod Gunjikar 	ASSERT(chanp);
107c39526b7SPramod Gunjikar 	ibchanp = &(chanp->chan_ib);
108c39526b7SPramod Gunjikar 
109c39526b7SPramod Gunjikar 	if (ibchanp->chan_mcast_cnt) {
110c39526b7SPramod Gunjikar 		genlist_entry_t	*entry;
111c39526b7SPramod Gunjikar 		ibcma_mcast_t	*ibmcastp;
112c39526b7SPramod Gunjikar 		ib_gid_t	zero_gid;
113c39526b7SPramod Gunjikar 
114c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
115c39526b7SPramod Gunjikar 		    "rdma_ib_destroy_id: pending mcast!!");
116c39526b7SPramod Gunjikar 		entry = remove_genlist_head(&ibchanp->chan_mcast_list);
117c39526b7SPramod Gunjikar 		while (entry) {
118c39526b7SPramod Gunjikar 			ibmcastp = (ibcma_mcast_t *)entry->data;
119c39526b7SPramod Gunjikar 
120c39526b7SPramod Gunjikar 			bzero(&zero_gid, sizeof (ib_gid_t));
121c39526b7SPramod Gunjikar 			status = ibt_leave_mcg(ibchanp->chan_devp->dev_sgid,
122c39526b7SPramod Gunjikar 			    ibmcastp->mcast_gid, zero_gid, IB_MC_JSTATE_FULL);
123c39526b7SPramod Gunjikar 			if (status != IBT_SUCCESS)
124c39526b7SPramod Gunjikar 				SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
125c39526b7SPramod Gunjikar 				    "destroy_id: ibt_leave_mcg failed %d",
126c39526b7SPramod Gunjikar 				    status);
127c39526b7SPramod Gunjikar 			kmem_free(ibmcastp, sizeof (ibcma_mcast_t));
128c39526b7SPramod Gunjikar 
129c39526b7SPramod Gunjikar 			entry = remove_genlist_head(&ibchanp->chan_mcast_list);
130c39526b7SPramod Gunjikar 		}
131c39526b7SPramod Gunjikar 	}
132c39526b7SPramod Gunjikar 	if (ibchanp->chan_devp) {
133c39526b7SPramod Gunjikar 		kmem_free(ibchanp->chan_devp, sizeof (ibcma_dev_t));
134c39526b7SPramod Gunjikar 		ibchanp->chan_devp = NULL;
135c39526b7SPramod Gunjikar 	}
136c39526b7SPramod Gunjikar 	if (ibchanp->chan_pathp) {
137c39526b7SPramod Gunjikar 		kmem_free(ibchanp->chan_pathp, ibchanp->chan_path_size);
138c39526b7SPramod Gunjikar 		ibchanp->chan_pathp = NULL;
139c39526b7SPramod Gunjikar 	}
140c39526b7SPramod Gunjikar 
141c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_ib_destroy_id: return");
142c39526b7SPramod Gunjikar }
143c39526b7SPramod Gunjikar 
144c39526b7SPramod Gunjikar int
rdma_ib_bind_addr(struct rdma_cm_id * idp,struct sockaddr * addr)145c39526b7SPramod Gunjikar rdma_ib_bind_addr(struct rdma_cm_id *idp, struct sockaddr *addr)
146c39526b7SPramod Gunjikar {
147c39526b7SPramod Gunjikar 	sol_cma_chan_t	*chanp = (sol_cma_chan_t *)idp;
148c39526b7SPramod Gunjikar 	ibcma_chan_t	*ibchanp;
149c39526b7SPramod Gunjikar 	int		ret;
150c39526b7SPramod Gunjikar 	in_port_t	port;
151c39526b7SPramod Gunjikar 
152c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_ib_bind_addr(%p, %p)",
153c39526b7SPramod Gunjikar 	    idp, addr);
154c39526b7SPramod Gunjikar 	ASSERT(chanp);
155c39526b7SPramod Gunjikar 	ibchanp = &(chanp->chan_ib);
156c39526b7SPramod Gunjikar 
157c39526b7SPramod Gunjikar 	sockaddr2ibtaddr_port(idp, addr, &ibchanp->chan_local_addr, &port);
158c39526b7SPramod Gunjikar 	ibchanp->chan_addr_flag = IBCMA_LOCAL_ADDR_SET_FLAG;
159c39526b7SPramod Gunjikar 
160c39526b7SPramod Gunjikar 	/*
161c39526b7SPramod Gunjikar 	 * If this is IF_ADDR_ANY, get info of IB port with IP @.
162c39526b7SPramod Gunjikar 	 * Return Failure, if there are no IB ports with IP @.
163c39526b7SPramod Gunjikar 	 */
164c39526b7SPramod Gunjikar 	if (sol_cma_any_addr(addr)) {
165c39526b7SPramod Gunjikar 		ibchanp->chan_port = port;
166c39526b7SPramod Gunjikar 		ibchanp->chan_addr_flag |= IBCMA_LOCAL_ADDR_IFADDRANY;
167a3077325SPramod Gunjikar 		return (0);
168c39526b7SPramod Gunjikar 	}
169c39526b7SPramod Gunjikar 
170c39526b7SPramod Gunjikar 	ret = ibcma_query_local_ip(idp, chanp, ibchanp);
171c39526b7SPramod Gunjikar 	if (ret == 0) {
172c39526b7SPramod Gunjikar 		init_genlist(&ibchanp->chan_mcast_list);
173c39526b7SPramod Gunjikar 		ibchanp->chan_sid = ibt_get_ip_sid(idp->ps, port);
174c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
175c39526b7SPramod Gunjikar 		    "chan SID %llx , ps %x, port %x",
176c39526b7SPramod Gunjikar 		    ibchanp->chan_sid, idp->ps, port);
177c39526b7SPramod Gunjikar 		ibchanp->chan_port = port;
178c39526b7SPramod Gunjikar 		chanp->chan_xport_type = SOL_CMA_XPORT_IB;
179c39526b7SPramod Gunjikar 	}
180c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_ib_bind_addr: return %x",
181c39526b7SPramod Gunjikar 	    ret);
182c39526b7SPramod Gunjikar 	return (ret);
183c39526b7SPramod Gunjikar }
184c39526b7SPramod Gunjikar 
185fffafeb2SJohnny Cheung extern void cma_resolve_addr_callback(sol_cma_chan_t *, int);
186c39526b7SPramod Gunjikar int
rdma_ib_resolve_addr(struct rdma_cm_id * idp,struct sockaddr * src_addr,struct sockaddr * dst_addr,int timeout_ms)187c39526b7SPramod Gunjikar rdma_ib_resolve_addr(struct rdma_cm_id *idp, struct sockaddr *src_addr,
188c39526b7SPramod Gunjikar     struct sockaddr *dst_addr, int timeout_ms)
189c39526b7SPramod Gunjikar {
190c39526b7SPramod Gunjikar 	sol_cma_chan_t	*chanp = (sol_cma_chan_t *)idp;
191c39526b7SPramod Gunjikar 	ibcma_chan_t	*ibchanp;
192c39526b7SPramod Gunjikar 	int		ret;
193c39526b7SPramod Gunjikar 	in_port_t	port;
194c39526b7SPramod Gunjikar 	in_addr_t	remote_addr;
195c39526b7SPramod Gunjikar 
196c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_ib_resolve_addr("
197c39526b7SPramod Gunjikar 	    "%p, %p, %p, %x)", idp, src_addr, dst_addr, timeout_ms);
198c39526b7SPramod Gunjikar 	ASSERT(chanp);
199c39526b7SPramod Gunjikar 	ibchanp = &(chanp->chan_ib);
200c39526b7SPramod Gunjikar 
201c39526b7SPramod Gunjikar 	/*
202c39526b7SPramod Gunjikar 	 * Copy src_addr if the passed src @ is valid IP address and
203c39526b7SPramod Gunjikar 	 * the local @ has not been set for this CMID.
204c39526b7SPramod Gunjikar 	 */
205c39526b7SPramod Gunjikar 	if ((ibchanp->chan_addr_flag & IBCMA_LOCAL_ADDR_SET_FLAG) == 0 &&
206c39526b7SPramod Gunjikar 	    IS_VALID_SOCKADDR(src_addr)) {
207c39526b7SPramod Gunjikar 		sockaddr2ibtaddr_port(idp, src_addr, &ibchanp->chan_local_addr,
208c39526b7SPramod Gunjikar 		    &port);
209c39526b7SPramod Gunjikar 		ibchanp->chan_addr_flag |= IBCMA_LOCAL_ADDR_SET_FLAG;
210c39526b7SPramod Gunjikar 		if (port) {
211c39526b7SPramod Gunjikar 			ibchanp->chan_sid = ibt_get_ip_sid(idp->ps, port);
212c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "resolve_addr, "
213c39526b7SPramod Gunjikar 			    "local @ SID %llx, ps %x, port %x",
214c39526b7SPramod Gunjikar 			    ibchanp->chan_sid, idp->ps, port);
215c39526b7SPramod Gunjikar 			ibchanp->chan_port = port;
216c39526b7SPramod Gunjikar 		}
217c39526b7SPramod Gunjikar 	}
218c39526b7SPramod Gunjikar 
219c39526b7SPramod Gunjikar 	sockaddr2ibtaddr_port(idp, dst_addr, &ibchanp->chan_remote_addr,
220c39526b7SPramod Gunjikar 	    &port);
221c39526b7SPramod Gunjikar 	ibchanp->chan_addr_flag |= IBCMA_REMOTE_ADDR_SET_FLAG;
222c39526b7SPramod Gunjikar 	if (ibchanp->chan_sid == 0) {
223c39526b7SPramod Gunjikar 		ASSERT(!sol_cma_any_addr(dst_addr));
224c39526b7SPramod Gunjikar 		ibchanp->chan_sid = ibt_get_ip_sid(idp->ps, port);
225c39526b7SPramod Gunjikar 		ibchanp->chan_port = port;
226c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "resolve_addr, remote @ "
227c39526b7SPramod Gunjikar 		    "SID %llx , ps %x, port %x", ibchanp->chan_sid,
228c39526b7SPramod Gunjikar 		    idp->ps, port);
229c39526b7SPramod Gunjikar 		init_genlist(&ibchanp->chan_mcast_list);
230c39526b7SPramod Gunjikar 	}
231c39526b7SPramod Gunjikar 
232c39526b7SPramod Gunjikar 	/*
233c39526b7SPramod Gunjikar 	 * Return SUCCESS if remote address is a MCAST address
234c39526b7SPramod Gunjikar 	 * and local address is not IF_ADDR_ANY. If local_addr
235c39526b7SPramod Gunjikar 	 * is IF_ADDR_ANY and remote is MCAST, return FAILURE.
236c39526b7SPramod Gunjikar 	 */
237c39526b7SPramod Gunjikar 	remote_addr = htonl((ibchanp->chan_remote_addr).un.ip4addr);
238c39526b7SPramod Gunjikar 	if ((ibchanp->chan_remote_addr).family == AF_INET &&
239c39526b7SPramod Gunjikar 	    (remote_addr >= 0xE0000000 && remote_addr <= 0xEFFFFFFF)) {
240c39526b7SPramod Gunjikar 		if (ibchanp->chan_devp) {
241c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
242c39526b7SPramod Gunjikar 			    "ib_resolve_addr - mcast dest @, local IP");
243c39526b7SPramod Gunjikar 			(idp->route).num_paths = 0;
244c39526b7SPramod Gunjikar 			ret = 0;
245c39526b7SPramod Gunjikar 		} else {
246c39526b7SPramod Gunjikar 			ret = ibcma_get_first_ib_ipaddr(idp);
247c39526b7SPramod Gunjikar 		}
248c39526b7SPramod Gunjikar 
249c39526b7SPramod Gunjikar 		if (ret == 0 && idp->device == NULL)
250c39526b7SPramod Gunjikar 			idp->device = sol_cma_acquire_device(ntohll(
251c39526b7SPramod Gunjikar 			    ibchanp->chan_devp->dev_node_guid));
252fffafeb2SJohnny Cheung 
253fffafeb2SJohnny Cheung 		cma_resolve_addr_callback(chanp, 0);
254c39526b7SPramod Gunjikar 		return (0);
255c39526b7SPramod Gunjikar 	}
256c39526b7SPramod Gunjikar 
257c39526b7SPramod Gunjikar 	if ((ret = ibcma_get_paths(idp, chanp, ibchanp)) == 0)
258c39526b7SPramod Gunjikar 		chanp->chan_xport_type = SOL_CMA_XPORT_IB;
259c39526b7SPramod Gunjikar 
260c39526b7SPramod Gunjikar 	return (ret);
261c39526b7SPramod Gunjikar }
262c39526b7SPramod Gunjikar 
263c39526b7SPramod Gunjikar /*
264c39526b7SPramod Gunjikar  * Linux OFED implementation is as below :
265c39526b7SPramod Gunjikar  *	1. librdmacm sends INIT_QP_ATTR command to get QP attributes
266c39526b7SPramod Gunjikar  *	   which the kernel CM expects QP attribute to be in. Kernel
267c39526b7SPramod Gunjikar  *	   CM sets the QP attribute to be set and passes it back to
268c39526b7SPramod Gunjikar  *	   user library.
269c39526b7SPramod Gunjikar  *	2. librdmacm calls ibv_modify_qp() to modify the QP attribute.
270c39526b7SPramod Gunjikar  *         The QP attribute used is the same as the that passed by
271c39526b7SPramod Gunjikar  *		   kernel sol_ucma.
272c39526b7SPramod Gunjikar  *
273c39526b7SPramod Gunjikar  * For RC connections, Solaris ibcm manages the QP state after :
274c39526b7SPramod Gunjikar  *	CM Event Handler is called	- Passive side
275c39526b7SPramod Gunjikar  *	ibv_open_rc_channel(9f)  	- Active Side
276c39526b7SPramod Gunjikar  * The client will *not* have to do an explcit modify_qp(). To fit this
277c39526b7SPramod Gunjikar  * INIT_QP_ATTR commands *marks* the QP to fake it's attributes and
278c39526b7SPramod Gunjikar  * ignore ibv_modify_qp() for this QP. Solaris ibcm manages QP state.
279c39526b7SPramod Gunjikar  *
280c39526b7SPramod Gunjikar  * Before the above calls, the client will have to maintain the QP state.
281c39526b7SPramod Gunjikar  * The sol_ucma driver will pass the appropriate QP atrributes, for the
282c39526b7SPramod Gunjikar  * clients to pass to ibv_modify_qp().
283c39526b7SPramod Gunjikar  *
284c39526b7SPramod Gunjikar  * For UD, OFED model is adhered to till the QP is transitioned to RTS.
285c39526b7SPramod Gunjikar  * Any transitions after the QP has transitioned to RTS are ignored.
286c39526b7SPramod Gunjikar  */
287c39526b7SPramod Gunjikar int
rdma_ib_init_qp_attr(struct rdma_cm_id * idp,struct ib_qp_attr * qpattr,int * qp_attr_mask)288c39526b7SPramod Gunjikar rdma_ib_init_qp_attr(struct rdma_cm_id *idp, struct ib_qp_attr *qpattr,
289c39526b7SPramod Gunjikar     int *qp_attr_mask)
290c39526b7SPramod Gunjikar {
291c39526b7SPramod Gunjikar 	sol_cma_chan_t	*chanp;
292c39526b7SPramod Gunjikar 	ibcma_chan_t	*ibchanp;
293c39526b7SPramod Gunjikar 	ibcma_dev_t	*devp;
294c39526b7SPramod Gunjikar 	uint32_t	qpstate;
295c39526b7SPramod Gunjikar 
296c39526b7SPramod Gunjikar 	ASSERT(idp);
297c39526b7SPramod Gunjikar 	chanp = (sol_cma_chan_t *)idp;
298c39526b7SPramod Gunjikar 	ibchanp = &chanp->chan_ib;
299c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_ib_init_qp_attr("
300c39526b7SPramod Gunjikar 	    "%p, %p, %p)", idp, qpattr, qp_attr_mask);
301c39526b7SPramod Gunjikar 
302c39526b7SPramod Gunjikar 	if (ibchanp->chan_qpmodifyflag == 1) {
303c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L4(sol_rdmacm_dbg_str,
304c39526b7SPramod Gunjikar 		    "Ignoring Init QP Attr");
305c39526b7SPramod Gunjikar 		return (0);
306c39526b7SPramod Gunjikar 	}
307c39526b7SPramod Gunjikar 
308c39526b7SPramod Gunjikar 	qpstate = qpattr->qp_state;
309c39526b7SPramod Gunjikar 	bzero(qpattr, sizeof (struct ib_qp_attr));
310c39526b7SPramod Gunjikar 	qpattr->qp_state = qpstate;
311c39526b7SPramod Gunjikar 
312c39526b7SPramod Gunjikar 	devp = ibchanp->chan_devp;
313c39526b7SPramod Gunjikar 	if (devp == NULL) {
314c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
315c39526b7SPramod Gunjikar 		    "init_qp_attr, devp NULL");
316c39526b7SPramod Gunjikar 		return (EINVAL);
317c39526b7SPramod Gunjikar 	}
318c39526b7SPramod Gunjikar 	qpattr->pkey_index = devp->dev_pkey_ix;
319c39526b7SPramod Gunjikar 	qpattr->port_num = devp->dev_port_num;
320c39526b7SPramod Gunjikar 
321c39526b7SPramod Gunjikar 	if (idp->ps == RDMA_PS_TCP && qpstate == IB_QPS_INIT) {
322c39526b7SPramod Gunjikar 		qpattr->qp_access_flags = IB_ACCESS_REMOTE_WRITE |
323c39526b7SPramod Gunjikar 		    IB_ACCESS_REMOTE_READ;
324c39526b7SPramod Gunjikar 		*qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT |
325c39526b7SPramod Gunjikar 		    IB_QP_ACCESS_FLAGS;
326c39526b7SPramod Gunjikar 		return (0);
327c39526b7SPramod Gunjikar 	} else if (idp->ps == RDMA_PS_TCP &&
328c39526b7SPramod Gunjikar 	    qpstate == IB_QPS_RTR) {
329c39526b7SPramod Gunjikar 		*qp_attr_mask = IB_QP_STATE | IB_QP_AV | IB_QP_PATH_MTU  |
330c39526b7SPramod Gunjikar 		    IB_QP_DEST_QPN | IB_QP_RQ_PSN |
331c39526b7SPramod Gunjikar 		    IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MIN_RNR_TIMER;
332c39526b7SPramod Gunjikar 		/*
333c39526b7SPramod Gunjikar 		 * Fill in valid values for address vector & Remote QPN.
334a3077325SPramod Gunjikar 		 * Fill in MTU from REQ data.
335c39526b7SPramod Gunjikar 		 */
336c39526b7SPramod Gunjikar 		ibt_addsvect2ah(&ibchanp->chan_rcreq_addr, &qpattr->ah_attr);
337c39526b7SPramod Gunjikar 		qpattr->path_mtu = (uint32_t)
338c39526b7SPramod Gunjikar 		    ((ibchanp->chan_rtr_data).req_path_mtu);
339c39526b7SPramod Gunjikar 		qpattr->dest_qp_num = ibchanp->chan_rcreq_qpn;
340c39526b7SPramod Gunjikar 		qpattr->rq_psn = (ibchanp->chan_rtr_data).req_rq_psn;
341c39526b7SPramod Gunjikar 		qpattr->max_dest_rd_atomic = ibchanp->chan_rcreq_ra_in;
342c39526b7SPramod Gunjikar 		qpattr->min_rnr_timer =
343c39526b7SPramod Gunjikar 		    (ibchanp->chan_rtr_data).req_rnr_nak_time;
344c39526b7SPramod Gunjikar 		return (0);
345c39526b7SPramod Gunjikar 	} else if (IS_UDP_CMID(idp)) {
346fffafeb2SJohnny Cheung 		if (idp->ps == RDMA_PS_UDP)
347fffafeb2SJohnny Cheung 			qpattr->qkey = RDMA_UDP_QKEY;
348fffafeb2SJohnny Cheung 		else
349fffafeb2SJohnny Cheung 			qpattr->qkey = SOL_IPOIB_DEFAULT_QKEY;
350c39526b7SPramod Gunjikar 		*qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX |
351c39526b7SPramod Gunjikar 		    IB_QP_PORT | IB_QP_QKEY;
352c39526b7SPramod Gunjikar 		return (0);
353c39526b7SPramod Gunjikar 	} else
354c39526b7SPramod Gunjikar 		return (EINVAL);
355c39526b7SPramod Gunjikar }
356c39526b7SPramod Gunjikar 
357c39526b7SPramod Gunjikar int
rdma_ib_connect(struct rdma_cm_id * idp,struct rdma_conn_param * conn_param)358c39526b7SPramod Gunjikar rdma_ib_connect(struct rdma_cm_id *idp, struct rdma_conn_param *conn_param)
359c39526b7SPramod Gunjikar {
360c39526b7SPramod Gunjikar 	sol_cma_chan_t	*chanp;
361c39526b7SPramod Gunjikar 	ibcma_chan_t	*ibchanp;
362c39526b7SPramod Gunjikar 	int		ret;
363c39526b7SPramod Gunjikar 
364c39526b7SPramod Gunjikar 	ASSERT(idp);
365c39526b7SPramod Gunjikar 	chanp = (sol_cma_chan_t *)idp;
366c39526b7SPramod Gunjikar 	ibchanp = &chanp->chan_ib;
367c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_ib_connect(%p, %p)", idp,
368c39526b7SPramod Gunjikar 	    conn_param);
369c39526b7SPramod Gunjikar 
370c39526b7SPramod Gunjikar 	ASSERT(chanp->chan_xport_type == SOL_CMA_XPORT_IB);
371c39526b7SPramod Gunjikar 	if (ibchanp->chan_devp == NULL || ibchanp->chan_pathp == NULL) {
372c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L3(sol_rdmacm_dbg_str, "rdma_ib_connect : "
373c39526b7SPramod Gunjikar 		    "invalid IP @");
374c39526b7SPramod Gunjikar 		return (EINVAL);
375c39526b7SPramod Gunjikar 	}
376c39526b7SPramod Gunjikar 	ASSERT(ibchanp->chan_devp);
377c39526b7SPramod Gunjikar 
378c39526b7SPramod Gunjikar 	ibchanp->chan_qpmodifyflag  = 1;
379c39526b7SPramod Gunjikar 	if (idp->ps == RDMA_PS_TCP)
380c39526b7SPramod Gunjikar 		ret = ibcma_tcp_connect(idp, ibchanp, conn_param);
381c39526b7SPramod Gunjikar 	else
382c39526b7SPramod Gunjikar 		ret = ibcma_udp_connect(idp, ibchanp, conn_param);
383c39526b7SPramod Gunjikar 
384c39526b7SPramod Gunjikar 	return (ret);
385c39526b7SPramod Gunjikar }
386c39526b7SPramod Gunjikar 
387c39526b7SPramod Gunjikar extern void sol_cma_add_hca_list(sol_cma_chan_t *, ib_guid_t);
388c39526b7SPramod Gunjikar void
ibcma_append_listen_list(struct rdma_cm_id * root_idp)389c39526b7SPramod Gunjikar ibcma_append_listen_list(struct rdma_cm_id  *root_idp)
390c39526b7SPramod Gunjikar {
391c39526b7SPramod Gunjikar 	int			num_hcas;
392c39526b7SPramod Gunjikar 	ib_guid_t		*hca_guidp;
393c39526b7SPramod Gunjikar 	struct rdma_cm_id	*ep_idp;
394c39526b7SPramod Gunjikar 	sol_cma_chan_t		*root_chanp, *ep_chanp;
395c39526b7SPramod Gunjikar 	ibcma_chan_t		*root_ibchanp, *ep_ibchanp;
396c39526b7SPramod Gunjikar 	genlist_t		dev_genlist;
397c39526b7SPramod Gunjikar 	genlist_entry_t		*entry;
398c39526b7SPramod Gunjikar 
399c39526b7SPramod Gunjikar 	sol_cma_listen_info_t	*listenp;
400c39526b7SPramod Gunjikar 	ibcma_dev_t		*devp;
401c39526b7SPramod Gunjikar 
402c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "append_listen(%p)", root_idp);
403c39526b7SPramod Gunjikar 	root_chanp = (sol_cma_chan_t *)root_idp;
404c39526b7SPramod Gunjikar 	root_ibchanp = &root_chanp->chan_ib;
405c39526b7SPramod Gunjikar 
406c39526b7SPramod Gunjikar 	/*
407c39526b7SPramod Gunjikar 	 * Address other than IF_ADDR_ANY bound to this channel. Listen on
408c39526b7SPramod Gunjikar 	 * this IP address alone.
409c39526b7SPramod Gunjikar 	 */
410c39526b7SPramod Gunjikar 	if (root_ibchanp->chan_devp &&
411c39526b7SPramod Gunjikar 	    (root_ibchanp->chan_addr_flag & IBCMA_LOCAL_ADDR_IFADDRANY) == 0) {
412c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "Create listen chan");
413c39526b7SPramod Gunjikar 		ep_idp = ibcma_create_new_id(root_idp);
414c39526b7SPramod Gunjikar 		ASSERT(ep_idp);
415c39526b7SPramod Gunjikar 
416c39526b7SPramod Gunjikar 		ep_chanp = (sol_cma_chan_t *)ep_idp;
417c39526b7SPramod Gunjikar 		listenp = kmem_zalloc(sizeof (sol_cma_listen_info_t),
418c39526b7SPramod Gunjikar 		    KM_SLEEP);
419c39526b7SPramod Gunjikar 		ep_chanp->chan_listenp = listenp;
420c39526b7SPramod Gunjikar 
421c39526b7SPramod Gunjikar 		ep_ibchanp = &ep_chanp->chan_ib;
422c39526b7SPramod Gunjikar 		ep_ibchanp->chan_port = root_ibchanp->chan_port;
423c39526b7SPramod Gunjikar 		listenp->listen_ep_root_entry = add_genlist(
424c39526b7SPramod Gunjikar 		    &(CHAN_LISTEN_LIST(root_chanp)),
425c39526b7SPramod Gunjikar 		    (uintptr_t)ep_idp, root_idp);
426c39526b7SPramod Gunjikar 		devp = ep_ibchanp->chan_devp;
427c39526b7SPramod Gunjikar 		sol_cma_add_hca_list(ep_chanp, ntohll(devp->dev_node_guid));
428c39526b7SPramod Gunjikar 		return;
429c39526b7SPramod Gunjikar 	}
430c39526b7SPramod Gunjikar 
431c39526b7SPramod Gunjikar 	/*
432c39526b7SPramod Gunjikar 	 * Get the list of IB devs with valid IP addresses
433c39526b7SPramod Gunjikar 	 * Append to the list of listeners for root_idp
434c39526b7SPramod Gunjikar 	 */
435c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "Search IP @");
436c39526b7SPramod Gunjikar 	num_hcas = ibt_get_hca_list(&hca_guidp);
437c39526b7SPramod Gunjikar 	ibcma_get_devlist(root_chanp, hca_guidp, num_hcas,
438a3077325SPramod Gunjikar 	    &dev_genlist, B_FALSE);
439c39526b7SPramod Gunjikar 	entry = remove_genlist_head(&dev_genlist);
440c39526b7SPramod Gunjikar 	while (entry) {
441c39526b7SPramod Gunjikar 		devp = (ibcma_dev_t *)(entry->data);
442c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
443c39526b7SPramod Gunjikar 		    "Create listen chan- ALL");
444c39526b7SPramod Gunjikar 		ep_idp = ibcma_create_new_id(root_idp);
445c39526b7SPramod Gunjikar 		ASSERT(ep_idp);
446c39526b7SPramod Gunjikar 
447c39526b7SPramod Gunjikar 		ep_chanp = (sol_cma_chan_t *)ep_idp;
448a3077325SPramod Gunjikar 		ep_chanp->chan_xport_type = SOL_CMA_XPORT_IB;
449c39526b7SPramod Gunjikar 		ipaddr2sockaddr(&devp->dev_ipaddr,
450c39526b7SPramod Gunjikar 		    &(ep_idp->route.addr.src_addr), NULL);
451c39526b7SPramod Gunjikar 		listenp = kmem_zalloc(sizeof (sol_cma_listen_info_t),
452c39526b7SPramod Gunjikar 		    KM_SLEEP);
453c39526b7SPramod Gunjikar 		ep_chanp->chan_listenp = listenp;
454c39526b7SPramod Gunjikar 
455c39526b7SPramod Gunjikar 		ep_ibchanp = &ep_chanp->chan_ib;
456a3077325SPramod Gunjikar 		ASSERT(ep_ibchanp->chan_devp == NULL);
457c39526b7SPramod Gunjikar 		ep_ibchanp->chan_devp = devp;
458c39526b7SPramod Gunjikar 		ep_ibchanp->chan_port = root_ibchanp->chan_port;
459c39526b7SPramod Gunjikar 
460c39526b7SPramod Gunjikar 		listenp->listen_ep_root_entry = add_genlist(
461c39526b7SPramod Gunjikar 		    &(CHAN_LISTEN_LIST(root_chanp)),
462c39526b7SPramod Gunjikar 		    (uintptr_t)ep_idp, root_idp);
463c39526b7SPramod Gunjikar 		sol_cma_add_hca_list(ep_chanp, ntohll(devp->dev_node_guid));
464c39526b7SPramod Gunjikar 		kmem_free(entry, sizeof (genlist_entry_t));
465c39526b7SPramod Gunjikar 		entry = remove_genlist_head(&dev_genlist);
466c39526b7SPramod Gunjikar 	}
467c39526b7SPramod Gunjikar 	ibt_free_hca_list(hca_guidp, num_hcas);
468c39526b7SPramod Gunjikar }
469c39526b7SPramod Gunjikar 
470c39526b7SPramod Gunjikar int
ibcma_init_root_chan(sol_cma_chan_t * root_chanp,sol_cma_glbl_listen_t * listenp)471c39526b7SPramod Gunjikar ibcma_init_root_chan(sol_cma_chan_t *root_chanp, sol_cma_glbl_listen_t *listenp)
472c39526b7SPramod Gunjikar {
473c39526b7SPramod Gunjikar 	ibcma_chan_t		*root_ibchanp;
474c39526b7SPramod Gunjikar 	ibt_srv_desc_t		service;
475c39526b7SPramod Gunjikar 	ibt_status_t		status;
476c39526b7SPramod Gunjikar 	struct rdma_cm_id	*root_idp;
477c39526b7SPramod Gunjikar 
478c39526b7SPramod Gunjikar 	root_idp = &(root_chanp->chan_rdma_cm);
479c39526b7SPramod Gunjikar 	root_ibchanp = &root_chanp->chan_ib;
480c39526b7SPramod Gunjikar 
481c39526b7SPramod Gunjikar 	if (root_idp->ps == RDMA_PS_TCP)
482c39526b7SPramod Gunjikar 		service.sd_handler = ibcma_rc_hdlr;
483c39526b7SPramod Gunjikar 	else
484c39526b7SPramod Gunjikar 		service.sd_ud_handler = ibcma_ud_hdlr;
485c39526b7SPramod Gunjikar 	service.sd_flags = IBT_SRV_NO_FLAGS;
486c39526b7SPramod Gunjikar 	status = ibt_register_service(root_chanp->chan_ib_client_hdl,
487c39526b7SPramod Gunjikar 	    &service, root_ibchanp->chan_sid,
488c39526b7SPramod Gunjikar 	    root_ibchanp->chan_port ? 1 : 0xffff,
489c39526b7SPramod Gunjikar 	    &((root_chanp->chan_listenp)->listen_ib_srv_hdl),
490c39526b7SPramod Gunjikar 	    NULL);
491c39526b7SPramod Gunjikar 	if (status != IBT_SUCCESS) {
492c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
493c39526b7SPramod Gunjikar 		    "init_root_chan: ibt_register_service ret %x"
494c39526b7SPramod Gunjikar 		    "SID %x, port %x", status, root_ibchanp->chan_sid,
495c39526b7SPramod Gunjikar 		    root_ibchanp->chan_port);
496c39526b7SPramod Gunjikar 		return (EINVAL);
497c39526b7SPramod Gunjikar 	}
498c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "init_root_chan: "
499c39526b7SPramod Gunjikar 	    "ibt_register_service: SID %x, port %x: done",
500c39526b7SPramod Gunjikar 	    root_ibchanp->chan_sid, root_ibchanp->chan_port);
501c39526b7SPramod Gunjikar 	listenp->cma_listen_svc_hdl =
502c39526b7SPramod Gunjikar 	    (void *)(root_chanp->chan_listenp)->listen_ib_srv_hdl;
503c39526b7SPramod Gunjikar 	return (0);
504c39526b7SPramod Gunjikar }
505c39526b7SPramod Gunjikar 
506c39526b7SPramod Gunjikar int
ibcma_fini_root_chan(sol_cma_chan_t * rchanp)507c39526b7SPramod Gunjikar ibcma_fini_root_chan(sol_cma_chan_t *rchanp)
508c39526b7SPramod Gunjikar {
509c39526b7SPramod Gunjikar 	ibt_status_t	status;
510c39526b7SPramod Gunjikar 
511c39526b7SPramod Gunjikar 	status = ibt_deregister_service(rchanp->chan_ib_client_hdl,
512c39526b7SPramod Gunjikar 	    (rchanp->chan_listenp)->listen_ib_srv_hdl);
513c39526b7SPramod Gunjikar 	if (status != IBT_SUCCESS) {
514c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
515c39526b7SPramod Gunjikar 		    "fini_root_chan: ibt_deregister_service ret %x",
516c39526b7SPramod Gunjikar 		    status);
517c39526b7SPramod Gunjikar 		return (EINVAL);
518c39526b7SPramod Gunjikar 	}
519c39526b7SPramod Gunjikar 	return (0);
520c39526b7SPramod Gunjikar }
521c39526b7SPramod Gunjikar 
522c39526b7SPramod Gunjikar void
ibcma_copy_srv_hdl(sol_cma_chan_t * root_chanp,sol_cma_glbl_listen_t * listenp)523c39526b7SPramod Gunjikar ibcma_copy_srv_hdl(sol_cma_chan_t *root_chanp, sol_cma_glbl_listen_t *listenp)
524c39526b7SPramod Gunjikar {
525c39526b7SPramod Gunjikar 	(root_chanp->chan_listenp)->listen_ib_srv_hdl =
526c39526b7SPramod Gunjikar 	    (ibt_srv_hdl_t)listenp->cma_listen_svc_hdl;
527c39526b7SPramod Gunjikar }
528c39526b7SPramod Gunjikar 
529c39526b7SPramod Gunjikar int
ibcma_fini_ep_chan(sol_cma_chan_t * ep_chanp)530c39526b7SPramod Gunjikar ibcma_fini_ep_chan(sol_cma_chan_t *ep_chanp)
531c39526b7SPramod Gunjikar {
532c39526b7SPramod Gunjikar 	struct rdma_cm_id	*root_idp;
533c39526b7SPramod Gunjikar 	sol_cma_chan_t		*root_chanp;
534c39526b7SPramod Gunjikar 	sol_cma_listen_info_t	*root_listenp, *ep_listenp;
535c39526b7SPramod Gunjikar 	ibt_status_t		status;
536c39526b7SPramod Gunjikar 	ibcma_chan_t		*ep_ibchanp = &ep_chanp->chan_ib;
537c39526b7SPramod Gunjikar 
538c39526b7SPramod Gunjikar 	ASSERT(ep_chanp);
539c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
540c39526b7SPramod Gunjikar 	    "fini_ep_chan(%p)", ep_chanp);
541c39526b7SPramod Gunjikar 	root_idp  = CHAN_LISTEN_ROOT(ep_chanp);
542c39526b7SPramod Gunjikar 	root_chanp = (sol_cma_chan_t *)root_idp;
543c39526b7SPramod Gunjikar 	root_listenp = root_chanp->chan_listenp;
544c39526b7SPramod Gunjikar 	ep_listenp = ep_chanp->chan_listenp;
545c39526b7SPramod Gunjikar 
546c39526b7SPramod Gunjikar 	if (ep_ibchanp->chan_devp)
547c39526b7SPramod Gunjikar 		kmem_free(ep_ibchanp->chan_devp, sizeof (ibcma_dev_t));
548c39526b7SPramod Gunjikar 	if (ep_ibchanp->chan_pathp)
549c39526b7SPramod Gunjikar 		kmem_free(ep_ibchanp->chan_pathp,
550c39526b7SPramod Gunjikar 		    ep_ibchanp->chan_path_size);
551c39526b7SPramod Gunjikar 
552c39526b7SPramod Gunjikar 	if (!ep_listenp->listen_ib_sbind_hdl)
553c39526b7SPramod Gunjikar 		return (0);
554c39526b7SPramod Gunjikar 	status = ibt_unbind_service(root_listenp->listen_ib_srv_hdl,
555c39526b7SPramod Gunjikar 	    ep_listenp->listen_ib_sbind_hdl);
556c39526b7SPramod Gunjikar 	if (status != IBT_SUCCESS) {
557c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
558c39526b7SPramod Gunjikar 		    "fini_ep_chan(%p) : ibt_unbind_service() ret %d",
559c39526b7SPramod Gunjikar 		    status);
560c39526b7SPramod Gunjikar 		return (-1);
561c39526b7SPramod Gunjikar 	}
562c39526b7SPramod Gunjikar 
563c39526b7SPramod Gunjikar 	return (0);
564c39526b7SPramod Gunjikar }
565c39526b7SPramod Gunjikar 
566c39526b7SPramod Gunjikar uint64_t
ibcma_init_root_sid(sol_cma_chan_t * root_chanp)567c39526b7SPramod Gunjikar ibcma_init_root_sid(sol_cma_chan_t *root_chanp)
568c39526b7SPramod Gunjikar {
569c39526b7SPramod Gunjikar 	ibcma_chan_t		*root_ibchanp;
570c39526b7SPramod Gunjikar 	struct rdma_cm_id	*root_idp;
571c39526b7SPramod Gunjikar 
572c39526b7SPramod Gunjikar 	root_ibchanp = &root_chanp->chan_ib;
573c39526b7SPramod Gunjikar 	root_idp = (struct rdma_cm_id *)root_chanp;
574c39526b7SPramod Gunjikar 	if (root_ibchanp->chan_sid == 0) {
575c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "listen No SID : ps %x",
576c39526b7SPramod Gunjikar 		    root_idp->ps);
577c39526b7SPramod Gunjikar 		root_ibchanp->chan_sid = ibt_get_ip_sid(root_idp->ps,
578c39526b7SPramod Gunjikar 		    root_ibchanp->chan_port);
579c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "chan SID %llx , ps %x, "
580c39526b7SPramod Gunjikar 		    "port %x", root_ibchanp->chan_sid, root_idp->ps,
581c39526b7SPramod Gunjikar 		    root_ibchanp->chan_port);
582c39526b7SPramod Gunjikar 	}
583c39526b7SPramod Gunjikar 	return ((uint64_t)root_ibchanp->chan_sid);
584c39526b7SPramod Gunjikar }
585c39526b7SPramod Gunjikar 
586c39526b7SPramod Gunjikar /*ARGSUSED*/
587c39526b7SPramod Gunjikar int
rdma_ib_listen(struct rdma_cm_id * ep_idp,int bklog)588c39526b7SPramod Gunjikar rdma_ib_listen(struct rdma_cm_id *ep_idp, int bklog)
589c39526b7SPramod Gunjikar {
590c39526b7SPramod Gunjikar 	struct rdma_cm_id	*root_idp;
591c39526b7SPramod Gunjikar 	ibcma_chan_t		*ep_ibchanp;
592c39526b7SPramod Gunjikar 	sol_cma_chan_t		*root_chanp, *ep_chanp;
593c39526b7SPramod Gunjikar 	ibcma_dev_t		*ep_devp;
594c39526b7SPramod Gunjikar 	ibt_status_t		status;
595c39526b7SPramod Gunjikar 
596c39526b7SPramod Gunjikar 	ASSERT(ep_idp);
597c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "ib_listen(%p)", ep_idp);
598c39526b7SPramod Gunjikar 	ep_chanp = (sol_cma_chan_t *)ep_idp;
599c39526b7SPramod Gunjikar 	root_idp  = CHAN_LISTEN_ROOT(ep_chanp);
600c39526b7SPramod Gunjikar 	root_chanp = (sol_cma_chan_t *)root_idp;
601c39526b7SPramod Gunjikar 	ep_ibchanp = &ep_chanp->chan_ib;
602c39526b7SPramod Gunjikar 
603c39526b7SPramod Gunjikar 	ep_devp = ep_ibchanp->chan_devp;
604c39526b7SPramod Gunjikar 	ASSERT(ep_devp);
605c39526b7SPramod Gunjikar 	status = ibt_bind_service(
606c39526b7SPramod Gunjikar 	    (root_chanp->chan_listenp)->listen_ib_srv_hdl,
607c39526b7SPramod Gunjikar 	    ep_devp->dev_sgid, NULL, ep_idp,
608c39526b7SPramod Gunjikar 	    &((ep_chanp->chan_listenp)->listen_ib_sbind_hdl));
609c39526b7SPramod Gunjikar 	if (status != IBT_SUCCESS) {
610c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "rdma_listen_ep: "
611c39526b7SPramod Gunjikar 		    "ibt_bind_service failed with %x", status);
612c39526b7SPramod Gunjikar 		return (EINVAL);
613c39526b7SPramod Gunjikar 	}
614c39526b7SPramod Gunjikar 	return (0);
615c39526b7SPramod Gunjikar }
616c39526b7SPramod Gunjikar 
617c39526b7SPramod Gunjikar #define	SOL_REP_PRIV_DATA_SZ 208
618c39526b7SPramod Gunjikar int
rdma_ib_accept(struct rdma_cm_id * idp,struct rdma_conn_param * conn_param)619c39526b7SPramod Gunjikar rdma_ib_accept(struct rdma_cm_id *idp, struct rdma_conn_param *conn_param)
620c39526b7SPramod Gunjikar {
621c39526b7SPramod Gunjikar 	sol_cma_chan_t	*chanp;
622c39526b7SPramod Gunjikar 	ibcma_chan_t	*ibchanp;
623c39526b7SPramod Gunjikar 	ibt_status_t	status;
624c39526b7SPramod Gunjikar 	void		*privp = NULL;
625c39526b7SPramod Gunjikar 	uint8_t		priv_len;
626c39526b7SPramod Gunjikar 
627c39526b7SPramod Gunjikar 	ASSERT(idp);
628c39526b7SPramod Gunjikar 	chanp = (sol_cma_chan_t *)idp;
629c39526b7SPramod Gunjikar 	ibchanp = &chanp->chan_ib;
630c39526b7SPramod Gunjikar 
631c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_ib_accept(%p, %p)",
632c39526b7SPramod Gunjikar 	    idp, conn_param);
633c39526b7SPramod Gunjikar 	if (chanp->chan_session_id == NULL) {
634c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L4(sol_rdmacm_dbg_str,
635c39526b7SPramod Gunjikar 		    "Active side, cm_proceed not needed");
636c39526b7SPramod Gunjikar 		return (0);
637c39526b7SPramod Gunjikar 	}
638c39526b7SPramod Gunjikar 
639c39526b7SPramod Gunjikar 	if (!conn_param) {
640c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L4(sol_rdmacm_dbg_str, "conn_param NULL");
641c39526b7SPramod Gunjikar 		return (0);
642c39526b7SPramod Gunjikar 	}
643c39526b7SPramod Gunjikar 
644c39526b7SPramod Gunjikar 	ibchanp->chan_qpmodifyflag  = 1;
645c39526b7SPramod Gunjikar 	if (idp->ps == RDMA_PS_TCP)  {
646c39526b7SPramod Gunjikar 		ibt_cm_proceed_reply_t	cm_reply;
647c39526b7SPramod Gunjikar 
648c39526b7SPramod Gunjikar 		/* Fill cm_reply */
649c39526b7SPramod Gunjikar 		cm_reply.rep.cm_channel =
650c39526b7SPramod Gunjikar 		    (ibt_channel_hdl_t)chanp->chan_qp_hdl;
651c39526b7SPramod Gunjikar 		cm_reply.rep.cm_rdma_ra_out = conn_param->initiator_depth;
652c39526b7SPramod Gunjikar 		cm_reply.rep.cm_rdma_ra_in = conn_param->responder_resources;
653c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "accept: "
654c39526b7SPramod Gunjikar 		    "init_dept %x, resp_res %x", conn_param->initiator_depth,
655c39526b7SPramod Gunjikar 		    conn_param->responder_resources);
656c39526b7SPramod Gunjikar 		cm_reply.rep.cm_rnr_retry_cnt = conn_param->rnr_retry_count;
657c39526b7SPramod Gunjikar 		priv_len = conn_param->private_data_len;
658c39526b7SPramod Gunjikar 		if (priv_len) {
659c39526b7SPramod Gunjikar 			privp = (void *)kmem_zalloc(
660c39526b7SPramod Gunjikar 			    SOL_REP_PRIV_DATA_SZ, KM_SLEEP);
661c39526b7SPramod Gunjikar 			bcopy((void *)conn_param->private_data,
662c39526b7SPramod Gunjikar 			    privp, priv_len);
663c39526b7SPramod Gunjikar #ifdef	DEBUG
664c39526b7SPramod Gunjikar 			dump_priv_data(privp, SOL_REP_PRIV_DATA_SZ,
665c39526b7SPramod Gunjikar 			    conn_param->private_data_len, "ib_accept");
666c39526b7SPramod Gunjikar #endif
667c39526b7SPramod Gunjikar 		}
668c39526b7SPramod Gunjikar 
669c39526b7SPramod Gunjikar 		status = ibt_ofuvcm_proceed(IBT_CM_EVENT_REQ_RCV,
670c39526b7SPramod Gunjikar 		    chanp->chan_session_id, IBT_CM_ACCEPT, &cm_reply,
671c39526b7SPramod Gunjikar 		    privp, priv_len);
672c39526b7SPramod Gunjikar 		if (status != IBT_SUCCESS) {
673c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "ib_accept: "
674c39526b7SPramod Gunjikar 			    "ibt_ofuvcm_proceed failed %x", status);
675c39526b7SPramod Gunjikar 			if (privp)
676c39526b7SPramod Gunjikar 				kmem_free(privp, SOL_REP_PRIV_DATA_SZ);
677c39526b7SPramod Gunjikar 			return (EINVAL);
678c39526b7SPramod Gunjikar 		}
679c39526b7SPramod Gunjikar 		if (privp)
680c39526b7SPramod Gunjikar 			kmem_free(privp, SOL_REP_PRIV_DATA_SZ);
681c39526b7SPramod Gunjikar 		chanp->chan_session_id = NULL;
682c39526b7SPramod Gunjikar 	} else  {
683c39526b7SPramod Gunjikar 		ibt_qp_hdl_t	qphdl = chanp->chan_qp_hdl;
684c39526b7SPramod Gunjikar 
685c39526b7SPramod Gunjikar 		priv_len = conn_param->private_data_len;
686c39526b7SPramod Gunjikar 		if (priv_len) {
687c39526b7SPramod Gunjikar 			privp = (void *)kmem_zalloc(
688c39526b7SPramod Gunjikar 			    SOL_REP_PRIV_DATA_SZ, KM_SLEEP);
689c39526b7SPramod Gunjikar 			bcopy((void *)conn_param->private_data,
690c39526b7SPramod Gunjikar 			    privp, priv_len);
691c39526b7SPramod Gunjikar #ifdef DEBUG
692c39526b7SPramod Gunjikar 			dump_priv_data(privp, SOL_REP_PRIV_DATA_SZ,
693c39526b7SPramod Gunjikar 			    conn_param->private_data_len, "ib_accept");
694c39526b7SPramod Gunjikar #endif
695c39526b7SPramod Gunjikar 		}
696c39526b7SPramod Gunjikar 
697c39526b7SPramod Gunjikar 		status = ibt_cm_ud_proceed(chanp->chan_session_id, qphdl,
698c39526b7SPramod Gunjikar 		    IBT_CM_ACCEPT, NULL, privp, priv_len);
699c39526b7SPramod Gunjikar 		if (status != IBT_SUCCESS) {
700c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "ib_accept: "
701c39526b7SPramod Gunjikar 			    "ibt_cm_ud_proceed failed %x", status);
702c39526b7SPramod Gunjikar 			if (privp)
703c39526b7SPramod Gunjikar 				kmem_free(privp, SOL_REP_PRIV_DATA_SZ);
704c39526b7SPramod Gunjikar 			return (EINVAL);
705c39526b7SPramod Gunjikar 		}
706c39526b7SPramod Gunjikar 
707c39526b7SPramod Gunjikar 		if (privp)
708c39526b7SPramod Gunjikar 			kmem_free(privp, SOL_REP_PRIV_DATA_SZ);
709c39526b7SPramod Gunjikar 	}
710c39526b7SPramod Gunjikar 	return (0);
711c39526b7SPramod Gunjikar }
712c39526b7SPramod Gunjikar 
713c39526b7SPramod Gunjikar int
rdma_ib_reject(struct rdma_cm_id * idp,const void * private_data,uint8_t private_data_len)714c39526b7SPramod Gunjikar rdma_ib_reject(struct rdma_cm_id *idp, const void *private_data,
715c39526b7SPramod Gunjikar     uint8_t private_data_len)
716c39526b7SPramod Gunjikar {
717c39526b7SPramod Gunjikar 	sol_cma_chan_t	*chanp;
718c39526b7SPramod Gunjikar 	ibt_status_t	status;
719c39526b7SPramod Gunjikar 	void		*privp = NULL;
720c39526b7SPramod Gunjikar 
721c39526b7SPramod Gunjikar 	ASSERT(idp);
722c39526b7SPramod Gunjikar 	chanp = (sol_cma_chan_t *)idp;
723c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
724c39526b7SPramod Gunjikar 	    "rdma_ib_reject(%p, %p, %x)", idp,
725c39526b7SPramod Gunjikar 	    private_data, private_data_len);
726c39526b7SPramod Gunjikar 
727c39526b7SPramod Gunjikar 	if (chanp->chan_session_id == NULL) {
728c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "rdma_ib_reject :"
729c39526b7SPramod Gunjikar 		    "chan_session_id NULL");
730c39526b7SPramod Gunjikar 		return (EINVAL);
731c39526b7SPramod Gunjikar 	}
732c39526b7SPramod Gunjikar 
733c39526b7SPramod Gunjikar 	if (private_data_len) {
734c39526b7SPramod Gunjikar 		privp = (void *)kmem_zalloc(SOL_REP_PRIV_DATA_SZ,
735c39526b7SPramod Gunjikar 		    KM_SLEEP);
736c39526b7SPramod Gunjikar 		bcopy((void *)private_data, privp,
737c39526b7SPramod Gunjikar 		    private_data_len);
738c39526b7SPramod Gunjikar #ifdef	DEBUG
739c39526b7SPramod Gunjikar 		dump_priv_data(privp, SOL_REP_PRIV_DATA_SZ,
740c39526b7SPramod Gunjikar 		    private_data_len, "ib_reject");
741c39526b7SPramod Gunjikar #endif
742c39526b7SPramod Gunjikar 	}
743c39526b7SPramod Gunjikar 
744c39526b7SPramod Gunjikar 	if (idp->ps == RDMA_PS_TCP)  {
745c39526b7SPramod Gunjikar 		ibt_cm_proceed_reply_t cm_reply;
746c39526b7SPramod Gunjikar 
747c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_ib_reject :"
748c39526b7SPramod Gunjikar 		    "calling ibt_cm_proceed");
749c39526b7SPramod Gunjikar 		status = ibt_cm_proceed(IBT_CM_EVENT_REQ_RCV,
750c39526b7SPramod Gunjikar 		    chanp->chan_session_id, IBT_CM_REJECT, &cm_reply,
751c39526b7SPramod Gunjikar 		    privp, private_data_len);
752c39526b7SPramod Gunjikar 		if (status != IBT_SUCCESS) {
753c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "ib_reject: "
754c39526b7SPramod Gunjikar 			    "ibt_cm_proceed failed %x", status);
755c39526b7SPramod Gunjikar 			if (privp)
756c39526b7SPramod Gunjikar 				kmem_free(privp, SOL_REP_PRIV_DATA_SZ);
757c39526b7SPramod Gunjikar 			return (EINVAL);
758c39526b7SPramod Gunjikar 		}
759c39526b7SPramod Gunjikar 	} else  {
760c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_ib_reject :"
761c39526b7SPramod Gunjikar 		    "calling ibt_cm_ud_proceed");
762c39526b7SPramod Gunjikar 		status = ibt_cm_ud_proceed(chanp->chan_session_id, NULL,
763c39526b7SPramod Gunjikar 		    IBT_CM_REJECT, NULL, privp, private_data_len);
764c39526b7SPramod Gunjikar 		if (status != IBT_SUCCESS) {
765c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "ib_reject: "
766c39526b7SPramod Gunjikar 			    "ibt_cm_ud_proceed failed %x", status);
767c39526b7SPramod Gunjikar 			if (privp)
768c39526b7SPramod Gunjikar 				kmem_free(privp, SOL_REP_PRIV_DATA_SZ);
769c39526b7SPramod Gunjikar 			return (EINVAL);
770c39526b7SPramod Gunjikar 		}
771c39526b7SPramod Gunjikar 	}
772c39526b7SPramod Gunjikar 
773c39526b7SPramod Gunjikar 	if (privp)
774c39526b7SPramod Gunjikar 		kmem_free(privp, SOL_REP_PRIV_DATA_SZ);
775c39526b7SPramod Gunjikar 	return (0);
776c39526b7SPramod Gunjikar }
777c39526b7SPramod Gunjikar 
778c39526b7SPramod Gunjikar int
rdma_ib_disconnect(struct rdma_cm_id * idp)779c39526b7SPramod Gunjikar rdma_ib_disconnect(struct rdma_cm_id *idp)
780c39526b7SPramod Gunjikar {
781c39526b7SPramod Gunjikar 	sol_cma_chan_t		*root_chanp, *chanp;
782c39526b7SPramod Gunjikar 	ibt_status_t		status;
783fffafeb2SJohnny Cheung 	struct rdma_cm_id	*root_idp;
784c39526b7SPramod Gunjikar 
785c39526b7SPramod Gunjikar 	ASSERT(idp);
786c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "ib_disconnect(%p)", idp);
787c39526b7SPramod Gunjikar 	chanp = (sol_cma_chan_t *)idp;
788c39526b7SPramod Gunjikar 
789fffafeb2SJohnny Cheung 	root_idp = CHAN_LISTEN_ROOT(chanp);
790fffafeb2SJohnny Cheung 	root_chanp = (sol_cma_chan_t *)root_idp;
791fffafeb2SJohnny Cheung 	if (!root_chanp)
792fffafeb2SJohnny Cheung 		goto handle_close_chan;
793fffafeb2SJohnny Cheung 
794fffafeb2SJohnny Cheung 	mutex_enter(&chanp->chan_mutex);
795fffafeb2SJohnny Cheung 	if (chanp->chan_req_state == REQ_CMID_NOTIFIED ||
796fffafeb2SJohnny Cheung 	    chanp->chan_req_state == REQ_CMID_CREATED) {
797c39526b7SPramod Gunjikar 		CHAN_LISTEN_ROOT(chanp) = NULL;
798c39526b7SPramod Gunjikar 		mutex_exit(&chanp->chan_mutex);
799c39526b7SPramod Gunjikar 
800fffafeb2SJohnny Cheung 		if (IS_UDP_CMID(idp)) {
801fffafeb2SJohnny Cheung 			status = ibt_cm_ud_proceed(chanp->chan_session_id,
802fffafeb2SJohnny Cheung 			    NULL, IBT_CM_NO_CHANNEL, NULL, NULL, 0);
803fffafeb2SJohnny Cheung 			if (status != IBT_SUCCESS) {
804fffafeb2SJohnny Cheung 				SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
805fffafeb2SJohnny Cheung 				    "ib_disconnect(%p) Reject for incoming REQ "
806fffafeb2SJohnny Cheung 				    "failed, status %d", status);
807fffafeb2SJohnny Cheung 				return (EINVAL);
808fffafeb2SJohnny Cheung 			}
809fffafeb2SJohnny Cheung 		} else {
810fffafeb2SJohnny Cheung 			ibt_cm_proceed_reply_t	cm_reply;
811c39526b7SPramod Gunjikar 
812fffafeb2SJohnny Cheung 			bzero(&cm_reply, sizeof (cm_reply));
813fffafeb2SJohnny Cheung 			status = ibt_cm_proceed(IBT_CM_EVENT_REQ_RCV,
814fffafeb2SJohnny Cheung 			    chanp->chan_session_id, IBT_CM_REJECT, &cm_reply,
815fffafeb2SJohnny Cheung 			    NULL, 0);
816fffafeb2SJohnny Cheung 			if (status != IBT_SUCCESS) {
817fffafeb2SJohnny Cheung 				SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
818fffafeb2SJohnny Cheung 				    "ib_disconnect(%p) Reject for incoming REQ "
819fffafeb2SJohnny Cheung 				    "failed, status %d", status);
820fffafeb2SJohnny Cheung 				return (EINVAL);
821fffafeb2SJohnny Cheung 			}
822c39526b7SPramod Gunjikar 		}
823fffafeb2SJohnny Cheung 		mutex_enter(&root_chanp->chan_mutex);
824c39526b7SPramod Gunjikar 		mutex_enter(&chanp->chan_mutex);
825fffafeb2SJohnny Cheung 		if (REQ_CMID_IN_REQ_AVL_TREE(chanp)) {
826fffafeb2SJohnny Cheung 			ASSERT(cma_get_req_idp(root_idp,
827fffafeb2SJohnny Cheung 			    chanp->chan_session_id));
828c39526b7SPramod Gunjikar 			avl_remove(&root_chanp->chan_req_avl_tree, idp);
829fffafeb2SJohnny Cheung 			chanp->chan_req_state = REQ_CMID_SERVER_NONE;
830c39526b7SPramod Gunjikar 		}
831fffafeb2SJohnny Cheung 		mutex_exit(&chanp->chan_mutex);
832fffafeb2SJohnny Cheung 		mutex_exit(&root_chanp->chan_mutex);
833fffafeb2SJohnny Cheung 	} else
834fffafeb2SJohnny Cheung 		mutex_exit(&chanp->chan_mutex);
835c39526b7SPramod Gunjikar 
836fffafeb2SJohnny Cheung handle_close_chan :
837c39526b7SPramod Gunjikar 	/*
838c39526b7SPramod Gunjikar 	 * Close RC channel for RC.
839c39526b7SPramod Gunjikar 	 * No explicit Disconnect required for UD
840c39526b7SPramod Gunjikar 	 */
841fffafeb2SJohnny Cheung 	mutex_enter(&chanp->chan_mutex);
842c39526b7SPramod Gunjikar 	if (idp->ps == RDMA_PS_TCP && chanp->chan_qp_hdl &&
843fffafeb2SJohnny Cheung 	    SOL_CMID_CLOSE_REQUIRED(chanp)) {
844c39526b7SPramod Gunjikar 		ibt_execution_mode_t	mode;
845c39526b7SPramod Gunjikar 		void			*qp_hdl = chanp->chan_qp_hdl;
846c39526b7SPramod Gunjikar 
847c39526b7SPramod Gunjikar 
848c39526b7SPramod Gunjikar 		/*
849fffafeb2SJohnny Cheung 		 * No callbacks for CMIDs for which destroy_id() has
850fffafeb2SJohnny Cheung 		 * been called.
851c39526b7SPramod Gunjikar 		 */
852fffafeb2SJohnny Cheung 		mode = (chanp->chan_cmid_destroy_state &
853fffafeb2SJohnny Cheung 		    SOL_CMA_CALLER_CMID_DESTROYED) ? IBT_NOCALLBACKS :
854fffafeb2SJohnny Cheung 		    IBT_BLOCKING;
855c39526b7SPramod Gunjikar 		mutex_exit(&chanp->chan_mutex);
856c39526b7SPramod Gunjikar 		status = ibt_close_rc_channel(qp_hdl,
857c39526b7SPramod Gunjikar 		    mode, NULL, 0, NULL, NULL, NULL);
858c39526b7SPramod Gunjikar 		if (status != IBT_SUCCESS) {
859c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
860c39526b7SPramod Gunjikar 			    "disconnect: close_rc_channel failed %x",
861c39526b7SPramod Gunjikar 			    status);
862c39526b7SPramod Gunjikar 			return (EINVAL);
863c39526b7SPramod Gunjikar 		}
864c39526b7SPramod Gunjikar 	} else
865c39526b7SPramod Gunjikar 		mutex_exit(&chanp->chan_mutex);
866c39526b7SPramod Gunjikar 
867c39526b7SPramod Gunjikar 	return (0);
868c39526b7SPramod Gunjikar }
869c39526b7SPramod Gunjikar 
870c39526b7SPramod Gunjikar int
rdma_ib_join_multicast(struct rdma_cm_id * idp,struct sockaddr * addr,void * context)871c39526b7SPramod Gunjikar rdma_ib_join_multicast(struct rdma_cm_id *idp, struct sockaddr *addr,
872c39526b7SPramod Gunjikar     void *context)
873c39526b7SPramod Gunjikar {
874c39526b7SPramod Gunjikar 	sol_cma_chan_t	*chanp = (sol_cma_chan_t *)idp;
875c39526b7SPramod Gunjikar 	ibcma_chan_t	*ibchanp;
876c39526b7SPramod Gunjikar 	ibt_mcg_attr_t	mcg_attr;
877c39526b7SPramod Gunjikar 	ibt_ip_addr_t	mcast_addr;
878c39526b7SPramod Gunjikar 	ibt_mcg_info_t	*mcg_infop;
879c39526b7SPramod Gunjikar 	ibt_status_t	status;
880c39526b7SPramod Gunjikar 	ib_gid_t	mcast_gid, mcast_gid_horder;
881c39526b7SPramod Gunjikar 	ibcma_dev_t	*devp;
882c39526b7SPramod Gunjikar 	ibcma_mcast_t	*ibmcastp = NULL;
883c39526b7SPramod Gunjikar 
884c39526b7SPramod Gunjikar 	ibchanp = &chanp->chan_ib;
885c39526b7SPramod Gunjikar 	devp = ibchanp->chan_devp;
886c39526b7SPramod Gunjikar 	if (devp == NULL) {
887c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "join_mcast: devp NULL");
888c39526b7SPramod Gunjikar 		return (EINVAL);
889c39526b7SPramod Gunjikar 	}
890c39526b7SPramod Gunjikar 
891c39526b7SPramod Gunjikar 	ibmcastp = kmem_zalloc(sizeof (ibcma_mcast_t), KM_SLEEP);
892c39526b7SPramod Gunjikar 	ibmcastp->mcast_idp = idp;
893c39526b7SPramod Gunjikar 	ibmcastp->mcast_ctx = context;
894c39526b7SPramod Gunjikar 	bcopy(addr, &ibmcastp->mcast_addr, sizeof (struct sockaddr));
895c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "join_mcast: ibmcastp %p",
896c39526b7SPramod Gunjikar 	    ibmcastp);
897c39526b7SPramod Gunjikar 
898c39526b7SPramod Gunjikar 	sockaddr2ibtaddr_port(idp, addr, &mcast_addr, NULL);
899c39526b7SPramod Gunjikar 
900c39526b7SPramod Gunjikar 	/* Check if input @ to rdma_join_mcast is multicast IP @ */
901c39526b7SPramod Gunjikar 	if (!(mcast_addr.family == AF_INET &&
902c39526b7SPramod Gunjikar 	    ((htonl(mcast_addr.un.ip4addr) & 0xE0000000) ==
903c39526b7SPramod Gunjikar 	    0xE0000000))) {
904c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
905c39526b7SPramod Gunjikar 		    "Invalid IP addr specified");
906c39526b7SPramod Gunjikar 		kmem_free(ibmcastp, sizeof (ibcma_mcast_t));
907c39526b7SPramod Gunjikar 		return (EINVAL);
908c39526b7SPramod Gunjikar 	}
909c39526b7SPramod Gunjikar 
910c39526b7SPramod Gunjikar 	bzero(&mcg_attr, sizeof (mcg_attr));
911c39526b7SPramod Gunjikar 	if (sol_cma_any_addr(addr)) {
912c39526b7SPramod Gunjikar 		bzero(&mcast_gid, sizeof (mcast_gid));
913c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "ANY mcast addr input");
914c39526b7SPramod Gunjikar 	} else {
915c39526b7SPramod Gunjikar 		ipaddr2mgid(addr, &mcast_gid_horder, devp->dev_pkey);
916c39526b7SPramod Gunjikar 
917c39526b7SPramod Gunjikar 		mcast_gid.gid_prefix = htonll(
918c39526b7SPramod Gunjikar 		    mcast_gid_horder.gid_prefix);
919c39526b7SPramod Gunjikar 		mcast_gid.gid_guid = htonll(
920c39526b7SPramod Gunjikar 		    mcast_gid_horder.gid_guid);
921c39526b7SPramod Gunjikar 	}
922c39526b7SPramod Gunjikar 	bcopy(&mcast_gid, &(mcg_attr.mc_mgid), sizeof (ib_gid_t));
923c39526b7SPramod Gunjikar 	mcg_attr.mc_mtu_req.r_selector = IBT_BEST;
924c39526b7SPramod Gunjikar 	mcg_attr.mc_flow = 0;
925c39526b7SPramod Gunjikar 	mcg_attr.mc_hop = 0xFF;
926c39526b7SPramod Gunjikar 	mcg_attr.mc_tclass = 0;
927c39526b7SPramod Gunjikar 	mcg_attr.mc_sl = 0;
928c39526b7SPramod Gunjikar 	mcg_attr.mc_pkt_lt_req.p_selector = IBT_BEST;
929c39526b7SPramod Gunjikar 	mcg_attr.mc_pkey = devp->dev_pkey;
930c39526b7SPramod Gunjikar 	mcg_attr.mc_rate_req.r_selector = IBT_BEST;
931c39526b7SPramod Gunjikar 	mcg_attr.mc_join_state = IB_MC_JSTATE_FULL;
932fffafeb2SJohnny Cheung 	if (idp->ps == RDMA_PS_UDP)
933fffafeb2SJohnny Cheung 		mcg_attr.mc_qkey = RDMA_UDP_QKEY;
934fffafeb2SJohnny Cheung 	else
935fffafeb2SJohnny Cheung 		mcg_attr.mc_qkey = SOL_IPOIB_DEFAULT_QKEY;
936c39526b7SPramod Gunjikar 	mcg_infop = kmem_zalloc(sizeof (ibt_mcg_info_t), KM_SLEEP);
937c39526b7SPramod Gunjikar 
938c39526b7SPramod Gunjikar 	status = ibt_join_mcg(ibchanp->chan_devp->dev_sgid,
939c39526b7SPramod Gunjikar 	    &mcg_attr, mcg_infop, ibcma_multicast_hdlr, ibmcastp);
940c39526b7SPramod Gunjikar 	if (status != IBT_SUCCESS) {
941c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "\t join_mcast : "
942c39526b7SPramod Gunjikar 		    "ibt_join_mcg failed with status %d", status);
943c39526b7SPramod Gunjikar 		kmem_free(ibmcastp, sizeof (ibcma_mcast_t));
944c39526b7SPramod Gunjikar 		return (EINVAL);
945c39526b7SPramod Gunjikar 	}
946c39526b7SPramod Gunjikar 
947c39526b7SPramod Gunjikar 	(void) add_genlist(&ibchanp->chan_mcast_list, (uintptr_t)ibmcastp,
948c39526b7SPramod Gunjikar 	    NULL);
949c39526b7SPramod Gunjikar 	ibchanp->chan_mcast_cnt++;
950c39526b7SPramod Gunjikar 
951c39526b7SPramod Gunjikar 	return (0);
952c39526b7SPramod Gunjikar }
953c39526b7SPramod Gunjikar 
954c39526b7SPramod Gunjikar void
rdma_ib_leave_multicast(struct rdma_cm_id * idp,struct sockaddr * addr)955c39526b7SPramod Gunjikar rdma_ib_leave_multicast(struct rdma_cm_id *idp, struct sockaddr *addr)
956c39526b7SPramod Gunjikar {
957c39526b7SPramod Gunjikar 	sol_cma_chan_t	*chanp = (sol_cma_chan_t *)idp;
958c39526b7SPramod Gunjikar 	ibcma_chan_t	*ibchanp;
959c39526b7SPramod Gunjikar 	ibcma_mcast_t	*ibmcastp = NULL;
960c39526b7SPramod Gunjikar 	genlist_entry_t	*entry;
961c39526b7SPramod Gunjikar 	ib_gid_t	zero_gid;
962c39526b7SPramod Gunjikar 	ibt_status_t	status;
963c39526b7SPramod Gunjikar 
964c39526b7SPramod Gunjikar 	ibchanp = &chanp->chan_ib;
965c39526b7SPramod Gunjikar 	genlist_for_each(entry, &ibchanp->chan_mcast_list) {
966c39526b7SPramod Gunjikar 		ibmcastp = (ibcma_mcast_t *)entry->data;
967c39526b7SPramod Gunjikar 		ASSERT(ibmcastp);
968c39526b7SPramod Gunjikar 		if (bcmp(&ibmcastp->mcast_addr, addr,
969c39526b7SPramod Gunjikar 		    sizeof (struct sockaddr)) == 0) {
970c39526b7SPramod Gunjikar 			delete_genlist(&ibchanp->chan_mcast_list, entry);
971c39526b7SPramod Gunjikar 			break;
972c39526b7SPramod Gunjikar 		}
973c39526b7SPramod Gunjikar 		ibmcastp = NULL;
974c39526b7SPramod Gunjikar 	}
975c39526b7SPramod Gunjikar 	if (ibmcastp == NULL) {
976c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
977c39526b7SPramod Gunjikar 		    "leave_mcast: No matching @");
978c39526b7SPramod Gunjikar 		return;
979c39526b7SPramod Gunjikar 	}
980c39526b7SPramod Gunjikar 	ibchanp->chan_mcast_cnt--;
981c39526b7SPramod Gunjikar 	bzero(&zero_gid, sizeof (ib_gid_t));
982c39526b7SPramod Gunjikar 	status = ibt_leave_mcg(ibchanp->chan_devp->dev_sgid,
983c39526b7SPramod Gunjikar 	    ibmcastp->mcast_gid, zero_gid, IB_MC_JSTATE_FULL);
984c39526b7SPramod Gunjikar 	if (status != IBT_SUCCESS)
985c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "leave_mcast: "
986c39526b7SPramod Gunjikar 		    "ibt_leave_mcg failed %d", status);
987c39526b7SPramod Gunjikar 	kmem_free(ibmcastp, sizeof (ibcma_mcast_t));
988c39526b7SPramod Gunjikar }
989c39526b7SPramod Gunjikar 
990c39526b7SPramod Gunjikar /* Local Functions */
991c39526b7SPramod Gunjikar #define	SOL_REQ_PRIV_DATA_SZ	96
992c39526b7SPramod Gunjikar static int
ibcma_tcp_connect(struct rdma_cm_id * idp,ibcma_chan_t * ibchanp,struct rdma_conn_param * conn_paramp)993c39526b7SPramod Gunjikar ibcma_tcp_connect(struct rdma_cm_id *idp, ibcma_chan_t *ibchanp,
994c39526b7SPramod Gunjikar     struct rdma_conn_param *conn_paramp)
995c39526b7SPramod Gunjikar {
996c39526b7SPramod Gunjikar 	sol_cma_chan_t		*chanp = (sol_cma_chan_t *)idp;
997c39526b7SPramod Gunjikar 	ibt_chan_open_flags_t	flags;
998c39526b7SPramod Gunjikar 	ibt_chan_open_args_t	args;
999c39526b7SPramod Gunjikar 	ibt_status_t		status;
1000c39526b7SPramod Gunjikar 	ibt_ip_cm_info_t	ipcm_info;
1001c39526b7SPramod Gunjikar 
1002c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "tcp_connect(%p, %p, %p)", idp,
1003c39526b7SPramod Gunjikar 	    ibchanp, conn_paramp);
1004c39526b7SPramod Gunjikar 	bzero(&args, sizeof (args));
1005c39526b7SPramod Gunjikar 	args.oc_path_retry_cnt = conn_paramp->retry_count;
1006c39526b7SPramod Gunjikar 	args.oc_path_rnr_retry_cnt = conn_paramp->rnr_retry_count;
1007c39526b7SPramod Gunjikar 	flags = IBT_OCHAN_OFUV;
1008c39526b7SPramod Gunjikar 	args.oc_path = ibchanp->chan_pathp;
1009c39526b7SPramod Gunjikar 	(args.oc_path)->pi_sid = ibchanp->chan_sid;
1010c39526b7SPramod Gunjikar 	args.oc_cm_handler =  ibcma_rc_hdlr;
1011c39526b7SPramod Gunjikar 	args.oc_cm_clnt_private = idp;
1012c39526b7SPramod Gunjikar 	args.oc_rdma_ra_out = conn_paramp->initiator_depth;
1013c39526b7SPramod Gunjikar 	args.oc_rdma_ra_in = conn_paramp->responder_resources;
1014c39526b7SPramod Gunjikar 	args.oc_priv_data_len = IBT_IP_HDR_PRIV_DATA_SZ +
1015c39526b7SPramod Gunjikar 	    conn_paramp->private_data_len;
1016c39526b7SPramod Gunjikar 	args.oc_priv_data = kmem_zalloc(SOL_REQ_PRIV_DATA_SZ, KM_SLEEP);
1017c39526b7SPramod Gunjikar 
1018c39526b7SPramod Gunjikar 	bcopy(&ibchanp->chan_local_addr, &ipcm_info.src_addr,
1019c39526b7SPramod Gunjikar 	    sizeof (ibt_ip_addr_t));
1020c39526b7SPramod Gunjikar 	bcopy(&ibchanp->chan_remote_addr, &ipcm_info.dst_addr,
1021c39526b7SPramod Gunjikar 	    sizeof (ibt_ip_addr_t));
1022c39526b7SPramod Gunjikar 	ipcm_info.src_port = ibchanp->chan_port;
1023c39526b7SPramod Gunjikar 	status = ibt_format_ip_private_data(&ipcm_info, args.oc_priv_data_len,
1024c39526b7SPramod Gunjikar 	    args.oc_priv_data);
1025c39526b7SPramod Gunjikar 	if (status != IBT_SUCCESS) {
1026c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
1027c39526b7SPramod Gunjikar 		    "ibt_format_ip_private_data failed!!");
1028c39526b7SPramod Gunjikar 		kmem_free(args.oc_priv_data, SOL_REQ_PRIV_DATA_SZ);
1029c39526b7SPramod Gunjikar 		return (EINVAL);
1030c39526b7SPramod Gunjikar 	}
1031c39526b7SPramod Gunjikar 
1032c39526b7SPramod Gunjikar 	if (conn_paramp->private_data_len) {
1033c39526b7SPramod Gunjikar 		void	*dest;
1034c39526b7SPramod Gunjikar 
1035c39526b7SPramod Gunjikar 		dest = (void *)((uint8_t *)args.oc_priv_data +
1036c39526b7SPramod Gunjikar 		    IBT_IP_HDR_PRIV_DATA_SZ);
1037c39526b7SPramod Gunjikar 		bcopy(conn_paramp->private_data, dest,
1038c39526b7SPramod Gunjikar 		    conn_paramp->private_data_len);
1039c39526b7SPramod Gunjikar 	}
1040c39526b7SPramod Gunjikar 
1041c39526b7SPramod Gunjikar 	/*
1042c39526b7SPramod Gunjikar 	 * Set the RDMA related flags for this QP, if required.
1043c39526b7SPramod Gunjikar 	 */
1044c39526b7SPramod Gunjikar 	if (conn_paramp->initiator_depth || conn_paramp->responder_resources) {
1045c39526b7SPramod Gunjikar 		ibt_cep_modify_flags_t	cep_flags = IBT_CEP_SET_NOTHING;
1046c39526b7SPramod Gunjikar 		ibt_cep_flags_t		flags = IBT_CEP_NO_FLAGS;
1047c39526b7SPramod Gunjikar 
1048c39526b7SPramod Gunjikar 		if (conn_paramp->initiator_depth) {
1049c39526b7SPramod Gunjikar 			cep_flags |= IBT_CEP_SET_RDMA_R;
1050c39526b7SPramod Gunjikar 			flags |= IBT_CEP_RDMA_RD;
1051c39526b7SPramod Gunjikar 		}
1052c39526b7SPramod Gunjikar 		if (conn_paramp->responder_resources) {
1053c39526b7SPramod Gunjikar 			cep_flags |= IBT_CEP_SET_RDMA_W;
1054c39526b7SPramod Gunjikar 			flags |= IBT_CEP_RDMA_WR;
1055c39526b7SPramod Gunjikar 		}
1056c39526b7SPramod Gunjikar 
1057c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
1058c39526b7SPramod Gunjikar 		    "tcp_connect: Calling  ibt_modify_rdma(%p, %x)",
1059c39526b7SPramod Gunjikar 		    chanp->chan_qp_hdl, cep_flags);
1060c39526b7SPramod Gunjikar 		status = ibt_modify_rdma(chanp->chan_qp_hdl,
1061c39526b7SPramod Gunjikar 		    cep_flags, flags);
1062c39526b7SPramod Gunjikar 		if (status != IBT_SUCCESS) {
1063c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "tcp_connect: "
1064c39526b7SPramod Gunjikar 			    "ibt_open_rdma failed %x", status);
1065c39526b7SPramod Gunjikar 			kmem_free(args.oc_priv_data, SOL_REQ_PRIV_DATA_SZ);
1066c39526b7SPramod Gunjikar 			return (EINVAL);
1067c39526b7SPramod Gunjikar 		}
1068c39526b7SPramod Gunjikar 	}
1069c39526b7SPramod Gunjikar 
1070c39526b7SPramod Gunjikar 	dump_priv_data(args.oc_priv_data, SOL_REQ_PRIV_DATA_SZ,
1071c39526b7SPramod Gunjikar 	    args.oc_priv_data_len, "tcp_connect");
1072c39526b7SPramod Gunjikar 	chanp->chan_connect_flag = SOL_CMA_CONNECT_INITIATED;
1073c39526b7SPramod Gunjikar 	status = ibt_open_rc_channel(chanp->chan_qp_hdl, flags,
1074c39526b7SPramod Gunjikar 	    IBT_NONBLOCKING, &args, NULL);
1075c39526b7SPramod Gunjikar 	if (status != IBT_SUCCESS) {
1076c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
1077c39526b7SPramod Gunjikar 		    "tcp_connect: ibv_open_rc_channel failed %x",
1078c39526b7SPramod Gunjikar 		    status);
1079c39526b7SPramod Gunjikar 		kmem_free(args.oc_priv_data, SOL_REQ_PRIV_DATA_SZ);
1080fffafeb2SJohnny Cheung 		chanp->chan_connect_flag = SOL_CMA_CONNECT_CLIENT_NONE;
1081c39526b7SPramod Gunjikar 		return (EINVAL);
1082c39526b7SPramod Gunjikar 	}
1083c39526b7SPramod Gunjikar 	kmem_free(args.oc_priv_data, SOL_REQ_PRIV_DATA_SZ);
1084c39526b7SPramod Gunjikar 
1085c39526b7SPramod Gunjikar 	return (0);
1086c39526b7SPramod Gunjikar }
1087c39526b7SPramod Gunjikar 
1088c39526b7SPramod Gunjikar static int
ibcma_udp_connect(struct rdma_cm_id * idp,ibcma_chan_t * ibchanp,struct rdma_conn_param * conn_paramp)1089c39526b7SPramod Gunjikar ibcma_udp_connect(struct rdma_cm_id *idp, ibcma_chan_t *ibchanp,
1090c39526b7SPramod Gunjikar     struct rdma_conn_param *conn_paramp)
1091c39526b7SPramod Gunjikar {
1092c39526b7SPramod Gunjikar 	ibt_status_t		status;
1093c39526b7SPramod Gunjikar 	ibt_ud_dest_attr_t	attr;
1094c39526b7SPramod Gunjikar 	ibt_path_info_t		*pathp;
1095c39526b7SPramod Gunjikar 	ibt_adds_vect_t		*addr_vect;
1096c39526b7SPramod Gunjikar 	ibcma_dev_t		*devp;
1097c39526b7SPramod Gunjikar 	ibt_ip_cm_info_t	ipcm_info;
1098c39526b7SPramod Gunjikar 	sol_cma_chan_t		*chanp = (sol_cma_chan_t *)idp;
1099c39526b7SPramod Gunjikar 
1100c39526b7SPramod Gunjikar 	devp = ibchanp->chan_devp;
1101c39526b7SPramod Gunjikar 	ASSERT(devp);
1102c39526b7SPramod Gunjikar 
1103c39526b7SPramod Gunjikar 	/* We always select the first path */
1104c39526b7SPramod Gunjikar 	pathp = ibchanp->chan_pathp;
1105c39526b7SPramod Gunjikar 	addr_vect = &((pathp->pi_prim_cep_path).cep_adds_vect);
1106c39526b7SPramod Gunjikar 
1107c39526b7SPramod Gunjikar 	bzero(&attr, sizeof (attr));
1108c39526b7SPramod Gunjikar 	attr.ud_pkey_ix = devp->dev_pkey_ix;
1109c39526b7SPramod Gunjikar 	attr.ud_cm_handler = ibcma_ud_hdlr;
1110c39526b7SPramod Gunjikar 	attr.ud_cm_private = idp;
1111c39526b7SPramod Gunjikar 	attr.ud_priv_data_len = IBT_IP_HDR_PRIV_DATA_SZ +
1112c39526b7SPramod Gunjikar 	    conn_paramp->private_data_len;
1113c39526b7SPramod Gunjikar 	attr.ud_priv_data = kmem_zalloc(attr.ud_priv_data_len, KM_SLEEP);
1114c39526b7SPramod Gunjikar 	if (conn_paramp->private_data_len) {
1115c39526b7SPramod Gunjikar 		bcopy(conn_paramp->private_data,
1116c39526b7SPramod Gunjikar 		    (void *)(((char *)attr.ud_priv_data) +
1117c39526b7SPramod Gunjikar 		    IBT_IP_HDR_PRIV_DATA_SZ),
1118c39526b7SPramod Gunjikar 		    conn_paramp->private_data_len);
1119c39526b7SPramod Gunjikar 	}
1120c39526b7SPramod Gunjikar 
1121c39526b7SPramod Gunjikar 	bcopy((void *)&ibchanp->chan_local_addr, &ipcm_info.src_addr,
1122c39526b7SPramod Gunjikar 	    sizeof (ibt_ip_addr_t));
1123c39526b7SPramod Gunjikar 	bcopy((void *)&ibchanp->chan_remote_addr, &ipcm_info.dst_addr,
1124c39526b7SPramod Gunjikar 	    sizeof (ibt_ip_addr_t));
1125c39526b7SPramod Gunjikar 	ipcm_info.src_port = ibchanp->chan_port;
1126c39526b7SPramod Gunjikar 	status = ibt_format_ip_private_data(&ipcm_info, attr.ud_priv_data_len,
1127c39526b7SPramod Gunjikar 	    attr.ud_priv_data);
1128c39526b7SPramod Gunjikar 	if (status != IBT_SUCCESS) {
1129c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "\tibudp_connect: "
1130c39526b7SPramod Gunjikar 		    "ibt_format_ip_private_data() failed with status %d",
1131c39526b7SPramod Gunjikar 		    status);
1132c39526b7SPramod Gunjikar 		kmem_free(attr.ud_priv_data, attr.ud_priv_data_len);
1133c39526b7SPramod Gunjikar 		return (EINVAL);
1134c39526b7SPramod Gunjikar 	}
1135c39526b7SPramod Gunjikar 	attr.ud_sid = ibchanp->chan_sid;
1136c39526b7SPramod Gunjikar 	attr.ud_addr = addr_vect;
1137c39526b7SPramod Gunjikar 
1138c39526b7SPramod Gunjikar 	chanp->chan_connect_flag = SOL_CMA_CONNECT_INITIATED;
1139c39526b7SPramod Gunjikar 	status = ibt_ud_get_dqpn(&attr, IBT_NONBLOCKING, NULL);
1140c39526b7SPramod Gunjikar 
1141c39526b7SPramod Gunjikar 	if (status != IBT_SUCCESS) {
1142c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "\tibudp_connect: "
1143c39526b7SPramod Gunjikar 		    "ibt_ud_get_dqpn failed with status %x", status);
1144c39526b7SPramod Gunjikar 		kmem_free(attr.ud_priv_data, attr.ud_priv_data_len);
1145fffafeb2SJohnny Cheung 		chanp->chan_connect_flag = SOL_CMA_CONNECT_CLIENT_NONE;
1146c39526b7SPramod Gunjikar 		return (EINVAL);
1147c39526b7SPramod Gunjikar 	}
1148c39526b7SPramod Gunjikar 
1149c39526b7SPramod Gunjikar 	kmem_free(attr.ud_priv_data, attr.ud_priv_data_len);
1150c39526b7SPramod Gunjikar 
1151c39526b7SPramod Gunjikar 	return (0);
1152c39526b7SPramod Gunjikar }
1153c39526b7SPramod Gunjikar 
1154c39526b7SPramod Gunjikar static int
ibcma_init_devinfo(struct rdma_cm_id * idp,ibcma_chan_t * ibchanp,ibt_path_info_t * pathp)1155c39526b7SPramod Gunjikar ibcma_init_devinfo(struct rdma_cm_id *idp, ibcma_chan_t	*ibchanp,
1156c39526b7SPramod Gunjikar     ibt_path_info_t *pathp)
1157c39526b7SPramod Gunjikar {
1158c39526b7SPramod Gunjikar 	ibcma_dev_t		*devp;
1159c39526b7SPramod Gunjikar 	ibt_status_t		status;
1160c39526b7SPramod Gunjikar 	uint_t			nports, psize;
1161c39526b7SPramod Gunjikar 	ib_pkey_t		pkey;
1162c39526b7SPramod Gunjikar 	ibt_hca_portinfo_t	*pinfop;
1163c39526b7SPramod Gunjikar 
1164c39526b7SPramod Gunjikar 	if (ibchanp->chan_devp)
1165c39526b7SPramod Gunjikar 		return (-1);
1166c39526b7SPramod Gunjikar 
1167c39526b7SPramod Gunjikar 	/* Get the port_info and the pkey */
1168c39526b7SPramod Gunjikar 	status = ibt_query_hca_ports_byguid(pathp->pi_hca_guid,
1169c39526b7SPramod Gunjikar 	    pathp->pi_prim_cep_path.cep_hca_port_num,
1170c39526b7SPramod Gunjikar 	    &pinfop, &nports, &psize);
1171c39526b7SPramod Gunjikar 	if (status != IBT_SUCCESS) {
1172c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "init_devinfo - "
1173c39526b7SPramod Gunjikar 		    "query_hca_port failed rc %d", status);
1174c39526b7SPramod Gunjikar 		return (-1);
1175c39526b7SPramod Gunjikar 	} else {
1176c39526b7SPramod Gunjikar 		int	index;
1177c39526b7SPramod Gunjikar 
1178c39526b7SPramod Gunjikar 		index = pathp->pi_prim_cep_path.cep_pkey_ix;
1179c39526b7SPramod Gunjikar 		pkey = (pinfop->p_pkey_tbl)[index];
1180c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "init_devinfo - pkey %x",
1181c39526b7SPramod Gunjikar 		    pkey);
1182c39526b7SPramod Gunjikar 		ibt_free_portinfo(pinfop, psize);
1183c39526b7SPramod Gunjikar 	}
1184c39526b7SPramod Gunjikar 	devp = kmem_zalloc(sizeof (ibcma_dev_t), KM_SLEEP);
1185c39526b7SPramod Gunjikar 	ibchanp->chan_devp = devp;
1186c39526b7SPramod Gunjikar 	devp->dev_node_guid = pathp->pi_hca_guid;
1187c39526b7SPramod Gunjikar 	devp->dev_port_num = pathp->pi_prim_cep_path.cep_hca_port_num;
1188c39526b7SPramod Gunjikar 	devp->dev_pkey_ix = pathp->pi_prim_cep_path.cep_pkey_ix;
1189c39526b7SPramod Gunjikar 	devp->dev_pkey = pkey;
1190c39526b7SPramod Gunjikar 	devp->dev_sgid = pathp->pi_prim_cep_path.cep_adds_vect.av_sgid;
1191c39526b7SPramod Gunjikar 
1192c39526b7SPramod Gunjikar 	idp->device = sol_cma_acquire_device(ntohll(devp->dev_node_guid));
1193c39526b7SPramod Gunjikar 	idp->port_num = devp->dev_port_num;
1194c39526b7SPramod Gunjikar 	return (0);
1195c39526b7SPramod Gunjikar }
1196c39526b7SPramod Gunjikar 
1197c39526b7SPramod Gunjikar static int
ibcma_query_local_ip(struct rdma_cm_id * idp,sol_cma_chan_t * chanp,ibcma_chan_t * ibchanp)1198c39526b7SPramod Gunjikar ibcma_query_local_ip(struct rdma_cm_id *idp, sol_cma_chan_t *chanp,
1199c39526b7SPramod Gunjikar     ibcma_chan_t *ibchanp)
1200c39526b7SPramod Gunjikar {
1201c39526b7SPramod Gunjikar 	ibt_status_t		status;
1202c39526b7SPramod Gunjikar 	ibt_ip_addr_t		*local_addrp;
1203c39526b7SPramod Gunjikar 	ibt_ip_path_attr_t	path_attr;
1204c39526b7SPramod Gunjikar 	ibt_path_info_t		local_path;
1205c39526b7SPramod Gunjikar 
1206c39526b7SPramod Gunjikar 	if (ibchanp->chan_pathp != NULL) {
1207c39526b7SPramod Gunjikar 		return (0);
1208c39526b7SPramod Gunjikar 	}
1209c39526b7SPramod Gunjikar 	local_addrp = &ibchanp->chan_local_addr;
1210c39526b7SPramod Gunjikar 	bzero(&path_attr, sizeof (path_attr));
1211c39526b7SPramod Gunjikar 	path_attr.ipa_dst_ip = local_addrp;
1212c39526b7SPramod Gunjikar 	bcopy(local_addrp, &path_attr.ipa_src_ip, sizeof (ibt_ip_addr_t));
1213c39526b7SPramod Gunjikar 	path_attr.ipa_ndst = 1;
1214c39526b7SPramod Gunjikar 	path_attr.ipa_max_paths = 1;
1215*17a2b317SBill Taylor 	path_attr.ipa_zoneid = 0;
1216c39526b7SPramod Gunjikar 
1217c39526b7SPramod Gunjikar 	if ((status = ibt_get_ip_paths(chanp->chan_ib_client_hdl,
1218c39526b7SPramod Gunjikar 	    IBT_PATH_NO_FLAGS, &path_attr, &local_path, NULL, NULL)) !=
1219c39526b7SPramod Gunjikar 	    IBT_SUCCESS) {
1220c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
1221c39526b7SPramod Gunjikar 		    "ib_cma_get_devinfo:status %d,  %p not IB IP @",
1222c39526b7SPramod Gunjikar 		    status, local_addrp);
1223c39526b7SPramod Gunjikar 		return (EINVAL);
1224c39526b7SPramod Gunjikar 	}
1225c39526b7SPramod Gunjikar 	if (ibcma_init_devinfo(idp, ibchanp, &local_path)) {
1226c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
1227c39526b7SPramod Gunjikar 		    "ib_cma_get_devinfo:init_devinfo failed");
1228c39526b7SPramod Gunjikar 		return (EINVAL);
1229c39526b7SPramod Gunjikar 	}
1230c39526b7SPramod Gunjikar 
1231c39526b7SPramod Gunjikar 	return (0);
1232c39526b7SPramod Gunjikar }
1233c39526b7SPramod Gunjikar 
1234fffafeb2SJohnny Cheung #define	IBCMA_FREE_IN_IPPATH_HDLR()				\
1235fffafeb2SJohnny Cheung 	if (pathp)						\
1236fffafeb2SJohnny Cheung 		kmem_free(pathp, sizeof (ibt_path_info_t) * 	\
1237fffafeb2SJohnny Cheung 		    num_paths);					\
1238fffafeb2SJohnny Cheung 	if (src_ip_p)						\
1239fffafeb2SJohnny Cheung 		kmem_free(src_ip_p, sizeof (ibt_path_ip_src_t) 	\
1240fffafeb2SJohnny Cheung 		    * num_paths);
1241c0dd49bdSEiji Ota 
1242c0dd49bdSEiji Ota static void
ibcma_path_hdlr(void * arg,ibt_status_t retval,ibt_path_info_t * pathp,uint8_t num_paths,ibt_path_ip_src_t * src_ip_p)1243c0dd49bdSEiji Ota ibcma_path_hdlr(void *arg, ibt_status_t retval, ibt_path_info_t *pathp,
1244c0dd49bdSEiji Ota     uint8_t num_paths, ibt_path_ip_src_t *src_ip_p)
1245c0dd49bdSEiji Ota {
1246c0dd49bdSEiji Ota 	struct rdma_cm_id	*idp = (struct rdma_cm_id *)arg;
1247c0dd49bdSEiji Ota 	sol_cma_chan_t		*chanp = (sol_cma_chan_t *)arg;
1248c0dd49bdSEiji Ota 	ibcma_chan_t		*ibchanp = &(chanp->chan_ib);
1249c0dd49bdSEiji Ota 	int			i;
1250c0dd49bdSEiji Ota 	ibcma_dev_t		*devp;
1251c0dd49bdSEiji Ota 	ib_lid_t		base_lid;
1252c0dd49bdSEiji Ota 
1253c0dd49bdSEiji Ota 	if (retval != IBT_SUCCESS && retval != IBT_INSUFF_DATA) {
1254c0dd49bdSEiji Ota 		cma_resolve_addr_callback(chanp, 1);
1255fffafeb2SJohnny Cheung 		IBCMA_FREE_IN_IPPATH_HDLR();
1256c0dd49bdSEiji Ota 		return;
1257c0dd49bdSEiji Ota 	}
1258c0dd49bdSEiji Ota 
1259c0dd49bdSEiji Ota 	ibchanp->chan_path_size = 2 * sizeof (ibt_path_info_t);
1260c0dd49bdSEiji Ota 	ibchanp->chan_pathp = kmem_zalloc(ibchanp->chan_path_size, KM_SLEEP);
1261c0dd49bdSEiji Ota 	bcopy(pathp, ibchanp->chan_pathp, num_paths *
1262c0dd49bdSEiji Ota 	    sizeof (ibt_path_info_t));
1263c0dd49bdSEiji Ota 	ibchanp->chan_numpaths = num_paths;
1264c0dd49bdSEiji Ota 
1265c0dd49bdSEiji Ota 	if (ibchanp->chan_devp == NULL && src_ip_p) {
1266c0dd49bdSEiji Ota 		ipaddr2sockaddr(&(src_ip_p[0].ip_primary),
1267c0dd49bdSEiji Ota 		    &(idp->route.addr.src_addr), NULL);
1268c0dd49bdSEiji Ota 		bcopy(&(src_ip_p[0].ip_primary), &ibchanp->chan_local_addr,
1269c0dd49bdSEiji Ota 		    sizeof (ibt_ip_addr_t));
1270c0dd49bdSEiji Ota 		if (ibcma_init_devinfo((struct rdma_cm_id *)chanp,
1271c0dd49bdSEiji Ota 		    ibchanp, pathp)) {
1272c0dd49bdSEiji Ota 			kmem_free(ibchanp->chan_pathp,
1273c0dd49bdSEiji Ota 			    ibchanp->chan_path_size);
1274c0dd49bdSEiji Ota 			cma_resolve_addr_callback(chanp, 1);
1275fffafeb2SJohnny Cheung 			IBCMA_FREE_IN_IPPATH_HDLR();
1276c0dd49bdSEiji Ota 			return;
1277c0dd49bdSEiji Ota 		}
1278c0dd49bdSEiji Ota 	}
1279c0dd49bdSEiji Ota 
1280c0dd49bdSEiji Ota 	if (ibchanp->chan_devp == NULL) {
1281c0dd49bdSEiji Ota 		cma_resolve_addr_callback(chanp, 1);
1282fffafeb2SJohnny Cheung 		IBCMA_FREE_IN_IPPATH_HDLR();
1283c0dd49bdSEiji Ota 		return;
1284c0dd49bdSEiji Ota 	}
1285c0dd49bdSEiji Ota 
1286c0dd49bdSEiji Ota 	devp = ibchanp->chan_devp;
1287c0dd49bdSEiji Ota 	(idp->route).num_paths = ibchanp->chan_numpaths;
1288c0dd49bdSEiji Ota 	idp->route.path_rec = kmem_zalloc(sizeof (struct ib_sa_path_rec) *
1289c0dd49bdSEiji Ota 	    ibchanp->chan_numpaths, KM_SLEEP);
1290c0dd49bdSEiji Ota 	base_lid = ibt_get_port_state_byguid(devp->dev_node_guid,
1291c0dd49bdSEiji Ota 	    devp->dev_port_num, NULL, &base_lid);
1292c0dd49bdSEiji Ota 	for (i = 0; i < ibchanp->chan_numpaths; i++)
1293c0dd49bdSEiji Ota 		ibt_path2sa_path(&((ibchanp->chan_pathp)[i]),
1294c0dd49bdSEiji Ota 		    &((idp->route.path_rec)[i]), base_lid);
1295c0dd49bdSEiji Ota 
1296c0dd49bdSEiji Ota 	cma_resolve_addr_callback(chanp, 0);
1297fffafeb2SJohnny Cheung 	IBCMA_FREE_IN_IPPATH_HDLR();
1298c0dd49bdSEiji Ota }
1299c0dd49bdSEiji Ota 
1300c39526b7SPramod Gunjikar static int
ibcma_get_paths(struct rdma_cm_id * idp,sol_cma_chan_t * chanp,ibcma_chan_t * ibchanp)1301c39526b7SPramod Gunjikar ibcma_get_paths(struct rdma_cm_id *idp, sol_cma_chan_t *chanp,
1302c39526b7SPramod Gunjikar     ibcma_chan_t *ibchanp)
1303c39526b7SPramod Gunjikar {
1304c39526b7SPramod Gunjikar 	ibt_ip_path_attr_t	path_attr;
1305c39526b7SPramod Gunjikar 	ibt_status_t		status;
1306c39526b7SPramod Gunjikar 	ibt_ip_addr_t		*dst_addrp;
1307c39526b7SPramod Gunjikar 
1308c39526b7SPramod Gunjikar 	ASSERT(ibchanp);
1309c39526b7SPramod Gunjikar 
1310c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "ibcma_get_paths(%p, %p)", idp,
1311c39526b7SPramod Gunjikar 	    ibchanp);
1312c39526b7SPramod Gunjikar 	bzero(&path_attr, sizeof (ibt_ip_path_attr_t));
1313c39526b7SPramod Gunjikar 	dst_addrp = kmem_zalloc(sizeof (ibt_ip_addr_t), KM_SLEEP);
1314c39526b7SPramod Gunjikar 	bcopy(&ibchanp->chan_remote_addr, dst_addrp, sizeof (ibt_ip_addr_t));
1315c39526b7SPramod Gunjikar 	path_attr.ipa_dst_ip = dst_addrp;
1316c39526b7SPramod Gunjikar 	bcopy(&ibchanp->chan_local_addr, &path_attr.ipa_src_ip,
1317c39526b7SPramod Gunjikar 	    sizeof (ibt_ip_addr_t));
1318c39526b7SPramod Gunjikar 	path_attr.ipa_ndst = 1;
1319c0dd49bdSEiji Ota 	path_attr.ipa_max_paths = 2;
1320*17a2b317SBill Taylor 	path_attr.ipa_zoneid = 0;
1321c39526b7SPramod Gunjikar 	if (ibcma_any_addr(&path_attr.ipa_src_ip))
1322c39526b7SPramod Gunjikar 		path_attr.ipa_src_ip.family = AF_UNSPEC;
1323c39526b7SPramod Gunjikar 
1324c0dd49bdSEiji Ota 	status = ibt_aget_ip_paths(chanp->chan_ib_client_hdl, IBT_PATH_NO_FLAGS,
1325c0dd49bdSEiji Ota 	    &path_attr, ibcma_path_hdlr, idp);
1326c0dd49bdSEiji Ota 	if (status != IBT_SUCCESS) {
1327c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
1328c0dd49bdSEiji Ota 		    "cma_get_paths : ibt_aget_paths() failed %d", status);
1329c39526b7SPramod Gunjikar 		kmem_free(dst_addrp, sizeof (ibt_ip_addr_t));
1330c39526b7SPramod Gunjikar 		return (EINVAL);
1331c39526b7SPramod Gunjikar 	}
1332c39526b7SPramod Gunjikar 
1333c39526b7SPramod Gunjikar 	kmem_free(dst_addrp, sizeof (ibt_ip_addr_t));
1334c39526b7SPramod Gunjikar 	return (0);
1335c39526b7SPramod Gunjikar }
1336c39526b7SPramod Gunjikar 
1337c39526b7SPramod Gunjikar /*
1338c39526b7SPramod Gunjikar  * Solaris Event Handlers
1339c39526b7SPramod Gunjikar  */
1340c39526b7SPramod Gunjikar 
1341c39526b7SPramod Gunjikar /* UD Event Handler */
1342c39526b7SPramod Gunjikar /*ARGSUSED*/
1343c39526b7SPramod Gunjikar static ibt_cm_status_t
ibcma_ud_hdlr(void * inp,ibt_cm_ud_event_t * eventp,ibt_cm_ud_return_args_t * ret_args,void * priv_data,ibt_priv_data_len_t priv_datalen)1344c39526b7SPramod Gunjikar ibcma_ud_hdlr(void *inp, ibt_cm_ud_event_t *eventp,
1345c39526b7SPramod Gunjikar     ibt_cm_ud_return_args_t *ret_args, void *priv_data,
1346c39526b7SPramod Gunjikar     ibt_priv_data_len_t priv_datalen)
1347c39526b7SPramod Gunjikar {
1348c39526b7SPramod Gunjikar 	struct rdma_cm_id	*root_idp, *event_idp, *idp;
1349c39526b7SPramod Gunjikar 	sol_cma_chan_t		*root_chanp, *chanp, *event_chanp;
1350c39526b7SPramod Gunjikar 	ibcma_chan_t		*ibchanp, *event_ibchanp;
1351c39526b7SPramod Gunjikar 	struct rdma_ud_param	ud_param, *ud_paramp = &ud_param;
1352c39526b7SPramod Gunjikar 	enum rdma_cm_event_type event;
1353c39526b7SPramod Gunjikar 	int			evt_status = -1;
1354c39526b7SPramod Gunjikar 	ibt_priv_data_len_t	cm_privlen;
1355c39526b7SPramod Gunjikar 	void			*cm_priv;
1356c39526b7SPramod Gunjikar 	ibt_status_t		ibt_status;
1357c39526b7SPramod Gunjikar 	ibt_ip_cm_info_t	info;
1358c39526b7SPramod Gunjikar 	cma_chan_state_t	chan_state;
1359c39526b7SPramod Gunjikar 
1360c39526b7SPramod Gunjikar 	event_idp = idp = (struct rdma_cm_id *)inp;
1361c39526b7SPramod Gunjikar 	chanp = (sol_cma_chan_t *)idp;
1362c39526b7SPramod Gunjikar 	ibchanp = &chanp->chan_ib;
1363c39526b7SPramod Gunjikar 	root_idp = CHAN_LISTEN_ROOT(chanp);
1364c39526b7SPramod Gunjikar 	root_chanp = (sol_cma_chan_t *)root_idp;
1365c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L3(sol_rdmacm_dbg_str, "cma_ud_hdlr(%p, %p)",
1366c39526b7SPramod Gunjikar 	    inp, eventp);
1367c39526b7SPramod Gunjikar 
1368c39526b7SPramod Gunjikar 	bzero(&ud_param, sizeof (struct rdma_ud_param));
1369c39526b7SPramod Gunjikar 	cm_privlen = eventp->cm_priv_data_len;
1370c39526b7SPramod Gunjikar 	cm_priv = eventp->cm_priv_data;
1371c39526b7SPramod Gunjikar 	if (eventp->cm_type == IBT_CM_UD_EVENT_SIDR_REQ) {
1372c39526b7SPramod Gunjikar 		ibt_cm_sidr_req_t	*sidr_req;
1373c39526b7SPramod Gunjikar 		void			*find_ret;
1374c39526b7SPramod Gunjikar 		avl_index_t		where;
1375c39526b7SPramod Gunjikar 
1376c39526b7SPramod Gunjikar 		ASSERT(root_chanp);
1377c39526b7SPramod Gunjikar 
1378c39526b7SPramod Gunjikar 		/*
1379c39526b7SPramod Gunjikar 		 * Reject further REQs if destroy of listen CMID
1380c39526b7SPramod Gunjikar 		 * has been called.
1381c39526b7SPramod Gunjikar 		 */
1382c39526b7SPramod Gunjikar 		mutex_enter(&root_chanp->chan_mutex);
1383c39526b7SPramod Gunjikar 		chan_state = cma_get_chan_state(root_chanp);
1384c39526b7SPramod Gunjikar 		mutex_exit(&root_chanp->chan_mutex);
1385c39526b7SPramod Gunjikar 		if (chan_state == SOL_CMA_CHAN_DESTROY_PENDING ||
1386c39526b7SPramod Gunjikar 		    chan_state == SOL_CMA_CHAN_DESTROY_WAIT) {
1387c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "UD Req Hdlr, "
1388c39526b7SPramod Gunjikar 			    "listen CMID destroy called");
1389c39526b7SPramod Gunjikar 			return (IBT_CM_REJECT);
1390c39526b7SPramod Gunjikar 		}
1391c39526b7SPramod Gunjikar 
1392c39526b7SPramod Gunjikar 		sidr_req = &((eventp->cm_event).sidr_req);
1393c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L4(sol_rdmacm_dbg_str, "SIDR REQ");
1394c39526b7SPramod Gunjikar 
1395c39526b7SPramod Gunjikar 		if (cm_privlen < IBT_IP_HDR_PRIV_DATA_SZ) {
1396c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "UD Req Hdlr, "
1397c39526b7SPramod Gunjikar 			    "Priv data len %x < %x", cm_privlen,
1398c39526b7SPramod Gunjikar 			    IBT_IP_HDR_PRIV_DATA_SZ);
1399c39526b7SPramod Gunjikar 			return (IBT_CM_REJECT);
1400c39526b7SPramod Gunjikar 		}
1401c39526b7SPramod Gunjikar 		ibt_status = ibt_get_ip_data(cm_privlen, cm_priv, &info);
1402c39526b7SPramod Gunjikar 		if (ibt_status != IBT_SUCCESS) {
1403c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "UD Req Hdlr, "
1404c39526b7SPramod Gunjikar 			    "ibt_get_ip_data failed, %x", ibt_status);
1405c39526b7SPramod Gunjikar 			return (IBT_CM_REJECT);
1406c39526b7SPramod Gunjikar 		}
1407c39526b7SPramod Gunjikar 		cm_privlen -= IBT_IP_HDR_PRIV_DATA_SZ;
1408c39526b7SPramod Gunjikar 		cm_priv = (void *)(((uchar_t *)cm_priv) +
1409c39526b7SPramod Gunjikar 		    IBT_IP_HDR_PRIV_DATA_SZ);
1410c39526b7SPramod Gunjikar 
1411c39526b7SPramod Gunjikar 		event_idp = ibcma_create_new_id(idp);
1412c39526b7SPramod Gunjikar 		if (event_idp == NULL) {
1413c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
1414c39526b7SPramod Gunjikar 			    "create_new_id failed!!");
1415c39526b7SPramod Gunjikar 			return (IBT_CM_REJECT);
1416c39526b7SPramod Gunjikar 		}
1417c39526b7SPramod Gunjikar 		event_idp->device = sol_cma_acquire_device(ntohll(
1418c39526b7SPramod Gunjikar 		    sidr_req->sreq_hca_guid));
1419c39526b7SPramod Gunjikar 		event_idp->port_num = sidr_req->sreq_hca_port;
1420c39526b7SPramod Gunjikar 		(event_idp->route).num_paths = 0;
1421c39526b7SPramod Gunjikar 
1422c39526b7SPramod Gunjikar 		event_chanp = (sol_cma_chan_t *)event_idp;
1423fffafeb2SJohnny Cheung 		event_chanp->chan_req_state = REQ_CMID_NOTIFIED;
1424c39526b7SPramod Gunjikar 		event_ibchanp = &event_chanp->chan_ib;
1425c39526b7SPramod Gunjikar 		event_chanp->chan_session_id = eventp->cm_session_id;
1426c39526b7SPramod Gunjikar 		bcopy(&info.src_addr, &event_ibchanp->chan_remote_addr,
1427c39526b7SPramod Gunjikar 		    sizeof (ibt_ip_addr_t));
1428c39526b7SPramod Gunjikar 		ipaddr2sockaddr(&info.src_addr,
1429c39526b7SPramod Gunjikar 		    &(event_idp->route.addr.dst_addr), &info.src_port);
1430a3077325SPramod Gunjikar 		bcopy(&info.dst_addr, &event_ibchanp->chan_local_addr,
1431a3077325SPramod Gunjikar 		    sizeof (ibt_ip_addr_t));
1432a3077325SPramod Gunjikar 		ipaddr2sockaddr(&info.dst_addr,
1433a3077325SPramod Gunjikar 		    &(event_idp->route.addr.src_addr), &info.src_port);
1434c39526b7SPramod Gunjikar 
1435c39526b7SPramod Gunjikar 		/*
1436c39526b7SPramod Gunjikar 		 * Increment number of Reqs for listening CMID,
1437c39526b7SPramod Gunjikar 		 * so that listening CMID is not deleted, till this
1438c39526b7SPramod Gunjikar 		 * connection expects no more events.
1439c39526b7SPramod Gunjikar 		 * chan_req_cnt is decremented connection is
1440c39526b7SPramod Gunjikar 		 * notified to the consumer.
1441c39526b7SPramod Gunjikar 		 *
1442c39526b7SPramod Gunjikar 		 * Insert the CMID into the REQ_AVL_TREE. This is
1443c39526b7SPramod Gunjikar 		 * deleted when the connection is accepted or rejected.
1444c39526b7SPramod Gunjikar 		 */
1445c39526b7SPramod Gunjikar 		mutex_enter(&root_chanp->chan_mutex);
1446c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
1447c39526b7SPramod Gunjikar 		    "Add to REQ AVL of %p IDP, idp %p, session_id %p",
1448c39526b7SPramod Gunjikar 		    root_idp, event_idp, event_chanp->chan_session_id);
1449c39526b7SPramod Gunjikar 		find_ret = avl_find(&root_chanp->chan_req_avl_tree,
1450c39526b7SPramod Gunjikar 		    (void *)event_chanp->chan_session_id, &where);
1451c39526b7SPramod Gunjikar 		if (find_ret) {
1452c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
1453c39526b7SPramod Gunjikar 			    "DUPLICATE ENTRY in REQ AVL : root %p, "
1454c39526b7SPramod Gunjikar 			    "idp %p, session_id %p",
1455c39526b7SPramod Gunjikar 			    root_idp, event_idp,
1456c39526b7SPramod Gunjikar 			    event_chanp->chan_session_id);
1457c39526b7SPramod Gunjikar 			mutex_exit(&root_chanp->chan_mutex);
1458fffafeb2SJohnny Cheung 			event_chanp->chan_req_state = REQ_CMID_CREATED;
1459c39526b7SPramod Gunjikar 			rdma_destroy_id(event_idp);
1460c39526b7SPramod Gunjikar 			return (IBT_CM_REJECT);
1461c39526b7SPramod Gunjikar 		}
1462c39526b7SPramod Gunjikar 		root_chanp->chan_req_cnt++;
1463c39526b7SPramod Gunjikar 		root_chanp->chan_req_state = REQ_CMID_CREATED;
1464c39526b7SPramod Gunjikar 		root_chanp->chan_req_total_cnt++;
1465c39526b7SPramod Gunjikar 		avl_insert(&root_chanp->chan_req_avl_tree,
1466c39526b7SPramod Gunjikar 		    (void *)event_idp, where);
1467c39526b7SPramod Gunjikar 		mutex_exit(&root_chanp->chan_mutex);
1468c39526b7SPramod Gunjikar 
1469c39526b7SPramod Gunjikar 		event = RDMA_CM_EVENT_CONNECT_REQUEST;
1470c39526b7SPramod Gunjikar 		evt_status = 0;
1471c39526b7SPramod Gunjikar 	} else if (eventp->cm_type == IBT_CM_UD_EVENT_SIDR_REP) {
1472c39526b7SPramod Gunjikar 		ibt_cm_sidr_rep_t	*sidr_rep;
1473c39526b7SPramod Gunjikar 
1474c39526b7SPramod Gunjikar 		ASSERT(chanp->chan_connect_flag == SOL_CMA_CONNECT_INITIATED);
1475c39526b7SPramod Gunjikar 		mutex_enter(&chanp->chan_mutex);
1476fffafeb2SJohnny Cheung 		chanp->chan_connect_flag = SOL_CMA_CONNECT_CLIENT_NONE;
1477c0dd49bdSEiji Ota 		chanp->chan_cmid_destroy_state |= SOL_CMA_CALLER_EVENT_PROGRESS;
1478c39526b7SPramod Gunjikar 		mutex_exit(&chanp->chan_mutex);
1479c39526b7SPramod Gunjikar 		sidr_rep = &((eventp->cm_event).sidr_rep);
1480c39526b7SPramod Gunjikar 		if (sidr_rep->srep_status == IBT_CM_SREP_CHAN_VALID) {
1481c39526b7SPramod Gunjikar 			evt_status = 0;
1482c39526b7SPramod Gunjikar 			event = RDMA_CM_EVENT_ESTABLISHED;
1483c39526b7SPramod Gunjikar 			ud_paramp->qp_num = sidr_rep->srep_remote_qpn;
1484c39526b7SPramod Gunjikar 			ud_paramp->qkey = sidr_rep->srep_remote_qkey;
1485c39526b7SPramod Gunjikar 			ibt_path2ah(ibchanp->chan_pathp, &ud_paramp->ah_attr);
1486c39526b7SPramod Gunjikar 		} else {
1487c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
1488c39526b7SPramod Gunjikar 			    "SIDR Response err with status %x",
1489c39526b7SPramod Gunjikar 			    sidr_rep->srep_status);
1490c39526b7SPramod Gunjikar 			event = RDMA_CM_EVENT_UNREACHABLE;
1491c39526b7SPramod Gunjikar 			evt_status = sidr_rep->srep_status;
1492c39526b7SPramod Gunjikar 			goto ud_gen_event;
1493c39526b7SPramod Gunjikar 		}
1494c39526b7SPramod Gunjikar 	}
1495c39526b7SPramod Gunjikar 
1496c39526b7SPramod Gunjikar 	ud_paramp->private_data_len = cm_privlen;
1497c39526b7SPramod Gunjikar 	if (evt_status == 0 && cm_privlen) {
1498c39526b7SPramod Gunjikar 		ud_paramp->private_data = kmem_zalloc(cm_privlen, KM_SLEEP);
1499c39526b7SPramod Gunjikar 		bcopy(cm_priv, (void *)ud_paramp->private_data,
1500c39526b7SPramod Gunjikar 		    cm_privlen);
1501c39526b7SPramod Gunjikar #ifdef DEBUG
1502c39526b7SPramod Gunjikar 		dump_priv_data((void *)ud_paramp->private_data,
1503c39526b7SPramod Gunjikar 		    SOL_REP_PRIV_DATA_SZ, cm_privlen, "ibcma_ud_hdlr");
1504c39526b7SPramod Gunjikar #endif
1505c39526b7SPramod Gunjikar 	}
1506c39526b7SPramod Gunjikar 
1507c39526b7SPramod Gunjikar ud_gen_event:
1508c39526b7SPramod Gunjikar 	/* Pass back the event to sol_cma consumer */
1509c39526b7SPramod Gunjikar 	cma_generate_event(event_idp, event, evt_status, NULL, ud_paramp);
1510c39526b7SPramod Gunjikar 
1511c39526b7SPramod Gunjikar 	if (ud_paramp->private_data)
1512c39526b7SPramod Gunjikar 		kmem_free((void *)ud_paramp->private_data, cm_privlen);
1513c39526b7SPramod Gunjikar 
1514c39526b7SPramod Gunjikar 	if (eventp->cm_type == IBT_CM_UD_EVENT_SIDR_REQ)
1515c39526b7SPramod Gunjikar 		return (IBT_CM_DEFER);
1516c39526b7SPramod Gunjikar 	else
1517c39526b7SPramod Gunjikar 		return (IBT_CM_DEFAULT);
1518c39526b7SPramod Gunjikar }
1519c39526b7SPramod Gunjikar 
1520c39526b7SPramod Gunjikar static ibt_cm_status_t
ibcma_handle_req(struct rdma_cm_id * idp,struct rdma_cm_id ** event_id_ptr,ibt_cm_event_t * eventp,struct rdma_conn_param * paramp,enum rdma_cm_event_type * event,int * evt_status)1521c39526b7SPramod Gunjikar ibcma_handle_req(struct rdma_cm_id *idp, struct rdma_cm_id **event_id_ptr,
1522c39526b7SPramod Gunjikar     ibt_cm_event_t *eventp, struct rdma_conn_param *paramp,
1523c39526b7SPramod Gunjikar     enum rdma_cm_event_type *event, int *evt_status)
1524c39526b7SPramod Gunjikar {
1525c39526b7SPramod Gunjikar 	struct rdma_cm_id	*root_idp, *event_idp;
1526c39526b7SPramod Gunjikar 	sol_cma_chan_t		*root_chanp, *event_chanp, *chanp;
1527c39526b7SPramod Gunjikar 	ibcma_chan_t		*event_ibchanp, *ibchanp;
1528c39526b7SPramod Gunjikar 	ibt_status_t		ibt_status;
1529c39526b7SPramod Gunjikar 	ibt_cm_req_rcv_t	*reqp;
1530c39526b7SPramod Gunjikar 	ibt_priv_data_len_t	cm_privlen;
1531c39526b7SPramod Gunjikar 	ibt_ofuvcm_req_data_t	rtr_data;
1532c39526b7SPramod Gunjikar 	ibt_ip_cm_info_t	info;
1533c39526b7SPramod Gunjikar 	void			*cm_priv, *priv_data;
1534c39526b7SPramod Gunjikar 	ib_lid_t		base_lid;
1535c39526b7SPramod Gunjikar 	void			*find_ret;
1536c39526b7SPramod Gunjikar 	avl_index_t		where;
1537c39526b7SPramod Gunjikar 	cma_chan_state_t	chan_state;
1538c39526b7SPramod Gunjikar #ifdef  DEBUG
1539c39526b7SPramod Gunjikar 	void			*dump_priv;
1540c39526b7SPramod Gunjikar #endif
1541c39526b7SPramod Gunjikar 
1542c39526b7SPramod Gunjikar 	chanp = (sol_cma_chan_t *)idp;
1543c39526b7SPramod Gunjikar 	ibchanp = &chanp->chan_ib;
1544c39526b7SPramod Gunjikar 	root_idp = CHAN_LISTEN_ROOT(chanp);
1545c39526b7SPramod Gunjikar 	root_chanp = (sol_cma_chan_t *)root_idp;
1546c39526b7SPramod Gunjikar 	ASSERT(chanp->chan_listenp);
1547c39526b7SPramod Gunjikar 	ASSERT(root_idp);
1548c39526b7SPramod Gunjikar 
1549c39526b7SPramod Gunjikar 	/*
1550c39526b7SPramod Gunjikar 	 * Reject further REQs if destroy of listen CMID
1551c39526b7SPramod Gunjikar 	 * has been called.
1552c39526b7SPramod Gunjikar 	 */
1553c39526b7SPramod Gunjikar 	mutex_enter(&root_chanp->chan_mutex);
1554c39526b7SPramod Gunjikar 	chan_state = cma_get_chan_state(root_chanp);
1555c39526b7SPramod Gunjikar 	mutex_exit(&root_chanp->chan_mutex);
1556c39526b7SPramod Gunjikar 	if (chan_state == SOL_CMA_CHAN_DESTROY_PENDING ||
1557c39526b7SPramod Gunjikar 	    chan_state == SOL_CMA_CHAN_DESTROY_WAIT) {
1558c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "RC Req Hdlr, "
1559c39526b7SPramod Gunjikar 		    "listen CMID destroy called");
1560c39526b7SPramod Gunjikar 		return (IBT_CM_REJECT);
1561c39526b7SPramod Gunjikar 	}
1562c39526b7SPramod Gunjikar 
1563c39526b7SPramod Gunjikar 	*event = RDMA_CM_EVENT_CONNECT_REQUEST;
1564c39526b7SPramod Gunjikar 	*evt_status = 0;
1565c39526b7SPramod Gunjikar 	reqp = &(eventp->cm_event.req);
1566c39526b7SPramod Gunjikar 	paramp->qp_num = reqp->req_remote_qpn;
1567c39526b7SPramod Gunjikar 	paramp->srq = (reqp->req_flags & IBT_CM_SRQ_EXISTS) ? 1 : 0;
1568c39526b7SPramod Gunjikar 	paramp->responder_resources = reqp->req_rdma_ra_in;
1569c39526b7SPramod Gunjikar 	paramp->initiator_depth = reqp->req_rdma_ra_out;
1570c39526b7SPramod Gunjikar 	paramp->flow_control = (reqp->req_flags & IBT_CM_FLOW_CONTROL)
1571c39526b7SPramod Gunjikar 	    ? 1 : 0;
1572c39526b7SPramod Gunjikar 	paramp->retry_count = reqp->req_retry_cnt;
1573c39526b7SPramod Gunjikar 	paramp->rnr_retry_count = reqp->req_rnr_retry_cnt;
1574c39526b7SPramod Gunjikar 
1575c39526b7SPramod Gunjikar #ifdef	DEBUG
1576c39526b7SPramod Gunjikar 	dump_priv = kmem_zalloc(SOL_REQ_PRIV_DATA_SZ, KM_SLEEP);
1577c39526b7SPramod Gunjikar 	bcopy(eventp->cm_priv_data, dump_priv, eventp->cm_priv_data_len);
1578c39526b7SPramod Gunjikar 	dump_priv_data(dump_priv, SOL_REQ_PRIV_DATA_SZ,
1579c39526b7SPramod Gunjikar 	    eventp->cm_priv_data_len, "handle_req");
1580c39526b7SPramod Gunjikar 	kmem_free(dump_priv, SOL_REQ_PRIV_DATA_SZ);
1581c39526b7SPramod Gunjikar #endif	/* DEBUG */
1582c39526b7SPramod Gunjikar 
1583c39526b7SPramod Gunjikar 	cm_privlen = eventp->cm_priv_data_len;
1584c39526b7SPramod Gunjikar 	cm_priv = eventp->cm_priv_data;
1585c39526b7SPramod Gunjikar 	if (cm_privlen < IBT_IP_HDR_PRIV_DATA_SZ) {
1586c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "RC Req Hdlr, "
1587c39526b7SPramod Gunjikar 		    "Priv data len %x < %x", cm_privlen,
1588c39526b7SPramod Gunjikar 		    IBT_IP_HDR_PRIV_DATA_SZ);
1589c39526b7SPramod Gunjikar 		return (IBT_CM_REJECT);
1590c39526b7SPramod Gunjikar 	}
1591c39526b7SPramod Gunjikar 	ibt_status = ibt_get_ip_data(cm_privlen, cm_priv, &info);
1592c39526b7SPramod Gunjikar 	if (ibt_status != IBT_SUCCESS) {
1593c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "RC Req Hdlr, "
1594c39526b7SPramod Gunjikar 		    "ibt_get_ip_data failed, %x", ibt_status);
1595c39526b7SPramod Gunjikar 		return (IBT_CM_REJECT);
1596c39526b7SPramod Gunjikar 	}
1597c39526b7SPramod Gunjikar 	bcopy(&info.dst_addr, &ibchanp->chan_remote_addr,
1598c39526b7SPramod Gunjikar 	    sizeof (ibt_ip_addr_t));
1599c39526b7SPramod Gunjikar 
1600c39526b7SPramod Gunjikar 	ibt_status = ibt_ofuvcm_get_req_data(eventp->cm_session_id, &rtr_data);
1601c39526b7SPramod Gunjikar 	if (ibt_status != IBT_SUCCESS) {
1602c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "RC Req Hdlr, "
1603c39526b7SPramod Gunjikar 		    "ibt_ofuvcm_get_req_data failed, %x", ibt_status);
1604c39526b7SPramod Gunjikar 		return (IBT_CM_REJECT);
1605c39526b7SPramod Gunjikar 	}
1606c39526b7SPramod Gunjikar 
1607c39526b7SPramod Gunjikar 	paramp->private_data_len = cm_privlen - IBT_IP_HDR_PRIV_DATA_SZ;
1608c39526b7SPramod Gunjikar 	if (paramp->private_data_len) {
1609c39526b7SPramod Gunjikar 		priv_data = (void *)((uint8_t *)cm_priv +
1610c39526b7SPramod Gunjikar 		    IBT_IP_HDR_PRIV_DATA_SZ);
1611c39526b7SPramod Gunjikar 		paramp->private_data = kmem_zalloc(paramp->private_data_len,
1612c39526b7SPramod Gunjikar 		    KM_SLEEP);
1613c39526b7SPramod Gunjikar 		bcopy(priv_data, (void *)paramp->private_data,
1614c39526b7SPramod Gunjikar 		    paramp->private_data_len);
1615c39526b7SPramod Gunjikar 	}
1616c39526b7SPramod Gunjikar 	event_idp = ibcma_create_new_id(idp);
1617c39526b7SPramod Gunjikar 	if (event_idp == NULL) {
1618c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
1619c39526b7SPramod Gunjikar 		    "create_new_id failed!!");
1620c39526b7SPramod Gunjikar 		if (paramp->private_data)
1621c39526b7SPramod Gunjikar 			kmem_free((void *)paramp->private_data,
1622c39526b7SPramod Gunjikar 			    paramp->private_data_len);
1623c39526b7SPramod Gunjikar 		return (IBT_CM_REJECT);
1624c39526b7SPramod Gunjikar 	}
1625c39526b7SPramod Gunjikar 
1626c39526b7SPramod Gunjikar 	/*
1627c39526b7SPramod Gunjikar 	 * Fill the route, device and port_num.
1628c39526b7SPramod Gunjikar 	 * TBD - Fill up packet_life_time
1629c39526b7SPramod Gunjikar 	 */
1630c39526b7SPramod Gunjikar 	event_idp->device = sol_cma_acquire_device(ntohll(
1631c39526b7SPramod Gunjikar 	    reqp->req_hca_guid));
1632c39526b7SPramod Gunjikar 	event_idp->port_num = reqp->req_prim_hca_port;
1633c39526b7SPramod Gunjikar 	(event_idp->route).num_paths = reqp->req_alt_hca_port ? 2 : 1;
1634c39526b7SPramod Gunjikar 	event_idp->route.path_rec = kmem_zalloc(
1635c39526b7SPramod Gunjikar 	    sizeof (struct ib_sa_path_rec) * ((event_idp->route).num_paths),
1636c39526b7SPramod Gunjikar 	    KM_SLEEP);
1637c39526b7SPramod Gunjikar 	base_lid = ibt_get_port_state_byguid(reqp->req_hca_guid,
1638c39526b7SPramod Gunjikar 	    reqp->req_prim_hca_port, NULL, &base_lid);
1639c39526b7SPramod Gunjikar 	ibt_addsvect2sa_path(&reqp->req_prim_addr,
1640c39526b7SPramod Gunjikar 	    &(event_idp->route.path_rec[0]), base_lid);
1641c39526b7SPramod Gunjikar 	(event_idp->route.path_rec[0]).mtu = (uint8_t)rtr_data.req_path_mtu;
1642c39526b7SPramod Gunjikar 	if (reqp->req_alt_hca_port) {
1643c39526b7SPramod Gunjikar 		base_lid = ibt_get_port_state_byguid(
1644c39526b7SPramod Gunjikar 		    reqp->req_hca_guid, reqp->req_alt_hca_port,
1645c39526b7SPramod Gunjikar 		    NULL, &base_lid);
1646c39526b7SPramod Gunjikar 		ibt_addsvect2sa_path(&reqp->req_alt_addr,
1647c39526b7SPramod Gunjikar 		    &(event_idp->route.path_rec[1]), base_lid);
1648c39526b7SPramod Gunjikar 		(event_idp->route.path_rec[1]).mtu =
1649c39526b7SPramod Gunjikar 		    (uint8_t)rtr_data.req_path_mtu;
1650c39526b7SPramod Gunjikar 	}
1651c39526b7SPramod Gunjikar 
1652c39526b7SPramod Gunjikar 	*event_id_ptr = event_idp;
1653c39526b7SPramod Gunjikar 
1654c39526b7SPramod Gunjikar 	event_chanp = (sol_cma_chan_t *)event_idp;
1655fffafeb2SJohnny Cheung 	event_chanp->chan_req_state = REQ_CMID_NOTIFIED;
1656c39526b7SPramod Gunjikar 	event_ibchanp = &event_chanp->chan_ib;
1657c39526b7SPramod Gunjikar 	event_chanp->chan_session_id = eventp->cm_session_id;
1658c39526b7SPramod Gunjikar 	bcopy((void *)(&reqp->req_prim_addr),
1659c39526b7SPramod Gunjikar 	    (void *)(&event_ibchanp->chan_rcreq_addr),
1660c39526b7SPramod Gunjikar 	    sizeof (ibt_adds_vect_t));
1661c39526b7SPramod Gunjikar 	bcopy(&rtr_data, &(event_ibchanp->chan_rtr_data),
1662c39526b7SPramod Gunjikar 	    sizeof (ibt_ofuvcm_req_data_t));
1663c39526b7SPramod Gunjikar 	event_ibchanp->chan_rcreq_qpn = reqp->req_remote_qpn;
1664c39526b7SPramod Gunjikar 	event_ibchanp->chan_rcreq_ra_in = reqp->req_rdma_ra_in;
1665a3077325SPramod Gunjikar 	bcopy(&info.src_addr, &event_ibchanp->chan_remote_addr,
1666a3077325SPramod Gunjikar 	    sizeof (ibt_ip_addr_t));
1667a3077325SPramod Gunjikar 	ipaddr2sockaddr(&info.src_addr,
1668a3077325SPramod Gunjikar 	    &(event_idp->route.addr.dst_addr), &info.src_port);
1669a3077325SPramod Gunjikar 	bcopy(&info.dst_addr, &event_ibchanp->chan_local_addr,
1670a3077325SPramod Gunjikar 	    sizeof (ibt_ip_addr_t));
1671a3077325SPramod Gunjikar 	ipaddr2sockaddr(&info.dst_addr,
1672a3077325SPramod Gunjikar 	    &(event_idp->route.addr.src_addr), &info.src_port);
1673c39526b7SPramod Gunjikar 
1674c39526b7SPramod Gunjikar 	/*
1675c39526b7SPramod Gunjikar 	 * Increment number of Reqs for listening CMID, so that
1676c39526b7SPramod Gunjikar 	 * listening CMID is not deleted, till this connection
1677c39526b7SPramod Gunjikar 	 * expects no more events. chan_req_cnt is decremented
1678c39526b7SPramod Gunjikar 	 * when connection is notified to the consumer.
1679c39526b7SPramod Gunjikar 	 *
1680c39526b7SPramod Gunjikar 	 * Insert the CMID into the REQ_AVL_TREE. This is
1681c39526b7SPramod Gunjikar 	 * deleted when the connection is accepted or rejected.
1682c39526b7SPramod Gunjikar 	 */
1683c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
1684c39526b7SPramod Gunjikar 	    "Add to REQ AVL of %p IDP, idp %p, session_id %p",
1685c39526b7SPramod Gunjikar 	    root_idp, event_idp, event_chanp->chan_session_id);
1686fffafeb2SJohnny Cheung 	mutex_enter(&root_chanp->chan_mutex);
1687c39526b7SPramod Gunjikar 	find_ret = avl_find(&root_chanp->chan_req_avl_tree,
1688c39526b7SPramod Gunjikar 	    (void *)event_chanp->chan_session_id, &where);
1689c39526b7SPramod Gunjikar 	if (find_ret) {
1690c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
1691c39526b7SPramod Gunjikar 		    "DUPLICATE ENTRY in REQ AVL : root %p, "
1692c39526b7SPramod Gunjikar 		    "idp %p, session_id %p",
1693c39526b7SPramod Gunjikar 		    root_idp, event_idp,
1694c39526b7SPramod Gunjikar 		    event_chanp->chan_session_id);
1695c39526b7SPramod Gunjikar 		mutex_exit(&root_chanp->chan_mutex);
1696fffafeb2SJohnny Cheung 		event_chanp->chan_req_state = REQ_CMID_CREATED;
1697fffafeb2SJohnny Cheung 		if (paramp->private_data)
1698fffafeb2SJohnny Cheung 			kmem_free((void *)paramp->private_data,
1699fffafeb2SJohnny Cheung 			    paramp->private_data_len);
1700c39526b7SPramod Gunjikar 		rdma_destroy_id(event_idp);
1701c39526b7SPramod Gunjikar 		return (IBT_CM_REJECT);
1702c39526b7SPramod Gunjikar 	}
1703c39526b7SPramod Gunjikar 	root_chanp->chan_req_cnt++;
1704c39526b7SPramod Gunjikar 	root_chanp->chan_req_state = REQ_CMID_CREATED;
1705c39526b7SPramod Gunjikar 	root_chanp->chan_req_total_cnt++;
1706fffafeb2SJohnny Cheung 
1707c39526b7SPramod Gunjikar 	avl_insert(&root_chanp->chan_req_avl_tree, (void *)event_idp, where);
1708c39526b7SPramod Gunjikar 	mutex_exit(&root_chanp->chan_mutex);
1709c39526b7SPramod Gunjikar 
1710c39526b7SPramod Gunjikar 	return (IBT_CM_DEFER);
1711c39526b7SPramod Gunjikar }
1712c39526b7SPramod Gunjikar 
1713c39526b7SPramod Gunjikar static void
ibcma_handle_rep(struct rdma_cm_id * idp,ibt_cm_event_t * eventp)1714c39526b7SPramod Gunjikar ibcma_handle_rep(struct rdma_cm_id *idp, ibt_cm_event_t *eventp)
1715c39526b7SPramod Gunjikar {
1716c39526b7SPramod Gunjikar 	sol_cma_chan_t		*chanp;
1717c39526b7SPramod Gunjikar 	ibt_cm_rep_rcv_t	*repp;
1718c39526b7SPramod Gunjikar 	struct rdma_conn_param	*paramp;
1719c39526b7SPramod Gunjikar 
1720c39526b7SPramod Gunjikar 	chanp = (sol_cma_chan_t *)idp;
1721c39526b7SPramod Gunjikar 
1722c39526b7SPramod Gunjikar 	paramp = &chanp->chan_param;
1723c39526b7SPramod Gunjikar 	bzero(paramp, sizeof (chanp->chan_param));
1724c39526b7SPramod Gunjikar 	repp = &((eventp->cm_event).rep);
1725c39526b7SPramod Gunjikar 	paramp->srq = (repp->rep_flags & IBT_CM_SRQ_EXISTS) ? 1 : 0;
1726c39526b7SPramod Gunjikar 	paramp->responder_resources = repp->rep_rdma_ra_in;
1727c39526b7SPramod Gunjikar 	paramp->initiator_depth = repp->rep_rdma_ra_out;
1728c39526b7SPramod Gunjikar 	paramp->flow_control = (repp->rep_flags & IBT_CM_FLOW_CONTROL) ? 1 : 0;
1729c39526b7SPramod Gunjikar 
1730c39526b7SPramod Gunjikar #ifdef DEBUG
1731c39526b7SPramod Gunjikar 	dump_priv_data(eventp->cm_priv_data, SOL_REP_PRIV_DATA_SZ,
1732c39526b7SPramod Gunjikar 	    eventp->cm_priv_data_len, "handle_rep");
1733c39526b7SPramod Gunjikar #endif
1734c39526b7SPramod Gunjikar 	paramp->private_data_len =  eventp->cm_priv_data_len;
1735c39526b7SPramod Gunjikar 	if (paramp->private_data_len) {
1736c39526b7SPramod Gunjikar 		paramp->private_data = kmem_zalloc(paramp->private_data_len,
1737c39526b7SPramod Gunjikar 		    KM_SLEEP);
1738c39526b7SPramod Gunjikar 		bcopy((void *)eventp->cm_priv_data,
1739c39526b7SPramod Gunjikar 		    (void *)paramp->private_data, paramp->private_data_len);
1740c39526b7SPramod Gunjikar 	}
1741c39526b7SPramod Gunjikar }
1742c39526b7SPramod Gunjikar 
1743c39526b7SPramod Gunjikar static ibt_cm_status_t
ibcma_handle_est(struct rdma_cm_id * idp,struct rdma_cm_id ** event_id_ptr,ibt_cm_event_t * eventp,struct rdma_conn_param * paramp,enum rdma_cm_event_type * event,int * evt_status)1744c39526b7SPramod Gunjikar ibcma_handle_est(struct rdma_cm_id *idp, struct rdma_cm_id **event_id_ptr,
1745c39526b7SPramod Gunjikar     ibt_cm_event_t *eventp, struct rdma_conn_param *paramp,
1746c39526b7SPramod Gunjikar     enum rdma_cm_event_type *event, int *evt_status)
1747c39526b7SPramod Gunjikar {
1748c39526b7SPramod Gunjikar 	struct rdma_cm_id	*event_idp, *root_idp;
1749c39526b7SPramod Gunjikar 	sol_cma_chan_t		*event_chanp, *chanp, *root_chanp;
1750c39526b7SPramod Gunjikar 	ibcma_chan_t		*event_ibchanp;
1751c39526b7SPramod Gunjikar 
1752c39526b7SPramod Gunjikar 	/* Established event on active / client side */
1753c39526b7SPramod Gunjikar 	chanp = (sol_cma_chan_t *)idp;
1754c39526b7SPramod Gunjikar 	if (chanp->chan_listenp == NULL) {
1755c39526b7SPramod Gunjikar 		ASSERT(chanp->chan_connect_flag == SOL_CMA_CONNECT_INITIATED);
1756fffafeb2SJohnny Cheung 		chanp->chan_connect_flag = SOL_CMA_CONNECT_ESTABLISHED;
1757c0dd49bdSEiji Ota 		*event_id_ptr = idp;
1758c39526b7SPramod Gunjikar 		bcopy(&chanp->chan_param, paramp,
1759c39526b7SPramod Gunjikar 		    sizeof (struct rdma_conn_param));
1760c39526b7SPramod Gunjikar 		if (paramp->private_data_len) {
1761c39526b7SPramod Gunjikar 			paramp->private_data = kmem_zalloc(
1762c39526b7SPramod Gunjikar 			    paramp->private_data_len, KM_SLEEP);
1763c39526b7SPramod Gunjikar 			bcopy((void *)((chanp->chan_param).private_data),
1764c39526b7SPramod Gunjikar 			    (void *)paramp->private_data,
1765c39526b7SPramod Gunjikar 			    paramp->private_data_len);
1766c39526b7SPramod Gunjikar 			kmem_free((void *)((chanp->chan_param).private_data),
1767c39526b7SPramod Gunjikar 			    paramp->private_data_len);
1768c39526b7SPramod Gunjikar 		}
1769c39526b7SPramod Gunjikar 		event_chanp = chanp;
1770c0dd49bdSEiji Ota 		mutex_enter(&chanp->chan_mutex);
1771c0dd49bdSEiji Ota 		chanp->chan_cmid_destroy_state |= SOL_CMA_CALLER_EVENT_PROGRESS;
1772c0dd49bdSEiji Ota 		mutex_exit(&chanp->chan_mutex);
1773c39526b7SPramod Gunjikar 		goto est_common;
1774c39526b7SPramod Gunjikar 	}
1775c39526b7SPramod Gunjikar 
1776c39526b7SPramod Gunjikar 	root_idp = CHAN_LISTEN_ROOT((chanp));
1777c39526b7SPramod Gunjikar 	ASSERT(root_idp);
1778c39526b7SPramod Gunjikar 	root_chanp = (sol_cma_chan_t *)root_idp;
1779c39526b7SPramod Gunjikar 	event_chanp = NULL;
1780c39526b7SPramod Gunjikar 
1781c0dd49bdSEiji Ota 	mutex_enter(&root_chanp->chan_mutex);
1782c39526b7SPramod Gunjikar 	event_idp = cma_get_acpt_idp(root_idp, eventp->cm_channel);
1783c0dd49bdSEiji Ota 	mutex_exit(&root_chanp->chan_mutex);
1784c39526b7SPramod Gunjikar 	if (event_idp == NULL) {
1785c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "ibcma_handle_est: "
1786c39526b7SPramod Gunjikar 		    "No matching CMID for qp_hdl %p in ACPT AVL of CMID %p",
1787c39526b7SPramod Gunjikar 		    eventp->cm_channel, root_chanp);
1788c39526b7SPramod Gunjikar 		return (IBT_CM_REJECT);
1789c39526b7SPramod Gunjikar 	}
1790c39526b7SPramod Gunjikar 	*event_id_ptr = event_idp;
1791c39526b7SPramod Gunjikar 	event_chanp = (sol_cma_chan_t *)event_idp;
1792c0dd49bdSEiji Ota 	mutex_enter(&event_chanp->chan_mutex);
1793c0dd49bdSEiji Ota 	event_chanp->chan_cmid_destroy_state |=
1794c0dd49bdSEiji Ota 	    SOL_CMA_CALLER_EVENT_PROGRESS;
1795c0dd49bdSEiji Ota 	mutex_exit(&event_chanp->chan_mutex);
1796c39526b7SPramod Gunjikar 
1797c39526b7SPramod Gunjikar est_common:
1798c39526b7SPramod Gunjikar #ifdef QP_DEBUG
1799c39526b7SPramod Gunjikar 	dump_qp_info(event_chanp->chan_qp_hdl);
1800c39526b7SPramod Gunjikar #endif
1801c39526b7SPramod Gunjikar 
1802c39526b7SPramod Gunjikar 	/*
1803c39526b7SPramod Gunjikar 	 * Pass back CONNECT_ESTABLISHED event to consumer.
1804c39526b7SPramod Gunjikar 	 */
1805c39526b7SPramod Gunjikar 	*event = RDMA_CM_EVENT_ESTABLISHED;
1806c39526b7SPramod Gunjikar 	event_ibchanp = &event_chanp->chan_ib;
1807c39526b7SPramod Gunjikar 	event_ibchanp->chan_qpmodifyflag  = 1;
1808c39526b7SPramod Gunjikar 
1809c39526b7SPramod Gunjikar 	*evt_status = 0;
1810c39526b7SPramod Gunjikar 	return (IBT_CM_DEFAULT);
1811c39526b7SPramod Gunjikar }
1812c39526b7SPramod Gunjikar 
1813c39526b7SPramod Gunjikar static ibt_cm_status_t
ibcma_handle_closed(struct rdma_cm_id * idp,struct rdma_cm_id ** event_id_ptr,ibt_cm_event_t * eventp,enum rdma_cm_event_type * event,int * evt_status)1814c39526b7SPramod Gunjikar ibcma_handle_closed(struct rdma_cm_id *idp, struct rdma_cm_id **event_id_ptr,
1815c39526b7SPramod Gunjikar     ibt_cm_event_t *eventp, enum rdma_cm_event_type *event, int *evt_status)
1816c39526b7SPramod Gunjikar {
1817c39526b7SPramod Gunjikar 	struct rdma_cm_id	*root_idp, *event_idp;
1818c0dd49bdSEiji Ota 	sol_cma_chan_t		*chanp, *root_chanp, *event_chanp;
1819c39526b7SPramod Gunjikar 
1820c39526b7SPramod Gunjikar 	*event = RDMA_CM_EVENT_DISCONNECTED;
1821c39526b7SPramod Gunjikar 	*evt_status = 0;
1822c39526b7SPramod Gunjikar 	chanp = (sol_cma_chan_t *)idp;
1823c39526b7SPramod Gunjikar 	mutex_enter(&chanp->chan_mutex);
1824c39526b7SPramod Gunjikar 	root_idp = CHAN_LISTEN_ROOT((chanp));
1825c0dd49bdSEiji Ota 	root_chanp = (sol_cma_chan_t *)root_idp;
1826c39526b7SPramod Gunjikar 	chanp->chan_qp_hdl = NULL;
1827c39526b7SPramod Gunjikar 	if (!root_idp) {
1828c0dd49bdSEiji Ota 		chanp->chan_cmid_destroy_state |=
1829c0dd49bdSEiji Ota 		    SOL_CMA_CALLER_EVENT_PROGRESS;
1830fffafeb2SJohnny Cheung 		chanp->chan_qp_hdl = NULL;
1831fffafeb2SJohnny Cheung 		chanp->chan_connect_flag = SOL_CMA_CONNECT_CLIENT_NONE;
1832c39526b7SPramod Gunjikar 		mutex_exit(&chanp->chan_mutex);
1833c0dd49bdSEiji Ota 		*event_id_ptr = idp;
1834c39526b7SPramod Gunjikar 		return (IBT_CM_DEFAULT);
1835c39526b7SPramod Gunjikar 	}
1836c39526b7SPramod Gunjikar 	mutex_exit(&chanp->chan_mutex);
1837c39526b7SPramod Gunjikar 
1838c39526b7SPramod Gunjikar 	/* On the passive side, search ACPT AVL Tree */
1839c0dd49bdSEiji Ota 	mutex_enter(&root_chanp->chan_mutex);
1840c39526b7SPramod Gunjikar 	event_idp = cma_get_acpt_idp(root_idp, eventp->cm_channel);
1841c0dd49bdSEiji Ota 	event_chanp = (sol_cma_chan_t *)event_idp;
1842c39526b7SPramod Gunjikar 	if (event_idp == NULL) {
1843c0dd49bdSEiji Ota 		mutex_exit(&root_chanp->chan_mutex);
1844c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
1845c39526b7SPramod Gunjikar 		    "ibcma_handle_closed: "
1846c39526b7SPramod Gunjikar 		    "No matching CMID for qp hdl %p in EST AVL of CMID %p",
1847c39526b7SPramod Gunjikar 		    eventp->cm_channel, root_idp);
1848c39526b7SPramod Gunjikar 		return (IBT_CM_DEFAULT);
1849c39526b7SPramod Gunjikar 	}
1850c0dd49bdSEiji Ota 	avl_remove(&root_chanp->chan_acpt_avl_tree, event_idp);
1851c0dd49bdSEiji Ota 	mutex_exit(&root_chanp->chan_mutex);
1852c39526b7SPramod Gunjikar 	mutex_enter(&event_chanp->chan_mutex);
1853fffafeb2SJohnny Cheung 	event_chanp->chan_req_state = REQ_CMID_SERVER_NONE;
1854c0dd49bdSEiji Ota 	event_chanp->chan_cmid_destroy_state |=
1855c0dd49bdSEiji Ota 	    SOL_CMA_CALLER_EVENT_PROGRESS;
1856c39526b7SPramod Gunjikar 	mutex_exit(&event_chanp->chan_mutex);
1857c0dd49bdSEiji Ota 
1858c39526b7SPramod Gunjikar 	*event_id_ptr = event_idp;
1859c39526b7SPramod Gunjikar 	return (IBT_CM_DEFAULT);
1860c39526b7SPramod Gunjikar }
1861c39526b7SPramod Gunjikar 
1862c39526b7SPramod Gunjikar static ibt_cm_status_t
ibcma_handle_failed(struct rdma_cm_id * idp,struct rdma_cm_id ** event_id_ptr,ibt_cm_event_t * eventp,struct rdma_conn_param * paramp,enum rdma_cm_event_type * event,int * evt_status)1863c39526b7SPramod Gunjikar ibcma_handle_failed(struct rdma_cm_id *idp, struct rdma_cm_id **event_id_ptr,
1864c39526b7SPramod Gunjikar     ibt_cm_event_t *eventp, struct rdma_conn_param *paramp,
1865c39526b7SPramod Gunjikar     enum rdma_cm_event_type *event, int *evt_status)
1866c39526b7SPramod Gunjikar {
1867c39526b7SPramod Gunjikar 	struct rdma_cm_id	*root_idp, *event_idp;
1868c39526b7SPramod Gunjikar 	sol_cma_chan_t		*event_chanp, *chanp, *root_chanp;
1869c39526b7SPramod Gunjikar 	ibt_cm_conn_failed_t	*failedp;
1870c39526b7SPramod Gunjikar 
1871c39526b7SPramod Gunjikar 	failedp = &(eventp->cm_event.failed);
1872c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "ibcma_handle_failed - idp %p, "
1873c39526b7SPramod Gunjikar 	    "cf_code %x, cf_msg %x, cf_arej_info_valid %x, cf_reason %x",
1874c39526b7SPramod Gunjikar 	    idp, failedp->cf_code, failedp->cf_msg,
1875c39526b7SPramod Gunjikar 	    failedp->cf_arej_info_valid, failedp->cf_reason);
1876c39526b7SPramod Gunjikar 	chanp = (sol_cma_chan_t *)idp;
1877c39526b7SPramod Gunjikar 	root_idp = CHAN_LISTEN_ROOT((chanp));
1878c39526b7SPramod Gunjikar 	root_chanp = (sol_cma_chan_t *)root_idp;
1879c39526b7SPramod Gunjikar 
1880c39526b7SPramod Gunjikar 	*evt_status = 0;
1881c39526b7SPramod Gunjikar 	switch (failedp->cf_code) {
1882c39526b7SPramod Gunjikar 	case IBT_CM_FAILURE_REJ_SENT :
1883c39526b7SPramod Gunjikar 		/*  Reject sent. No event to userland. */
1884c39526b7SPramod Gunjikar 		break;
1885c39526b7SPramod Gunjikar 
1886c39526b7SPramod Gunjikar 	case IBT_CM_FAILURE_REJ_RCV :
1887c39526b7SPramod Gunjikar 		/*
1888c39526b7SPramod Gunjikar 		 * Reject recieved. If this is a consumer reject, copy the
1889c39526b7SPramod Gunjikar 		 * private * data. Send RDMA_CM_EVENT_REJECTED to user land.
1890c39526b7SPramod Gunjikar 		 */
1891c39526b7SPramod Gunjikar 		if (failedp->cf_reason == IBT_CM_CONSUMER &&
1892c39526b7SPramod Gunjikar 		    eventp->cm_priv_data_len) {
1893c39526b7SPramod Gunjikar 			paramp->private_data_len = eventp->cm_priv_data_len;
1894c39526b7SPramod Gunjikar 			paramp->private_data = kmem_zalloc(
1895c39526b7SPramod Gunjikar 			    paramp->private_data_len, KM_SLEEP);
1896c39526b7SPramod Gunjikar 			bcopy(eventp->cm_priv_data,
1897c39526b7SPramod Gunjikar 			    (void *)paramp->private_data,
1898c39526b7SPramod Gunjikar 			    paramp->private_data_len);
1899c39526b7SPramod Gunjikar 		}
1900c39526b7SPramod Gunjikar 
1901c39526b7SPramod Gunjikar 		/*
1902c39526b7SPramod Gunjikar 		 * If this an REJECT for an accepted CMID, pass the
1903c39526b7SPramod Gunjikar 		 * event to accepted CMID.
1904c39526b7SPramod Gunjikar 		 */
1905c39526b7SPramod Gunjikar 		if (root_idp) {
1906c0dd49bdSEiji Ota 			sol_cma_chan_t	*root_chanp;
1907c39526b7SPramod Gunjikar 			ASSERT(eventp->cm_channel);
1908c0dd49bdSEiji Ota 
1909c0dd49bdSEiji Ota 			root_chanp = (sol_cma_chan_t *)root_idp;
1910c0dd49bdSEiji Ota 			mutex_enter(&root_chanp->chan_mutex);
1911c39526b7SPramod Gunjikar 			event_idp = cma_get_acpt_idp(root_idp,
1912c39526b7SPramod Gunjikar 			    eventp->cm_channel);
1913c39526b7SPramod Gunjikar 			if (event_idp == NULL) {
1914fffafeb2SJohnny Cheung 				SOL_OFS_DPRINTF_L3(sol_rdmacm_dbg_str,
1915c39526b7SPramod Gunjikar 				    "ibcma_handle_failed: No matching CMID "
1916c39526b7SPramod Gunjikar 				    "for qp_hdl %p in ACPT AVL of CMID %p",
1917c39526b7SPramod Gunjikar 				    eventp->cm_channel, idp);
1918fffafeb2SJohnny Cheung 				mutex_exit(&root_chanp->chan_mutex);
1919c39526b7SPramod Gunjikar 				break;
1920c39526b7SPramod Gunjikar 			}
1921c39526b7SPramod Gunjikar 
1922c39526b7SPramod Gunjikar 			event_chanp = (sol_cma_chan_t *)event_idp;
1923fffafeb2SJohnny Cheung 			*event_id_ptr = event_idp;
1924c39526b7SPramod Gunjikar 			mutex_enter(&event_chanp->chan_mutex);
1925fffafeb2SJohnny Cheung 			avl_remove(&root_chanp->chan_acpt_avl_tree,
1926fffafeb2SJohnny Cheung 			    event_idp);
1927fffafeb2SJohnny Cheung 			event_chanp->chan_req_state = REQ_CMID_SERVER_NONE;
1928c0dd49bdSEiji Ota 			event_chanp->chan_cmid_destroy_state |=
1929c0dd49bdSEiji Ota 			    SOL_CMA_CALLER_EVENT_PROGRESS;
1930c39526b7SPramod Gunjikar 			event_chanp->chan_qp_hdl = NULL;
1931c39526b7SPramod Gunjikar 			mutex_exit(&event_chanp->chan_mutex);
1932c39526b7SPramod Gunjikar 			mutex_exit(&root_chanp->chan_mutex);
1933c0dd49bdSEiji Ota 		} else {
1934c0dd49bdSEiji Ota 			mutex_enter(&chanp->chan_mutex);
1935c0dd49bdSEiji Ota 			chanp->chan_cmid_destroy_state |=
1936c0dd49bdSEiji Ota 			    SOL_CMA_CALLER_EVENT_PROGRESS;
1937c0dd49bdSEiji Ota 			chanp->chan_qp_hdl = NULL;
1938fffafeb2SJohnny Cheung 			chanp->chan_connect_flag =
1939fffafeb2SJohnny Cheung 			    SOL_CMA_CONNECT_CLIENT_NONE;
1940c0dd49bdSEiji Ota 			mutex_exit(&chanp->chan_mutex);
1941c0dd49bdSEiji Ota 			*event_id_ptr  = idp;
1942c0dd49bdSEiji Ota 		}
1943c39526b7SPramod Gunjikar 		*evt_status = failedp->cf_reason;
1944c39526b7SPramod Gunjikar 		*event = RDMA_CM_EVENT_REJECTED;
1945c39526b7SPramod Gunjikar 		break;
1946c39526b7SPramod Gunjikar 
1947c39526b7SPramod Gunjikar 	case IBT_CM_FAILURE_TIMEOUT :
1948c39526b7SPramod Gunjikar 		/*
1949c39526b7SPramod Gunjikar 		 * Connection Timeout, Send RDMA_CM_EVENT_REJECTED event and
1950c39526b7SPramod Gunjikar 		 * status as IBT_CM_TIMEOUT.
1951c39526b7SPramod Gunjikar 		 */
1952c39526b7SPramod Gunjikar 		if (eventp->cm_session_id && root_idp) {
1953fffafeb2SJohnny Cheung 			mutex_enter(&root_chanp->chan_mutex);
1954c39526b7SPramod Gunjikar 			event_idp = cma_get_req_idp(root_idp,
1955c39526b7SPramod Gunjikar 			    eventp->cm_session_id);
1956c39526b7SPramod Gunjikar 			if (event_idp == NULL) {
1957fffafeb2SJohnny Cheung 				mutex_exit(&root_chanp->chan_mutex);
1958fffafeb2SJohnny Cheung 				SOL_OFS_DPRINTF_L3(sol_rdmacm_dbg_str,
1959c39526b7SPramod Gunjikar 				    "ibcma_handle_failed: No matching CMID "
1960c39526b7SPramod Gunjikar 				    "for qp_hdl %p in REQ AVL of CMID %p",
1961c39526b7SPramod Gunjikar 				    eventp->cm_session_id, idp);
1962c39526b7SPramod Gunjikar 				break;
1963c39526b7SPramod Gunjikar 			}
1964c39526b7SPramod Gunjikar 
1965c39526b7SPramod Gunjikar 			event_chanp = (sol_cma_chan_t *)event_idp;
1966c39526b7SPramod Gunjikar 			mutex_enter(&event_chanp->chan_mutex);
1967c39526b7SPramod Gunjikar 			*event_id_ptr = event_idp;
1968c39526b7SPramod Gunjikar 			avl_remove(&root_chanp->chan_req_avl_tree,
1969c39526b7SPramod Gunjikar 			    event_idp);
1970c39526b7SPramod Gunjikar 			root_chanp->chan_req_cnt--;
1971fffafeb2SJohnny Cheung 			event_chanp->chan_req_state = REQ_CMID_SERVER_NONE;
1972fffafeb2SJohnny Cheung 			event_chanp->chan_qp_hdl = NULL;
1973fffafeb2SJohnny Cheung 			mutex_exit(&event_chanp->chan_mutex);
1974c39526b7SPramod Gunjikar 			mutex_exit(&root_chanp->chan_mutex);
1975c39526b7SPramod Gunjikar 
1976fffafeb2SJohnny Cheung 
1977c39526b7SPramod Gunjikar 			*evt_status = IBT_CM_TIMEOUT;
1978c39526b7SPramod Gunjikar 			*event = RDMA_CM_EVENT_REJECTED;
1979c39526b7SPramod Gunjikar 		}
1980c39526b7SPramod Gunjikar 		if (!eventp->cm_session_id && root_idp) {
1981c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L0(sol_rdmacm_dbg_str,
1982c39526b7SPramod Gunjikar 			    "ibcma_handle_failed: timeout "
1983c39526b7SPramod Gunjikar 			    "session_id NULL");
1984c39526b7SPramod Gunjikar 		}
1985c39526b7SPramod Gunjikar 		if (!root_idp) {
1986c0dd49bdSEiji Ota 			*event_id_ptr  = idp;
1987c0dd49bdSEiji Ota 			mutex_enter(&chanp->chan_mutex);
1988c0dd49bdSEiji Ota 			chanp->chan_cmid_destroy_state |=
1989c0dd49bdSEiji Ota 			    SOL_CMA_CALLER_EVENT_PROGRESS;
1990c0dd49bdSEiji Ota 			chanp->chan_qp_hdl = NULL;
1991fffafeb2SJohnny Cheung 			chanp->chan_connect_flag =
1992fffafeb2SJohnny Cheung 			    SOL_CMA_CONNECT_CLIENT_NONE;
1993c0dd49bdSEiji Ota 			mutex_exit(&chanp->chan_mutex);
1994c39526b7SPramod Gunjikar 			*evt_status = IBT_CM_TIMEOUT;
1995c39526b7SPramod Gunjikar 			*event = RDMA_CM_EVENT_REJECTED;
1996c39526b7SPramod Gunjikar 		}
1997c39526b7SPramod Gunjikar 		break;
1998c39526b7SPramod Gunjikar 
1999c39526b7SPramod Gunjikar 	case IBT_CM_FAILURE_STALE :
2000c39526b7SPramod Gunjikar 		/* Stale connection, ignore */
2001c39526b7SPramod Gunjikar 		break;
2002c39526b7SPramod Gunjikar 	}
2003c39526b7SPramod Gunjikar 	return (IBT_CM_DEFAULT);
2004c39526b7SPramod Gunjikar }
2005c39526b7SPramod Gunjikar 
2006c39526b7SPramod Gunjikar static ibt_cm_status_t
ibcma_rc_hdlr(void * inp,ibt_cm_event_t * eventp,ibt_cm_return_args_t * ret_args,void * priv_data,ibt_priv_data_len_t priv_datalen)2007c39526b7SPramod Gunjikar ibcma_rc_hdlr(void *inp, ibt_cm_event_t *eventp,
2008c39526b7SPramod Gunjikar     ibt_cm_return_args_t *ret_args, void *priv_data,
2009c39526b7SPramod Gunjikar     ibt_priv_data_len_t priv_datalen)
2010c39526b7SPramod Gunjikar {
2011c39526b7SPramod Gunjikar 	struct rdma_cm_id	*idp, *event_idp;
2012c39526b7SPramod Gunjikar 	sol_cma_chan_t		*chanp;
2013c39526b7SPramod Gunjikar 	ibt_cm_status_t		status;
2014c39526b7SPramod Gunjikar 	ibt_status_t		ibt_status;
2015c39526b7SPramod Gunjikar 	enum rdma_cm_event_type event;
2016c39526b7SPramod Gunjikar 	struct rdma_conn_param	conn_param, *paramp = &conn_param;
2017c39526b7SPramod Gunjikar 	int	event_status;
2018c39526b7SPramod Gunjikar 
2019c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "ib_cma_rc_hdlr(%p, %p, %p, "
2020c39526b7SPramod Gunjikar 	    "%p, %x)", inp, eventp, ret_args, priv_data, priv_datalen);
2021c39526b7SPramod Gunjikar 	idp = event_idp = (struct rdma_cm_id *)inp;
2022c39526b7SPramod Gunjikar 	chanp = (sol_cma_chan_t *)idp;
2023c39526b7SPramod Gunjikar 	chanp->chan_session_id = NULL;
2024c39526b7SPramod Gunjikar 
2025c39526b7SPramod Gunjikar 	bzero(paramp, sizeof (struct rdma_conn_param));
2026c39526b7SPramod Gunjikar 	switch (eventp->cm_type) {
2027c39526b7SPramod Gunjikar 
2028c39526b7SPramod Gunjikar 	case IBT_CM_EVENT_REQ_RCV :
2029c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2030c39526b7SPramod Gunjikar 		    "ibcma_rc_hdlr : REQ Event");
2031c39526b7SPramod Gunjikar 
2032c39526b7SPramod Gunjikar 		/*
2033c39526b7SPramod Gunjikar 		 * We need to do a round trip to userland. Send a MRA
2034c39526b7SPramod Gunjikar 		 * so that the client does not send multiple REQs. Then
2035c39526b7SPramod Gunjikar 		 * continue the processing of REQs.
2036c39526b7SPramod Gunjikar 		 */
2037c39526b7SPramod Gunjikar 		ibt_status =  ibt_cm_delay(IBT_CM_DELAY_REQ,
2038c39526b7SPramod Gunjikar 		    eventp->cm_session_id, SOL_OFS_REQ_DELAY, NULL, 0);
2039c39526b7SPramod Gunjikar 		if (ibt_status != IBT_SUCCESS) {
2040c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
2041c39526b7SPramod Gunjikar 			    "ibcma_rc_hdlr : ibt_cma_delay failed %x",
2042c39526b7SPramod Gunjikar 			    ibt_status);
2043c39526b7SPramod Gunjikar 			return (IBT_CM_REJECT);
2044c39526b7SPramod Gunjikar 		}
2045c39526b7SPramod Gunjikar 		status = ibcma_handle_req(idp, &event_idp, eventp, paramp,
2046c39526b7SPramod Gunjikar 		    &event, &event_status);
2047c39526b7SPramod Gunjikar 		if (status == IBT_CM_REJECT)
2048c39526b7SPramod Gunjikar 			return (status);
2049c39526b7SPramod Gunjikar 		break;
2050c39526b7SPramod Gunjikar 	case IBT_CM_EVENT_REP_RCV :
2051c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2052c39526b7SPramod Gunjikar 		    "ibcma_rc_hdlr : REP Event");
2053c39526b7SPramod Gunjikar 
2054c39526b7SPramod Gunjikar 		ibcma_handle_rep(idp, eventp);
2055c39526b7SPramod Gunjikar 		return (IBT_CM_DEFAULT);
2056c39526b7SPramod Gunjikar 		/* NOTREACHED */
2057c39526b7SPramod Gunjikar 		/* break; */
2058c39526b7SPramod Gunjikar 	case IBT_CM_EVENT_LAP_RCV :
2059c39526b7SPramod Gunjikar 	case IBT_CM_EVENT_APR_RCV :
2060c39526b7SPramod Gunjikar 		/*
2061c39526b7SPramod Gunjikar 		 * Alternate Paths not supported from userland. Return
2062c39526b7SPramod Gunjikar 		 * IBT_CM_REJECT.
2063c39526b7SPramod Gunjikar 		 */
2064c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2065c39526b7SPramod Gunjikar 		    "ibcma_rc_hdlr : AP Event");
2066c39526b7SPramod Gunjikar 		return (IBT_CM_REJECT);
2067c39526b7SPramod Gunjikar 		/* NOTREACHED */
2068c39526b7SPramod Gunjikar 		/* break; */
2069c39526b7SPramod Gunjikar 	case IBT_CM_EVENT_MRA_RCV :
2070c39526b7SPramod Gunjikar 		/* Let Solaris ibcm take default action for MRA */
2071c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2072c39526b7SPramod Gunjikar 		    "ibcma_rc_hdlr : MRA Event");
2073c39526b7SPramod Gunjikar 		return (IBT_CM_DEFAULT);
2074c39526b7SPramod Gunjikar 		/* NOTREACHED */
2075c39526b7SPramod Gunjikar 		/* break; */
2076c39526b7SPramod Gunjikar 	case IBT_CM_EVENT_CONN_EST :
2077c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2078c39526b7SPramod Gunjikar 		    "ibcma_rc_hdlr : EST Event");
2079c39526b7SPramod Gunjikar 		status = ibcma_handle_est(idp, &event_idp, eventp, paramp,
2080c39526b7SPramod Gunjikar 		    &event, &event_status);
2081c39526b7SPramod Gunjikar 		break;
2082c39526b7SPramod Gunjikar 	case IBT_CM_EVENT_CONN_CLOSED :
2083c39526b7SPramod Gunjikar 		/*
2084c39526b7SPramod Gunjikar 		 * Pass on RDMA_CM_EVENT_DISCONNECTED to consumer
2085c39526b7SPramod Gunjikar 		 */
2086c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2087c39526b7SPramod Gunjikar 		    "ibcma_rc_hdlr : CLOSED Event");
2088c39526b7SPramod Gunjikar 		status = ibcma_handle_closed(idp, &event_idp, eventp,
2089c39526b7SPramod Gunjikar 		    &event, &event_status);
2090c39526b7SPramod Gunjikar 		break;
2091c39526b7SPramod Gunjikar 
2092c39526b7SPramod Gunjikar 	case IBT_CM_EVENT_FAILURE :
2093c39526b7SPramod Gunjikar 		/* Handle Failure Event */
2094c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2095c39526b7SPramod Gunjikar 		    "ibcma_rc_hdlr : FAIL Event");
2096c39526b7SPramod Gunjikar 		status = ibcma_handle_failed(idp, &event_idp, eventp, paramp,
2097c39526b7SPramod Gunjikar 		    &event, &event_status);
2098c39526b7SPramod Gunjikar 
2099c39526b7SPramod Gunjikar 		/*
2100c39526b7SPramod Gunjikar 		 * Check if there is an event to be send to the userland.
2101c39526b7SPramod Gunjikar 		 * Return if there are none.
2102c39526b7SPramod Gunjikar 		 */
2103c39526b7SPramod Gunjikar 		if (event_status == 0)
2104c39526b7SPramod Gunjikar 			return (status);
2105c39526b7SPramod Gunjikar 		break;
2106c39526b7SPramod Gunjikar 	}
2107c39526b7SPramod Gunjikar 
2108c39526b7SPramod Gunjikar 	/* Pass back the event to sol_cma consumer */
2109c39526b7SPramod Gunjikar 	if (event_idp) {
2110c39526b7SPramod Gunjikar 		cma_generate_event(event_idp, event, event_status,
2111c39526b7SPramod Gunjikar 		    paramp, NULL);
2112c39526b7SPramod Gunjikar 	} else
2113c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
2114c39526b7SPramod Gunjikar 		    "No Event to userland!!");
2115c39526b7SPramod Gunjikar 	if (paramp->private_data)
2116c39526b7SPramod Gunjikar 		kmem_free((void *)paramp->private_data,
2117c39526b7SPramod Gunjikar 		    paramp->private_data_len);
2118c39526b7SPramod Gunjikar 
2119c39526b7SPramod Gunjikar 	return (status);
2120c39526b7SPramod Gunjikar }
2121c39526b7SPramod Gunjikar 
2122c39526b7SPramod Gunjikar static void
ibcma_multicast_hdlr(void * arg,ibt_status_t status,ibt_mcg_info_t * mcg_infop)2123c39526b7SPramod Gunjikar ibcma_multicast_hdlr(void *arg, ibt_status_t status, ibt_mcg_info_t *mcg_infop)
2124c39526b7SPramod Gunjikar {
2125c39526b7SPramod Gunjikar 	struct rdma_cm_id	*idp;
2126c39526b7SPramod Gunjikar 	ibcma_mcast_t		*ib_mcastp = (ibcma_mcast_t *)arg;
2127c39526b7SPramod Gunjikar 	int			evt_status;
2128c39526b7SPramod Gunjikar 	struct rdma_ud_param	uddata, *ud_param = &uddata;
2129c39526b7SPramod Gunjikar 	enum rdma_cm_event_type event;
2130c39526b7SPramod Gunjikar 
2131c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "multicast_hdlr(%p, %x, %p)",
2132c39526b7SPramod Gunjikar 	    arg, status, mcg_infop);
2133c39526b7SPramod Gunjikar 	idp = ib_mcastp->mcast_idp;
2134c39526b7SPramod Gunjikar 
2135c39526b7SPramod Gunjikar 	bzero(ud_param, sizeof (struct rdma_ud_param));
2136c39526b7SPramod Gunjikar 	bcopy(&(mcg_infop->mc_adds_vect.av_dgid),
2137c39526b7SPramod Gunjikar 	    &(ib_mcastp->mcast_gid), sizeof (ib_gid_t));
2138c39526b7SPramod Gunjikar 	ud_param->private_data = ib_mcastp->mcast_ctx;
2139c39526b7SPramod Gunjikar 
2140c39526b7SPramod Gunjikar 	event = (status == IBT_SUCCESS) ?
2141c39526b7SPramod Gunjikar 	    RDMA_CM_EVENT_MULTICAST_JOIN : RDMA_CM_EVENT_MULTICAST_ERROR;
2142c39526b7SPramod Gunjikar 	evt_status = (status == IBT_SUCCESS) ? 0 : -1;
2143c39526b7SPramod Gunjikar 	if (status == IBT_SUCCESS) {
2144c39526b7SPramod Gunjikar 		mcginfo2ah(mcg_infop, &ud_param->ah_attr);
2145c39526b7SPramod Gunjikar 		ud_param->qp_num = IB_MC_QPN;
2146fffafeb2SJohnny Cheung 		if (idp->ps == RDMA_PS_UDP)
2147fffafeb2SJohnny Cheung 			ud_param->qkey = RDMA_UDP_QKEY;
2148fffafeb2SJohnny Cheung 		else
2149fffafeb2SJohnny Cheung 			ud_param->qkey = SOL_IPOIB_DEFAULT_QKEY;
2150c39526b7SPramod Gunjikar 	}
2151c39526b7SPramod Gunjikar 
2152c39526b7SPramod Gunjikar 	/* Send the event to consumer of sol_cma.  */
2153c39526b7SPramod Gunjikar 	cma_generate_event(idp, event, evt_status, NULL, ud_param);
2154c39526b7SPramod Gunjikar 	kmem_free(mcg_infop, sizeof (ibt_mcg_info_t));
2155c39526b7SPramod Gunjikar }
2156c39526b7SPramod Gunjikar 
2157c39526b7SPramod Gunjikar static int
ibcma_get_first_ib_ipaddr(struct rdma_cm_id * idp)2158c39526b7SPramod Gunjikar ibcma_get_first_ib_ipaddr(struct rdma_cm_id *idp)
2159c39526b7SPramod Gunjikar {
2160c39526b7SPramod Gunjikar 	sol_cma_chan_t	*chanp = (sol_cma_chan_t *)idp;
2161c39526b7SPramod Gunjikar 	ibcma_chan_t	*ibchanp;
2162c39526b7SPramod Gunjikar 	int		num_hcas, info_inited = 0;
2163c39526b7SPramod Gunjikar 	ib_guid_t	*hca_guidp;
2164c39526b7SPramod Gunjikar 	genlist_t	devlist;
2165c39526b7SPramod Gunjikar 	genlist_entry_t	*entry;
2166c39526b7SPramod Gunjikar 	ibcma_dev_t	*devp;
2167c39526b7SPramod Gunjikar 
2168c39526b7SPramod Gunjikar 	ASSERT(idp);
2169c39526b7SPramod Gunjikar 	ibchanp = &(chanp->chan_ib);
2170c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "get_first_ib_ipaddr(%p)", idp);
2171c39526b7SPramod Gunjikar 
2172c39526b7SPramod Gunjikar 	num_hcas = ibt_get_hca_list(&hca_guidp);
2173a3077325SPramod Gunjikar 	ibcma_get_devlist(chanp, hca_guidp, num_hcas, &devlist, B_TRUE);
2174c39526b7SPramod Gunjikar 	entry = remove_genlist_head(&devlist);
2175c39526b7SPramod Gunjikar 	while (entry) {
2176c39526b7SPramod Gunjikar 		devp = (ibcma_dev_t *)entry->data;
2177c39526b7SPramod Gunjikar 		if (info_inited == 0) {
2178c39526b7SPramod Gunjikar 			(idp->route).num_paths = 0;
2179c39526b7SPramod Gunjikar 			idp->port_num = devp->dev_port_num;
2180c39526b7SPramod Gunjikar 			chanp->chan_xport_type = SOL_CMA_XPORT_IB;
2181c39526b7SPramod Gunjikar 			ibchanp->chan_devp = devp;
2182c39526b7SPramod Gunjikar 			info_inited = 1;
2183c39526b7SPramod Gunjikar 		} else {
2184c39526b7SPramod Gunjikar 			kmem_free(devp, sizeof (ibcma_dev_t));
2185c39526b7SPramod Gunjikar 		}
2186c39526b7SPramod Gunjikar 		kmem_free(entry, sizeof (genlist_entry_t));
2187c39526b7SPramod Gunjikar 		entry = remove_genlist_head(&devlist);
2188c39526b7SPramod Gunjikar 	}
2189c39526b7SPramod Gunjikar 	ibt_free_hca_list(hca_guidp, num_hcas);
2190c39526b7SPramod Gunjikar 
2191c39526b7SPramod Gunjikar 	if (info_inited)
2192c39526b7SPramod Gunjikar 		return (0);
2193c39526b7SPramod Gunjikar 	else
2194c39526b7SPramod Gunjikar 		return (ENODEV);
2195c39526b7SPramod Gunjikar }
2196c39526b7SPramod Gunjikar 
2197c39526b7SPramod Gunjikar /* Utility Conversion functions */
2198c39526b7SPramod Gunjikar static void
ipaddr2sockaddr(ibt_ip_addr_t * ibt_addrp,struct sockaddr * sock_addrp,in_port_t * portp)2199c39526b7SPramod Gunjikar ipaddr2sockaddr(ibt_ip_addr_t *ibt_addrp, struct sockaddr *sock_addrp,
2200c39526b7SPramod Gunjikar     in_port_t *portp)
2201c39526b7SPramod Gunjikar {
2202c39526b7SPramod Gunjikar 		sock_addrp->sa_family = ibt_addrp->family;
2203c39526b7SPramod Gunjikar 		if (ibt_addrp->family == AF_INET) {
2204c39526b7SPramod Gunjikar 			struct sockaddr_in	*sock_in4p;
2205c39526b7SPramod Gunjikar 			sock_in4p = (struct sockaddr_in *)sock_addrp;
2206c39526b7SPramod Gunjikar 
2207c39526b7SPramod Gunjikar 			sock_in4p->sin_addr.s_addr = ibt_addrp->un.ip4addr;
2208c39526b7SPramod Gunjikar 			if (portp)
2209c39526b7SPramod Gunjikar 				sock_in4p->sin_port = ntohs(*portp);
2210c39526b7SPramod Gunjikar 		} else {
2211c39526b7SPramod Gunjikar 			struct sockaddr_in6 *in6_addr;
2212c39526b7SPramod Gunjikar 			in6_addr = (struct sockaddr_in6 *)sock_addrp;
2213c39526b7SPramod Gunjikar 
2214c39526b7SPramod Gunjikar 			bcopy(&(ibt_addrp->un.ip6addr), &(in6_addr->sin6_addr),
2215c39526b7SPramod Gunjikar 			    sizeof (in6_addr_t));
2216c39526b7SPramod Gunjikar 			if (portp)
2217c39526b7SPramod Gunjikar 				in6_addr->sin6_port = *portp;
2218c39526b7SPramod Gunjikar 		}
2219c39526b7SPramod Gunjikar }
2220c39526b7SPramod Gunjikar 
2221c39526b7SPramod Gunjikar static void
sockaddr2ibtaddr_port(struct rdma_cm_id * idp,struct sockaddr * sock_addrp,ibt_ip_addr_t * ibt_addrp,in_port_t * portp)2222c39526b7SPramod Gunjikar sockaddr2ibtaddr_port(struct rdma_cm_id *idp, struct sockaddr *sock_addrp,
2223c39526b7SPramod Gunjikar     ibt_ip_addr_t *ibt_addrp, in_port_t *portp)
2224c39526b7SPramod Gunjikar {
2225c39526b7SPramod Gunjikar 	in_port_t	ip_port;
2226c39526b7SPramod Gunjikar 
2227c39526b7SPramod Gunjikar 	ibt_addrp->family = sock_addrp->sa_family;
2228c39526b7SPramod Gunjikar 	if (sock_addrp->sa_family == AF_INET) {
2229c39526b7SPramod Gunjikar 		struct sockaddr_in	*sock_in4p;
2230c39526b7SPramod Gunjikar 		sock_in4p = (struct sockaddr_in *)sock_addrp;
2231c39526b7SPramod Gunjikar 
2232c39526b7SPramod Gunjikar 		ibt_addrp->un.ip4addr = sock_in4p->sin_addr.s_addr;
2233c39526b7SPramod Gunjikar 		if (IS_UDP_CMID(idp))
2234c39526b7SPramod Gunjikar 			ip_port = ddi_swap16(sock_in4p->sin_port);
2235c39526b7SPramod Gunjikar 		else
2236c39526b7SPramod Gunjikar 			ip_port = htons(sock_in4p->sin_port);
2237c39526b7SPramod Gunjikar 
2238c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "sockaddr2ibtaddr : "
2239c39526b7SPramod Gunjikar 		    "AF_INET addr %x, port %x, %x", ibt_addrp->un.ip4addr,
2240c39526b7SPramod Gunjikar 		    sock_in4p->sin_port, ip_port);
2241c39526b7SPramod Gunjikar 
2242c39526b7SPramod Gunjikar 		if (portp)
2243c39526b7SPramod Gunjikar 			*portp = ip_port;
2244c39526b7SPramod Gunjikar 
2245c39526b7SPramod Gunjikar 	} else {
2246c39526b7SPramod Gunjikar 		struct sockaddr_in6	*in6_addr;
2247c39526b7SPramod Gunjikar 		in6_addr = (struct sockaddr_in6 *)sock_addrp;
2248c39526b7SPramod Gunjikar 		bcopy(&(in6_addr->sin6_addr), &(ibt_addrp->un.ip6addr),
2249c39526b7SPramod Gunjikar 		    sizeof (in6_addr_t));
2250c39526b7SPramod Gunjikar 		if (portp)
2251c39526b7SPramod Gunjikar 			*portp = in6_addr->sin6_port;
2252c39526b7SPramod Gunjikar 	}
2253c39526b7SPramod Gunjikar }
2254c39526b7SPramod Gunjikar 
2255c39526b7SPramod Gunjikar static void
mcginfo2ah(ibt_mcg_info_t * mcgp,struct ib_ah_attr * ah_attr)2256c39526b7SPramod Gunjikar mcginfo2ah(ibt_mcg_info_t *mcgp, struct ib_ah_attr *ah_attr)
2257c39526b7SPramod Gunjikar {
2258c39526b7SPramod Gunjikar 	ibt_adds_vect_t	*adds_vectp;
2259c39526b7SPramod Gunjikar 	ib_gid_t	dgid_nworder;
2260c39526b7SPramod Gunjikar 
2261c39526b7SPramod Gunjikar 	adds_vectp = &(mcgp->mc_adds_vect);
2262c39526b7SPramod Gunjikar 
2263c39526b7SPramod Gunjikar 	/*
2264c39526b7SPramod Gunjikar 	 * Libraries expect the GID to be in network order. Convert
2265c39526b7SPramod Gunjikar 	 * to network order before passing it to the library.
2266c39526b7SPramod Gunjikar 	 */
2267c39526b7SPramod Gunjikar 	dgid_nworder.gid_prefix = htonll(
2268c39526b7SPramod Gunjikar 	    (adds_vectp->av_dgid).gid_prefix);
2269c39526b7SPramod Gunjikar 	dgid_nworder.gid_guid = htonll(
2270c39526b7SPramod Gunjikar 	    (adds_vectp->av_dgid).gid_guid);
2271c39526b7SPramod Gunjikar 	bcopy(&dgid_nworder, &((ah_attr->grh).dgid), sizeof (ib_gid_t));
2272c39526b7SPramod Gunjikar 
2273c39526b7SPramod Gunjikar 	(ah_attr->grh).flow_label =  adds_vectp->av_flow;
2274c39526b7SPramod Gunjikar 	(ah_attr->grh).sgid_index = adds_vectp->av_sgid_ix;
2275c39526b7SPramod Gunjikar 	(ah_attr->grh).hop_limit = adds_vectp->av_hop;
2276c39526b7SPramod Gunjikar 	(ah_attr->grh).traffic_class = adds_vectp->av_tclass;
2277c39526b7SPramod Gunjikar 
2278c39526b7SPramod Gunjikar 	ah_attr->dlid = adds_vectp->av_dlid;
2279c39526b7SPramod Gunjikar 	ah_attr->sl = adds_vectp->av_srvl;
2280c39526b7SPramod Gunjikar 	ah_attr->src_path_bits = adds_vectp->av_src_path;
2281c39526b7SPramod Gunjikar 	ah_attr->static_rate = adds_vectp->av_srate;
2282c39526b7SPramod Gunjikar 	ah_attr->ah_flags = (adds_vectp->av_send_grh) ? 1 : 0;
2283c39526b7SPramod Gunjikar 	ah_attr->port_num = adds_vectp->av_port_num;
2284c39526b7SPramod Gunjikar }
2285c39526b7SPramod Gunjikar 
2286c39526b7SPramod Gunjikar static void
ibt_path2ah(ibt_path_info_t * pathp,struct ib_ah_attr * ah_attr)2287c39526b7SPramod Gunjikar ibt_path2ah(ibt_path_info_t *pathp, struct ib_ah_attr *ah_attr)
2288c39526b7SPramod Gunjikar {
2289c39526b7SPramod Gunjikar 
2290c39526b7SPramod Gunjikar 	ibt_addsvect2ah(&((pathp->pi_prim_cep_path).cep_adds_vect), ah_attr);
2291c39526b7SPramod Gunjikar }
2292c39526b7SPramod Gunjikar 
2293c39526b7SPramod Gunjikar static void
ibt_addsvect2ah(ibt_adds_vect_t * adds_vectp,struct ib_ah_attr * ah_attr)2294c39526b7SPramod Gunjikar ibt_addsvect2ah(ibt_adds_vect_t *adds_vectp, struct ib_ah_attr *ah_attr)
2295c39526b7SPramod Gunjikar {
2296c39526b7SPramod Gunjikar 	ib_gid_t	dgid_nworder;
2297c39526b7SPramod Gunjikar 
2298c39526b7SPramod Gunjikar 	/*
2299c39526b7SPramod Gunjikar 	 * Libraries expect the GID to be in network order. Convert
2300c39526b7SPramod Gunjikar 	 * to network order before passing it to the library.
2301c39526b7SPramod Gunjikar 	 */
2302c39526b7SPramod Gunjikar 	dgid_nworder.gid_prefix = htonll(
2303c39526b7SPramod Gunjikar 	    (adds_vectp->av_dgid).gid_prefix);
2304c39526b7SPramod Gunjikar 	dgid_nworder.gid_guid = htonll(
2305c39526b7SPramod Gunjikar 	    (adds_vectp->av_dgid).gid_guid);
2306c39526b7SPramod Gunjikar 	bcopy(&dgid_nworder, &((ah_attr->grh).dgid), sizeof (ib_gid_t));
2307c39526b7SPramod Gunjikar 	(ah_attr->grh).flow_label =  adds_vectp->av_flow;
2308c39526b7SPramod Gunjikar 	(ah_attr->grh).sgid_index = adds_vectp->av_sgid_ix;
2309c39526b7SPramod Gunjikar 	(ah_attr->grh).hop_limit = adds_vectp->av_hop;
2310c39526b7SPramod Gunjikar 	(ah_attr->grh).traffic_class = adds_vectp->av_tclass;
2311c39526b7SPramod Gunjikar 
2312c39526b7SPramod Gunjikar 	ah_attr->dlid = adds_vectp->av_dlid;
2313c39526b7SPramod Gunjikar 	ah_attr->sl = adds_vectp->av_srvl;
2314c39526b7SPramod Gunjikar 	ah_attr->src_path_bits = adds_vectp->av_src_path;
2315c39526b7SPramod Gunjikar 	ah_attr->static_rate = adds_vectp->av_srate;
2316c39526b7SPramod Gunjikar 	ah_attr->ah_flags = (adds_vectp->av_send_grh) ? 1 : 0;
2317c39526b7SPramod Gunjikar 	ah_attr->port_num = adds_vectp->av_port_num;
2318c39526b7SPramod Gunjikar }
2319c39526b7SPramod Gunjikar 
2320c39526b7SPramod Gunjikar static void
ibt_path2sa_path(ibt_path_info_t * pathp,struct ib_sa_path_rec * sa_pathp,ib_lid_t base_lid)2321c39526b7SPramod Gunjikar ibt_path2sa_path(ibt_path_info_t *pathp, struct ib_sa_path_rec *sa_pathp,
2322c39526b7SPramod Gunjikar     ib_lid_t base_lid)
2323c39526b7SPramod Gunjikar {
2324c39526b7SPramod Gunjikar 	ibt_adds_vect_t	*adds_vectp;
2325c39526b7SPramod Gunjikar 
2326c39526b7SPramod Gunjikar 	adds_vectp = &((pathp->pi_prim_cep_path).cep_adds_vect);
2327c39526b7SPramod Gunjikar 	ibt_addsvect2sa_path(adds_vectp, sa_pathp, base_lid);
2328c39526b7SPramod Gunjikar 	sa_pathp->mtu = pathp->pi_path_mtu;
2329c39526b7SPramod Gunjikar 	sa_pathp->packet_life_time = pathp->pi_prim_pkt_lt;
2330c39526b7SPramod Gunjikar }
2331c39526b7SPramod Gunjikar 
2332c39526b7SPramod Gunjikar static void
ibt_addsvect2sa_path(ibt_adds_vect_t * adds_vectp,struct ib_sa_path_rec * sa_pathp,ib_lid_t base_lid)2333c39526b7SPramod Gunjikar ibt_addsvect2sa_path(ibt_adds_vect_t *adds_vectp,
2334c39526b7SPramod Gunjikar     struct ib_sa_path_rec *sa_pathp, ib_lid_t base_lid)
2335c39526b7SPramod Gunjikar {
2336c39526b7SPramod Gunjikar 	bcopy(&(adds_vectp->av_dgid), &(sa_pathp->dgid), 16);
2337c39526b7SPramod Gunjikar 	bcopy(&(adds_vectp->av_sgid), &(sa_pathp->sgid), 16);
2338c39526b7SPramod Gunjikar 	sa_pathp->dlid = adds_vectp->av_dlid;
2339c39526b7SPramod Gunjikar 	sa_pathp->slid = base_lid + adds_vectp->av_src_path;
2340c39526b7SPramod Gunjikar 	sa_pathp->flow_label =  adds_vectp->av_flow;
2341c39526b7SPramod Gunjikar 	sa_pathp->reversible = 1;
2342c39526b7SPramod Gunjikar 	sa_pathp->hop_limit = adds_vectp->av_hop;
2343c39526b7SPramod Gunjikar 	sa_pathp->traffic_class  = adds_vectp->av_tclass;
2344c39526b7SPramod Gunjikar 	sa_pathp->sl = adds_vectp->av_srvl;
2345c39526b7SPramod Gunjikar 	sa_pathp->rate = adds_vectp->av_srate;
2346c39526b7SPramod Gunjikar 	sa_pathp->mtu_selector = IBT_EQU;
2347c39526b7SPramod Gunjikar 	sa_pathp->rate_selector = IBT_EQU;
2348c39526b7SPramod Gunjikar 	sa_pathp->packet_life_time_selector = IBT_EQU;
2349c39526b7SPramod Gunjikar }
2350c39526b7SPramod Gunjikar 
2351c39526b7SPramod Gunjikar /*
2352c39526b7SPramod Gunjikar  * Map a multicast IP onto multicast MAC for type IP-over-InfiniBand.
2353c39526b7SPramod Gunjikar  * Leave P_Key as 0 to be filled in by caller
2354c39526b7SPramod Gunjikar  */
2355c39526b7SPramod Gunjikar static void
ip_ib_mc_map(uint32_t addr,char * buf)2356c39526b7SPramod Gunjikar ip_ib_mc_map(uint32_t addr, char *buf)
2357c39526b7SPramod Gunjikar {
2358c39526b7SPramod Gunjikar 	buf[0]  = 0;		/* Reserved */
2359c39526b7SPramod Gunjikar 	buf[1]  = 0xff;		/* Multicast QPN */
2360c39526b7SPramod Gunjikar 	buf[2]  = 0xff;
2361c39526b7SPramod Gunjikar 	buf[3]  = 0xff;
2362c39526b7SPramod Gunjikar 	addr    = ntohl(addr);
2363c39526b7SPramod Gunjikar 	buf[4]  = 0xff;
2364c39526b7SPramod Gunjikar 	buf[5]  = 0x12;		/* link local scope */
2365c39526b7SPramod Gunjikar 	buf[6]  = 0x40;		/* IPv4 signature */
2366c39526b7SPramod Gunjikar 	buf[7]  = 0x1b;
2367c39526b7SPramod Gunjikar 	buf[8]  = 0;		/* P_Key */
2368c39526b7SPramod Gunjikar 	buf[9]  = 0;
2369c39526b7SPramod Gunjikar 	buf[10] = 0;
2370c39526b7SPramod Gunjikar 	buf[11] = 0;
2371c39526b7SPramod Gunjikar 	buf[12] = 0;
2372c39526b7SPramod Gunjikar 	buf[13] = 0;
2373c39526b7SPramod Gunjikar 	buf[14] = 0;
2374c39526b7SPramod Gunjikar 	buf[15] = 0;
2375c39526b7SPramod Gunjikar 	buf[19] = addr & 0xff;
2376c39526b7SPramod Gunjikar 	addr  >>= 8;
2377c39526b7SPramod Gunjikar 	buf[18] = addr & 0xff;
2378c39526b7SPramod Gunjikar 	addr  >>= 8;
2379c39526b7SPramod Gunjikar 	buf[17] = addr & 0xff;
2380c39526b7SPramod Gunjikar 	addr  >>= 8;
2381c39526b7SPramod Gunjikar 	buf[16] = addr & 0x0f;
2382c39526b7SPramod Gunjikar }
2383c39526b7SPramod Gunjikar 
2384c39526b7SPramod Gunjikar static void
ipaddr2mgid(struct sockaddr * addrp,ib_gid_t * mgidp,ib_pkey_t pkey)2385c39526b7SPramod Gunjikar ipaddr2mgid(struct sockaddr *addrp, ib_gid_t *mgidp, ib_pkey_t pkey)
2386c39526b7SPramod Gunjikar {
2387c39526b7SPramod Gunjikar 	char			mc_map[32];	/* Max H/W addr len */
2388c39526b7SPramod Gunjikar 	struct sockaddr_in	*sin = (struct sockaddr_in *)addrp;
2389c39526b7SPramod Gunjikar 	struct sockaddr_in6	*sin6 = (struct sockaddr_in6 *)addrp;
2390c39526b7SPramod Gunjikar 
2391c39526b7SPramod Gunjikar 	if ((addrp->sa_family ==  AF_INET6) &&
2392c39526b7SPramod Gunjikar 	    b2h32((sin6->sin6_addr.s6_addr32[0]) & 0xFF10A01B) ==
2393c39526b7SPramod Gunjikar 	    0xFF10A01B) {
2394c39526b7SPramod Gunjikar 		bcopy(&sin6->sin6_addr, mgidp, sizeof (ib_gid_t));
2395c39526b7SPramod Gunjikar 	} else {
2396c39526b7SPramod Gunjikar 		ip_ib_mc_map(sin->sin_addr.s_addr, mc_map);
2397c39526b7SPramod Gunjikar 		mc_map[7] = 0x01;   /* Use RDMA CM signature */
2398c39526b7SPramod Gunjikar 		mc_map[8] = (char)(pkey >> 8);
2399c39526b7SPramod Gunjikar 		mc_map[9] = (char)(pkey);
2400c39526b7SPramod Gunjikar 		bcopy(mc_map+4, mgidp, sizeof (ib_gid_t));
2401c39526b7SPramod Gunjikar 	}
2402c39526b7SPramod Gunjikar }
2403c39526b7SPramod Gunjikar 
2404c39526b7SPramod Gunjikar static int
ibcma_any_addr(ibt_ip_addr_t * addr)2405c39526b7SPramod Gunjikar ibcma_any_addr(ibt_ip_addr_t *addr)
2406c39526b7SPramod Gunjikar {
2407c39526b7SPramod Gunjikar 	ASSERT(addr);
2408c39526b7SPramod Gunjikar 	if (addr->family == AF_INET)
2409c39526b7SPramod Gunjikar 		return (addr->un.ip4addr == INADDR_ANY);
2410c39526b7SPramod Gunjikar 	else if (addr->family == AF_INET6)
2411c39526b7SPramod Gunjikar 		return (IN6_IS_ADDR_UNSPECIFIED(&(addr->un.ip6addr)));
2412c39526b7SPramod Gunjikar 	return (0);
2413c39526b7SPramod Gunjikar }
2414c39526b7SPramod Gunjikar 
2415c39526b7SPramod Gunjikar static struct rdma_cm_id *
ibcma_create_new_id(struct rdma_cm_id * idp)2416c39526b7SPramod Gunjikar ibcma_create_new_id(struct rdma_cm_id *idp)
2417c39526b7SPramod Gunjikar {
2418c39526b7SPramod Gunjikar 	struct rdma_cm_id	*new_idp;
2419c39526b7SPramod Gunjikar 	sol_cma_chan_t		*chanp, *new_chanp;
2420c39526b7SPramod Gunjikar 	ibcma_chan_t		*ibchanp, *new_ibchanp;
2421c39526b7SPramod Gunjikar 
2422c39526b7SPramod Gunjikar 	new_idp = cma_create_new_id(idp);
2423c39526b7SPramod Gunjikar 	if (new_idp == NULL)
2424c39526b7SPramod Gunjikar 		return (new_idp);
2425c39526b7SPramod Gunjikar 	new_chanp = (sol_cma_chan_t *)new_idp;
2426c39526b7SPramod Gunjikar 	new_ibchanp = &new_chanp->chan_ib;
2427c39526b7SPramod Gunjikar 	chanp = (sol_cma_chan_t *)idp;
2428c39526b7SPramod Gunjikar 	ibchanp = &chanp->chan_ib;
2429c39526b7SPramod Gunjikar 	if (ibchanp->chan_devp) {
2430c39526b7SPramod Gunjikar 		ibcma_dev_t	*devp;
2431c39526b7SPramod Gunjikar 
2432c39526b7SPramod Gunjikar 		devp = (ibcma_dev_t *)kmem_zalloc(sizeof (ibcma_dev_t),
2433c39526b7SPramod Gunjikar 		    KM_SLEEP);
2434c39526b7SPramod Gunjikar 		new_ibchanp->chan_devp = devp;
2435c39526b7SPramod Gunjikar 		bcopy(ibchanp->chan_devp, devp, sizeof (ibcma_dev_t));
2436c39526b7SPramod Gunjikar 	}
2437c39526b7SPramod Gunjikar 
2438c39526b7SPramod Gunjikar 	if (ibchanp->chan_pathp && ibchanp->chan_numpaths &&
2439c39526b7SPramod Gunjikar 	    ibchanp->chan_path_size) {
2440c39526b7SPramod Gunjikar 		new_ibchanp->chan_pathp = (ibt_path_info_t *)kmem_zalloc(
2441c39526b7SPramod Gunjikar 		    ibchanp->chan_path_size, KM_SLEEP);
2442c39526b7SPramod Gunjikar 		bcopy(ibchanp->chan_pathp, new_ibchanp->chan_pathp,
2443c39526b7SPramod Gunjikar 		    ibchanp->chan_path_size);
2444c39526b7SPramod Gunjikar 		new_ibchanp->chan_path_size = ibchanp->chan_path_size;
2445c39526b7SPramod Gunjikar 		new_ibchanp->chan_numpaths = ibchanp->chan_numpaths;
2446c39526b7SPramod Gunjikar 	}
2447c39526b7SPramod Gunjikar 	bcopy(&ibchanp->chan_local_addr, &new_ibchanp->chan_local_addr,
2448c39526b7SPramod Gunjikar 	    sizeof (ibt_ip_addr_t));
2449c39526b7SPramod Gunjikar 	bcopy(&ibchanp->chan_remote_addr, &new_ibchanp->chan_remote_addr,
2450c39526b7SPramod Gunjikar 	    sizeof (ibt_ip_addr_t));
2451c39526b7SPramod Gunjikar 	new_ibchanp->chan_port = ibchanp->chan_port;
2452c39526b7SPramod Gunjikar 	new_ibchanp->chan_sid = ibchanp->chan_sid;
2453c39526b7SPramod Gunjikar 
2454c39526b7SPramod Gunjikar 	return (new_idp);
2455c39526b7SPramod Gunjikar }
2456c39526b7SPramod Gunjikar 
2457c39526b7SPramod Gunjikar static void
ibcma_get_devlist(sol_cma_chan_t * root_chanp,ib_guid_t * hca_guidp,int num_hcas,genlist_t * ret_devlist,boolean_t with_ipaddr_only)2458c39526b7SPramod Gunjikar ibcma_get_devlist(sol_cma_chan_t *root_chanp, ib_guid_t *hca_guidp,
2459a3077325SPramod Gunjikar     int num_hcas, genlist_t *ret_devlist, boolean_t with_ipaddr_only)
2460c39526b7SPramod Gunjikar {
2461c39526b7SPramod Gunjikar 	int			i;
2462c39526b7SPramod Gunjikar 	ibt_status_t		status;
2463c39526b7SPramod Gunjikar 	ibcma_dev_t		*devp;
2464c39526b7SPramod Gunjikar 	uint_t			num_ports, p;
2465c39526b7SPramod Gunjikar 	uint_t			port_size;
2466c39526b7SPramod Gunjikar 	ibt_hca_portinfo_t	*port_info, *tmp;
2467*17a2b317SBill Taylor 	ibt_srcip_info_t	*src_info;
2468*17a2b317SBill Taylor 	ibt_srcip_attr_t	attr;
2469*17a2b317SBill Taylor 	uint_t			entries;
2470c39526b7SPramod Gunjikar 
2471a3077325SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2472a3077325SPramod Gunjikar 	    "get_devlist(%p, %p, %x, %p, %x)", root_chanp, hca_guidp,
2473a3077325SPramod Gunjikar 	    num_hcas, ret_devlist, with_ipaddr_only);
2474c39526b7SPramod Gunjikar 
2475c39526b7SPramod Gunjikar 	init_genlist(ret_devlist);
2476c39526b7SPramod Gunjikar 	for (i = 0; i < num_hcas; i++) {
2477c39526b7SPramod Gunjikar 		status = ibt_query_hca_ports_byguid(hca_guidp[i], 0, &port_info,
2478c39526b7SPramod Gunjikar 		    &num_ports, &port_size);
2479c39526b7SPramod Gunjikar 		if (status !=  IBT_SUCCESS) {
2480c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
2481c39526b7SPramod Gunjikar 			    "ibt_query_hca_ports_byguid failed %d", status);
2482c39526b7SPramod Gunjikar 			continue;
2483c39526b7SPramod Gunjikar 		}
2484c39526b7SPramod Gunjikar 
2485c39526b7SPramod Gunjikar 		for (p = 0, tmp = port_info; p < num_ports; p++, tmp++) {
2486c39526b7SPramod Gunjikar 			uint_t		s, num_sgids;
2487c39526b7SPramod Gunjikar 			uint16_t	pk;
2488c39526b7SPramod Gunjikar 			uint_t		num_pkeys;
2489c39526b7SPramod Gunjikar 
2490c39526b7SPramod Gunjikar 			if (tmp->p_linkstate != IBT_PORT_ACTIVE)
2491c39526b7SPramod Gunjikar 				continue;
2492c39526b7SPramod Gunjikar 
2493c39526b7SPramod Gunjikar 			num_sgids = tmp->p_sgid_tbl_sz / sizeof (ib_gid_t);
2494c39526b7SPramod Gunjikar 			num_pkeys = tmp->p_pkey_tbl_sz / sizeof (ib_pkey_t);
2495c39526b7SPramod Gunjikar 
2496c39526b7SPramod Gunjikar 			for (s = 0; s < num_sgids; s++) {
2497c39526b7SPramod Gunjikar 				/* Skip holes in sgid table */
2498c39526b7SPramod Gunjikar 				if (tmp->p_sgid_tbl[s].gid_guid == 0x0LL)
2499c39526b7SPramod Gunjikar 					continue;
2500c39526b7SPramod Gunjikar 				for (pk = 0; pk < num_pkeys; pk++) {
2501c39526b7SPramod Gunjikar 					/* Skip holes in pkey table */
2502c39526b7SPramod Gunjikar 					if (tmp->p_pkey_tbl[pk] == 0)
2503c39526b7SPramod Gunjikar 						continue;
2504a3077325SPramod Gunjikar 					if (with_ipaddr_only == B_TRUE) {
2505*17a2b317SBill Taylor 						bcopy(&tmp->p_sgid_tbl[s],
2506*17a2b317SBill Taylor 						    &attr.sip_gid,
2507*17a2b317SBill Taylor 						    sizeof (ib_gid_t));
2508*17a2b317SBill Taylor 						attr.sip_pkey =
2509*17a2b317SBill Taylor 						    tmp->p_pkey_tbl[pk];
2510*17a2b317SBill Taylor 						attr.sip_family = AF_INET;
2511*17a2b317SBill Taylor 						attr.sip_zoneid = 0;
2512*17a2b317SBill Taylor 
2513*17a2b317SBill Taylor 						status = ibt_get_src_ip(&attr,
2514*17a2b317SBill Taylor 						    &src_info, &entries);
2515a3077325SPramod Gunjikar 						if (status != IBT_SUCCESS)
2516a3077325SPramod Gunjikar 							continue;
2517a3077325SPramod Gunjikar 					}
2518c39526b7SPramod Gunjikar 
2519c39526b7SPramod Gunjikar 					/* allocate devinfo & fill in info */
2520c39526b7SPramod Gunjikar 					devp = kmem_zalloc(
2521c39526b7SPramod Gunjikar 					    sizeof (ibcma_dev_t), KM_SLEEP);
2522c39526b7SPramod Gunjikar 					devp->dev_node_guid = hca_guidp[i];
2523c39526b7SPramod Gunjikar 					devp->dev_port_num = p + 1;
2524c39526b7SPramod Gunjikar 					devp->dev_pkey_ix = pk;
2525c39526b7SPramod Gunjikar 					devp->dev_pkey = tmp->p_pkey_tbl[pk];
2526c39526b7SPramod Gunjikar 					devp->dev_sgid = tmp->p_sgid_tbl[s];
2527*17a2b317SBill Taylor 					if (with_ipaddr_only == B_TRUE) {
2528*17a2b317SBill Taylor 						bcopy(&src_info[0].ip_addr,
2529a3077325SPramod Gunjikar 						    &devp->dev_ipaddr,
2530a3077325SPramod Gunjikar 						    sizeof (ibt_ip_addr_t));
2531*17a2b317SBill Taylor 						ibt_free_srcip_info(src_info,
2532*17a2b317SBill Taylor 						    entries);
2533*17a2b317SBill Taylor 					}
2534c39526b7SPramod Gunjikar 
2535c39526b7SPramod Gunjikar 					SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2536c39526b7SPramod Gunjikar 					    "get_devlist: add2devlist "
2537c39526b7SPramod Gunjikar 					    "node_guid %llx", hca_guidp[i]);
2538c39526b7SPramod Gunjikar 					(void) add_genlist(ret_devlist,
2539c39526b7SPramod Gunjikar 					    (uintptr_t)devp, NULL);
2540c39526b7SPramod Gunjikar 				}
2541c39526b7SPramod Gunjikar 			}
2542c39526b7SPramod Gunjikar 		}
2543c39526b7SPramod Gunjikar 		ibt_free_portinfo(port_info, port_size);
2544c39526b7SPramod Gunjikar 	}
2545c39526b7SPramod Gunjikar }
2546c39526b7SPramod Gunjikar 
2547c39526b7SPramod Gunjikar 
2548c39526b7SPramod Gunjikar #ifdef	QP_DEBUG
2549c39526b7SPramod Gunjikar static void
dump_qp_info(ibt_qp_hdl_t qphdl)2550c39526b7SPramod Gunjikar dump_qp_info(ibt_qp_hdl_t qphdl)
2551c39526b7SPramod Gunjikar {
2552c39526b7SPramod Gunjikar 	ibt_qp_query_attr_t	qp_query;
2553c39526b7SPramod Gunjikar 	ibt_qp_info_t		*qp_info;
2554c39526b7SPramod Gunjikar 	ibt_status_t		status;
2555c39526b7SPramod Gunjikar 	ibt_qp_rc_attr_t	*rcp;
2556c39526b7SPramod Gunjikar 
2557c39526b7SPramod Gunjikar 	bzero(&qp_query, sizeof (qp_query));
2558c39526b7SPramod Gunjikar 	status = ibt_query_qp(qphdl, &qp_query);
2559c39526b7SPramod Gunjikar 	if (status != IBT_SUCCESS) {
2560c39526b7SPramod Gunjikar 		cmn_err(CE_WARN, "query_qp failed!!");
2561c39526b7SPramod Gunjikar 		return;
2562c39526b7SPramod Gunjikar 	}
2563c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2564c39526b7SPramod Gunjikar 	    "QP HDL : %p, qp_sq_cq %p, qp_rq_cq %p, "
2565c39526b7SPramod Gunjikar 	    "qp_rdd_hdl %p, qp_qpn %x, qp_sq_sgl %x, qp_rq_sgl %x, "
2566c39526b7SPramod Gunjikar 	    "qp_srq %p, quer_attr.qp_flags %x",
2567c39526b7SPramod Gunjikar 	    qphdl, qp_query.qp_sq_cq, qp_query.qp_rq_cq,
2568c39526b7SPramod Gunjikar 	    qp_query.qp_rdd_hdl, qp_query.qp_qpn,
2569c39526b7SPramod Gunjikar 	    qp_query.qp_sq_sgl, qp_query.qp_rq_sgl,
2570c39526b7SPramod Gunjikar 	    qp_query.qp_srq, qp_query.qp_flags);
2571c39526b7SPramod Gunjikar 	qp_info = &(qp_query.qp_info);
2572c39526b7SPramod Gunjikar 	rcp = &((qp_info->qp_transport).rc);
2573c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2574c39526b7SPramod Gunjikar 	    "qp_sq_sz %x, qp_rq_sz %x, qp_state %x, "
2575c39526b7SPramod Gunjikar 	    "qp_current_state %x, qp_info.qp_flags %x, qp_trans %x",
2576c39526b7SPramod Gunjikar 	    qp_info->qp_sq_sz, qp_info->qp_rq_sz, qp_info->qp_state,
2577c39526b7SPramod Gunjikar 	    qp_info->qp_current_state, qp_info->qp_flags,
2578c39526b7SPramod Gunjikar 	    qp_info->qp_trans);
2579c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2580c39526b7SPramod Gunjikar 	    "rc_sq_psn %x, rc_rq_psn %x, rc_dst_qpn %x, "
2581c39526b7SPramod Gunjikar 	    "rc_mig_state %x, rc_rnr_retry_cnt %x, rc_retry_cnt %x, "
2582c39526b7SPramod Gunjikar 	    "rc_rdma_ra_out %x, rc_rdma_ra_in %x, rc_min_rnr_nak %x, "
2583c39526b7SPramod Gunjikar 	    "rc_path_mtu %x", rcp->rc_sq_psn, rcp->rc_rq_psn,
2584c39526b7SPramod Gunjikar 	    rcp->rc_dst_qpn, rcp->rc_mig_state, rcp->rc_rnr_retry_cnt,
2585c39526b7SPramod Gunjikar 	    rcp->rc_retry_cnt, rcp->rc_rdma_ra_out, rcp->rc_rdma_ra_in,
2586c39526b7SPramod Gunjikar 	    rcp->rc_min_rnr_nak, rcp->rc_path_mtu);
2587c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2588c39526b7SPramod Gunjikar 	    "av_dgid %llx: %llx, av_sgid: %llx, "
2589c39526b7SPramod Gunjikar 	    "srate %x, srvl %x, flow %x, tclass %x, hop %x, "
2590c39526b7SPramod Gunjikar 	    "av_port_num %x, av_send_grh %x, av_dlid %x, "
2591c39526b7SPramod Gunjikar 	    "av_src_path %x, av_sgid_ix %x, pkey_index %x, "
2592c39526b7SPramod Gunjikar 	    "port_num %x",
2593c39526b7SPramod Gunjikar 	    (rcp->rc_path).cep_adds_vect.av_sgid.gid_prefix,
2594c39526b7SPramod Gunjikar 	    (rcp->rc_path).cep_adds_vect.av_sgid.gid_guid,
2595c39526b7SPramod Gunjikar 	    (rcp->rc_path).cep_adds_vect.av_dgid.gid_prefix,
2596c39526b7SPramod Gunjikar 	    (rcp->rc_path).cep_adds_vect.av_dgid.gid_guid,
2597c39526b7SPramod Gunjikar 	    (rcp->rc_path).cep_adds_vect.av_srate,
2598c39526b7SPramod Gunjikar 	    (rcp->rc_path).cep_adds_vect.av_srvl,
2599c39526b7SPramod Gunjikar 	    (rcp->rc_path).cep_adds_vect.av_flow,
2600c39526b7SPramod Gunjikar 	    (rcp->rc_path).cep_adds_vect.av_tclass,
2601c39526b7SPramod Gunjikar 	    (rcp->rc_path).cep_adds_vect.av_hop,
2602c39526b7SPramod Gunjikar 	    (rcp->rc_path).cep_adds_vect.av_port_num,
2603c39526b7SPramod Gunjikar 	    (rcp->rc_path).cep_adds_vect.av_opaque1,
2604c39526b7SPramod Gunjikar 	    (rcp->rc_path).cep_adds_vect.av_opaque2,
2605c39526b7SPramod Gunjikar 	    (rcp->rc_path).cep_adds_vect.av_opaque3,
2606c39526b7SPramod Gunjikar 	    (rcp->rc_path).cep_adds_vect.av_opaque4,
2607c39526b7SPramod Gunjikar 	    (rcp->rc_path).cep_pkey_ix,
2608c39526b7SPramod Gunjikar 	    (rcp->rc_path).cep_hca_port_num);
2609c39526b7SPramod Gunjikar }
2610c39526b7SPramod Gunjikar #endif
2611c39526b7SPramod Gunjikar 
2612c39526b7SPramod Gunjikar static void
dump_priv_data(void * priv_data,ibt_priv_data_len_t arr_len,ibt_priv_data_len_t priv_len,char * caller)2613c39526b7SPramod Gunjikar dump_priv_data(void *priv_data, ibt_priv_data_len_t arr_len,
2614c39526b7SPramod Gunjikar     ibt_priv_data_len_t priv_len, char *caller)
2615c39526b7SPramod Gunjikar {
2616c39526b7SPramod Gunjikar 	uint8_t	i;
2617c39526b7SPramod Gunjikar 	uchar_t *c = (uchar_t *)priv_data;
2618c39526b7SPramod Gunjikar 
2619c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "priv_data to %s: %p, len %d",
2620c39526b7SPramod Gunjikar 	    caller, priv_data, priv_len);
2621c39526b7SPramod Gunjikar 	if (!priv_len || !priv_data)
2622c39526b7SPramod Gunjikar 		return;
2623c39526b7SPramod Gunjikar 
2624c39526b7SPramod Gunjikar 	/* Display in rows of 16 uchar_t */
2625c39526b7SPramod Gunjikar 	for (i = 0; i < arr_len; i += 16)
2626c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2627c39526b7SPramod Gunjikar 		    "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
2628c39526b7SPramod Gunjikar 		    c[i], c[i + 1], c[i + 2], c[i + 3], c[i + 4], c[i + 5],
2629c39526b7SPramod Gunjikar 		    c[i + 6], c[i + 7], c[i + 8], c[i + 9], c[i + 10],
2630c39526b7SPramod Gunjikar 		    c[i + 11], c[i + 12], c[i + 13], c[i + 14], c[i + 15]);
2631c39526b7SPramod Gunjikar 
2632c39526b7SPramod Gunjikar }
2633