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