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