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