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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * ibtl_chan.c 28 * 29 * This file contains Transport API functions related to Channel Functions 30 * and internal Protection Domain and Address Handle Verbs functions. 31 */ 32 33 #include <sys/ib/ibtl/impl/ibtl.h> 34 #include <sys/ib/ibtl/impl/ibtl_cm.h> 35 #include <sys/ib/ib_pkt_hdrs.h> 36 37 static char ibtl_chan[] = "ibtl_chan"; 38 39 /* 40 * RC Channel. 41 */ 42 /* 43 * Function: 44 * ibt_alloc_rc_channel 45 * Input: 46 * hca_hdl HCA Handle. 47 * flags Channel allocate flags. 48 * args A pointer to an ibt_rc_chan_alloc_args_t struct that 49 * specifies required channel attributes. 50 * Output: 51 * rc_chan_p The returned RC Channel handle. 52 * sizes NULL or a pointer to ibt_chan_sizes_s struct where 53 * new SendQ/RecvQ, and WR SGL sizes are returned. 54 * Returns: 55 * IBT_SUCCESS 56 * IBT_INVALID_PARAM 57 * Description: 58 * Allocates a RC communication channels that satisfy the specified 59 * channel attributes. 60 */ 61 ibt_status_t 62 ibt_alloc_rc_channel(ibt_hca_hdl_t hca_hdl, ibt_chan_alloc_flags_t flags, 63 ibt_rc_chan_alloc_args_t *args, ibt_channel_hdl_t *rc_chan_p, 64 ibt_chan_sizes_t *sizes) 65 { 66 ibt_status_t retval; 67 ibt_qp_alloc_attr_t qp_attr; 68 ibt_qp_info_t qp_modify_attr; 69 ibt_channel_hdl_t chanp; 70 71 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_rc_channel(%p, %x, %p, %p)", 72 hca_hdl, flags, args, sizes); 73 74 bzero(&qp_modify_attr, sizeof (ibt_qp_info_t)); 75 76 qp_attr.qp_alloc_flags = IBT_QP_NO_FLAGS; 77 if (flags & IBT_ACHAN_USER_MAP) 78 qp_attr.qp_alloc_flags |= IBT_QP_USER_MAP; 79 80 if (flags & IBT_ACHAN_DEFER_ALLOC) 81 qp_attr.qp_alloc_flags |= IBT_QP_DEFER_ALLOC; 82 83 if (flags & IBT_ACHAN_USES_SRQ) { 84 if (args->rc_srq == NULL) { 85 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: " 86 "NULL SRQ Handle specified."); 87 return (IBT_INVALID_PARAM); 88 } 89 qp_attr.qp_alloc_flags |= IBT_QP_USES_SRQ; 90 } 91 92 /* 93 * Check if this request is to clone the channel, or to allocate a 94 * fresh one. 95 */ 96 if (flags & IBT_ACHAN_CLONE) { 97 98 ibt_rc_chan_query_attr_t chan_attrs; 99 100 if (args->rc_clone_chan == NULL) { 101 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: " 102 "Clone Channel info not available."); 103 return (IBT_INVALID_PARAM); 104 } else if (args->rc_clone_chan->ch_qp.qp_hca != hca_hdl) { 105 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: " 106 "Clone Channel's & requested HCA Handle mismatch"); 107 return (IBT_INVALID_PARAM); 108 } 109 110 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_rc_channel: " 111 "Clone <%p> - RC Channel", args->rc_clone_chan); 112 113 /* 114 * Query the source channel, to obtained the attributes 115 * so that the new channel share the same attributes. 116 */ 117 retval = ibt_query_rc_channel(args->rc_clone_chan, &chan_attrs); 118 if (retval != IBT_SUCCESS) { 119 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: " 120 "Failed to query the source channel: %d", retval); 121 return (retval); 122 } 123 124 /* Setup QP alloc attributes. */ 125 qp_attr.qp_scq_hdl = chan_attrs.rc_scq; 126 qp_attr.qp_rcq_hdl = chan_attrs.rc_rcq; 127 qp_attr.qp_pd_hdl = chan_attrs.rc_pd; 128 qp_attr.qp_flags = chan_attrs.rc_flags; 129 qp_attr.qp_srq_hdl = chan_attrs.rc_srq; 130 131 bcopy(&chan_attrs.rc_chan_sizes, &qp_attr.qp_sizes, 132 sizeof (ibt_chan_sizes_t)); 133 134 qp_modify_attr.qp_flags = chan_attrs.rc_control; 135 qp_modify_attr.qp_transport.rc.rc_path.cep_hca_port_num = 136 chan_attrs.rc_prim_path.cep_hca_port_num; 137 qp_modify_attr.qp_transport.rc.rc_path.cep_pkey_ix = 138 chan_attrs.rc_prim_path.cep_pkey_ix; 139 140 } else { 141 142 /* Setup QP alloc attributes. */ 143 qp_attr.qp_scq_hdl = args->rc_scq; 144 qp_attr.qp_rcq_hdl = args->rc_rcq; 145 qp_attr.qp_pd_hdl = args->rc_pd; 146 qp_attr.qp_flags = args->rc_flags; 147 qp_attr.qp_srq_hdl = args->rc_srq; 148 149 bcopy(&args->rc_sizes, &qp_attr.qp_sizes, 150 sizeof (ibt_chan_sizes_t)); 151 152 qp_modify_attr.qp_flags = args->rc_control; 153 154 if ((args->rc_hca_port_num == 0) || 155 (args->rc_hca_port_num > IBTL_HCA2NPORTS(hca_hdl))) { 156 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: " 157 "Invalid port_num %d, range is (1 to %d)", 158 args->rc_hca_port_num, IBTL_HCA2NPORTS(hca_hdl)); 159 return (IBT_HCA_PORT_INVALID); 160 } 161 qp_modify_attr.qp_transport.rc.rc_path.cep_hca_port_num = 162 args->rc_hca_port_num; 163 164 /* 165 * We allocate the Channel initially with the default PKey, 166 * and later client can update this when the channel is opened 167 * with the pkey returned from a path record lookup. 168 */ 169 mutex_enter(&ibtl_clnt_list_mutex); 170 qp_modify_attr.qp_transport.rc.rc_path.cep_pkey_ix = 171 hca_hdl->ha_hca_devp-> 172 hd_portinfop[args->rc_hca_port_num - 1].p_def_pkey_ix; 173 mutex_exit(&ibtl_clnt_list_mutex); 174 } 175 176 /* Allocate Channel and Initialize the channel. */ 177 retval = ibt_alloc_qp(hca_hdl, IBT_RC_RQP, &qp_attr, sizes, NULL, 178 &chanp); 179 if (retval != IBT_SUCCESS) { 180 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: " 181 "Failed to allocate QP: %d", retval); 182 *rc_chan_p = NULL; 183 return (retval); 184 } 185 186 qp_modify_attr.qp_trans = IBT_RC_SRV; 187 188 /* Initialize RC Channel by transitioning it to INIT State. */ 189 retval = ibt_initialize_qp(chanp, &qp_modify_attr); 190 if (retval != IBT_SUCCESS) { 191 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: " 192 "Failed to Initialize QP: %d", retval); 193 194 /* Free the QP as we failed to initialize it. */ 195 (void) ibt_free_qp(chanp); 196 197 *rc_chan_p = NULL; 198 return (retval); 199 } 200 201 *rc_chan_p = chanp; 202 203 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_rc_channel(%p): - SUCCESS (%p)", 204 hca_hdl, chanp); 205 206 return (IBT_SUCCESS); 207 } 208 209 210 /* 211 * Function: 212 * ibt_query_rc_channel 213 * Input: 214 * rc_chan A previously allocated channel handle. 215 * chan_attrs A pointer to an ibt_rc_chan_query_args_t struct where 216 * Channel's current attributes are returned. 217 * Output: 218 * chan_attrs A pointer to an ibt_rc_chan_query_args_t struct where 219 * Channel's current attributes are returned. 220 * Returns: 221 * IBT_SUCCESS 222 * Description: 223 * Query an RC channel's attributes. 224 */ 225 ibt_status_t 226 ibt_query_rc_channel(ibt_channel_hdl_t rc_chan, 227 ibt_rc_chan_query_attr_t *chan_attrs) 228 { 229 ibt_status_t retval; 230 ibt_qp_query_attr_t qp_attr; 231 232 IBTF_DPRINTF_L3(ibtl_chan, "ibt_query_rc_channel(%p, %p)", 233 rc_chan, chan_attrs); 234 235 if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) { 236 IBTF_DPRINTF_L2(ibtl_chan, "ibt_query_rc_channel: " 237 "type of channel (%d) is not RC", rc_chan->ch_qp.qp_type); 238 return (IBT_CHAN_SRV_TYPE_INVALID); 239 } 240 241 bzero(&qp_attr, sizeof (ibt_qp_query_attr_t)); 242 243 /* Query the channel (QP) */ 244 retval = ibt_query_qp(rc_chan, &qp_attr); 245 if (retval != IBT_SUCCESS) { 246 IBTF_DPRINTF_L2(ibtl_chan, "ibt_query_rc_channel: " 247 "ibt_query_qp failed on QP %p: %d", rc_chan, retval); 248 return (retval); 249 } 250 251 chan_attrs->rc_hca_guid = IBTL_HCA2HCAGUID(IBTL_CHAN2HCA(rc_chan)); 252 253 chan_attrs->rc_scq = qp_attr.qp_sq_cq; 254 chan_attrs->rc_rcq = qp_attr.qp_rq_cq; 255 chan_attrs->rc_pd = rc_chan->ch_qp.qp_pd_hdl; 256 chan_attrs->rc_state = qp_attr.qp_info.qp_state; 257 chan_attrs->rc_path_mtu = qp_attr.qp_info.qp_transport.rc.rc_path_mtu; 258 chan_attrs->rc_path_retry_cnt = 259 qp_attr.qp_info.qp_transport.rc.rc_retry_cnt; 260 chan_attrs->rc_path_rnr_retry_cnt = 261 qp_attr.qp_info.qp_transport.rc.rc_rnr_retry_cnt; 262 chan_attrs->rc_min_rnr_nak = 263 qp_attr.qp_info.qp_transport.rc.rc_min_rnr_nak; 264 265 chan_attrs->rc_prim_path = qp_attr.qp_info.qp_transport.rc.rc_path; 266 chan_attrs->rc_alt_path = qp_attr.qp_info.qp_transport.rc.rc_alt_path; 267 268 chan_attrs->rc_chan_sizes.cs_sq = qp_attr.qp_info.qp_sq_sz; 269 chan_attrs->rc_chan_sizes.cs_rq = qp_attr.qp_info.qp_rq_sz; 270 chan_attrs->rc_chan_sizes.cs_sq_sgl = qp_attr.qp_sq_sgl; 271 chan_attrs->rc_chan_sizes.cs_rq_sgl = qp_attr.qp_rq_sgl; 272 chan_attrs->rc_srq = qp_attr.qp_srq; 273 274 chan_attrs->rc_rdma_ra_out = 275 qp_attr.qp_info.qp_transport.rc.rc_rdma_ra_out; 276 chan_attrs->rc_rdma_ra_in = 277 qp_attr.qp_info.qp_transport.rc.rc_rdma_ra_in; 278 279 chan_attrs->rc_flags = rc_chan->ch_qp.qp_flags; 280 chan_attrs->rc_control = qp_attr.qp_info.qp_flags; 281 chan_attrs->rc_mig_state = qp_attr.qp_info.qp_transport.rc.rc_mig_state; 282 283 chan_attrs->rc_qpn = qp_attr.qp_qpn & IB_QPN_MASK; 284 chan_attrs->rc_dst_qpn = 285 qp_attr.qp_info.qp_transport.rc.rc_dst_qpn & IB_QPN_MASK; 286 287 return (retval); 288 } 289 290 291 /* 292 * Function: 293 * ibt_modify_rc_channel 294 * Input: 295 * rc_chan A previously allocated channel handle. 296 * flags Specifies which attributes in ibt_rc_chan_modify_attr_t 297 * are to be modified. 298 * attrs Attributes to be modified. 299 * Output: 300 * actual_sz On return contains the new send and receive queue sizes. 301 * Returns: 302 * IBT_SUCCESS 303 * Description: 304 * Modifies an RC channel's attributes, as specified by a 305 * ibt_cep_modify_flags_t parameter to those specified in the 306 * ibt_rc_chan_modify_attr_t structure. 307 */ 308 ibt_status_t 309 ibt_modify_rc_channel(ibt_channel_hdl_t rc_chan, ibt_cep_modify_flags_t flags, 310 ibt_rc_chan_modify_attr_t *attrs, ibt_queue_sizes_t *actual_sz) 311 { 312 ibt_status_t retval; 313 ibt_qp_info_t qp_info; 314 int retries = 1; 315 316 IBTF_DPRINTF_L3(ibtl_chan, "ibt_modify_rc_channel(%p, %x, %p, %p)", 317 rc_chan, flags, attrs, actual_sz); 318 319 if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) { 320 IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_rc_channel: " 321 "type of channel (%d) is not RC", rc_chan->ch_qp.qp_type); 322 return (IBT_CHAN_SRV_TYPE_INVALID); 323 } 324 325 retry: 326 bzero(&qp_info, sizeof (ibt_qp_info_t)); 327 328 if (flags & IBT_CEP_SET_ADDS_VECT) { 329 bcopy(&attrs->rc_prim_adds_vect, 330 &qp_info.qp_transport.rc.rc_path.cep_adds_vect, 331 sizeof (ibt_adds_vect_t)); 332 } 333 334 qp_info.qp_trans = IBT_RC_SRV; 335 qp_info.qp_transport.rc.rc_path.cep_hca_port_num = 336 attrs->rc_prim_port_num; 337 qp_info.qp_transport.rc.rc_retry_cnt = attrs->rc_path_retry_cnt; 338 qp_info.qp_transport.rc.rc_rnr_retry_cnt = 339 attrs->rc_path_rnr_retry_cnt; 340 qp_info.qp_transport.rc.rc_rdma_ra_out = attrs->rc_rdma_ra_out; 341 qp_info.qp_transport.rc.rc_rdma_ra_in = attrs->rc_rdma_ra_in; 342 343 /* Current channel state must be either SQD or RTS. */ 344 qp_info.qp_current_state = rc_chan->ch_current_state; 345 qp_info.qp_state = rc_chan->ch_current_state; /* No Change in State */ 346 347 qp_info.qp_flags = attrs->rc_control; 348 qp_info.qp_sq_sz = attrs->rc_sq_sz; 349 qp_info.qp_rq_sz = attrs->rc_rq_sz; 350 qp_info.qp_transport.rc.rc_min_rnr_nak = attrs->rc_min_rnr_nak; 351 352 if (flags & IBT_CEP_SET_ALT_PATH) { 353 bcopy(&attrs->rc_alt_adds_vect, 354 &qp_info.qp_transport.rc.rc_alt_path.cep_adds_vect, 355 sizeof (ibt_adds_vect_t)); 356 qp_info.qp_transport.rc.rc_alt_path.cep_hca_port_num = 357 attrs->rc_alt_port_num; 358 } 359 360 flags |= IBT_CEP_SET_STATE; 361 362 retval = ibt_modify_qp(rc_chan, flags, &qp_info, actual_sz); 363 if (retval != IBT_SUCCESS) { 364 IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_rc_channel: " 365 "ibt_modify_qp failed on QP %p: %d", rc_chan, retval); 366 /* give it one more shot if the old current state was stale */ 367 if (qp_info.qp_current_state != rc_chan->ch_current_state && 368 --retries >= 0 && 369 (qp_info.qp_current_state == IBT_STATE_RTS || 370 qp_info.qp_current_state == IBT_STATE_SQD)) 371 goto retry; 372 } 373 374 return (retval); 375 } 376 377 378 /* 379 * UD Channel. 380 */ 381 /* 382 * Function: 383 * ibt_alloc_ud_channel 384 * Input: 385 * hca_hdl HCA Handle. 386 * flags Channel allocate flags. 387 * args A pointer to an ibt_ud_chan_alloc_args_t struct that 388 * specifies required channel attributes. 389 * Output: 390 * ud_chan_p The returned UD Channel handle. 391 * sizes NULL or a pointer to ibt_chan_sizes_s struct where 392 * new SendQ/RecvQ, and WR SGL sizes are returned. 393 * Returns: 394 * IBT_SUCCESS 395 * IBT_INVALID_PARAM 396 * Description: 397 * Allocate UD channels that satisfy the specified channel attributes. 398 */ 399 ibt_status_t 400 ibt_alloc_ud_channel(ibt_hca_hdl_t hca_hdl, ibt_chan_alloc_flags_t flags, 401 ibt_ud_chan_alloc_args_t *args, ibt_channel_hdl_t *ud_chan_p, 402 ibt_chan_sizes_t *sizes) 403 { 404 ibt_status_t retval; 405 ibt_qp_alloc_attr_t qp_attr; 406 ibt_qp_info_t qp_modify_attr; 407 ibt_channel_hdl_t chanp; 408 409 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_ud_channel(%p, %x, %p, %p)", 410 hca_hdl, flags, args, sizes); 411 412 bzero(&qp_modify_attr, sizeof (ibt_qp_info_t)); 413 414 qp_attr.qp_alloc_flags = IBT_QP_NO_FLAGS; 415 if (flags & IBT_ACHAN_USER_MAP) 416 qp_attr.qp_alloc_flags |= IBT_QP_USER_MAP; 417 418 if (flags & IBT_ACHAN_DEFER_ALLOC) 419 qp_attr.qp_alloc_flags |= IBT_QP_DEFER_ALLOC; 420 421 if (flags & IBT_ACHAN_USES_SRQ) { 422 if (args->ud_srq == NULL) { 423 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: " 424 "NULL SRQ Handle specified."); 425 return (IBT_INVALID_PARAM); 426 } 427 qp_attr.qp_alloc_flags |= IBT_QP_USES_SRQ; 428 } 429 430 /* 431 * Check if this request is to clone the channel, or to allocate a 432 * fresh one. 433 */ 434 if (flags & IBT_ACHAN_CLONE) { 435 436 ibt_ud_chan_query_attr_t chan_attrs; 437 438 if (args->ud_clone_chan == NULL) { 439 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: " 440 "Clone Channel info not available."); 441 return (IBT_INVALID_PARAM); 442 } else if (args->ud_clone_chan->ch_qp.qp_hca != hca_hdl) { 443 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: " 444 "Clone Channel and HCA Handle mismatch"); 445 return (IBT_INVALID_PARAM); 446 } 447 448 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_ud_channel: " 449 "Clone <%p> - UD Channel", args->ud_clone_chan); 450 451 retval = ibt_query_ud_channel(args->ud_clone_chan, &chan_attrs); 452 if (retval != IBT_SUCCESS) { 453 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: " 454 "Failed to Query the source channel: %d", retval); 455 return (retval); 456 } 457 458 /* Setup QP alloc attributes. */ 459 qp_attr.qp_scq_hdl = chan_attrs.ud_scq; 460 qp_attr.qp_rcq_hdl = chan_attrs.ud_rcq; 461 qp_attr.qp_pd_hdl = chan_attrs.ud_pd; 462 qp_attr.qp_flags = chan_attrs.ud_flags; 463 qp_attr.qp_srq_hdl = chan_attrs.ud_srq; 464 465 bcopy(&chan_attrs.ud_chan_sizes, &qp_attr.qp_sizes, 466 sizeof (ibt_chan_sizes_t)); 467 468 qp_modify_attr.qp_transport.ud.ud_port = 469 chan_attrs.ud_hca_port_num; 470 qp_modify_attr.qp_transport.ud.ud_qkey = chan_attrs.ud_qkey; 471 qp_modify_attr.qp_transport.ud.ud_pkey_ix = 472 chan_attrs.ud_pkey_ix; 473 } else { 474 ib_pkey_t tmp_pkey; 475 476 /* Setup QP alloc attributes. */ 477 qp_attr.qp_scq_hdl = args->ud_scq; 478 qp_attr.qp_rcq_hdl = args->ud_rcq; 479 qp_attr.qp_pd_hdl = args->ud_pd; 480 qp_attr.qp_flags = args->ud_flags; 481 qp_attr.qp_srq_hdl = args->ud_srq; 482 483 bcopy(&args->ud_sizes, &qp_attr.qp_sizes, 484 sizeof (ibt_chan_sizes_t)); 485 486 qp_modify_attr.qp_transport.ud.ud_port = args->ud_hca_port_num; 487 qp_modify_attr.qp_transport.ud.ud_qkey = args->ud_qkey; 488 489 /* Validate input hca_port_num and pkey_ix values. */ 490 if ((retval = ibt_index2pkey(hca_hdl, args->ud_hca_port_num, 491 args->ud_pkey_ix, &tmp_pkey)) != IBT_SUCCESS) { 492 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: " 493 "ibt_index2pkey failed, status: %d", retval); 494 *ud_chan_p = NULL; 495 return (retval); 496 } 497 qp_modify_attr.qp_transport.ud.ud_pkey_ix = args->ud_pkey_ix; 498 } 499 500 /* Allocate Channel and Initialize the channel. */ 501 retval = ibt_alloc_qp(hca_hdl, IBT_UD_RQP, &qp_attr, sizes, NULL, 502 &chanp); 503 if (retval != IBT_SUCCESS) { 504 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: " 505 "Failed to allocate QP: %d", retval); 506 *ud_chan_p = NULL; 507 return (retval); 508 } 509 510 /* Initialize UD Channel by transitioning it to RTS State. */ 511 qp_modify_attr.qp_trans = IBT_UD_SRV; 512 qp_modify_attr.qp_flags = IBT_CEP_NO_FLAGS; 513 qp_modify_attr.qp_transport.ud.ud_sq_psn = 0; 514 515 retval = ibt_initialize_qp(chanp, &qp_modify_attr); 516 if (retval != IBT_SUCCESS) { 517 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: " 518 "Failed to Initialize QP: %d", retval); 519 520 /* Free the QP as we failed to initialize it. */ 521 (void) ibt_free_qp(chanp); 522 523 *ud_chan_p = NULL; 524 return (retval); 525 } 526 527 *ud_chan_p = chanp; 528 529 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_ud_channel(%p): - SUCCESS (%p)", 530 hca_hdl, chanp); 531 532 return (IBT_SUCCESS); 533 } 534 535 536 /* 537 * Function: 538 * ibt_query_ud_channel 539 * Input: 540 * ud_chan A previously allocated UD channel handle. 541 * Output: 542 * chan_attrs Channel's current attributes. 543 * Returns: 544 * IBT_SUCCESS 545 * Description: 546 * Query a UD channel's attributes. 547 */ 548 ibt_status_t 549 ibt_query_ud_channel(ibt_channel_hdl_t ud_chan, 550 ibt_ud_chan_query_attr_t *ud_chan_attrs) 551 { 552 ibt_status_t retval; 553 ibt_qp_query_attr_t qp_attr; 554 555 IBTF_DPRINTF_L3(ibtl_chan, "ibt_query_ud_channel(%p, %p)", 556 ud_chan, ud_chan_attrs); 557 558 if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) { 559 IBTF_DPRINTF_L2(ibtl_chan, "ibt_query_ud_channel: " 560 "type of channel (%d) is not UD", ud_chan->ch_qp.qp_type); 561 return (IBT_CHAN_SRV_TYPE_INVALID); 562 } 563 564 bzero(&qp_attr, sizeof (ibt_qp_query_attr_t)); 565 566 /* Query the channel (QP) */ 567 retval = ibt_query_qp(ud_chan, &qp_attr); 568 if (retval != IBT_SUCCESS) { 569 IBTF_DPRINTF_L2(ibtl_chan, "ibt_query_ud_channel: " 570 "ibt_query_qp failed on QP %p: %d", ud_chan, retval); 571 return (retval); 572 } 573 574 ud_chan_attrs->ud_qpn = qp_attr.qp_qpn & IB_QPN_MASK; 575 ud_chan_attrs->ud_hca_guid = IBTL_HCA2HCAGUID(IBTL_CHAN2HCA(ud_chan)); 576 577 ud_chan_attrs->ud_scq = qp_attr.qp_sq_cq; 578 ud_chan_attrs->ud_rcq = qp_attr.qp_rq_cq; 579 ud_chan_attrs->ud_pd = ud_chan->ch_qp.qp_pd_hdl; 580 581 ud_chan_attrs->ud_hca_port_num = 582 qp_attr.qp_info.qp_transport.ud.ud_port; 583 584 ud_chan_attrs->ud_state = qp_attr.qp_info.qp_state; 585 ud_chan_attrs->ud_pkey_ix = qp_attr.qp_info.qp_transport.ud.ud_pkey_ix; 586 ud_chan_attrs->ud_qkey = qp_attr.qp_info.qp_transport.ud.ud_qkey; 587 588 ud_chan_attrs->ud_chan_sizes.cs_sq = qp_attr.qp_info.qp_sq_sz; 589 ud_chan_attrs->ud_chan_sizes.cs_rq = qp_attr.qp_info.qp_rq_sz; 590 ud_chan_attrs->ud_chan_sizes.cs_sq_sgl = qp_attr.qp_sq_sgl; 591 ud_chan_attrs->ud_chan_sizes.cs_rq_sgl = qp_attr.qp_rq_sgl; 592 ud_chan_attrs->ud_srq = qp_attr.qp_srq; 593 594 ud_chan_attrs->ud_flags = ud_chan->ch_qp.qp_flags; 595 596 return (retval); 597 } 598 599 600 /* 601 * Function: 602 * ibt_modify_ud_channel 603 * Input: 604 * ud_chan A previously allocated UD channel handle. 605 * flags Specifies which attributes in ibt_ud_chan_modify_attr_t 606 * are to be modified. 607 * attrs Attributes to be modified. 608 * Output: 609 * actual_sz On return contains the new send and receive queue sizes. 610 * Returns: 611 * IBT_SUCCESS 612 * Description: 613 * Modifies an UD channel's attributes, as specified by a 614 * ibt_cep_modify_flags_t parameter to those specified in the 615 * ibt_ud_chan_modify_attr_t structure. 616 */ 617 ibt_status_t 618 ibt_modify_ud_channel(ibt_channel_hdl_t ud_chan, ibt_cep_modify_flags_t flags, 619 ibt_ud_chan_modify_attr_t *attrs, ibt_queue_sizes_t *actual_sz) 620 { 621 ibt_status_t retval; 622 ibt_qp_info_t qp_info; 623 ibt_cep_modify_flags_t good_flags; 624 int retries = 1; 625 626 IBTF_DPRINTF_L3(ibtl_chan, "ibt_modify_ud_channel(%p, %x, %p, %p)", 627 ud_chan, flags, attrs, actual_sz); 628 629 if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) { 630 IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_ud_channel: " 631 "type of channel (%d) is not UD", ud_chan->ch_qp.qp_type); 632 return (IBT_CHAN_SRV_TYPE_INVALID); 633 } 634 635 good_flags = IBT_CEP_SET_SQ_SIZE | IBT_CEP_SET_RQ_SIZE | 636 IBT_CEP_SET_QKEY; 637 638 if (flags & ~good_flags) { 639 IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_ud_channel: " 640 "Invalid Modify Flags: %x", flags); 641 return (IBT_INVALID_PARAM); 642 } 643 644 retry: 645 bzero(&qp_info, sizeof (ibt_qp_info_t)); 646 647 qp_info.qp_state = ud_chan->ch_current_state; /* No Change in State */ 648 qp_info.qp_current_state = ud_chan->ch_current_state; 649 qp_info.qp_flags = IBT_CEP_NO_FLAGS; 650 651 qp_info.qp_sq_sz = attrs->ud_sq_sz; 652 qp_info.qp_rq_sz = attrs->ud_rq_sz; 653 qp_info.qp_trans = IBT_UD_SRV; 654 qp_info.qp_transport.ud.ud_qkey = attrs->ud_qkey; 655 656 flags |= IBT_CEP_SET_STATE; 657 658 retval = ibt_modify_qp(ud_chan, flags, &qp_info, actual_sz); 659 if (retval != IBT_SUCCESS) { 660 IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_ud_channel: " 661 "ibt_modify_qp failed on QP %p: %d", ud_chan, retval); 662 /* give it one more shot if the old current state was stale */ 663 if (qp_info.qp_current_state != ud_chan->ch_current_state && 664 --retries >= 0 && 665 (qp_info.qp_current_state == IBT_STATE_RTS || 666 qp_info.qp_current_state == IBT_STATE_SQD)) 667 goto retry; 668 } 669 670 return (retval); 671 } 672 673 674 /* 675 * Function: 676 * ibt_recover_ud_channel 677 * Input: 678 * ud_chan An UD channel handle which is in SQError state. 679 * Output: 680 * none. 681 * Returns: 682 * IBT_SUCCESS 683 * IBT_CHAN_HDL_INVALID 684 * IBT_CHAN_SRV_TYPE_INVALID 685 * IBT_CHAN_STATE_INVALID 686 * Description: 687 * Recover an UD Channel which has transitioned to SQ Error state. The 688 * ibt_recover_ud_channel() transitions the channel from SQ Error state 689 * to Ready-To-Send channel state. 690 * 691 * If a work request posted to a UD channel's send queue completes with 692 * an error (see ibt_wc_status_t), the channel gets transitioned to SQ 693 * Error state. In order to reuse this channel, ibt_recover_ud_channel() 694 * can be used to recover the channel to a usable (Ready-to-Send) state. 695 */ 696 ibt_status_t 697 ibt_recover_ud_channel(ibt_channel_hdl_t ud_chan) 698 { 699 ibt_qp_info_t modify_attr; 700 ibt_status_t retval; 701 702 IBTF_DPRINTF_L3(ibtl_chan, "ibt_recover_ud_channel(%p)", ud_chan); 703 704 if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) { 705 IBTF_DPRINTF_L2(ibtl_chan, "ibt_recover_ud_channel: " 706 "Called for non-UD channels<%d>", ud_chan->ch_qp.qp_type); 707 return (IBT_CHAN_SRV_TYPE_INVALID); 708 } 709 710 bzero(&modify_attr, sizeof (ibt_qp_info_t)); 711 712 /* Set the channel state to RTS, to activate the send processing. */ 713 modify_attr.qp_state = IBT_STATE_RTS; 714 modify_attr.qp_trans = ud_chan->ch_qp.qp_type; 715 modify_attr.qp_current_state = IBT_STATE_SQE; 716 717 retval = ibt_modify_qp(ud_chan, IBT_CEP_SET_STATE, &modify_attr, NULL); 718 719 if (retval != IBT_SUCCESS) 720 IBTF_DPRINTF_L2(ibtl_chan, "ibt_recover_ud_channel: " 721 "ibt_modify_qp failed on qp %p: status = %d", 722 ud_chan, retval); 723 724 return (retval); 725 } 726 727 728 /* 729 * Function: 730 * ibt_flush_channel 731 * Input: 732 * chan The opaque channel handle returned in a previous call 733 * to ibt_alloc_ud_channel() or ibt_alloc_rc_channel(). 734 * Output: 735 * none. 736 * Returns: 737 * IBT_SUCCESS 738 * Description: 739 * Flush the specified channel. Outstanding work requests are flushed 740 * so that the client can do the associated clean up. After that, the 741 * client will usually deregister the previously registered memory, 742 * then free the channel by calling ibt_free_channel(). This function 743 * applies to UD channels, or to RC channels that have not successfully 744 * been opened. 745 */ 746 ibt_status_t 747 ibt_flush_channel(ibt_channel_hdl_t chan) 748 { 749 ibt_status_t retval; 750 751 IBTF_DPRINTF_L3(ibtl_chan, "ibt_flush_channel(%p)", chan); 752 753 retval = ibt_flush_qp(chan); 754 if (retval != IBT_SUCCESS) { 755 IBTF_DPRINTF_L2(ibtl_chan, "ibt_flush_channel: " 756 "ibt_flush_qp failed on QP %p: %d", chan, retval); 757 } 758 759 return (retval); 760 } 761 762 763 /* 764 * Function: 765 * ibt_free_channel 766 * Input: 767 * chan The opaque channel handle returned in a previous 768 * call to ibt_alloc_{ud,rc}_channel(). 769 * Output: 770 * none. 771 * Returns: 772 * IBT_SUCCESS 773 * Description: 774 * Releases the resources associated with the specified channel. 775 * It is well assumed that channel has been closed before this. 776 */ 777 ibt_status_t 778 ibt_free_channel(ibt_channel_hdl_t chan) 779 { 780 return (ibt_free_qp(chan)); 781 } 782 783 784 /* 785 * UD Destination. 786 */ 787 /* 788 * Function: 789 * ibt_alloc_ud_dest 790 * Input: 791 * hca_hdl HCA Handle. 792 * pd Protection Domain 793 * Output: 794 * ud_dest_p Address to store the returned UD destination handle. 795 * Returns: 796 * IBT_SUCCESS 797 * Description: 798 * Allocate a UD destination handle. The returned UD destination handle 799 * has no useful contents, but is usable after calling ibt_modify_ud_dest, 800 * ibt_modify_reply_ud_dest, or ibt_open_ud_dest. 801 */ 802 ibt_status_t 803 ibt_alloc_ud_dest(ibt_hca_hdl_t hca_hdl, ibt_ud_dest_flags_t flags, 804 ibt_pd_hdl_t pd, ibt_ud_dest_hdl_t *ud_dest_p) 805 { 806 ibt_status_t retval; 807 ibt_ud_dest_t *ud_destp; 808 ibt_ah_hdl_t ah; 809 ibt_adds_vect_t adds_vect; 810 811 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_ud_dest(%p, %x, %p)", 812 hca_hdl, flags, pd); 813 814 bzero(&adds_vect, sizeof (adds_vect)); 815 adds_vect.av_port_num = 1; 816 adds_vect.av_srate = IBT_SRATE_1X; /* assume the minimum */ 817 retval = ibt_alloc_ah(hca_hdl, flags, pd, &adds_vect, &ah); 818 if (retval != IBT_SUCCESS) { 819 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_dest: " 820 "Address Handle Allocation failed: %d", retval); 821 *ud_dest_p = NULL; 822 return (retval); 823 } 824 ud_destp = kmem_alloc(sizeof (*ud_destp), KM_SLEEP); 825 ud_destp->ud_ah = ah; 826 ud_destp->ud_dest_hca = hca_hdl; 827 ud_destp->ud_dst_qpn = 0; 828 ud_destp->ud_qkey = 0; 829 *ud_dest_p = ud_destp; 830 return (IBT_SUCCESS); 831 } 832 833 /* 834 * Function: 835 * ibt_query_ud_dest 836 * Input: 837 * ud_dest A previously allocated UD destination handle. 838 * Output: 839 * dest_attrs UD destination's current attributes. 840 * Returns: 841 * IBT_SUCCESS 842 * Description: 843 * Query a UD destination's attributes. 844 */ 845 ibt_status_t 846 ibt_query_ud_dest(ibt_ud_dest_hdl_t ud_dest, 847 ibt_ud_dest_query_attr_t *dest_attrs) 848 { 849 ibt_status_t retval; 850 851 ASSERT(dest_attrs != NULL); 852 853 /* Query Address Handle */ 854 retval = ibt_query_ah(ud_dest->ud_dest_hca, ud_dest->ud_ah, 855 &dest_attrs->ud_pd, &dest_attrs->ud_addr_vect); 856 857 if (retval != IBT_SUCCESS) { 858 IBTF_DPRINTF_L2(ibtl_chan, "ibt_query_ud_dest: " 859 "Failed to Query Address Handle: %d", retval); 860 return (retval); 861 } 862 863 /* Update the return struct. */ 864 dest_attrs->ud_hca_hdl = ud_dest->ud_dest_hca; 865 dest_attrs->ud_dst_qpn = ud_dest->ud_dst_qpn; 866 dest_attrs->ud_qkey = ud_dest->ud_qkey; 867 868 return (retval); 869 } 870 871 /* 872 * Function: 873 * ibt_modify_ud_dest 874 * Input: 875 * ud_dest A previously allocated UD destination handle 876 * as returned by ibt_alloc_ud_dest(). 877 * qkey QKey of the destination. 878 * dest_qpn QPN of the destination. 879 * adds_vect NULL or Address Vector for the destination. 880 * 881 * Output: 882 * none. 883 * Returns: 884 * IBT_SUCCESS 885 * Description: 886 * Modify a previously allocated UD destination handle from the 887 * arguments supplied by the caller. 888 */ 889 ibt_status_t 890 ibt_modify_ud_dest(ibt_ud_dest_hdl_t ud_dest, ib_qkey_t qkey, 891 ib_qpn_t dest_qpn, ibt_adds_vect_t *adds_vect) 892 { 893 ibt_status_t retval; 894 895 IBTF_DPRINTF_L3(ibtl_chan, "ibt_modify_ud_dest(%p, %x, %x, %p) ", 896 ud_dest, qkey, dest_qpn, adds_vect); 897 898 if ((adds_vect != NULL) && 899 (retval = ibt_modify_ah(ud_dest->ud_dest_hca, ud_dest->ud_ah, 900 adds_vect)) != IBT_SUCCESS) { 901 IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_ud_dest: " 902 "ibt_modify_ah() failed: status = %d", retval); 903 return (retval); 904 } 905 ud_dest->ud_dst_qpn = dest_qpn; 906 ud_dest->ud_qkey = qkey; 907 return (IBT_SUCCESS); 908 } 909 910 /* 911 * Function: 912 * ibt_free_ud_dest 913 * Input: 914 * ud_dest The opaque destination handle returned in a previous 915 * call to ibt_alloc_ud_dest() or ibt_alloc_mcg_dest(). 916 * Output: 917 * none. 918 * Returns: 919 * IBT_SUCCESS 920 * Description: 921 * Releases the resources associated with the specified destination 922 * handle. 923 */ 924 ibt_status_t 925 ibt_free_ud_dest(ibt_ud_dest_hdl_t ud_dest) 926 { 927 ibt_status_t retval; 928 929 retval = ibt_free_ah(ud_dest->ud_dest_hca, ud_dest->ud_ah); 930 if (retval != IBT_SUCCESS) { 931 IBTF_DPRINTF_L2(ibtl_chan, "ibt_free_ud_dest: " 932 "Address Handle free failed: %d", retval); 933 return (retval); 934 } 935 kmem_free(ud_dest, sizeof (*ud_dest)); 936 return (IBT_SUCCESS); 937 } 938 939 static ibt_status_t 940 ibtl_find_sgid_ix(ib_gid_t *sgid, ibt_channel_hdl_t ud_chan, uint8_t port, 941 uint_t *sgid_ix_p) 942 { 943 ibtl_hca_devinfo_t *hca_devp = ud_chan->ch_qp.qp_hca->ha_hca_devp; 944 ib_gid_t *sgidp; 945 uint_t i; 946 uint_t sgid_tbl_sz; 947 948 if (port == 0 || port > hca_devp->hd_hca_attr->hca_nports || 949 sgid->gid_prefix == 0 || sgid->gid_guid == 0) { 950 *sgid_ix_p = 0; 951 return (IBT_INVALID_PARAM); 952 } 953 mutex_enter(&ibtl_clnt_list_mutex); 954 sgidp = &hca_devp->hd_portinfop[port - 1].p_sgid_tbl[0]; 955 sgid_tbl_sz = hca_devp->hd_portinfop[port - 1].p_sgid_tbl_sz; 956 for (i = 0; i < sgid_tbl_sz; i++, sgidp++) { 957 if ((sgid->gid_guid != sgidp->gid_guid) || 958 (sgid->gid_prefix != sgidp->gid_prefix)) 959 continue; 960 mutex_exit(&ibtl_clnt_list_mutex); 961 *sgid_ix_p = i; 962 return (IBT_SUCCESS); 963 } 964 mutex_exit(&ibtl_clnt_list_mutex); 965 *sgid_ix_p = 0; 966 return (IBT_INVALID_PARAM); 967 } 968 969 /* 970 * Function: 971 * ibt_modify_reply_ud_dest 972 * Input: 973 * ud_dest A previously allocated UD reply destination handle 974 * as returned by ibt_alloc_ud_dest(). 975 * qkey Qkey. 0 means "not specified", so use the Q_Key 976 * in the QP context. 977 * recv_buf Pointer to the first data buffer associated with the 978 * receive work request. 979 * Output: 980 * Returns: 981 * IBT_SUCCESS 982 * Description: 983 * Modify a previously allocated UD destination handle, so that it 984 * can be used to reply to the sender of the datagram contained in the 985 * specified work request completion. If the qkey is not supplied (0), 986 * then use the qkey in the QP (we just set qkey to a privileged QKEY). 987 */ 988 ibt_status_t 989 ibt_modify_reply_ud_dest(ibt_channel_hdl_t ud_chan, ibt_ud_dest_hdl_t ud_dest, 990 ib_qkey_t qkey, ibt_wc_t *wc, ib_vaddr_t recv_buf) 991 { 992 ibt_status_t retval; 993 ibt_adds_vect_t adds_vect; 994 ib_grh_t *grh; 995 uint8_t port; 996 uint32_t ver_tc_flow; 997 998 IBTF_DPRINTF_L3(ibtl_chan, "ibt_modify_reply_ud_dest(%p, %p, %x, %p, " 999 "%llx)", ud_chan, ud_dest, qkey, wc, recv_buf); 1000 1001 if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) { 1002 IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_reply_ud_dest: " 1003 "type of channel (%d) is not UD", 1004 ud_chan->ch_qp.qp_type); 1005 return (IBT_CHAN_SRV_TYPE_INVALID); 1006 } 1007 if (qkey == 0) 1008 qkey = ud_chan->ch_transport.ud.ud_qkey; 1009 port = ud_chan->ch_transport.ud.ud_port_num; 1010 1011 if (wc->wc_flags & IBT_WC_GRH_PRESENT) { 1012 grh = (ib_grh_t *)(uintptr_t)recv_buf; 1013 adds_vect.av_send_grh = B_TRUE; 1014 adds_vect.av_dgid.gid_prefix = b2h64(grh->SGID.gid_prefix); 1015 adds_vect.av_dgid.gid_guid = b2h64(grh->SGID.gid_guid); 1016 adds_vect.av_sgid.gid_prefix = b2h64(grh->DGID.gid_prefix); 1017 adds_vect.av_sgid.gid_guid = b2h64(grh->DGID.gid_guid); 1018 (void) ibtl_find_sgid_ix(&adds_vect.av_sgid, ud_chan, 1019 port, &adds_vect.av_sgid_ix); 1020 ver_tc_flow = b2h32(grh->IPVer_TC_Flow); 1021 adds_vect.av_flow = ver_tc_flow & IB_GRH_FLOW_LABEL_MASK; 1022 adds_vect.av_tclass = (ver_tc_flow & IB_GRH_TCLASS_MASK) >> 20; 1023 adds_vect.av_hop = grh->HopLmt; 1024 } else { 1025 adds_vect.av_send_grh = B_FALSE; 1026 adds_vect.av_dgid.gid_prefix = 0; 1027 adds_vect.av_sgid.gid_prefix = 0; 1028 adds_vect.av_dgid.gid_guid = 0; 1029 adds_vect.av_sgid.gid_guid = 0; 1030 adds_vect.av_sgid_ix = 0; 1031 adds_vect.av_flow = 0; 1032 adds_vect.av_tclass = 0; 1033 adds_vect.av_hop = 0; 1034 } 1035 1036 adds_vect.av_srate = IBT_SRATE_1X; /* assume the minimum */ 1037 adds_vect.av_srvl = wc->wc_sl; 1038 adds_vect.av_dlid = wc->wc_slid; 1039 adds_vect.av_src_path = wc->wc_path_bits; 1040 adds_vect.av_port_num = port; 1041 1042 if ((retval = ibt_modify_ah(ud_dest->ud_dest_hca, ud_dest->ud_ah, 1043 &adds_vect)) != IBT_SUCCESS) { 1044 IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_reply_ud_dest: " 1045 "ibt_alloc_ah() failed: status = %d", retval); 1046 return (retval); 1047 } 1048 ud_dest->ud_dst_qpn = wc->wc_qpn & IB_QPN_MASK; 1049 ud_dest->ud_qkey = qkey; 1050 1051 return (IBT_SUCCESS); 1052 } 1053 1054 1055 /* 1056 * Function: 1057 * ibt_is_privileged_ud_dest 1058 * Input: 1059 * ud_dest A previously allocated destination handle. 1060 * Output: 1061 * none 1062 * Returns: 1063 * B_FALSE/B_TRUE 1064 * Description: 1065 * Determine if a UD destination Handle is a privileged handle. 1066 */ 1067 boolean_t 1068 ibt_is_privileged_ud_dest(ibt_ud_dest_hdl_t ud_dest) 1069 { 1070 return ((ud_dest->ud_qkey & IB_PRIVILEGED_QKEY_BIT) ? B_TRUE : B_FALSE); 1071 } 1072 1073 1074 /* 1075 * Function: 1076 * ibt_update_channel_qkey 1077 * Input: 1078 * ud_chan The UD channel handle, that is to be used to 1079 * communicate with the specified destination. 1080 * 1081 * ud_dest A UD destination handle returned from 1082 * ibt_alloc_ud_dest(9F). 1083 * Output: 1084 * none 1085 * Returns: 1086 * IBT_SUCCESS 1087 * Description: 1088 * ibt_update_channel_qkey() sets the Q_Key in the specified channel context 1089 * to the Q_Key in the specified destination handle. This function can be used 1090 * to enable sends to a privileged destination. All posted send work requests 1091 * that contain a privileged destination handle now use the Q_Key in the 1092 * channel context. 1093 * 1094 * ibt_update_channel_qkey() can also be used to enable the caller to receive 1095 * from the specified remote destination on the specified channel. 1096 */ 1097 ibt_status_t 1098 ibt_update_channel_qkey(ibt_channel_hdl_t ud_chan, ibt_ud_dest_hdl_t ud_dest) 1099 { 1100 ibt_status_t retval; 1101 ibt_qp_info_t qp_info; 1102 1103 IBTF_DPRINTF_L3(ibtl_chan, "ibt_update_channel_qkey(%p, %p)", 1104 ud_chan, ud_dest); 1105 1106 if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) { 1107 IBTF_DPRINTF_L2(ibtl_chan, "ibt_update_channel_qkey: " 1108 "type of channel (%d) is not UD", 1109 ud_chan->ch_qp.qp_type); 1110 return (IBT_CHAN_SRV_TYPE_INVALID); 1111 } 1112 bzero(&qp_info, sizeof (ibt_qp_info_t)); 1113 1114 qp_info.qp_trans = IBT_UD_SRV; 1115 qp_info.qp_state = ud_chan->ch_current_state; 1116 qp_info.qp_current_state = ud_chan->ch_current_state; 1117 qp_info.qp_transport.ud.ud_qkey = ud_dest->ud_qkey; 1118 1119 retval = ibt_modify_qp(ud_chan, IBT_CEP_SET_QKEY | IBT_CEP_SET_STATE, 1120 &qp_info, NULL); 1121 if (retval != IBT_SUCCESS) { 1122 IBTF_DPRINTF_L2(ibtl_chan, "ibt_update_channel_qkey: " 1123 "Failed to modify QP %p: status %d", ud_chan, retval); 1124 } else { 1125 ud_chan->ch_transport.ud.ud_qkey = ud_dest->ud_qkey; 1126 } 1127 1128 return (retval); 1129 } 1130 1131 1132 /* 1133 * Function: 1134 * ibt_set_chan_private 1135 * Input: 1136 * chan A previously allocated channel handle. 1137 * clnt_private The client private data. 1138 * Output: 1139 * none. 1140 * Returns: 1141 * none. 1142 * Description: 1143 * Set the client private data. 1144 */ 1145 void 1146 ibt_set_chan_private(ibt_channel_hdl_t chan, void *clnt_private) 1147 { 1148 chan->ch_clnt_private = clnt_private; 1149 } 1150 1151 1152 /* 1153 * Function: 1154 * ibt_get_chan_private 1155 * Input: 1156 * chan A previously allocated channel handle. 1157 * Output: 1158 * A pointer to the client private data. 1159 * Returns: 1160 * none. 1161 * Description: 1162 * Get a pointer to client private data. 1163 */ 1164 void * 1165 ibt_get_chan_private(ibt_channel_hdl_t chan) 1166 { 1167 return (chan->ch_clnt_private); 1168 } 1169 1170 /* 1171 * Function: 1172 * ibt_channel_to_hca_guid 1173 * Input: 1174 * chan Channel Handle. 1175 * Output: 1176 * none. 1177 * Returns: 1178 * hca_guid Returned HCA GUID on which the specified Channel is 1179 * allocated. Valid if it is non-NULL on return. 1180 * Description: 1181 * A helper function to retrieve HCA GUID for the specified Channel. 1182 */ 1183 ib_guid_t 1184 ibt_channel_to_hca_guid(ibt_channel_hdl_t chan) 1185 { 1186 IBTF_DPRINTF_L3(ibtl_chan, "ibt_channel_to_hca_guid(%p)", chan); 1187 1188 return (IBTL_HCA2HCAGUID(IBTL_CHAN2HCA(chan))); 1189 } 1190 1191 /* 1192 * Protection Domain Verbs Functions. 1193 */ 1194 1195 /* 1196 * Function: 1197 * ibt_alloc_pd 1198 * Input: 1199 * hca_hdl The IBT HCA handle, the device on which we need 1200 * to create the requested Protection Domain. 1201 * flags IBT_PD_NO_FLAGS, IBT_PD_USER_MAP or IBT_PD_DEFER_ALLOC 1202 * Output: 1203 * pd IBT Protection Domain Handle. 1204 * Returns: 1205 * IBT_SUCCESS 1206 * IBT_HCA_HDL_INVALID 1207 * Description: 1208 * Allocate a Protection Domain. 1209 */ 1210 ibt_status_t 1211 ibt_alloc_pd(ibt_hca_hdl_t hca_hdl, ibt_pd_flags_t flags, ibt_pd_hdl_t *pd) 1212 { 1213 ibt_status_t retval; 1214 1215 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_pd(%p, %x)", hca_hdl, flags); 1216 1217 /* re-direct the call to CI's call */ 1218 ibtl_qp_flow_control_enter(); 1219 retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_pd( 1220 IBTL_HCA2CIHCA(hca_hdl), flags, pd); 1221 ibtl_qp_flow_control_exit(); 1222 if (retval != IBT_SUCCESS) { 1223 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_pd: CI PD Alloc Err"); 1224 return (retval); 1225 } 1226 1227 /* Update the PDs Resource Count per HCA Device. */ 1228 mutex_enter(&hca_hdl->ha_mutex); 1229 hca_hdl->ha_pd_cnt++; 1230 mutex_exit(&hca_hdl->ha_mutex); 1231 1232 return (retval); 1233 } 1234 1235 /* 1236 * Function: 1237 * ibt_free_pd 1238 * Input: 1239 * hca_hdl The IBT HCA handle, the device on which we need 1240 * to free the requested Protection Domain. 1241 * pd IBT Protection Domain Handle. 1242 * Output: 1243 * none. 1244 * Returns: 1245 * IBT_SUCCESS 1246 * IBT_HCA_HDL_INVALID 1247 * IBT_MEM_PD_HDL_INVALID 1248 * IBT_MEM_PD_IN_USE 1249 * Description: 1250 * Release/de-allocate a Protection Domain. 1251 */ 1252 ibt_status_t 1253 ibt_free_pd(ibt_hca_hdl_t hca_hdl, ibt_pd_hdl_t pd) 1254 { 1255 ibt_status_t retval; 1256 1257 IBTF_DPRINTF_L3(ibtl_chan, "ibt_free_pd(%p, %p)", hca_hdl, pd); 1258 1259 /* re-direct the call to CI's call */ 1260 retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_free_pd( 1261 IBTL_HCA2CIHCA(hca_hdl), pd); 1262 if (retval != IBT_SUCCESS) { 1263 IBTF_DPRINTF_L2(ibtl_chan, "ibt_free_pd: CI Free PD Failed"); 1264 return (retval); 1265 } 1266 1267 /* Update the PDs Resource Count per HCA Device. */ 1268 mutex_enter(&hca_hdl->ha_mutex); 1269 hca_hdl->ha_pd_cnt--; 1270 mutex_exit(&hca_hdl->ha_mutex); 1271 1272 return (retval); 1273 } 1274 1275 1276 /* 1277 * Address Handle Verbs Functions. 1278 */ 1279 1280 /* 1281 * Function: 1282 * ibt_alloc_ah 1283 * Input: 1284 * hca_hdl The IBT HCA Handle. 1285 * pd The IBT Protection Domain to associate with this handle. 1286 * adds_vectp Points to an ibt_adds_vect_t struct. 1287 * Output: 1288 * ah IBT Address Handle. 1289 * Returns: 1290 * IBT_SUCCESS 1291 * IBT_HCA_HDL_INVALID 1292 * IBT_INSUFF_RESOURCE 1293 * IBT_MEM_PD_HDL_INVALID 1294 * Description: 1295 * Allocate and returns an Address Handle. 1296 */ 1297 ibt_status_t 1298 ibt_alloc_ah(ibt_hca_hdl_t hca_hdl, ibt_ah_flags_t flags, ibt_pd_hdl_t pd, 1299 ibt_adds_vect_t *adds_vectp, ibt_ah_hdl_t *ah) 1300 { 1301 ibt_status_t retval; 1302 1303 IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_ah(%p, %x, %p, %p)", 1304 hca_hdl, flags, pd, adds_vectp); 1305 1306 /* XXX - if av_send_grh, need to compute av_sgid_ix from av_sgid */ 1307 1308 /* re-direct the call to CI's call */ 1309 retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_ah( 1310 IBTL_HCA2CIHCA(hca_hdl), flags, pd, adds_vectp, ah); 1311 1312 if (retval != IBT_SUCCESS) { 1313 IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ah: " 1314 "ibc_alloc_ah failed: status = %d", retval); 1315 return (retval); 1316 } 1317 1318 /* Update the AHs Resource Count per HCA Device. */ 1319 mutex_enter(&hca_hdl->ha_mutex); 1320 hca_hdl->ha_ah_cnt++; 1321 mutex_exit(&hca_hdl->ha_mutex); 1322 1323 return (retval); 1324 } 1325 1326 1327 /* 1328 * Function: 1329 * ibt_free_ah 1330 * Input: 1331 * hca_hdl The IBT HCA Handle. 1332 * ah IBT Address Handle. 1333 * Output: 1334 * none. 1335 * Returns: 1336 * IBT_SUCCESS 1337 * IBT_HCA_HDL_INVALID 1338 * IBT_AH_HDL_INVALID 1339 * Description: 1340 * Release/de-allocate the specified Address Handle. 1341 */ 1342 ibt_status_t 1343 ibt_free_ah(ibt_hca_hdl_t hca_hdl, ibt_ah_hdl_t ah) 1344 { 1345 ibt_status_t retval; 1346 1347 IBTF_DPRINTF_L3(ibtl_chan, "ibt_free_ah(%p, %p)", hca_hdl, ah); 1348 1349 /* re-direct the call to CI's call */ 1350 retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_free_ah( 1351 IBTL_HCA2CIHCA(hca_hdl), ah); 1352 1353 if (retval != IBT_SUCCESS) { 1354 IBTF_DPRINTF_L2(ibtl_chan, "ibt_free_ah: CI Free AH Failed"); 1355 return (retval); 1356 } 1357 1358 /* Update the AHs Resource Count per HCA Device. */ 1359 mutex_enter(&hca_hdl->ha_mutex); 1360 hca_hdl->ha_ah_cnt--; 1361 mutex_exit(&hca_hdl->ha_mutex); 1362 1363 return (retval); 1364 } 1365 1366 1367 /* 1368 * Function: 1369 * ibt_query_ah 1370 * Input: 1371 * hca_hdl The IBT HCA Handle. 1372 * ah IBT Address Handle. 1373 * Output: 1374 * pd The Protection Domain Handle with which this 1375 * Address Handle is associated. 1376 * adds_vectp Points to an ibt_adds_vect_t struct. 1377 * Returns: 1378 * IBT_SUCCESS/IBT_HCA_HDL_INVALID/IBT_AH_HDL_INVALID 1379 * Description: 1380 * Obtain the address vector information for the specified address handle. 1381 */ 1382 ibt_status_t 1383 ibt_query_ah(ibt_hca_hdl_t hca_hdl, ibt_ah_hdl_t ah, ibt_pd_hdl_t *pd, 1384 ibt_adds_vect_t *adds_vectp) 1385 { 1386 ibt_status_t retval; 1387 1388 IBTF_DPRINTF_L3(ibtl_chan, "ibt_query_ah(%p, %p)", hca_hdl, ah); 1389 1390 /* re-direct the call to CI's call */ 1391 retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_query_ah( 1392 IBTL_HCA2CIHCA(hca_hdl), ah, pd, adds_vectp)); 1393 1394 /* 1395 * We need to fill in av_sgid, as the CI does only saves/restores 1396 * av_sgid_ix. 1397 */ 1398 if (retval == IBT_SUCCESS) { 1399 ibtl_hca_devinfo_t *hca_devp = hca_hdl->ha_hca_devp; 1400 uint8_t port = adds_vectp->av_port_num; 1401 1402 mutex_enter(&ibtl_clnt_list_mutex); 1403 if (port > 0 && port <= hca_devp->hd_hca_attr->hca_nports && 1404 adds_vectp->av_sgid_ix < IBTL_HDIP2SGIDTBLSZ(hca_devp)) { 1405 ib_gid_t *sgidp; 1406 1407 sgidp = hca_devp->hd_portinfop[port-1].p_sgid_tbl; 1408 adds_vectp->av_sgid = sgidp[adds_vectp->av_sgid_ix]; 1409 } else { 1410 adds_vectp->av_sgid.gid_prefix = 0; 1411 adds_vectp->av_sgid.gid_guid = 0; 1412 } 1413 mutex_exit(&ibtl_clnt_list_mutex); 1414 } 1415 return (retval); 1416 } 1417 1418 1419 /* 1420 * Function: 1421 * ibt_modify_ah 1422 * Input: 1423 * hca_hdl The IBT HCA Handle. 1424 * ah IBT Address Handle. 1425 * Output: 1426 * adds_vectp Points to an ibt_adds_vect_t struct. The new address 1427 * vector information is specified is returned in this 1428 * structure. 1429 * Returns: 1430 * IBT_SUCCESS/IBT_HCA_HDL_INVALID/IBT_AH_HDL_INVALID 1431 * Description: 1432 * Modify the address vector information for the specified Address Handle. 1433 */ 1434 ibt_status_t 1435 ibt_modify_ah(ibt_hca_hdl_t hca_hdl, ibt_ah_hdl_t ah, 1436 ibt_adds_vect_t *adds_vectp) 1437 { 1438 IBTF_DPRINTF_L3(ibtl_chan, "ibt_modify_ah(%p, %p)", hca_hdl, ah); 1439 1440 /* XXX - if av_send_grh, need to compute av_sgid_ix from av_sgid */ 1441 1442 /* re-direct the call to CI's call */ 1443 return (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_modify_ah( 1444 IBTL_HCA2CIHCA(hca_hdl), ah, adds_vectp)); 1445 } 1446