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