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