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