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 *, boolean_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 (0);
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 from REQ data.
335 		 */
336 		ibt_addsvect2ah(&ibchanp->chan_rcreq_addr, &qpattr->ah_attr);
337 		qpattr->path_mtu = (uint32_t)
338 		    ((ibchanp->chan_rtr_data).req_path_mtu);
339 		qpattr->dest_qp_num = ibchanp->chan_rcreq_qpn;
340 		qpattr->rq_psn = (ibchanp->chan_rtr_data).req_rq_psn;
341 		qpattr->max_dest_rd_atomic = ibchanp->chan_rcreq_ra_in;
342 		qpattr->min_rnr_timer =
343 		    (ibchanp->chan_rtr_data).req_rnr_nak_time;
344 		return (0);
345 	} else if (IS_UDP_CMID(idp)) {
346 		if (idp->ps == RDMA_PS_UDP)
347 			qpattr->qkey = RDMA_UDP_QKEY;
348 		else
349 			qpattr->qkey = SOL_IPOIB_DEFAULT_QKEY;
350 		*qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX |
351 		    IB_QP_PORT | IB_QP_QKEY;
352 		return (0);
353 	} else
354 		return (EINVAL);
355 }
356 
357 int
358 rdma_ib_connect(struct rdma_cm_id *idp, struct rdma_conn_param *conn_param)
359 {
360 	sol_cma_chan_t	*chanp;
361 	ibcma_chan_t	*ibchanp;
362 	int		ret;
363 
364 	ASSERT(idp);
365 	chanp = (sol_cma_chan_t *)idp;
366 	ibchanp = &chanp->chan_ib;
367 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "rdma_ib_connect(%p, %p)", idp,
368 	    conn_param);
369 
370 	ASSERT(chanp->chan_xport_type == SOL_CMA_XPORT_IB);
371 	if (ibchanp->chan_devp == NULL || ibchanp->chan_pathp == NULL) {
372 		SOL_OFS_DPRINTF_L3(sol_rdmacm_dbg_str, "rdma_ib_connect : "
373 		    "invalid IP @");
374 		return (EINVAL);
375 	}
376 	ASSERT(ibchanp->chan_devp);
377 
378 	ibchanp->chan_qpmodifyflag  = 1;
379 	if (idp->ps == RDMA_PS_TCP)
380 		ret = ibcma_tcp_connect(idp, ibchanp, conn_param);
381 	else
382 		ret = ibcma_udp_connect(idp, ibchanp, conn_param);
383 
384 	return (ret);
385 }
386 
387 extern void sol_cma_add_hca_list(sol_cma_chan_t *, ib_guid_t);
388 void
389 ibcma_append_listen_list(struct rdma_cm_id  *root_idp)
390 {
391 	int			num_hcas;
392 	ib_guid_t		*hca_guidp;
393 	struct rdma_cm_id	*ep_idp;
394 	sol_cma_chan_t		*root_chanp, *ep_chanp;
395 	ibcma_chan_t		*root_ibchanp, *ep_ibchanp;
396 	genlist_t		dev_genlist;
397 	genlist_entry_t		*entry;
398 
399 	sol_cma_listen_info_t	*listenp;
400 	ibcma_dev_t		*devp;
401 
402 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "append_listen(%p)", root_idp);
403 	root_chanp = (sol_cma_chan_t *)root_idp;
404 	root_ibchanp = &root_chanp->chan_ib;
405 
406 	/*
407 	 * Address other than IF_ADDR_ANY bound to this channel. Listen on
408 	 * this IP address alone.
409 	 */
410 	if (root_ibchanp->chan_devp &&
411 	    (root_ibchanp->chan_addr_flag & IBCMA_LOCAL_ADDR_IFADDRANY) == 0) {
412 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "Create listen chan");
413 		ep_idp = ibcma_create_new_id(root_idp);
414 		ASSERT(ep_idp);
415 
416 		ep_chanp = (sol_cma_chan_t *)ep_idp;
417 		listenp = kmem_zalloc(sizeof (sol_cma_listen_info_t),
418 		    KM_SLEEP);
419 		ep_chanp->chan_listenp = listenp;
420 
421 		ep_ibchanp = &ep_chanp->chan_ib;
422 		ep_ibchanp->chan_port = root_ibchanp->chan_port;
423 		listenp->listen_ep_root_entry = add_genlist(
424 		    &(CHAN_LISTEN_LIST(root_chanp)),
425 		    (uintptr_t)ep_idp, root_idp);
426 		devp = ep_ibchanp->chan_devp;
427 		sol_cma_add_hca_list(ep_chanp, ntohll(devp->dev_node_guid));
428 		return;
429 	}
430 
431 	/*
432 	 * Get the list of IB devs with valid IP addresses
433 	 * Append to the list of listeners for root_idp
434 	 */
435 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "Search IP @");
436 	num_hcas = ibt_get_hca_list(&hca_guidp);
437 	ibcma_get_devlist(root_chanp, hca_guidp, num_hcas,
438 	    &dev_genlist, B_FALSE);
439 	entry = remove_genlist_head(&dev_genlist);
440 	while (entry) {
441 		devp = (ibcma_dev_t *)(entry->data);
442 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
443 		    "Create listen chan- ALL");
444 		ep_idp = ibcma_create_new_id(root_idp);
445 		ASSERT(ep_idp);
446 
447 		ep_chanp = (sol_cma_chan_t *)ep_idp;
448 		ep_chanp->chan_xport_type = SOL_CMA_XPORT_IB;
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 		ASSERT(ep_ibchanp->chan_devp == NULL);
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 		bcopy(&info.dst_addr, &event_ibchanp->chan_local_addr,
1429 		    sizeof (ibt_ip_addr_t));
1430 		ipaddr2sockaddr(&info.dst_addr,
1431 		    &(event_idp->route.addr.src_addr), &info.src_port);
1432 
1433 		/*
1434 		 * Increment number of Reqs for listening CMID,
1435 		 * so that listening CMID is not deleted, till this
1436 		 * connection expects no more events.
1437 		 * chan_req_cnt is decremented connection is
1438 		 * notified to the consumer.
1439 		 *
1440 		 * Insert the CMID into the REQ_AVL_TREE. This is
1441 		 * deleted when the connection is accepted or rejected.
1442 		 */
1443 		mutex_enter(&root_chanp->chan_mutex);
1444 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
1445 		    "Add to REQ AVL of %p IDP, idp %p, session_id %p",
1446 		    root_idp, event_idp, event_chanp->chan_session_id);
1447 		find_ret = avl_find(&root_chanp->chan_req_avl_tree,
1448 		    (void *)event_chanp->chan_session_id, &where);
1449 		if (find_ret) {
1450 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
1451 			    "DUPLICATE ENTRY in REQ AVL : root %p, "
1452 			    "idp %p, session_id %p",
1453 			    root_idp, event_idp,
1454 			    event_chanp->chan_session_id);
1455 			mutex_exit(&root_chanp->chan_mutex);
1456 			event_chanp->chan_req_state = REQ_CMID_CREATED;
1457 			rdma_destroy_id(event_idp);
1458 			return (IBT_CM_REJECT);
1459 		}
1460 		root_chanp->chan_req_cnt++;
1461 		root_chanp->chan_req_state = REQ_CMID_CREATED;
1462 		root_chanp->chan_req_total_cnt++;
1463 		avl_insert(&root_chanp->chan_req_avl_tree,
1464 		    (void *)event_idp, where);
1465 		mutex_exit(&root_chanp->chan_mutex);
1466 
1467 		event = RDMA_CM_EVENT_CONNECT_REQUEST;
1468 		evt_status = 0;
1469 	} else if (eventp->cm_type == IBT_CM_UD_EVENT_SIDR_REP) {
1470 		ibt_cm_sidr_rep_t	*sidr_rep;
1471 
1472 		ASSERT(chanp->chan_connect_flag == SOL_CMA_CONNECT_INITIATED);
1473 		mutex_enter(&chanp->chan_mutex);
1474 		chanp->chan_connect_flag = SOL_CMA_CONNECT_CLIENT_NONE;
1475 		chanp->chan_cmid_destroy_state |= SOL_CMA_CALLER_EVENT_PROGRESS;
1476 		mutex_exit(&chanp->chan_mutex);
1477 		sidr_rep = &((eventp->cm_event).sidr_rep);
1478 		if (sidr_rep->srep_status == IBT_CM_SREP_CHAN_VALID) {
1479 			evt_status = 0;
1480 			event = RDMA_CM_EVENT_ESTABLISHED;
1481 			ud_paramp->qp_num = sidr_rep->srep_remote_qpn;
1482 			ud_paramp->qkey = sidr_rep->srep_remote_qkey;
1483 			ibt_path2ah(ibchanp->chan_pathp, &ud_paramp->ah_attr);
1484 		} else {
1485 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
1486 			    "SIDR Response err with status %x",
1487 			    sidr_rep->srep_status);
1488 			event = RDMA_CM_EVENT_UNREACHABLE;
1489 			evt_status = sidr_rep->srep_status;
1490 			goto ud_gen_event;
1491 		}
1492 	}
1493 
1494 	ud_paramp->private_data_len = cm_privlen;
1495 	if (evt_status == 0 && cm_privlen) {
1496 		ud_paramp->private_data = kmem_zalloc(cm_privlen, KM_SLEEP);
1497 		bcopy(cm_priv, (void *)ud_paramp->private_data,
1498 		    cm_privlen);
1499 #ifdef DEBUG
1500 		dump_priv_data((void *)ud_paramp->private_data,
1501 		    SOL_REP_PRIV_DATA_SZ, cm_privlen, "ibcma_ud_hdlr");
1502 #endif
1503 	}
1504 
1505 ud_gen_event:
1506 	/* Pass back the event to sol_cma consumer */
1507 	cma_generate_event(event_idp, event, evt_status, NULL, ud_paramp);
1508 
1509 	if (ud_paramp->private_data)
1510 		kmem_free((void *)ud_paramp->private_data, cm_privlen);
1511 
1512 	if (eventp->cm_type == IBT_CM_UD_EVENT_SIDR_REQ)
1513 		return (IBT_CM_DEFER);
1514 	else
1515 		return (IBT_CM_DEFAULT);
1516 }
1517 
1518 static ibt_cm_status_t
1519 ibcma_handle_req(struct rdma_cm_id *idp, struct rdma_cm_id **event_id_ptr,
1520     ibt_cm_event_t *eventp, struct rdma_conn_param *paramp,
1521     enum rdma_cm_event_type *event, int *evt_status)
1522 {
1523 	struct rdma_cm_id	*root_idp, *event_idp;
1524 	sol_cma_chan_t		*root_chanp, *event_chanp, *chanp;
1525 	ibcma_chan_t		*event_ibchanp, *ibchanp;
1526 	ibt_status_t		ibt_status;
1527 	ibt_cm_req_rcv_t	*reqp;
1528 	ibt_priv_data_len_t	cm_privlen;
1529 	ibt_ofuvcm_req_data_t	rtr_data;
1530 	ibt_ip_cm_info_t	info;
1531 	void			*cm_priv, *priv_data;
1532 	ib_lid_t		base_lid;
1533 	void			*find_ret;
1534 	avl_index_t		where;
1535 	cma_chan_state_t	chan_state;
1536 #ifdef  DEBUG
1537 	void			*dump_priv;
1538 #endif
1539 
1540 	chanp = (sol_cma_chan_t *)idp;
1541 	ibchanp = &chanp->chan_ib;
1542 	root_idp = CHAN_LISTEN_ROOT(chanp);
1543 	root_chanp = (sol_cma_chan_t *)root_idp;
1544 	ASSERT(chanp->chan_listenp);
1545 	ASSERT(root_idp);
1546 
1547 	/*
1548 	 * Reject further REQs if destroy of listen CMID
1549 	 * has been called.
1550 	 */
1551 	mutex_enter(&root_chanp->chan_mutex);
1552 	chan_state = cma_get_chan_state(root_chanp);
1553 	mutex_exit(&root_chanp->chan_mutex);
1554 	if (chan_state == SOL_CMA_CHAN_DESTROY_PENDING ||
1555 	    chan_state == SOL_CMA_CHAN_DESTROY_WAIT) {
1556 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "RC Req Hdlr, "
1557 		    "listen CMID destroy called");
1558 		return (IBT_CM_REJECT);
1559 	}
1560 
1561 	*event = RDMA_CM_EVENT_CONNECT_REQUEST;
1562 	*evt_status = 0;
1563 	reqp = &(eventp->cm_event.req);
1564 	paramp->qp_num = reqp->req_remote_qpn;
1565 	paramp->srq = (reqp->req_flags & IBT_CM_SRQ_EXISTS) ? 1 : 0;
1566 	paramp->responder_resources = reqp->req_rdma_ra_in;
1567 	paramp->initiator_depth = reqp->req_rdma_ra_out;
1568 	paramp->flow_control = (reqp->req_flags & IBT_CM_FLOW_CONTROL)
1569 	    ? 1 : 0;
1570 	paramp->retry_count = reqp->req_retry_cnt;
1571 	paramp->rnr_retry_count = reqp->req_rnr_retry_cnt;
1572 
1573 #ifdef	DEBUG
1574 	dump_priv = kmem_zalloc(SOL_REQ_PRIV_DATA_SZ, KM_SLEEP);
1575 	bcopy(eventp->cm_priv_data, dump_priv, eventp->cm_priv_data_len);
1576 	dump_priv_data(dump_priv, SOL_REQ_PRIV_DATA_SZ,
1577 	    eventp->cm_priv_data_len, "handle_req");
1578 	kmem_free(dump_priv, SOL_REQ_PRIV_DATA_SZ);
1579 #endif	/* DEBUG */
1580 
1581 	cm_privlen = eventp->cm_priv_data_len;
1582 	cm_priv = eventp->cm_priv_data;
1583 	if (cm_privlen < IBT_IP_HDR_PRIV_DATA_SZ) {
1584 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "RC Req Hdlr, "
1585 		    "Priv data len %x < %x", cm_privlen,
1586 		    IBT_IP_HDR_PRIV_DATA_SZ);
1587 		return (IBT_CM_REJECT);
1588 	}
1589 	ibt_status = ibt_get_ip_data(cm_privlen, cm_priv, &info);
1590 	if (ibt_status != IBT_SUCCESS) {
1591 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "RC Req Hdlr, "
1592 		    "ibt_get_ip_data failed, %x", ibt_status);
1593 		return (IBT_CM_REJECT);
1594 	}
1595 	bcopy(&info.dst_addr, &ibchanp->chan_remote_addr,
1596 	    sizeof (ibt_ip_addr_t));
1597 
1598 	ibt_status = ibt_ofuvcm_get_req_data(eventp->cm_session_id, &rtr_data);
1599 	if (ibt_status != IBT_SUCCESS) {
1600 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "RC Req Hdlr, "
1601 		    "ibt_ofuvcm_get_req_data failed, %x", ibt_status);
1602 		return (IBT_CM_REJECT);
1603 	}
1604 
1605 	paramp->private_data_len = cm_privlen - IBT_IP_HDR_PRIV_DATA_SZ;
1606 	if (paramp->private_data_len) {
1607 		priv_data = (void *)((uint8_t *)cm_priv +
1608 		    IBT_IP_HDR_PRIV_DATA_SZ);
1609 		paramp->private_data = kmem_zalloc(paramp->private_data_len,
1610 		    KM_SLEEP);
1611 		bcopy(priv_data, (void *)paramp->private_data,
1612 		    paramp->private_data_len);
1613 	}
1614 	event_idp = ibcma_create_new_id(idp);
1615 	if (event_idp == NULL) {
1616 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
1617 		    "create_new_id failed!!");
1618 		if (paramp->private_data)
1619 			kmem_free((void *)paramp->private_data,
1620 			    paramp->private_data_len);
1621 		return (IBT_CM_REJECT);
1622 	}
1623 
1624 	/*
1625 	 * Fill the route, device and port_num.
1626 	 * TBD - Fill up packet_life_time
1627 	 */
1628 	event_idp->device = sol_cma_acquire_device(ntohll(
1629 	    reqp->req_hca_guid));
1630 	event_idp->port_num = reqp->req_prim_hca_port;
1631 	(event_idp->route).num_paths = reqp->req_alt_hca_port ? 2 : 1;
1632 	event_idp->route.path_rec = kmem_zalloc(
1633 	    sizeof (struct ib_sa_path_rec) * ((event_idp->route).num_paths),
1634 	    KM_SLEEP);
1635 	base_lid = ibt_get_port_state_byguid(reqp->req_hca_guid,
1636 	    reqp->req_prim_hca_port, NULL, &base_lid);
1637 	ibt_addsvect2sa_path(&reqp->req_prim_addr,
1638 	    &(event_idp->route.path_rec[0]), base_lid);
1639 	(event_idp->route.path_rec[0]).mtu = (uint8_t)rtr_data.req_path_mtu;
1640 	if (reqp->req_alt_hca_port) {
1641 		base_lid = ibt_get_port_state_byguid(
1642 		    reqp->req_hca_guid, reqp->req_alt_hca_port,
1643 		    NULL, &base_lid);
1644 		ibt_addsvect2sa_path(&reqp->req_alt_addr,
1645 		    &(event_idp->route.path_rec[1]), base_lid);
1646 		(event_idp->route.path_rec[1]).mtu =
1647 		    (uint8_t)rtr_data.req_path_mtu;
1648 	}
1649 
1650 	*event_id_ptr = event_idp;
1651 
1652 	event_chanp = (sol_cma_chan_t *)event_idp;
1653 	event_chanp->chan_req_state = REQ_CMID_NOTIFIED;
1654 	event_ibchanp = &event_chanp->chan_ib;
1655 	event_chanp->chan_session_id = eventp->cm_session_id;
1656 	bcopy((void *)(&reqp->req_prim_addr),
1657 	    (void *)(&event_ibchanp->chan_rcreq_addr),
1658 	    sizeof (ibt_adds_vect_t));
1659 	bcopy(&rtr_data, &(event_ibchanp->chan_rtr_data),
1660 	    sizeof (ibt_ofuvcm_req_data_t));
1661 	event_ibchanp->chan_rcreq_qpn = reqp->req_remote_qpn;
1662 	event_ibchanp->chan_rcreq_ra_in = reqp->req_rdma_ra_in;
1663 	bcopy(&info.src_addr, &event_ibchanp->chan_remote_addr,
1664 	    sizeof (ibt_ip_addr_t));
1665 	ipaddr2sockaddr(&info.src_addr,
1666 	    &(event_idp->route.addr.dst_addr), &info.src_port);
1667 	bcopy(&info.dst_addr, &event_ibchanp->chan_local_addr,
1668 	    sizeof (ibt_ip_addr_t));
1669 	ipaddr2sockaddr(&info.dst_addr,
1670 	    &(event_idp->route.addr.src_addr), &info.src_port);
1671 
1672 	/*
1673 	 * Increment number of Reqs for listening CMID, so that
1674 	 * listening CMID is not deleted, till this connection
1675 	 * expects no more events. chan_req_cnt is decremented
1676 	 * when connection is notified to the consumer.
1677 	 *
1678 	 * Insert the CMID into the REQ_AVL_TREE. This is
1679 	 * deleted when the connection is accepted or rejected.
1680 	 */
1681 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
1682 	    "Add to REQ AVL of %p IDP, idp %p, session_id %p",
1683 	    root_idp, event_idp, event_chanp->chan_session_id);
1684 	mutex_enter(&root_chanp->chan_mutex);
1685 	find_ret = avl_find(&root_chanp->chan_req_avl_tree,
1686 	    (void *)event_chanp->chan_session_id, &where);
1687 	if (find_ret) {
1688 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
1689 		    "DUPLICATE ENTRY in REQ AVL : root %p, "
1690 		    "idp %p, session_id %p",
1691 		    root_idp, event_idp,
1692 		    event_chanp->chan_session_id);
1693 		mutex_exit(&root_chanp->chan_mutex);
1694 		event_chanp->chan_req_state = REQ_CMID_CREATED;
1695 		if (paramp->private_data)
1696 			kmem_free((void *)paramp->private_data,
1697 			    paramp->private_data_len);
1698 		rdma_destroy_id(event_idp);
1699 		return (IBT_CM_REJECT);
1700 	}
1701 	root_chanp->chan_req_cnt++;
1702 	root_chanp->chan_req_state = REQ_CMID_CREATED;
1703 	root_chanp->chan_req_total_cnt++;
1704 
1705 	avl_insert(&root_chanp->chan_req_avl_tree, (void *)event_idp, where);
1706 	mutex_exit(&root_chanp->chan_mutex);
1707 
1708 	return (IBT_CM_DEFER);
1709 }
1710 
1711 static void
1712 ibcma_handle_rep(struct rdma_cm_id *idp, ibt_cm_event_t *eventp)
1713 {
1714 	sol_cma_chan_t		*chanp;
1715 	ibt_cm_rep_rcv_t	*repp;
1716 	struct rdma_conn_param	*paramp;
1717 
1718 	chanp = (sol_cma_chan_t *)idp;
1719 
1720 	paramp = &chanp->chan_param;
1721 	bzero(paramp, sizeof (chanp->chan_param));
1722 	repp = &((eventp->cm_event).rep);
1723 	paramp->srq = (repp->rep_flags & IBT_CM_SRQ_EXISTS) ? 1 : 0;
1724 	paramp->responder_resources = repp->rep_rdma_ra_in;
1725 	paramp->initiator_depth = repp->rep_rdma_ra_out;
1726 	paramp->flow_control = (repp->rep_flags & IBT_CM_FLOW_CONTROL) ? 1 : 0;
1727 
1728 #ifdef DEBUG
1729 	dump_priv_data(eventp->cm_priv_data, SOL_REP_PRIV_DATA_SZ,
1730 	    eventp->cm_priv_data_len, "handle_rep");
1731 #endif
1732 	paramp->private_data_len =  eventp->cm_priv_data_len;
1733 	if (paramp->private_data_len) {
1734 		paramp->private_data = kmem_zalloc(paramp->private_data_len,
1735 		    KM_SLEEP);
1736 		bcopy((void *)eventp->cm_priv_data,
1737 		    (void *)paramp->private_data, paramp->private_data_len);
1738 	}
1739 }
1740 
1741 static ibt_cm_status_t
1742 ibcma_handle_est(struct rdma_cm_id *idp, struct rdma_cm_id **event_id_ptr,
1743     ibt_cm_event_t *eventp, struct rdma_conn_param *paramp,
1744     enum rdma_cm_event_type *event, int *evt_status)
1745 {
1746 	struct rdma_cm_id	*event_idp, *root_idp;
1747 	sol_cma_chan_t		*event_chanp, *chanp, *root_chanp;
1748 	ibcma_chan_t		*event_ibchanp;
1749 
1750 	/* Established event on active / client side */
1751 	chanp = (sol_cma_chan_t *)idp;
1752 	if (chanp->chan_listenp == NULL) {
1753 		ASSERT(chanp->chan_connect_flag == SOL_CMA_CONNECT_INITIATED);
1754 		chanp->chan_connect_flag = SOL_CMA_CONNECT_ESTABLISHED;
1755 		*event_id_ptr = idp;
1756 		bcopy(&chanp->chan_param, paramp,
1757 		    sizeof (struct rdma_conn_param));
1758 		if (paramp->private_data_len) {
1759 			paramp->private_data = kmem_zalloc(
1760 			    paramp->private_data_len, KM_SLEEP);
1761 			bcopy((void *)((chanp->chan_param).private_data),
1762 			    (void *)paramp->private_data,
1763 			    paramp->private_data_len);
1764 			kmem_free((void *)((chanp->chan_param).private_data),
1765 			    paramp->private_data_len);
1766 		}
1767 		event_chanp = chanp;
1768 		mutex_enter(&chanp->chan_mutex);
1769 		chanp->chan_cmid_destroy_state |= SOL_CMA_CALLER_EVENT_PROGRESS;
1770 		mutex_exit(&chanp->chan_mutex);
1771 		goto est_common;
1772 	}
1773 
1774 	root_idp = CHAN_LISTEN_ROOT((chanp));
1775 	ASSERT(root_idp);
1776 	root_chanp = (sol_cma_chan_t *)root_idp;
1777 	event_chanp = NULL;
1778 
1779 	mutex_enter(&root_chanp->chan_mutex);
1780 	event_idp = cma_get_acpt_idp(root_idp, eventp->cm_channel);
1781 	mutex_exit(&root_chanp->chan_mutex);
1782 	if (event_idp == NULL) {
1783 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str, "ibcma_handle_est: "
1784 		    "No matching CMID for qp_hdl %p in ACPT AVL of CMID %p",
1785 		    eventp->cm_channel, root_chanp);
1786 		return (IBT_CM_REJECT);
1787 	}
1788 	*event_id_ptr = event_idp;
1789 	event_chanp = (sol_cma_chan_t *)event_idp;
1790 	mutex_enter(&event_chanp->chan_mutex);
1791 	event_chanp->chan_cmid_destroy_state |=
1792 	    SOL_CMA_CALLER_EVENT_PROGRESS;
1793 	mutex_exit(&event_chanp->chan_mutex);
1794 
1795 est_common:
1796 #ifdef QP_DEBUG
1797 	dump_qp_info(event_chanp->chan_qp_hdl);
1798 #endif
1799 
1800 	/*
1801 	 * Pass back CONNECT_ESTABLISHED event to consumer.
1802 	 */
1803 	*event = RDMA_CM_EVENT_ESTABLISHED;
1804 	event_ibchanp = &event_chanp->chan_ib;
1805 	event_ibchanp->chan_qpmodifyflag  = 1;
1806 
1807 	*evt_status = 0;
1808 	return (IBT_CM_DEFAULT);
1809 }
1810 
1811 static ibt_cm_status_t
1812 ibcma_handle_closed(struct rdma_cm_id *idp, struct rdma_cm_id **event_id_ptr,
1813     ibt_cm_event_t *eventp, enum rdma_cm_event_type *event, int *evt_status)
1814 {
1815 	struct rdma_cm_id	*root_idp, *event_idp;
1816 	sol_cma_chan_t		*chanp, *root_chanp, *event_chanp;
1817 
1818 	*event = RDMA_CM_EVENT_DISCONNECTED;
1819 	*evt_status = 0;
1820 	chanp = (sol_cma_chan_t *)idp;
1821 	mutex_enter(&chanp->chan_mutex);
1822 	root_idp = CHAN_LISTEN_ROOT((chanp));
1823 	root_chanp = (sol_cma_chan_t *)root_idp;
1824 	chanp->chan_qp_hdl = NULL;
1825 	if (!root_idp) {
1826 		chanp->chan_cmid_destroy_state |=
1827 		    SOL_CMA_CALLER_EVENT_PROGRESS;
1828 		chanp->chan_qp_hdl = NULL;
1829 		chanp->chan_connect_flag = SOL_CMA_CONNECT_CLIENT_NONE;
1830 		mutex_exit(&chanp->chan_mutex);
1831 		*event_id_ptr = idp;
1832 		return (IBT_CM_DEFAULT);
1833 	}
1834 	mutex_exit(&chanp->chan_mutex);
1835 
1836 	/* On the passive side, search ACPT AVL Tree */
1837 	mutex_enter(&root_chanp->chan_mutex);
1838 	event_idp = cma_get_acpt_idp(root_idp, eventp->cm_channel);
1839 	event_chanp = (sol_cma_chan_t *)event_idp;
1840 	if (event_idp == NULL) {
1841 		mutex_exit(&root_chanp->chan_mutex);
1842 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
1843 		    "ibcma_handle_closed: "
1844 		    "No matching CMID for qp hdl %p in EST AVL of CMID %p",
1845 		    eventp->cm_channel, root_idp);
1846 		return (IBT_CM_DEFAULT);
1847 	}
1848 	avl_remove(&root_chanp->chan_acpt_avl_tree, event_idp);
1849 	mutex_exit(&root_chanp->chan_mutex);
1850 	mutex_enter(&event_chanp->chan_mutex);
1851 	event_chanp->chan_req_state = REQ_CMID_SERVER_NONE;
1852 	event_chanp->chan_cmid_destroy_state |=
1853 	    SOL_CMA_CALLER_EVENT_PROGRESS;
1854 	mutex_exit(&event_chanp->chan_mutex);
1855 
1856 	*event_id_ptr = event_idp;
1857 	return (IBT_CM_DEFAULT);
1858 }
1859 
1860 static ibt_cm_status_t
1861 ibcma_handle_failed(struct rdma_cm_id *idp, struct rdma_cm_id **event_id_ptr,
1862     ibt_cm_event_t *eventp, struct rdma_conn_param *paramp,
1863     enum rdma_cm_event_type *event, int *evt_status)
1864 {
1865 	struct rdma_cm_id	*root_idp, *event_idp;
1866 	sol_cma_chan_t		*event_chanp, *chanp, *root_chanp;
1867 	ibt_cm_conn_failed_t	*failedp;
1868 
1869 	failedp = &(eventp->cm_event.failed);
1870 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "ibcma_handle_failed - idp %p, "
1871 	    "cf_code %x, cf_msg %x, cf_arej_info_valid %x, cf_reason %x",
1872 	    idp, failedp->cf_code, failedp->cf_msg,
1873 	    failedp->cf_arej_info_valid, failedp->cf_reason);
1874 	chanp = (sol_cma_chan_t *)idp;
1875 	root_idp = CHAN_LISTEN_ROOT((chanp));
1876 	root_chanp = (sol_cma_chan_t *)root_idp;
1877 
1878 	*evt_status = 0;
1879 	switch (failedp->cf_code) {
1880 	case IBT_CM_FAILURE_REJ_SENT :
1881 		/*  Reject sent. No event to userland. */
1882 		break;
1883 
1884 	case IBT_CM_FAILURE_REJ_RCV :
1885 		/*
1886 		 * Reject recieved. If this is a consumer reject, copy the
1887 		 * private * data. Send RDMA_CM_EVENT_REJECTED to user land.
1888 		 */
1889 		if (failedp->cf_reason == IBT_CM_CONSUMER &&
1890 		    eventp->cm_priv_data_len) {
1891 			paramp->private_data_len = eventp->cm_priv_data_len;
1892 			paramp->private_data = kmem_zalloc(
1893 			    paramp->private_data_len, KM_SLEEP);
1894 			bcopy(eventp->cm_priv_data,
1895 			    (void *)paramp->private_data,
1896 			    paramp->private_data_len);
1897 		}
1898 
1899 		/*
1900 		 * If this an REJECT for an accepted CMID, pass the
1901 		 * event to accepted CMID.
1902 		 */
1903 		if (root_idp) {
1904 			sol_cma_chan_t	*root_chanp;
1905 			ASSERT(eventp->cm_channel);
1906 
1907 			root_chanp = (sol_cma_chan_t *)root_idp;
1908 			mutex_enter(&root_chanp->chan_mutex);
1909 			event_idp = cma_get_acpt_idp(root_idp,
1910 			    eventp->cm_channel);
1911 			if (event_idp == NULL) {
1912 				SOL_OFS_DPRINTF_L3(sol_rdmacm_dbg_str,
1913 				    "ibcma_handle_failed: No matching CMID "
1914 				    "for qp_hdl %p in ACPT AVL of CMID %p",
1915 				    eventp->cm_channel, idp);
1916 				mutex_exit(&root_chanp->chan_mutex);
1917 				break;
1918 			}
1919 
1920 			event_chanp = (sol_cma_chan_t *)event_idp;
1921 			*event_id_ptr = event_idp;
1922 			mutex_enter(&event_chanp->chan_mutex);
1923 			avl_remove(&root_chanp->chan_acpt_avl_tree,
1924 			    event_idp);
1925 			event_chanp->chan_req_state = REQ_CMID_SERVER_NONE;
1926 			event_chanp->chan_cmid_destroy_state |=
1927 			    SOL_CMA_CALLER_EVENT_PROGRESS;
1928 			event_chanp->chan_qp_hdl = NULL;
1929 			mutex_exit(&event_chanp->chan_mutex);
1930 			mutex_exit(&root_chanp->chan_mutex);
1931 		} else {
1932 			mutex_enter(&chanp->chan_mutex);
1933 			chanp->chan_cmid_destroy_state |=
1934 			    SOL_CMA_CALLER_EVENT_PROGRESS;
1935 			chanp->chan_qp_hdl = NULL;
1936 			chanp->chan_connect_flag =
1937 			    SOL_CMA_CONNECT_CLIENT_NONE;
1938 			mutex_exit(&chanp->chan_mutex);
1939 			*event_id_ptr  = idp;
1940 		}
1941 		*evt_status = failedp->cf_reason;
1942 		*event = RDMA_CM_EVENT_REJECTED;
1943 		break;
1944 
1945 	case IBT_CM_FAILURE_TIMEOUT :
1946 		/*
1947 		 * Connection Timeout, Send RDMA_CM_EVENT_REJECTED event and
1948 		 * status as IBT_CM_TIMEOUT.
1949 		 */
1950 		if (eventp->cm_session_id && root_idp) {
1951 			mutex_enter(&root_chanp->chan_mutex);
1952 			event_idp = cma_get_req_idp(root_idp,
1953 			    eventp->cm_session_id);
1954 			if (event_idp == NULL) {
1955 				mutex_exit(&root_chanp->chan_mutex);
1956 				SOL_OFS_DPRINTF_L3(sol_rdmacm_dbg_str,
1957 				    "ibcma_handle_failed: No matching CMID "
1958 				    "for qp_hdl %p in REQ AVL of CMID %p",
1959 				    eventp->cm_session_id, idp);
1960 				break;
1961 			}
1962 
1963 			event_chanp = (sol_cma_chan_t *)event_idp;
1964 			mutex_enter(&event_chanp->chan_mutex);
1965 			*event_id_ptr = event_idp;
1966 			avl_remove(&root_chanp->chan_req_avl_tree,
1967 			    event_idp);
1968 			root_chanp->chan_req_cnt--;
1969 			event_chanp->chan_req_state = REQ_CMID_SERVER_NONE;
1970 			event_chanp->chan_qp_hdl = NULL;
1971 			mutex_exit(&event_chanp->chan_mutex);
1972 			mutex_exit(&root_chanp->chan_mutex);
1973 
1974 
1975 			*evt_status = IBT_CM_TIMEOUT;
1976 			*event = RDMA_CM_EVENT_REJECTED;
1977 		}
1978 		if (!eventp->cm_session_id && root_idp) {
1979 			SOL_OFS_DPRINTF_L0(sol_rdmacm_dbg_str,
1980 			    "ibcma_handle_failed: timeout "
1981 			    "session_id NULL");
1982 		}
1983 		if (!root_idp) {
1984 			*event_id_ptr  = idp;
1985 			mutex_enter(&chanp->chan_mutex);
1986 			chanp->chan_cmid_destroy_state |=
1987 			    SOL_CMA_CALLER_EVENT_PROGRESS;
1988 			chanp->chan_qp_hdl = NULL;
1989 			chanp->chan_connect_flag =
1990 			    SOL_CMA_CONNECT_CLIENT_NONE;
1991 			mutex_exit(&chanp->chan_mutex);
1992 			*evt_status = IBT_CM_TIMEOUT;
1993 			*event = RDMA_CM_EVENT_REJECTED;
1994 		}
1995 		break;
1996 
1997 	case IBT_CM_FAILURE_STALE :
1998 		/* Stale connection, ignore */
1999 		break;
2000 	}
2001 	return (IBT_CM_DEFAULT);
2002 }
2003 
2004 static ibt_cm_status_t
2005 ibcma_rc_hdlr(void *inp, ibt_cm_event_t *eventp,
2006     ibt_cm_return_args_t *ret_args, void *priv_data,
2007     ibt_priv_data_len_t priv_datalen)
2008 {
2009 	struct rdma_cm_id	*idp, *event_idp;
2010 	sol_cma_chan_t		*chanp;
2011 	ibt_cm_status_t		status;
2012 	ibt_status_t		ibt_status;
2013 	enum rdma_cm_event_type event;
2014 	struct rdma_conn_param	conn_param, *paramp = &conn_param;
2015 	int	event_status;
2016 
2017 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "ib_cma_rc_hdlr(%p, %p, %p, "
2018 	    "%p, %x)", inp, eventp, ret_args, priv_data, priv_datalen);
2019 	idp = event_idp = (struct rdma_cm_id *)inp;
2020 	chanp = (sol_cma_chan_t *)idp;
2021 	chanp->chan_session_id = NULL;
2022 
2023 	bzero(paramp, sizeof (struct rdma_conn_param));
2024 	switch (eventp->cm_type) {
2025 
2026 	case IBT_CM_EVENT_REQ_RCV :
2027 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2028 		    "ibcma_rc_hdlr : REQ Event");
2029 
2030 		/*
2031 		 * We need to do a round trip to userland. Send a MRA
2032 		 * so that the client does not send multiple REQs. Then
2033 		 * continue the processing of REQs.
2034 		 */
2035 		ibt_status =  ibt_cm_delay(IBT_CM_DELAY_REQ,
2036 		    eventp->cm_session_id, SOL_OFS_REQ_DELAY, NULL, 0);
2037 		if (ibt_status != IBT_SUCCESS) {
2038 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
2039 			    "ibcma_rc_hdlr : ibt_cma_delay failed %x",
2040 			    ibt_status);
2041 			return (IBT_CM_REJECT);
2042 		}
2043 		status = ibcma_handle_req(idp, &event_idp, eventp, paramp,
2044 		    &event, &event_status);
2045 		if (status == IBT_CM_REJECT)
2046 			return (status);
2047 		break;
2048 	case IBT_CM_EVENT_REP_RCV :
2049 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2050 		    "ibcma_rc_hdlr : REP Event");
2051 
2052 		ibcma_handle_rep(idp, eventp);
2053 		return (IBT_CM_DEFAULT);
2054 		/* NOTREACHED */
2055 		/* break; */
2056 	case IBT_CM_EVENT_LAP_RCV :
2057 	case IBT_CM_EVENT_APR_RCV :
2058 		/*
2059 		 * Alternate Paths not supported from userland. Return
2060 		 * IBT_CM_REJECT.
2061 		 */
2062 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2063 		    "ibcma_rc_hdlr : AP Event");
2064 		return (IBT_CM_REJECT);
2065 		/* NOTREACHED */
2066 		/* break; */
2067 	case IBT_CM_EVENT_MRA_RCV :
2068 		/* Let Solaris ibcm take default action for MRA */
2069 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2070 		    "ibcma_rc_hdlr : MRA Event");
2071 		return (IBT_CM_DEFAULT);
2072 		/* NOTREACHED */
2073 		/* break; */
2074 	case IBT_CM_EVENT_CONN_EST :
2075 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2076 		    "ibcma_rc_hdlr : EST Event");
2077 		status = ibcma_handle_est(idp, &event_idp, eventp, paramp,
2078 		    &event, &event_status);
2079 		break;
2080 	case IBT_CM_EVENT_CONN_CLOSED :
2081 		/*
2082 		 * Pass on RDMA_CM_EVENT_DISCONNECTED to consumer
2083 		 */
2084 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2085 		    "ibcma_rc_hdlr : CLOSED Event");
2086 		status = ibcma_handle_closed(idp, &event_idp, eventp,
2087 		    &event, &event_status);
2088 		break;
2089 
2090 	case IBT_CM_EVENT_FAILURE :
2091 		/* Handle Failure Event */
2092 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2093 		    "ibcma_rc_hdlr : FAIL Event");
2094 		status = ibcma_handle_failed(idp, &event_idp, eventp, paramp,
2095 		    &event, &event_status);
2096 
2097 		/*
2098 		 * Check if there is an event to be send to the userland.
2099 		 * Return if there are none.
2100 		 */
2101 		if (event_status == 0)
2102 			return (status);
2103 		break;
2104 	}
2105 
2106 	/* Pass back the event to sol_cma consumer */
2107 	if (event_idp) {
2108 		cma_generate_event(event_idp, event, event_status,
2109 		    paramp, NULL);
2110 	} else
2111 		SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
2112 		    "No Event to userland!!");
2113 	if (paramp->private_data)
2114 		kmem_free((void *)paramp->private_data,
2115 		    paramp->private_data_len);
2116 
2117 	return (status);
2118 }
2119 
2120 static void
2121 ibcma_multicast_hdlr(void *arg, ibt_status_t status, ibt_mcg_info_t *mcg_infop)
2122 {
2123 	struct rdma_cm_id	*idp;
2124 	ibcma_mcast_t		*ib_mcastp = (ibcma_mcast_t *)arg;
2125 	int			evt_status;
2126 	struct rdma_ud_param	uddata, *ud_param = &uddata;
2127 	enum rdma_cm_event_type event;
2128 
2129 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "multicast_hdlr(%p, %x, %p)",
2130 	    arg, status, mcg_infop);
2131 	idp = ib_mcastp->mcast_idp;
2132 
2133 	bzero(ud_param, sizeof (struct rdma_ud_param));
2134 	bcopy(&(mcg_infop->mc_adds_vect.av_dgid),
2135 	    &(ib_mcastp->mcast_gid), sizeof (ib_gid_t));
2136 	ud_param->private_data = ib_mcastp->mcast_ctx;
2137 
2138 	event = (status == IBT_SUCCESS) ?
2139 	    RDMA_CM_EVENT_MULTICAST_JOIN : RDMA_CM_EVENT_MULTICAST_ERROR;
2140 	evt_status = (status == IBT_SUCCESS) ? 0 : -1;
2141 	if (status == IBT_SUCCESS) {
2142 		mcginfo2ah(mcg_infop, &ud_param->ah_attr);
2143 		ud_param->qp_num = IB_MC_QPN;
2144 		if (idp->ps == RDMA_PS_UDP)
2145 			ud_param->qkey = RDMA_UDP_QKEY;
2146 		else
2147 			ud_param->qkey = SOL_IPOIB_DEFAULT_QKEY;
2148 	}
2149 
2150 	/* Send the event to consumer of sol_cma.  */
2151 	cma_generate_event(idp, event, evt_status, NULL, ud_param);
2152 	kmem_free(mcg_infop, sizeof (ibt_mcg_info_t));
2153 }
2154 
2155 static int
2156 ibcma_get_first_ib_ipaddr(struct rdma_cm_id *idp)
2157 {
2158 	sol_cma_chan_t	*chanp = (sol_cma_chan_t *)idp;
2159 	ibcma_chan_t	*ibchanp;
2160 	int		num_hcas, info_inited = 0;
2161 	ib_guid_t	*hca_guidp;
2162 	genlist_t	devlist;
2163 	genlist_entry_t	*entry;
2164 	ibcma_dev_t	*devp;
2165 
2166 	ASSERT(idp);
2167 	ibchanp = &(chanp->chan_ib);
2168 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "get_first_ib_ipaddr(%p)", idp);
2169 
2170 	num_hcas = ibt_get_hca_list(&hca_guidp);
2171 	ibcma_get_devlist(chanp, hca_guidp, num_hcas, &devlist, B_TRUE);
2172 	entry = remove_genlist_head(&devlist);
2173 	while (entry) {
2174 		devp = (ibcma_dev_t *)entry->data;
2175 		if (info_inited == 0) {
2176 			(idp->route).num_paths = 0;
2177 			idp->port_num = devp->dev_port_num;
2178 			chanp->chan_xport_type = SOL_CMA_XPORT_IB;
2179 			ibchanp->chan_devp = devp;
2180 			info_inited = 1;
2181 		} else {
2182 			kmem_free(devp, sizeof (ibcma_dev_t));
2183 		}
2184 		kmem_free(entry, sizeof (genlist_entry_t));
2185 		entry = remove_genlist_head(&devlist);
2186 	}
2187 	ibt_free_hca_list(hca_guidp, num_hcas);
2188 
2189 	if (info_inited)
2190 		return (0);
2191 	else
2192 		return (ENODEV);
2193 }
2194 
2195 /* Utility Conversion functions */
2196 static void
2197 ipaddr2sockaddr(ibt_ip_addr_t *ibt_addrp, struct sockaddr *sock_addrp,
2198     in_port_t *portp)
2199 {
2200 		sock_addrp->sa_family = ibt_addrp->family;
2201 		if (ibt_addrp->family == AF_INET) {
2202 			struct sockaddr_in	*sock_in4p;
2203 			sock_in4p = (struct sockaddr_in *)sock_addrp;
2204 
2205 			sock_in4p->sin_addr.s_addr = ibt_addrp->un.ip4addr;
2206 			if (portp)
2207 				sock_in4p->sin_port = ntohs(*portp);
2208 		} else {
2209 			struct sockaddr_in6 *in6_addr;
2210 			in6_addr = (struct sockaddr_in6 *)sock_addrp;
2211 
2212 			bcopy(&(ibt_addrp->un.ip6addr), &(in6_addr->sin6_addr),
2213 			    sizeof (in6_addr_t));
2214 			if (portp)
2215 				in6_addr->sin6_port = *portp;
2216 		}
2217 }
2218 
2219 static void
2220 sockaddr2ibtaddr_port(struct rdma_cm_id *idp, struct sockaddr *sock_addrp,
2221     ibt_ip_addr_t *ibt_addrp, in_port_t *portp)
2222 {
2223 	in_port_t	ip_port;
2224 
2225 	ibt_addrp->family = sock_addrp->sa_family;
2226 	if (sock_addrp->sa_family == AF_INET) {
2227 		struct sockaddr_in	*sock_in4p;
2228 		sock_in4p = (struct sockaddr_in *)sock_addrp;
2229 
2230 		ibt_addrp->un.ip4addr = sock_in4p->sin_addr.s_addr;
2231 		if (IS_UDP_CMID(idp))
2232 			ip_port = ddi_swap16(sock_in4p->sin_port);
2233 		else
2234 			ip_port = htons(sock_in4p->sin_port);
2235 
2236 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "sockaddr2ibtaddr : "
2237 		    "AF_INET addr %x, port %x, %x", ibt_addrp->un.ip4addr,
2238 		    sock_in4p->sin_port, ip_port);
2239 
2240 		if (portp)
2241 			*portp = ip_port;
2242 
2243 	} else {
2244 		struct sockaddr_in6	*in6_addr;
2245 		in6_addr = (struct sockaddr_in6 *)sock_addrp;
2246 		bcopy(&(in6_addr->sin6_addr), &(ibt_addrp->un.ip6addr),
2247 		    sizeof (in6_addr_t));
2248 		if (portp)
2249 			*portp = in6_addr->sin6_port;
2250 	}
2251 }
2252 
2253 static void
2254 mcginfo2ah(ibt_mcg_info_t *mcgp, struct ib_ah_attr *ah_attr)
2255 {
2256 	ibt_adds_vect_t	*adds_vectp;
2257 	ib_gid_t	dgid_nworder;
2258 
2259 	adds_vectp = &(mcgp->mc_adds_vect);
2260 
2261 	/*
2262 	 * Libraries expect the GID to be in network order. Convert
2263 	 * to network order before passing it to the library.
2264 	 */
2265 	dgid_nworder.gid_prefix = htonll(
2266 	    (adds_vectp->av_dgid).gid_prefix);
2267 	dgid_nworder.gid_guid = htonll(
2268 	    (adds_vectp->av_dgid).gid_guid);
2269 	bcopy(&dgid_nworder, &((ah_attr->grh).dgid), sizeof (ib_gid_t));
2270 
2271 	(ah_attr->grh).flow_label =  adds_vectp->av_flow;
2272 	(ah_attr->grh).sgid_index = adds_vectp->av_sgid_ix;
2273 	(ah_attr->grh).hop_limit = adds_vectp->av_hop;
2274 	(ah_attr->grh).traffic_class = adds_vectp->av_tclass;
2275 
2276 	ah_attr->dlid = adds_vectp->av_dlid;
2277 	ah_attr->sl = adds_vectp->av_srvl;
2278 	ah_attr->src_path_bits = adds_vectp->av_src_path;
2279 	ah_attr->static_rate = adds_vectp->av_srate;
2280 	ah_attr->ah_flags = (adds_vectp->av_send_grh) ? 1 : 0;
2281 	ah_attr->port_num = adds_vectp->av_port_num;
2282 }
2283 
2284 static void
2285 ibt_path2ah(ibt_path_info_t *pathp, struct ib_ah_attr *ah_attr)
2286 {
2287 
2288 	ibt_addsvect2ah(&((pathp->pi_prim_cep_path).cep_adds_vect), ah_attr);
2289 }
2290 
2291 static void
2292 ibt_addsvect2ah(ibt_adds_vect_t *adds_vectp, struct ib_ah_attr *ah_attr)
2293 {
2294 	ib_gid_t	dgid_nworder;
2295 
2296 	/*
2297 	 * Libraries expect the GID to be in network order. Convert
2298 	 * to network order before passing it to the library.
2299 	 */
2300 	dgid_nworder.gid_prefix = htonll(
2301 	    (adds_vectp->av_dgid).gid_prefix);
2302 	dgid_nworder.gid_guid = htonll(
2303 	    (adds_vectp->av_dgid).gid_guid);
2304 	bcopy(&dgid_nworder, &((ah_attr->grh).dgid), sizeof (ib_gid_t));
2305 	(ah_attr->grh).flow_label =  adds_vectp->av_flow;
2306 	(ah_attr->grh).sgid_index = adds_vectp->av_sgid_ix;
2307 	(ah_attr->grh).hop_limit = adds_vectp->av_hop;
2308 	(ah_attr->grh).traffic_class = adds_vectp->av_tclass;
2309 
2310 	ah_attr->dlid = adds_vectp->av_dlid;
2311 	ah_attr->sl = adds_vectp->av_srvl;
2312 	ah_attr->src_path_bits = adds_vectp->av_src_path;
2313 	ah_attr->static_rate = adds_vectp->av_srate;
2314 	ah_attr->ah_flags = (adds_vectp->av_send_grh) ? 1 : 0;
2315 	ah_attr->port_num = adds_vectp->av_port_num;
2316 }
2317 
2318 static void
2319 ibt_path2sa_path(ibt_path_info_t *pathp, struct ib_sa_path_rec *sa_pathp,
2320     ib_lid_t base_lid)
2321 {
2322 	ibt_adds_vect_t	*adds_vectp;
2323 
2324 	adds_vectp = &((pathp->pi_prim_cep_path).cep_adds_vect);
2325 	ibt_addsvect2sa_path(adds_vectp, sa_pathp, base_lid);
2326 	sa_pathp->mtu = pathp->pi_path_mtu;
2327 	sa_pathp->packet_life_time = pathp->pi_prim_pkt_lt;
2328 }
2329 
2330 static void
2331 ibt_addsvect2sa_path(ibt_adds_vect_t *adds_vectp,
2332     struct ib_sa_path_rec *sa_pathp, ib_lid_t base_lid)
2333 {
2334 	bcopy(&(adds_vectp->av_dgid), &(sa_pathp->dgid), 16);
2335 	bcopy(&(adds_vectp->av_sgid), &(sa_pathp->sgid), 16);
2336 	sa_pathp->dlid = adds_vectp->av_dlid;
2337 	sa_pathp->slid = base_lid + adds_vectp->av_src_path;
2338 	sa_pathp->flow_label =  adds_vectp->av_flow;
2339 	sa_pathp->reversible = 1;
2340 	sa_pathp->hop_limit = adds_vectp->av_hop;
2341 	sa_pathp->traffic_class  = adds_vectp->av_tclass;
2342 	sa_pathp->sl = adds_vectp->av_srvl;
2343 	sa_pathp->rate = adds_vectp->av_srate;
2344 	sa_pathp->mtu_selector = IBT_EQU;
2345 	sa_pathp->rate_selector = IBT_EQU;
2346 	sa_pathp->packet_life_time_selector = IBT_EQU;
2347 }
2348 
2349 /*
2350  * Map a multicast IP onto multicast MAC for type IP-over-InfiniBand.
2351  * Leave P_Key as 0 to be filled in by caller
2352  */
2353 static void
2354 ip_ib_mc_map(uint32_t addr, char *buf)
2355 {
2356 	buf[0]  = 0;		/* Reserved */
2357 	buf[1]  = 0xff;		/* Multicast QPN */
2358 	buf[2]  = 0xff;
2359 	buf[3]  = 0xff;
2360 	addr    = ntohl(addr);
2361 	buf[4]  = 0xff;
2362 	buf[5]  = 0x12;		/* link local scope */
2363 	buf[6]  = 0x40;		/* IPv4 signature */
2364 	buf[7]  = 0x1b;
2365 	buf[8]  = 0;		/* P_Key */
2366 	buf[9]  = 0;
2367 	buf[10] = 0;
2368 	buf[11] = 0;
2369 	buf[12] = 0;
2370 	buf[13] = 0;
2371 	buf[14] = 0;
2372 	buf[15] = 0;
2373 	buf[19] = addr & 0xff;
2374 	addr  >>= 8;
2375 	buf[18] = addr & 0xff;
2376 	addr  >>= 8;
2377 	buf[17] = addr & 0xff;
2378 	addr  >>= 8;
2379 	buf[16] = addr & 0x0f;
2380 }
2381 
2382 static void
2383 ipaddr2mgid(struct sockaddr *addrp, ib_gid_t *mgidp, ib_pkey_t pkey)
2384 {
2385 	char			mc_map[32];	/* Max H/W addr len */
2386 	struct sockaddr_in	*sin = (struct sockaddr_in *)addrp;
2387 	struct sockaddr_in6	*sin6 = (struct sockaddr_in6 *)addrp;
2388 
2389 	if ((addrp->sa_family ==  AF_INET6) &&
2390 	    b2h32((sin6->sin6_addr.s6_addr32[0]) & 0xFF10A01B) ==
2391 	    0xFF10A01B) {
2392 		bcopy(&sin6->sin6_addr, mgidp, sizeof (ib_gid_t));
2393 	} else {
2394 		ip_ib_mc_map(sin->sin_addr.s_addr, mc_map);
2395 		mc_map[7] = 0x01;   /* Use RDMA CM signature */
2396 		mc_map[8] = (char)(pkey >> 8);
2397 		mc_map[9] = (char)(pkey);
2398 		bcopy(mc_map+4, mgidp, sizeof (ib_gid_t));
2399 	}
2400 }
2401 
2402 static int
2403 ibcma_any_addr(ibt_ip_addr_t *addr)
2404 {
2405 	ASSERT(addr);
2406 	if (addr->family == AF_INET)
2407 		return (addr->un.ip4addr == INADDR_ANY);
2408 	else if (addr->family == AF_INET6)
2409 		return (IN6_IS_ADDR_UNSPECIFIED(&(addr->un.ip6addr)));
2410 	return (0);
2411 }
2412 
2413 static struct rdma_cm_id *
2414 ibcma_create_new_id(struct rdma_cm_id *idp)
2415 {
2416 	struct rdma_cm_id	*new_idp;
2417 	sol_cma_chan_t		*chanp, *new_chanp;
2418 	ibcma_chan_t		*ibchanp, *new_ibchanp;
2419 
2420 	new_idp = cma_create_new_id(idp);
2421 	if (new_idp == NULL)
2422 		return (new_idp);
2423 	new_chanp = (sol_cma_chan_t *)new_idp;
2424 	new_ibchanp = &new_chanp->chan_ib;
2425 	chanp = (sol_cma_chan_t *)idp;
2426 	ibchanp = &chanp->chan_ib;
2427 	if (ibchanp->chan_devp) {
2428 		ibcma_dev_t	*devp;
2429 
2430 		devp = (ibcma_dev_t *)kmem_zalloc(sizeof (ibcma_dev_t),
2431 		    KM_SLEEP);
2432 		new_ibchanp->chan_devp = devp;
2433 		bcopy(ibchanp->chan_devp, devp, sizeof (ibcma_dev_t));
2434 	}
2435 
2436 	if (ibchanp->chan_pathp && ibchanp->chan_numpaths &&
2437 	    ibchanp->chan_path_size) {
2438 		new_ibchanp->chan_pathp = (ibt_path_info_t *)kmem_zalloc(
2439 		    ibchanp->chan_path_size, KM_SLEEP);
2440 		bcopy(ibchanp->chan_pathp, new_ibchanp->chan_pathp,
2441 		    ibchanp->chan_path_size);
2442 		new_ibchanp->chan_path_size = ibchanp->chan_path_size;
2443 		new_ibchanp->chan_numpaths = ibchanp->chan_numpaths;
2444 	}
2445 	bcopy(&ibchanp->chan_local_addr, &new_ibchanp->chan_local_addr,
2446 	    sizeof (ibt_ip_addr_t));
2447 	bcopy(&ibchanp->chan_remote_addr, &new_ibchanp->chan_remote_addr,
2448 	    sizeof (ibt_ip_addr_t));
2449 	new_ibchanp->chan_port = ibchanp->chan_port;
2450 	new_ibchanp->chan_sid = ibchanp->chan_sid;
2451 
2452 	return (new_idp);
2453 }
2454 
2455 static void
2456 ibcma_get_devlist(sol_cma_chan_t *root_chanp, ib_guid_t *hca_guidp,
2457     int num_hcas, genlist_t *ret_devlist, boolean_t with_ipaddr_only)
2458 {
2459 	int			i;
2460 	ibt_status_t		status;
2461 	ibcma_dev_t		*devp;
2462 	uint_t			num_ports, p;
2463 	uint_t			port_size;
2464 	ibt_hca_portinfo_t	*port_info, *tmp;
2465 	ibt_ip_addr_t		hca_ipaddr;
2466 
2467 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2468 	    "get_devlist(%p, %p, %x, %p, %x)", root_chanp, hca_guidp,
2469 	    num_hcas, ret_devlist, with_ipaddr_only);
2470 
2471 	init_genlist(ret_devlist);
2472 	for (i = 0; i < num_hcas; i++) {
2473 		status = ibt_query_hca_ports_byguid(hca_guidp[i], 0, &port_info,
2474 		    &num_ports, &port_size);
2475 		if (status !=  IBT_SUCCESS) {
2476 			SOL_OFS_DPRINTF_L2(sol_rdmacm_dbg_str,
2477 			    "ibt_query_hca_ports_byguid failed %d", status);
2478 			continue;
2479 		}
2480 
2481 		for (p = 0, tmp = port_info; p < num_ports; p++, tmp++) {
2482 			uint_t		s, num_sgids;
2483 			uint16_t	pk;
2484 			uint_t		num_pkeys;
2485 
2486 			if (tmp->p_linkstate != IBT_PORT_ACTIVE)
2487 				continue;
2488 
2489 			num_sgids = tmp->p_sgid_tbl_sz / sizeof (ib_gid_t);
2490 			num_pkeys = tmp->p_pkey_tbl_sz / sizeof (ib_pkey_t);
2491 
2492 			for (s = 0; s < num_sgids; s++) {
2493 				/* Skip holes in sgid table */
2494 				if (tmp->p_sgid_tbl[s].gid_guid == 0x0LL)
2495 					continue;
2496 				for (pk = 0; pk < num_pkeys; pk++) {
2497 					/* Skip holes in pkey table */
2498 					if (tmp->p_pkey_tbl[pk] == 0)
2499 						continue;
2500 					if (with_ipaddr_only == B_TRUE) {
2501 						status = ibt_get_src_ip(
2502 						    tmp->p_sgid_tbl[s],
2503 						    tmp->p_pkey_tbl[pk],
2504 						    &hca_ipaddr);
2505 						if (status != IBT_SUCCESS)
2506 							continue;
2507 					}
2508 
2509 					/* allocate devinfo & fill in info */
2510 					devp = kmem_zalloc(
2511 					    sizeof (ibcma_dev_t), KM_SLEEP);
2512 					devp->dev_node_guid = hca_guidp[i];
2513 					devp->dev_port_num = p + 1;
2514 					devp->dev_pkey_ix = pk;
2515 					devp->dev_pkey = tmp->p_pkey_tbl[pk];
2516 					devp->dev_sgid = tmp->p_sgid_tbl[s];
2517 					if (with_ipaddr_only == B_TRUE)
2518 						bcopy(&hca_ipaddr,
2519 						    &devp->dev_ipaddr,
2520 						    sizeof (ibt_ip_addr_t));
2521 
2522 					SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2523 					    "get_devlist: add2devlist "
2524 					    "node_guid %llx", hca_guidp[i]);
2525 					(void) add_genlist(ret_devlist,
2526 					    (uintptr_t)devp, NULL);
2527 				}
2528 			}
2529 		}
2530 		ibt_free_portinfo(port_info, port_size);
2531 	}
2532 }
2533 
2534 
2535 #ifdef	QP_DEBUG
2536 static void
2537 dump_qp_info(ibt_qp_hdl_t qphdl)
2538 {
2539 	ibt_qp_query_attr_t	qp_query;
2540 	ibt_qp_info_t		*qp_info;
2541 	ibt_status_t		status;
2542 	ibt_qp_rc_attr_t	*rcp;
2543 
2544 	bzero(&qp_query, sizeof (qp_query));
2545 	status = ibt_query_qp(qphdl, &qp_query);
2546 	if (status != IBT_SUCCESS) {
2547 		cmn_err(CE_WARN, "query_qp failed!!");
2548 		return;
2549 	}
2550 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2551 	    "QP HDL : %p, qp_sq_cq %p, qp_rq_cq %p, "
2552 	    "qp_rdd_hdl %p, qp_qpn %x, qp_sq_sgl %x, qp_rq_sgl %x, "
2553 	    "qp_srq %p, quer_attr.qp_flags %x",
2554 	    qphdl, qp_query.qp_sq_cq, qp_query.qp_rq_cq,
2555 	    qp_query.qp_rdd_hdl, qp_query.qp_qpn,
2556 	    qp_query.qp_sq_sgl, qp_query.qp_rq_sgl,
2557 	    qp_query.qp_srq, qp_query.qp_flags);
2558 	qp_info = &(qp_query.qp_info);
2559 	rcp = &((qp_info->qp_transport).rc);
2560 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2561 	    "qp_sq_sz %x, qp_rq_sz %x, qp_state %x, "
2562 	    "qp_current_state %x, qp_info.qp_flags %x, qp_trans %x",
2563 	    qp_info->qp_sq_sz, qp_info->qp_rq_sz, qp_info->qp_state,
2564 	    qp_info->qp_current_state, qp_info->qp_flags,
2565 	    qp_info->qp_trans);
2566 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2567 	    "rc_sq_psn %x, rc_rq_psn %x, rc_dst_qpn %x, "
2568 	    "rc_mig_state %x, rc_rnr_retry_cnt %x, rc_retry_cnt %x, "
2569 	    "rc_rdma_ra_out %x, rc_rdma_ra_in %x, rc_min_rnr_nak %x, "
2570 	    "rc_path_mtu %x", rcp->rc_sq_psn, rcp->rc_rq_psn,
2571 	    rcp->rc_dst_qpn, rcp->rc_mig_state, rcp->rc_rnr_retry_cnt,
2572 	    rcp->rc_retry_cnt, rcp->rc_rdma_ra_out, rcp->rc_rdma_ra_in,
2573 	    rcp->rc_min_rnr_nak, rcp->rc_path_mtu);
2574 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2575 	    "av_dgid %llx: %llx, av_sgid: %llx, "
2576 	    "srate %x, srvl %x, flow %x, tclass %x, hop %x, "
2577 	    "av_port_num %x, av_send_grh %x, av_dlid %x, "
2578 	    "av_src_path %x, av_sgid_ix %x, pkey_index %x, "
2579 	    "port_num %x",
2580 	    (rcp->rc_path).cep_adds_vect.av_sgid.gid_prefix,
2581 	    (rcp->rc_path).cep_adds_vect.av_sgid.gid_guid,
2582 	    (rcp->rc_path).cep_adds_vect.av_dgid.gid_prefix,
2583 	    (rcp->rc_path).cep_adds_vect.av_dgid.gid_guid,
2584 	    (rcp->rc_path).cep_adds_vect.av_srate,
2585 	    (rcp->rc_path).cep_adds_vect.av_srvl,
2586 	    (rcp->rc_path).cep_adds_vect.av_flow,
2587 	    (rcp->rc_path).cep_adds_vect.av_tclass,
2588 	    (rcp->rc_path).cep_adds_vect.av_hop,
2589 	    (rcp->rc_path).cep_adds_vect.av_port_num,
2590 	    (rcp->rc_path).cep_adds_vect.av_opaque1,
2591 	    (rcp->rc_path).cep_adds_vect.av_opaque2,
2592 	    (rcp->rc_path).cep_adds_vect.av_opaque3,
2593 	    (rcp->rc_path).cep_adds_vect.av_opaque4,
2594 	    (rcp->rc_path).cep_pkey_ix,
2595 	    (rcp->rc_path).cep_hca_port_num);
2596 }
2597 #endif
2598 
2599 static void
2600 dump_priv_data(void *priv_data, ibt_priv_data_len_t arr_len,
2601     ibt_priv_data_len_t priv_len, char *caller)
2602 {
2603 	uint8_t	i;
2604 	uchar_t *c = (uchar_t *)priv_data;
2605 
2606 	SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str, "priv_data to %s: %p, len %d",
2607 	    caller, priv_data, priv_len);
2608 	if (!priv_len || !priv_data)
2609 		return;
2610 
2611 	/* Display in rows of 16 uchar_t */
2612 	for (i = 0; i < arr_len; i += 16)
2613 		SOL_OFS_DPRINTF_L5(sol_rdmacm_dbg_str,
2614 		    "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
2615 		    c[i], c[i + 1], c[i + 2], c[i + 3], c[i + 4], c[i + 5],
2616 		    c[i + 6], c[i + 7], c[i + 8], c[i + 9], c[i + 10],
2617 		    c[i + 11], c[i + 12], c[i + 13], c[i + 14], c[i + 15]);
2618 
2619 }
2620