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