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