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