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 #include <sys/ib/ibtl/impl/ibtl.h> 26 #include <sys/ib/ibtl/impl/ibtl_cm.h> 27 28 /* 29 * ibtl_qp.c 30 * These routines implement (most of) the verbs related to 31 * Queue Pairs. 32 */ 33 34 /* Globals. */ 35 static char ibtf_qp[] = "ibtl"; 36 37 /* This table indirectly initializes the ibt_cep_next_state[] table. */ 38 typedef struct ibt_cep_next_state_s { 39 ibt_cep_state_t next_state; 40 ibt_cep_modify_flags_t modify_flags; 41 } ibt_cep_next_state_t; 42 43 struct { 44 ibt_cep_state_t current_state; 45 ibt_cep_state_t next_state; 46 ibt_cep_modify_flags_t modify_flags; 47 } ibt_cep_next_state_inits[] = { 48 { IBT_STATE_RESET, IBT_STATE_INIT, IBT_CEP_SET_RESET_INIT}, 49 { IBT_STATE_INIT, IBT_STATE_RTR, IBT_CEP_SET_INIT_RTR}, 50 { IBT_STATE_RTR, IBT_STATE_RTS, IBT_CEP_SET_RTR_RTS} 51 }; 52 53 ibt_cep_next_state_t ibt_cep_next_state[IBT_STATE_NUM]; 54 55 _NOTE(SCHEME_PROTECTS_DATA("unique", ibt_cep_next_state)) 56 57 /* The following data and functions can increase system stability. */ 58 59 int ibtl_qp_calls_curr; 60 int ibtl_qp_calls_max = 128; /* limit on # of simultaneous QP verb calls */ 61 kmutex_t ibtl_qp_mutex; 62 kcondvar_t ibtl_qp_cv; 63 64 void 65 ibtl_qp_flow_control_enter(void) 66 { 67 mutex_enter(&ibtl_qp_mutex); 68 while (ibtl_qp_calls_curr >= ibtl_qp_calls_max) { 69 cv_wait(&ibtl_qp_cv, &ibtl_qp_mutex); 70 } 71 ++ibtl_qp_calls_curr; 72 mutex_exit(&ibtl_qp_mutex); 73 } 74 75 void 76 ibtl_qp_flow_control_exit(void) 77 { 78 mutex_enter(&ibtl_qp_mutex); 79 cv_signal(&ibtl_qp_cv); 80 --ibtl_qp_calls_curr; 81 mutex_exit(&ibtl_qp_mutex); 82 } 83 84 /* 85 * Function: 86 * ibt_alloc_qp 87 * Input: 88 * hca_hdl HCA Handle. 89 * type Specifies the type of QP to alloc in ibt_alloc_qp() 90 * qp_attrp Specifies the ibt_qp_alloc_attr_t that are needed to 91 * allocate a QP and transition it to the RTS state for 92 * UDs and INIT state for all other QPs. 93 * Output: 94 * queue_sizes_p Returned sizes for SQ, RQ, SQ WR SGL elements & RQ 95 * WR SGL elements. 96 * qpn_p Returned QP Number of the allocated QP. 97 * ibt_qp_p The ibt_qp_hdl_t of the allocated QP. 98 * Returns: 99 * IBT_SUCCESS 100 * Description: 101 * Allocate a QP with specified attributes. 102 */ 103 ibt_status_t 104 ibt_alloc_qp(ibt_hca_hdl_t hca_hdl, ibt_qp_type_t type, 105 ibt_qp_alloc_attr_t *qp_attrp, ibt_chan_sizes_t *queue_sizes_p, 106 ib_qpn_t *qpn_p, ibt_qp_hdl_t *ibt_qp_p) 107 { 108 ibt_status_t retval; 109 ibtl_channel_t *chanp; 110 ibt_tran_srv_t qp_type; 111 112 IBTF_DPRINTF_L3(ibtf_qp, "ibt_alloc_qp(%p, %d, %p, %p, %p, %p) ", 113 hca_hdl, type, qp_attrp, queue_sizes_p, qpn_p, ibt_qp_p); 114 115 switch (type) { 116 case IBT_UD_RQP: 117 qp_type = IBT_UD_SRV; 118 break; 119 case IBT_RC_RQP: 120 qp_type = IBT_RC_SRV; 121 break; 122 case IBT_UC_RQP: 123 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Unreliable Connected " 124 "Transport Type is not supported."); 125 *ibt_qp_p = NULL; 126 return (IBT_NOT_SUPPORTED); 127 case IBT_RD_RQP: 128 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Reliable Datagram " 129 "Transport Type is not supported."); 130 *ibt_qp_p = NULL; 131 return (IBT_NOT_SUPPORTED); 132 default: 133 /* shouldn't happen ILLEGAL Type */ 134 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Illegal Transport Type " 135 "%d", type); 136 *ibt_qp_p = NULL; 137 return (IBT_QP_SRV_TYPE_INVALID); 138 } 139 140 /* Get CI CQ handles */ 141 if ((qp_attrp->qp_scq_hdl == NULL) || (qp_attrp->qp_rcq_hdl == NULL)) { 142 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Invalid CQ Handle"); 143 *ibt_qp_p = NULL; 144 return (IBT_CQ_HDL_INVALID); 145 } 146 qp_attrp->qp_ibc_scq_hdl = qp_attrp->qp_scq_hdl->cq_ibc_cq_hdl; 147 qp_attrp->qp_ibc_rcq_hdl = qp_attrp->qp_rcq_hdl->cq_ibc_cq_hdl; 148 149 if ((qp_attrp->qp_alloc_flags & IBT_QP_USES_SRQ) && 150 (qp_attrp->qp_srq_hdl != NULL)) 151 qp_attrp->qp_ibc_srq_hdl = 152 qp_attrp->qp_srq_hdl->srq_ibc_srq_hdl; 153 else 154 qp_attrp->qp_ibc_srq_hdl = NULL; 155 156 /* Allocate Channel structure */ 157 chanp = kmem_zalloc(sizeof (*chanp), KM_SLEEP); 158 159 ibtl_qp_flow_control_enter(); 160 retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_qp)( 161 IBTL_HCA2CIHCA(hca_hdl), &chanp->ch_qp, type, qp_attrp, 162 queue_sizes_p, qpn_p, &chanp->ch_qp.qp_ibc_qp_hdl); 163 ibtl_qp_flow_control_exit(); 164 if (retval != IBT_SUCCESS) { 165 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: " 166 "Failed to allocate QP: %d", retval); 167 kmem_free(chanp, sizeof (*chanp)); 168 *ibt_qp_p = NULL; 169 return (retval); 170 } 171 172 /* Initialize the internal QP struct. */ 173 chanp->ch_qp.qp_type = qp_type; 174 chanp->ch_qp.qp_hca = hca_hdl; 175 chanp->ch_qp.qp_send_cq = qp_attrp->qp_scq_hdl; 176 chanp->ch_qp.qp_recv_cq = qp_attrp->qp_rcq_hdl; 177 chanp->ch_current_state = IBT_STATE_RESET; 178 /* 179 * The IBTA spec does not include the signal type or PD on a QP 180 * query operation. In order to implement the "CLONE" feature 181 * we need to cache these values. Mostly used by TI client. 182 */ 183 chanp->ch_qp.qp_flags = qp_attrp->qp_flags; 184 chanp->ch_qp.qp_pd_hdl = qp_attrp->qp_pd_hdl; 185 mutex_init(&chanp->ch_cm_mutex, NULL, MUTEX_DEFAULT, NULL); 186 cv_init(&chanp->ch_cm_cv, NULL, CV_DEFAULT, NULL); 187 188 mutex_enter(&hca_hdl->ha_mutex); 189 hca_hdl->ha_qp_cnt++; 190 mutex_exit(&hca_hdl->ha_mutex); 191 192 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: SUCCESS: qp %p owned by '%s'", 193 chanp, hca_hdl->ha_clnt_devp->clnt_name); 194 195 *ibt_qp_p = chanp; 196 197 return (retval); 198 } 199 200 201 /* 202 * Function: 203 * ibt_initialize_qp 204 * Input: 205 * ibt_qp The previously allocated IBT QP Handle. 206 * modify_attrp Specifies the QP Modify attributes that to transition 207 * the QP to the RTS state for UDs (including special QPs) 208 * and INIT state for all other QPs. 209 * Output: 210 * none. 211 * Returns: 212 * IBT_SUCCESS 213 * Description: 214 * Transition the QP to the RTS state for UDs (including special QPs) 215 * and INIT state for all other QPs. 216 */ 217 ibt_status_t 218 ibt_initialize_qp(ibt_qp_hdl_t ibt_qp, ibt_qp_info_t *modify_attrp) 219 { 220 ibt_status_t status; 221 ibt_cep_state_t state; 222 ibc_hca_hdl_t ibc_hca_hdl = IBTL_CHAN2CIHCA(ibt_qp); 223 ibc_qp_hdl_t ibc_qp_hdl = IBTL_CHAN2CIQP(ibt_qp); 224 ibc_operations_t *hca_ops_p = IBTL_CHAN2CIHCAOPS_P(ibt_qp); 225 ibt_cep_modify_flags_t modify_flags; 226 227 IBTF_DPRINTF_L3(ibtf_qp, "ibt_initialize_qp(%p, %p)", 228 ibt_qp, modify_attrp); 229 230 /* 231 * Validate the QP Type from the channel with QP Type from the 232 * modify attribute struct. 233 */ 234 if (ibt_qp->ch_qp.qp_type != modify_attrp->qp_trans) { 235 IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: " 236 "QP Type mismatch: Chan QP Type<%d>, Modify QP Type<%d>", 237 ibt_qp->ch_qp.qp_type, modify_attrp->qp_trans); 238 return (IBT_QP_SRV_TYPE_INVALID); 239 } 240 if (ibt_qp->ch_current_state != IBT_STATE_RESET) { 241 IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: " 242 "QP needs to be in RESET state: Chan QP State<%d>", 243 ibt_qp->ch_current_state); 244 return (IBT_CHAN_STATE_INVALID); 245 } 246 247 /* 248 * Initialize the QP to the RTS state for UDs 249 * and INIT state for all other QPs. 250 */ 251 switch (modify_attrp->qp_trans) { 252 case IBT_UD_SRV: 253 254 /* 255 * Bring the QP to the RTS state. 256 */ 257 state = IBT_STATE_RESET; 258 ibtl_qp_flow_control_enter(); 259 do { 260 modify_attrp->qp_current_state = state; 261 modify_flags = ibt_cep_next_state[state].modify_flags; 262 modify_attrp->qp_state = state = 263 ibt_cep_next_state[state].next_state; 264 265 IBTF_DPRINTF_L3(ibtf_qp, "ibt_initialize_qp: " 266 "modifying qp state to 0x%x", state); 267 status = (hca_ops_p->ibc_modify_qp)(ibc_hca_hdl, 268 ibc_qp_hdl, modify_flags, modify_attrp, NULL); 269 } while ((state != IBT_STATE_RTS) && (status == IBT_SUCCESS)); 270 ibtl_qp_flow_control_exit(); 271 272 if (status == IBT_SUCCESS) { 273 ibt_qp->ch_current_state = state; 274 ibt_qp->ch_transport.ud.ud_port_num = 275 modify_attrp->qp_transport.ud.ud_port; 276 ibt_qp->ch_transport.ud.ud_qkey = 277 modify_attrp->qp_transport.ud.ud_qkey; 278 } 279 break; 280 case IBT_UC_SRV: 281 case IBT_RD_SRV: 282 case IBT_RC_SRV: 283 284 /* 285 * Bring the QP to the INIT state. 286 */ 287 modify_attrp->qp_state = IBT_STATE_INIT; 288 289 ibtl_qp_flow_control_enter(); 290 status = (hca_ops_p->ibc_modify_qp)(ibc_hca_hdl, ibc_qp_hdl, 291 IBT_CEP_SET_RESET_INIT, modify_attrp, NULL); 292 ibtl_qp_flow_control_exit(); 293 if (status == IBT_SUCCESS) 294 ibt_qp->ch_current_state = IBT_STATE_INIT; 295 break; 296 default: 297 /* shouldn't happen ILLEGAL Type */ 298 IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: Illegal Type %d", 299 modify_attrp->qp_trans); 300 return (IBT_QP_SRV_TYPE_INVALID); 301 } /* End switch */ 302 303 return (status); 304 } 305 306 307 /* 308 * Function: 309 * ibt_alloc_special_qp 310 * Input: 311 * hca_hdl HCA Handle. 312 * type Specifies the type of Special QP to be allocated. 313 * qp_attrp Specifies the ibt_qp_alloc_attr_t that are needed to 314 * allocate a special QP. 315 * Output: 316 * queue_sizes_p Returned sizes for SQ, RQ, SQ WR SGL elements & RQ 317 * WR SGL elements. 318 * qpn_p Returned qpn of the allocated QP. 319 * ibt_qp_p The ibt_qp_hdl_t of the allocated QP. 320 * Returns: 321 * IBT_SUCCESS 322 * Description: 323 * Allocate a special QP with specified attributes. 324 */ 325 ibt_status_t 326 ibt_alloc_special_qp(ibt_hca_hdl_t hca_hdl, uint8_t port, ibt_sqp_type_t type, 327 ibt_qp_alloc_attr_t *qp_attrp, ibt_chan_sizes_t *queue_sizes_p, 328 ibt_qp_hdl_t *ibt_qp_p) 329 { 330 ibt_qp_hdl_t chanp; 331 ibt_status_t retval; 332 ibt_tran_srv_t sqp_type; 333 334 IBTF_DPRINTF_L3(ibtf_qp, "ibt_alloc_special_qp(%p, %d, %x, %p, %p, %p)", 335 hca_hdl, port, type, qp_attrp, queue_sizes_p, ibt_qp_p); 336 337 switch (type) { 338 case IBT_SMI_SQP: 339 case IBT_GSI_SQP: 340 sqp_type = IBT_UD_SRV; 341 break; 342 343 case IBT_RAWIP_SQP: 344 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: Raw IP " 345 "Transport Type is not supported."); 346 *ibt_qp_p = NULL; 347 return (IBT_NOT_SUPPORTED); 348 349 case IBT_RAWETHER_SQP: 350 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: Raw Ethernet " 351 "Transport Type is not supported."); 352 *ibt_qp_p = NULL; 353 return (IBT_NOT_SUPPORTED); 354 355 default: 356 /* Shouldn't happen */ 357 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: " 358 "Illegal Type 0x%x", type); 359 *ibt_qp_p = NULL; 360 return (IBT_QP_SPECIAL_TYPE_INVALID); 361 } 362 363 /* convert the CQ handles for the CI */ 364 qp_attrp->qp_ibc_scq_hdl = qp_attrp->qp_scq_hdl->cq_ibc_cq_hdl; 365 qp_attrp->qp_ibc_rcq_hdl = qp_attrp->qp_rcq_hdl->cq_ibc_cq_hdl; 366 367 /* Allocate Channel structure */ 368 chanp = kmem_zalloc(sizeof (*chanp), KM_SLEEP); 369 370 ibtl_qp_flow_control_enter(); 371 retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_special_qp)( 372 IBTL_HCA2CIHCA(hca_hdl), port, &chanp->ch_qp, type, qp_attrp, 373 queue_sizes_p, &chanp->ch_qp.qp_ibc_qp_hdl); 374 ibtl_qp_flow_control_exit(); 375 if (retval != IBT_SUCCESS) { 376 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: " 377 "Failed to allocate Special QP: %d", retval); 378 kmem_free(chanp, sizeof (*chanp)); 379 *ibt_qp_p = NULL; 380 return (retval); 381 } 382 383 /* Initialize the internal QP struct. */ 384 chanp->ch_qp.qp_type = sqp_type; 385 chanp->ch_qp.qp_hca = hca_hdl; 386 chanp->ch_qp.qp_send_cq = qp_attrp->qp_scq_hdl; 387 chanp->ch_qp.qp_recv_cq = qp_attrp->qp_rcq_hdl; 388 chanp->ch_current_state = IBT_STATE_RESET; 389 mutex_init(&chanp->ch_cm_mutex, NULL, MUTEX_DEFAULT, NULL); 390 cv_init(&chanp->ch_cm_cv, NULL, CV_DEFAULT, NULL); 391 392 /* Updating these variable, so that debugger shows correct values. */ 393 chanp->ch_qp.qp_flags = qp_attrp->qp_flags; 394 chanp->ch_qp.qp_pd_hdl = qp_attrp->qp_pd_hdl; 395 396 mutex_enter(&hca_hdl->ha_mutex); 397 hca_hdl->ha_qp_cnt++; 398 mutex_exit(&hca_hdl->ha_mutex); 399 400 *ibt_qp_p = chanp; 401 402 return (retval); 403 } 404 405 406 /* 407 * Function: 408 * ibt_flush_qp 409 * Input: 410 * ibtl_qp Handle for QP that needs to be flushed. 411 * Output: 412 * none. 413 * Returns: 414 * IBT_SUCCESS 415 * IBT_QP_HDL_INVALID 416 * Description: 417 * Put the QP into error state to flush out work requests. 418 */ 419 ibt_status_t 420 ibt_flush_qp(ibt_qp_hdl_t ibt_qp) 421 { 422 ibt_qp_info_t modify_attr; 423 ibt_status_t retval; 424 425 IBTF_DPRINTF_L3(ibtf_qp, "ibt_flush_qp(%p)", ibt_qp); 426 427 if (ibt_qp->ch_qp.qp_type == IBT_RC_SRV) { 428 mutex_enter(&ibtl_free_qp_mutex); 429 if ((ibt_qp->ch_transport.rc.rc_free_flags & 430 (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING)) == 431 IBTL_RC_QP_CONNECTED) { 432 mutex_exit(&ibtl_free_qp_mutex); 433 IBTF_DPRINTF_L2(ibtf_qp, "ibt_flush_qp(%p): " 434 "called with a connected RC QP", ibt_qp); 435 return (IBT_CHAN_STATE_INVALID); 436 } 437 mutex_exit(&ibtl_free_qp_mutex); 438 } 439 440 bzero(&modify_attr, sizeof (ibt_qp_info_t)); 441 442 /* 443 * Set the QP state to error to flush any uncompleted WRs. 444 */ 445 modify_attr.qp_state = IBT_STATE_ERROR; 446 modify_attr.qp_trans = ibt_qp->ch_qp.qp_type; 447 448 retval = ibt_modify_qp(ibt_qp, IBT_CEP_SET_STATE, &modify_attr, NULL); 449 450 if (retval != IBT_SUCCESS) { 451 IBTF_DPRINTF_L2(ibtf_qp, "ibt_flush_qp: " 452 "failed on chan %p: %d", ibt_qp, retval); 453 } 454 return (retval); 455 } 456 457 458 /* 459 * ibtl_cm_chan_is_opening() 460 * 461 * Inform IBTL that the connection established process is in progress 462 * on this channel so that care need to be taken while free'ing when 463 * open is NOT yet complete. 464 * 465 * chan Channel Handle 466 */ 467 void 468 ibtl_cm_chan_is_opening(ibt_channel_hdl_t chan) 469 { 470 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_opening(%p)", chan); 471 ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV); 472 mutex_enter(&ibtl_free_qp_mutex); 473 ASSERT(chan->ch_transport.rc.rc_free_flags == 0); 474 chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CONNECTING; 475 mutex_exit(&ibtl_free_qp_mutex); 476 } 477 478 /* 479 * ibtl_cm_chan_open_is_aborted() 480 * 481 * Inform IBTL that the connection established on this channel has 482 * aborted. So undo what was done in ibtl_cm_chan_is_opening(). 483 * 484 * chan Channel Handle 485 */ 486 void 487 ibtl_cm_chan_open_is_aborted(ibt_channel_hdl_t chan) 488 { 489 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_open_is_aborted(%p)", chan); 490 ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV); 491 mutex_enter(&ibtl_free_qp_mutex); 492 chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTING; 493 mutex_exit(&ibtl_free_qp_mutex); 494 } 495 496 /* 497 * ibtl_cm_chan_is_open() 498 * 499 * Inform IBTL that the connection has been established on this 500 * channel so that a later call to ibtl_cm_chan_is_closed() 501 * will be required to free the QPN used by this channel. 502 * 503 * chan Channel Handle 504 */ 505 void 506 ibtl_cm_chan_is_open(ibt_channel_hdl_t chan) 507 { 508 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_open(%p)", chan); 509 ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV); 510 mutex_enter(&ibtl_free_qp_mutex); 511 chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTING; 512 chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CONNECTED; 513 mutex_exit(&ibtl_free_qp_mutex); 514 } 515 516 /* 517 * ibtl_cm_is_chan_closing() 518 * 519 * Returns 1, if the connection that has been 520 * started for this channel has moved to TIMEWAIT 521 * If not, returns 0 522 * 523 * chan Channel Handle 524 */ 525 int 526 ibtl_cm_is_chan_closing(ibt_channel_hdl_t chan) 527 { 528 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_is_chan_closing(%p)", chan); 529 ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV); 530 mutex_enter(&ibtl_free_qp_mutex); 531 if (chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CLOSING) { 532 mutex_exit(&ibtl_free_qp_mutex); 533 return (1); 534 } 535 mutex_exit(&ibtl_free_qp_mutex); 536 return (0); 537 } 538 539 /* 540 * ibtl_cm_is_chan_closed() 541 * 542 * Returns 1, if the connection that has been 543 * started for this channel has completed TIMEWAIT 544 * If not, returns 0 545 * 546 * chan Channel Handle 547 */ 548 int 549 ibtl_cm_is_chan_closed(ibt_channel_hdl_t chan) 550 { 551 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_is_chan_closed(%p)", chan); 552 ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV); 553 mutex_enter(&ibtl_free_qp_mutex); 554 if (chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CLOSED) { 555 mutex_exit(&ibtl_free_qp_mutex); 556 return (1); 557 } 558 mutex_exit(&ibtl_free_qp_mutex); 559 return (0); 560 } 561 /* 562 * ibtl_cm_chan_is_closing() 563 * 564 * Inform IBTL that the TIMEWAIT delay for the connection has been 565 * started for this channel so that the QP can be freed. 566 * 567 * chan Channel Handle 568 */ 569 void 570 ibtl_cm_chan_is_closing(ibt_channel_hdl_t chan) 571 { 572 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_closing(%p)", chan); 573 ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV); 574 mutex_enter(&ibtl_free_qp_mutex); 575 ASSERT(chan->ch_transport.rc.rc_free_flags == IBTL_RC_QP_CONNECTED); 576 chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CLOSING; 577 mutex_exit(&ibtl_free_qp_mutex); 578 } 579 /* 580 * ibtl_cm_chan_is_closed() 581 * 582 * Inform IBTL that the TIMEWAIT delay for the connection has been 583 * reached for this channel so that the QPN can be reused. 584 * 585 * chan Channel Handle 586 */ 587 void 588 ibtl_cm_chan_is_closed(ibt_channel_hdl_t chan) 589 { 590 ibt_status_t status; 591 ibtl_hca_t *ibtl_hca = chan->ch_qp.qp_hca; 592 593 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_closed(%p)", chan); 594 ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV); 595 mutex_enter(&ibtl_free_qp_mutex); 596 ASSERT((chan->ch_transport.rc.rc_free_flags & 597 (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING)) == 598 (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING)); 599 600 chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTED; 601 chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CLOSING; 602 chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CLOSED; 603 604 ibtl_cm_set_chan_private(chan, NULL); 605 606 if ((chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_FREED) == 0) { 607 mutex_exit(&ibtl_free_qp_mutex); 608 return; 609 } 610 mutex_exit(&ibtl_free_qp_mutex); 611 ibtl_qp_flow_control_enter(); 612 if ((status = (IBTL_CHAN2CIHCAOPS_P(chan)->ibc_release_qpn) 613 (IBTL_CHAN2CIHCA(chan), chan->ch_transport.rc.rc_qpn_hdl)) == 614 IBT_SUCCESS) { 615 /* effectively, this is kmem_free(chan); */ 616 ibtl_free_qp_async_check(&chan->ch_qp); 617 618 /* decrement ha_qpn_cnt and check for close in progress */ 619 ibtl_close_hca_check(ibtl_hca); 620 } else 621 IBTF_DPRINTF_L2(ibtf_qp, "ibtl_cm_chan_is_closed: " 622 "ibc_release_qpn failed: status = %d\n", status); 623 ibtl_qp_flow_control_exit(); 624 } 625 626 /* 627 * ibtl_cm_chan_is_reused() 628 * 629 * Inform IBTL that the channel is going to be re-used 630 * chan Channel Handle 631 */ 632 void 633 ibtl_cm_chan_is_reused(ibt_channel_hdl_t chan) 634 { 635 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_reused(%p)", chan); 636 ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV); 637 mutex_enter(&ibtl_free_qp_mutex); 638 ASSERT(((chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CONNECTED) != 639 IBTL_RC_QP_CONNECTED)); 640 641 /* channel is no longer in closed state, shall be re-used */ 642 chan->ch_transport.rc.rc_free_flags = 0; 643 644 mutex_exit(&ibtl_free_qp_mutex); 645 646 } 647 648 /* 649 * Function: ibt_free_qp() 650 * 651 * Input: ibt_qp Handle for Channel(QP) that needs to be freed. 652 * 653 * Output: NONE. 654 * 655 * Returns: IBT_SUCCESS 656 * IBT_QP_STATE_INVALID 657 * IBT_QP_HDL_INVALID 658 * 659 * Description: 660 * Free a previously allocated QP. 661 */ 662 ibt_status_t 663 ibt_free_qp(ibt_qp_hdl_t ibt_qp) 664 { 665 ibt_status_t status; 666 ibtl_hca_t *ibtl_hca = ibt_qp->ch_qp.qp_hca; 667 668 IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p)", ibt_qp); 669 670 if (ibt_qp->ch_qp.qp_type == IBT_RC_SRV) { 671 ibtl_qp_flow_control_enter(); 672 mutex_enter(&ibtl_free_qp_mutex); 673 if (ibt_qp->ch_transport.rc.rc_free_flags & 674 IBTL_RC_QP_CONNECTING) { 675 IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: ERROR - " 676 "Channel establishment is still in PROGRESS."); 677 mutex_exit(&ibtl_free_qp_mutex); 678 ibtl_qp_flow_control_exit(); 679 return (IBT_CHAN_STATE_INVALID); 680 } 681 if (ibt_qp->ch_transport.rc.rc_free_flags & 682 IBTL_RC_QP_CONNECTED) { 683 if ((ibt_qp->ch_transport.rc.rc_free_flags & 684 IBTL_RC_QP_CLOSING) == 0) { 685 IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: ERROR - " 686 "need to call ibt_close_rc_channel"); 687 mutex_exit(&ibtl_free_qp_mutex); 688 ibtl_qp_flow_control_exit(); 689 return (IBT_CHAN_STATE_INVALID); 690 } 691 ibt_qp->ch_transport.rc.rc_free_flags |= 692 IBTL_RC_QP_FREED; 693 status = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_free_qp) 694 (IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), 695 IBC_FREE_QP_ONLY, 696 &ibt_qp->ch_transport.rc.rc_qpn_hdl); 697 mutex_exit(&ibtl_free_qp_mutex); 698 ibtl_qp_flow_control_exit(); 699 700 if (status == IBT_SUCCESS) { 701 mutex_enter(&ibtl_clnt_list_mutex); 702 ibtl_hca->ha_qpn_cnt++; 703 mutex_exit(&ibtl_clnt_list_mutex); 704 mutex_enter(&ibtl_hca->ha_mutex); 705 ibtl_hca->ha_qp_cnt--; 706 mutex_exit(&ibtl_hca->ha_mutex); 707 IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p) - " 708 "SUCCESS", ibt_qp); 709 } else 710 IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: " 711 "ibc_free_qp failed: status = %d", status); 712 return (status); 713 } 714 mutex_exit(&ibtl_free_qp_mutex); 715 } else 716 ibtl_qp_flow_control_enter(); 717 718 status = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_free_qp) 719 (IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), 720 IBC_FREE_QP_AND_QPN, NULL); 721 ibtl_qp_flow_control_exit(); 722 723 if (status == IBT_SUCCESS) { 724 /* effectively, this is kmem_free(ibt_qp); */ 725 ibtl_free_qp_async_check(&ibt_qp->ch_qp); 726 727 mutex_enter(&ibtl_hca->ha_mutex); 728 ibtl_hca->ha_qp_cnt--; 729 mutex_exit(&ibtl_hca->ha_mutex); 730 IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p) - SUCCESS", ibt_qp); 731 } else { 732 IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: " 733 "ibc_free_qp failed with error %d", status); 734 } 735 736 return (status); 737 } 738 739 740 /* helper function for ibt_query_qp */ 741 static void 742 ibtl_fillin_sgid(ibt_cep_path_t *pathp, ibtl_hca_devinfo_t *hca_devp) 743 { 744 uint8_t port; 745 uint32_t sgid_ix; 746 ib_gid_t *sgidp; 747 748 port = pathp->cep_hca_port_num; 749 sgid_ix = pathp->cep_adds_vect.av_sgid_ix; 750 if (port == 0 || port > hca_devp->hd_hca_attr->hca_nports || 751 sgid_ix >= IBTL_HDIP2SGIDTBLSZ(hca_devp)) { 752 pathp->cep_adds_vect.av_sgid.gid_prefix = 0; 753 pathp->cep_adds_vect.av_sgid.gid_guid = 0; 754 } else { 755 mutex_enter(&ibtl_clnt_list_mutex); 756 sgidp = hca_devp->hd_portinfop[port-1].p_sgid_tbl; 757 pathp->cep_adds_vect.av_sgid = sgidp[sgid_ix]; 758 mutex_exit(&ibtl_clnt_list_mutex); 759 } 760 } 761 762 763 /* 764 * Function: ibt_query_qp 765 * 766 * Input: ibt_qp - The IBT QP Handle. 767 * 768 * Output: ibt_qp_query_attrp - Points to a ibt_qp_query_attr_t 769 * that on return contains all the 770 * attributes of the specified qp. 771 * 772 * Returns: IBT_SUCCESS 773 * IBT_QP_HDL_INVALID 774 * 775 * Description: 776 * Query QP attributes 777 * 778 */ 779 ibt_status_t 780 ibt_query_qp(ibt_qp_hdl_t ibt_qp, ibt_qp_query_attr_t *qp_query_attrp) 781 { 782 ibt_status_t retval; 783 ibtl_hca_devinfo_t *hca_devp; 784 ibt_qp_info_t *qp_infop; 785 786 IBTF_DPRINTF_L3(ibtf_qp, "ibt_query_qp(%p, %p)", 787 ibt_qp, qp_query_attrp); 788 789 ibtl_qp_flow_control_enter(); 790 retval = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_query_qp( 791 IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), qp_query_attrp)); 792 ibtl_qp_flow_control_exit(); 793 if (retval == IBT_SUCCESS) { 794 ibt_qp->ch_current_state = qp_query_attrp->qp_info.qp_state; 795 796 /* need to fill in sgid from port and sgid_ix for RC and UC */ 797 hca_devp = ibt_qp->ch_qp.qp_hca->ha_hca_devp; 798 qp_infop = &qp_query_attrp->qp_info; 799 800 switch (qp_infop->qp_trans) { 801 case IBT_RC_SRV: 802 ibtl_fillin_sgid(&qp_infop->qp_transport.rc.rc_path, 803 hca_devp); 804 ibtl_fillin_sgid(&qp_infop->qp_transport.rc.rc_alt_path, 805 hca_devp); 806 break; 807 case IBT_UC_SRV: 808 ibtl_fillin_sgid(&qp_infop->qp_transport.uc.uc_path, 809 hca_devp); 810 ibtl_fillin_sgid(&qp_infop->qp_transport.uc.uc_alt_path, 811 hca_devp); 812 break; 813 } 814 } else { 815 IBTF_DPRINTF_L2(ibtf_qp, "ibt_query_qp: " 816 "failed on chan %p: %d", ibt_qp, retval); 817 } 818 819 return (retval); 820 } 821 822 823 /* 824 * Function: 825 * ibt_modify_qp 826 * Input: 827 * ibt_qp The IBT QP Handle. 828 * flags Specifies which attributes in ibt_qp_mod_attr_t 829 * are to be modified. 830 * qp_attrp Points to an ibt_qp_mod_attr_t struct that contains all 831 * the attributes of the specified QP that a client is 832 * allowed to modify after a QP has been allocated 833 * Output: 834 * actual_sz Returned actual queue sizes. 835 * Returns: 836 * IBT_SUCCESS 837 * Description: 838 * Modify the attributes of an existing QP. 839 */ 840 ibt_status_t 841 ibt_modify_qp(ibt_qp_hdl_t ibt_qp, ibt_cep_modify_flags_t flags, 842 ibt_qp_info_t *modify_attrp, ibt_queue_sizes_t *actual_sz) 843 { 844 ibt_status_t retval; 845 846 IBTF_DPRINTF_L3(ibtf_qp, "ibt_modify_qp(%p, %d, %p, %p)", 847 ibt_qp, flags, modify_attrp, actual_sz); 848 849 ibtl_qp_flow_control_enter(); 850 retval = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_modify_qp)( 851 IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), flags, 852 modify_attrp, actual_sz); 853 ibtl_qp_flow_control_exit(); 854 if (retval == IBT_SUCCESS) { 855 ibt_qp->ch_current_state = modify_attrp->qp_state; 856 if (ibt_qp->ch_qp.qp_type == IBT_UD_SRV) { 857 if (flags & (IBT_CEP_SET_PORT | IBT_CEP_SET_RESET_INIT)) 858 ibt_qp->ch_transport.ud.ud_port_num = 859 modify_attrp->qp_transport.ud.ud_port; 860 if (flags & (IBT_CEP_SET_QKEY | IBT_CEP_SET_RESET_INIT)) 861 ibt_qp->ch_transport.ud.ud_qkey = 862 modify_attrp->qp_transport.ud.ud_qkey; 863 } 864 } else { 865 IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_qp: failed on chan %p: %d", 866 ibt_qp, retval); 867 868 if (retval == IBT_CHAN_STATE_INVALID) { 869 /* That means our cache had invalid QP state value. */ 870 ibt_qp_query_attr_t qp_attr; 871 872 /* Query the channel (QP) */ 873 if (ibt_query_qp(ibt_qp, &qp_attr) == IBT_SUCCESS) 874 ibt_qp->ch_current_state = 875 qp_attr.qp_info.qp_state; 876 } 877 } 878 return (retval); 879 } 880 881 882 /* 883 * Function: 884 * ibt_migrate_path 885 * Input: 886 * rc_chan A previously allocated RC channel handle. 887 * Output: 888 * none. 889 * Returns: 890 * IBT_SUCCESS on Success else appropriate error. 891 * Description: 892 * Force the CI to use the alternate path. The alternate path becomes 893 * the primary path. A new alternate path should be loaded and enabled. 894 * Assumes that the given channel is in RTS/SQD state 895 */ 896 ibt_status_t 897 ibt_migrate_path(ibt_channel_hdl_t rc_chan) 898 { 899 ibt_status_t retval; 900 ibt_qp_info_t qp_info; 901 ibt_qp_query_attr_t qp_attr; 902 ibt_cep_modify_flags_t cep_flags; 903 int retries = 1; 904 905 IBTF_DPRINTF_L3(ibtf_qp, "ibt_migrate_path: channel %p", rc_chan); 906 907 if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) { 908 IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path: " 909 "Invalid Channel type: Applicable only to RC Channel"); 910 return (IBT_CHAN_SRV_TYPE_INVALID); 911 } 912 913 if (rc_chan->ch_current_state != IBT_STATE_RTS && 914 rc_chan->ch_current_state != IBT_STATE_SQD) { 915 if (ibt_query_qp(rc_chan, &qp_attr) == IBT_SUCCESS) { 916 /* ch_current_state is fixed by ibt_query_qp */ 917 if (rc_chan->ch_current_state != IBT_STATE_RTS && 918 rc_chan->ch_current_state != IBT_STATE_SQD) 919 return (IBT_CHAN_STATE_INVALID); 920 retries = 0; 921 } else /* query_qp should never really fail */ 922 return (IBT_CHAN_STATE_INVALID); 923 } 924 925 retry: 926 /* Call modify_qp */ 927 cep_flags = IBT_CEP_SET_MIG | IBT_CEP_SET_STATE; 928 qp_info.qp_state = rc_chan->ch_current_state; 929 qp_info.qp_current_state = rc_chan->ch_current_state; 930 qp_info.qp_trans = IBT_RC_SRV; 931 qp_info.qp_transport.rc.rc_mig_state = IBT_STATE_MIGRATED; 932 retval = ibt_modify_qp(rc_chan, cep_flags, &qp_info, NULL); 933 934 if (retval != IBT_SUCCESS) { 935 IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path:" 936 " ibt_modify_qp() returned = %d", retval); 937 if (rc_chan->ch_current_state != qp_info.qp_state && 938 --retries >= 0) { 939 /* 940 * That means our cached 'state' was invalid. 941 * We know ibt_modify_qp() fixed it up, so it 942 * might be worth retrying. 943 */ 944 if (rc_chan->ch_current_state != IBT_STATE_RTS && 945 rc_chan->ch_current_state != IBT_STATE_SQD) 946 return (IBT_CHAN_STATE_INVALID); 947 IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path:" 948 " retrying after 'state' fixed"); 949 goto retry; 950 } 951 } 952 return (retval); 953 } 954 955 956 /* 957 * Function: 958 * ibt_set_qp_private 959 * Input: 960 * ibt_qp The ibt_qp_hdl_t of the allocated QP. 961 * clnt_private The client private data. 962 * Output: 963 * none. 964 * Returns: 965 * none. 966 * Description: 967 * Set the client private data. 968 */ 969 void 970 ibt_set_qp_private(ibt_qp_hdl_t ibt_qp, void *clnt_private) 971 { 972 ibt_qp->ch_clnt_private = clnt_private; 973 } 974 975 976 /* 977 * Function: 978 * ibt_get_qp_private 979 * Input: 980 * ibt_qp The ibt_qp_hdl_t of the allocated QP. 981 * Output: 982 * none. 983 * Returns: 984 * The client private data. 985 * Description: 986 * Get the client private data. 987 */ 988 void * 989 ibt_get_qp_private(ibt_qp_hdl_t ibt_qp) 990 { 991 return (ibt_qp->ch_clnt_private); 992 } 993 994 995 /* 996 * Function: 997 * ibt_qp_to_hca_guid 998 * Input: 999 * ibt_qp The ibt_qp_hdl_t of the allocated QP. 1000 * Output: 1001 * none. 1002 * Returns: 1003 * hca_guid Returned HCA GUID on which the specified QP is 1004 * allocated. Valid if it is non-NULL on return. 1005 * Description: 1006 * A helper function to retrieve HCA GUID for the specified QP. 1007 */ 1008 ib_guid_t 1009 ibt_qp_to_hca_guid(ibt_qp_hdl_t ibt_qp) 1010 { 1011 IBTF_DPRINTF_L3(ibtf_qp, "ibt_qp_to_hca_guid(%p)", ibt_qp); 1012 1013 return (IBTL_HCA2HCAGUID(IBTL_CHAN2HCA(ibt_qp))); 1014 } 1015 1016 1017 /* 1018 * Function: 1019 * ibt_recover_ud_qp 1020 * Input: 1021 * ibt_qp An QP Handle which is in SQError state. 1022 * Output: 1023 * none. 1024 * Returns: 1025 * IBT_SUCCESS 1026 * IBT_QP_SRV_TYPE_INVALID 1027 * IBT_QP_STATE_INVALID. 1028 * Description: 1029 * Recover an UD QP which has transitioned to SQ Error state. The 1030 * ibt_recover_ud_qp() transitions the QP from SQ Error state to 1031 * Ready-To-Send QP state. 1032 * 1033 * If a work request posted to a UD QP's send queue completes with an 1034 * error (see ibt_wc_status_t), the QP gets transitioned to SQ Error state. 1035 * In order to reuse this QP, ibt_recover_ud_qp() can be used to recover 1036 * the QP to a usable (Ready-to-Send) state. 1037 */ 1038 ibt_status_t 1039 ibt_recover_ud_qp(ibt_qp_hdl_t ibt_qp) 1040 { 1041 IBTF_DPRINTF_L3(ibtf_qp, "ibt_recover_ud_qp(%p)", ibt_qp); 1042 1043 return (ibt_recover_ud_channel(IBTL_QP2CHAN(ibt_qp))); 1044 } 1045 1046 1047 /* 1048 * Function: 1049 * ibt_recycle_ud 1050 * Input: 1051 * ud_chan The IBT UD QP Handle. 1052 * various attributes 1053 * 1054 * Output: 1055 * none 1056 * Returns: 1057 * IBT_SUCCESS 1058 * IBT_CHAN_SRV_TYPE_INVALID 1059 * IBT_CHAN_STATE_INVALID 1060 * 1061 * Description: 1062 * Revert the UD QP back to a usable state. 1063 */ 1064 ibt_status_t 1065 ibt_recycle_ud(ibt_channel_hdl_t ud_chan, uint8_t hca_port_num, 1066 uint16_t pkey_ix, ib_qkey_t qkey) 1067 { 1068 ibt_qp_query_attr_t qp_attr; 1069 ibt_status_t retval; 1070 1071 IBTF_DPRINTF_L3(ibtf_qp, "ibt_recycle_ud(%p, %d, %x, %x): ", 1072 ud_chan, hca_port_num, pkey_ix, qkey); 1073 1074 if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) { 1075 IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: " 1076 "chan %p is not a UD channel", ud_chan); 1077 return (IBT_CHAN_SRV_TYPE_INVALID); 1078 } 1079 1080 retval = ibt_query_qp(ud_chan, &qp_attr); 1081 if (retval != IBT_SUCCESS) { 1082 IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: " 1083 "ibt_query_qp failed on chan %p: %d", ud_chan, retval); 1084 return (retval); 1085 } 1086 if (qp_attr.qp_info.qp_state != IBT_STATE_ERROR) { 1087 IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: " 1088 "chan %p is in state %d (not in ERROR state)", 1089 ud_chan, qp_attr.qp_info.qp_state); 1090 ud_chan->ch_current_state = qp_attr.qp_info.qp_state; 1091 return (IBT_CHAN_STATE_INVALID); 1092 } 1093 1094 /* transition the QP from ERROR to RESET */ 1095 qp_attr.qp_info.qp_state = IBT_STATE_RESET; 1096 qp_attr.qp_info.qp_trans = ud_chan->ch_qp.qp_type; 1097 retval = ibt_modify_qp(ud_chan, IBT_CEP_SET_STATE, &qp_attr.qp_info, 1098 NULL); 1099 if (retval != IBT_SUCCESS) { 1100 IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: " 1101 "ibt_modify_qp(ERROR=>RESET) failed on chan %p: %d", 1102 ud_chan, retval); 1103 return (retval); 1104 } 1105 ud_chan->ch_current_state = IBT_STATE_RESET; 1106 1107 /* transition the QP back to RTS */ 1108 qp_attr.qp_info.qp_transport.ud.ud_port = hca_port_num; 1109 qp_attr.qp_info.qp_transport.ud.ud_qkey = qkey; 1110 qp_attr.qp_info.qp_transport.ud.ud_pkey_ix = pkey_ix; 1111 retval = ibt_initialize_qp(ud_chan, &qp_attr.qp_info); 1112 if (retval != IBT_SUCCESS) { 1113 IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: " 1114 "ibt_initialize_qp failed on chan %p: %d", ud_chan, retval); 1115 /* the man page says the QP should be left in ERROR state */ 1116 (void) ibt_flush_qp(ud_chan); 1117 } 1118 return (retval); 1119 } 1120 1121 /* 1122 * Function: 1123 * ibt_pause_sendq 1124 * Input: 1125 * chan The IBT QP Handle. 1126 * modify_flags IBT_CEP_SET_NOTHING or IBT_CEP_SET_SQD_EVENT 1127 * 1128 * Output: 1129 * none. 1130 * Returns: 1131 * IBT_SUCCESS 1132 * IBT_CHAN_HDL_INVALID 1133 * IBT_CHAN_STATE_INVALID 1134 * IBT_INVALID_PARAM 1135 * 1136 * Description: 1137 * Place the send queue of the specified channel into the send queue 1138 * drained (SQD) state. 1139 * 1140 */ 1141 ibt_status_t 1142 ibt_pause_sendq(ibt_channel_hdl_t chan, ibt_cep_modify_flags_t modify_flags) 1143 { 1144 ibt_qp_info_t modify_attr; 1145 ibt_status_t retval; 1146 1147 IBTF_DPRINTF_L3(ibtf_qp, "ibt_pause_sendq(%p, %x)", chan, modify_flags); 1148 1149 modify_flags &= IBT_CEP_SET_SQD_EVENT; /* ignore other bits */ 1150 modify_flags |= IBT_CEP_SET_STATE; 1151 1152 bzero(&modify_attr, sizeof (ibt_qp_info_t)); 1153 /* 1154 * Set the QP state to SQD. 1155 */ 1156 modify_attr.qp_state = IBT_STATE_SQD; 1157 modify_attr.qp_trans = chan->ch_qp.qp_type; 1158 1159 retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL); 1160 1161 if (retval != IBT_SUCCESS) { 1162 IBTF_DPRINTF_L2(ibtf_qp, "ibt_pause_sendq: " 1163 "failed on chan %p: %d", chan, retval); 1164 } 1165 return (retval); 1166 } 1167 1168 1169 /* 1170 * Function: 1171 * ibt_unpause_sendq 1172 * Input: 1173 * chan The IBT Channel Handle. 1174 * Output: 1175 * none. 1176 * Returns: 1177 * IBT_SUCCESS 1178 * IBT_CHAN_HDL_INVALID 1179 * IBT_CHAN_STATE_INVALID 1180 * Description: 1181 * Un-pauses the previously paused channel. This call will transition the 1182 * QP from SQD to RTS state. 1183 */ 1184 ibt_status_t 1185 ibt_unpause_sendq(ibt_channel_hdl_t chan) 1186 { 1187 ibt_qp_info_t modify_attr; 1188 ibt_status_t retval; 1189 1190 IBTF_DPRINTF_L3(ibtf_qp, "ibt_unpause_sendq(%p)", chan); 1191 1192 bzero(&modify_attr, sizeof (ibt_qp_info_t)); 1193 1194 /* 1195 * Set the QP state to RTS. 1196 */ 1197 modify_attr.qp_current_state = IBT_STATE_SQD; 1198 modify_attr.qp_state = IBT_STATE_RTS; 1199 modify_attr.qp_trans = chan->ch_qp.qp_type; 1200 1201 retval = ibt_modify_qp(chan, IBT_CEP_SET_STATE, &modify_attr, NULL); 1202 if (retval != IBT_SUCCESS) { 1203 IBTF_DPRINTF_L2(ibtf_qp, "ibt_unpause_sendq: " 1204 "failed on chan %p: %d", chan, retval); 1205 } 1206 return (retval); 1207 } 1208 1209 1210 /* 1211 * Function: 1212 * ibt_resize_queues 1213 * Input: 1214 * chan A previously allocated channel handle. 1215 * flags QP Flags 1216 * IBT_SEND_Q 1217 * IBT_RECV_Q 1218 * request_sz Requested new sizes. 1219 * Output: 1220 * actual_sz Returned actual sizes. 1221 * Returns: 1222 * IBT_SUCCESS 1223 * Description: 1224 * Resize the SendQ/RecvQ sizes of a channel. Can only be called on 1225 * a previously opened channel. 1226 */ 1227 ibt_status_t 1228 ibt_resize_queues(ibt_channel_hdl_t chan, ibt_qflags_t flags, 1229 ibt_queue_sizes_t *request_sz, ibt_queue_sizes_t *actual_sz) 1230 { 1231 ibt_cep_modify_flags_t modify_flags = IBT_CEP_SET_STATE; 1232 ibt_qp_info_t modify_attr; 1233 ibt_status_t retval; 1234 1235 IBTF_DPRINTF_L3(ibtf_qp, "ibt_resize_queues(%p, 0x%X, %p, %p)", 1236 chan, flags, request_sz, actual_sz); 1237 1238 if ((flags & (IBT_SEND_Q | IBT_RECV_Q)) == 0) { 1239 IBTF_DPRINTF_L2(ibtf_qp, "ibt_resize_queues: " 1240 "Flags <0x%X> not set", flags); 1241 return (IBT_INVALID_PARAM); 1242 } 1243 1244 bzero(&modify_attr, sizeof (ibt_qp_info_t)); 1245 1246 modify_attr.qp_current_state = chan->ch_current_state; 1247 modify_attr.qp_trans = chan->ch_qp.qp_type; 1248 modify_attr.qp_state = chan->ch_current_state; 1249 1250 if (flags & IBT_SEND_Q) { 1251 modify_attr.qp_sq_sz = request_sz->qs_sq; 1252 modify_flags |= IBT_CEP_SET_SQ_SIZE; 1253 } 1254 1255 if (flags & IBT_RECV_Q) { 1256 modify_attr.qp_rq_sz = request_sz->qs_rq; 1257 modify_flags |= IBT_CEP_SET_RQ_SIZE; 1258 } 1259 1260 retval = ibt_modify_qp(chan, modify_flags, &modify_attr, actual_sz); 1261 if (retval != IBT_SUCCESS) { 1262 IBTF_DPRINTF_L2(ibtf_qp, "ibt_resize_queues: " 1263 "failed on QP %p: %d", chan, retval); 1264 } 1265 1266 return (retval); 1267 } 1268 1269 1270 /* 1271 * Function: 1272 * ibt_query_queues 1273 * Input: 1274 * chan A previously allocated channel handle. 1275 * Output: 1276 * actual_sz Returned actual sizes. 1277 * Returns: 1278 * IBT_SUCCESS 1279 * Description: 1280 * Query the SendQ/RecvQ sizes of a channel. 1281 */ 1282 ibt_status_t 1283 ibt_query_queues(ibt_channel_hdl_t chan, ibt_queue_sizes_t *actual_sz) 1284 { 1285 ibt_status_t retval; 1286 ibt_qp_query_attr_t qp_query_attr; 1287 1288 IBTF_DPRINTF_L3(ibtf_qp, "ibt_query_queues(%p)", chan); 1289 1290 /* Perform Query QP and retrieve QP sizes. */ 1291 retval = ibt_query_qp(chan, &qp_query_attr); 1292 if (retval != IBT_SUCCESS) { 1293 IBTF_DPRINTF_L2(ibtf_qp, "ibt_query_queues: " 1294 "ibt_query_qp failed: qp %p: %d", chan, retval); 1295 return (retval); 1296 } 1297 1298 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(actual_sz->qs_rq, 1299 actual_sz->qs_sq)) 1300 actual_sz->qs_sq = qp_query_attr.qp_info.qp_sq_sz; 1301 actual_sz->qs_rq = qp_query_attr.qp_info.qp_rq_sz; 1302 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(actual_sz->qs_rq, 1303 actual_sz->qs_sq)) 1304 chan->ch_current_state = qp_query_attr.qp_info.qp_state; 1305 1306 return (retval); 1307 } 1308 1309 1310 /* 1311 * Function: 1312 * ibt_modify_rdma 1313 * Input: 1314 * rc_chan A previously allocated channel handle. 1315 * 1316 * modify_flags Bitwise "or" of any of the following: 1317 * IBT_CEP_SET_RDMA_R Enable/Disable RDMA RD 1318 * IBT_CEP_SET_RDMA_W Enable/Disable RDMA WR 1319 * IBT_CEP_SET_ATOMIC Enable/Disable Atomics 1320 * 1321 * flags Channel End Point (CEP) Disable Flags (0 => enable). 1322 * IBT_CEP_NO_RDMA_RD Disable incoming RDMA RD's 1323 * IBT_CEP_NO_RDMA_WR Disable incoming RDMA WR's 1324 * IBT_CEP_NO_ATOMIC Disable incoming Atomics. 1325 * Output: 1326 * none. 1327 * Returns: 1328 * IBT_SUCCESS 1329 * IBT_QP_SRV_TYPE_INVALID 1330 * IBT_CHAN_HDL_INVALID 1331 * IBT_CHAN_ATOMICS_NOT_SUPPORTED 1332 * IBT_CHAN_STATE_INVALID 1333 * Description: 1334 * Enable/disable RDMA operations. To enable an operation clear the 1335 * "disable" flag. Can call this function when the channel is in 1336 * INIT, RTS or SQD states. If called in any other state 1337 * IBT_CHAN_STATE_INVALID is returned. When the operation completes the 1338 * channel state is left unchanged. 1339 */ 1340 ibt_status_t 1341 ibt_modify_rdma(ibt_channel_hdl_t rc_chan, 1342 ibt_cep_modify_flags_t modify_flags, ibt_cep_flags_t flags) 1343 { 1344 ibt_status_t retval; 1345 ibt_qp_info_t modify_attr; 1346 1347 IBTF_DPRINTF_L3(ibtf_qp, "ibt_modify_rdma(%p, 0x%x, 0x%x)", 1348 rc_chan, modify_flags, flags); 1349 1350 if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) { 1351 IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: " 1352 "Invalid Channel type: 0x%X, Applicable only to RC Channel", 1353 rc_chan->ch_qp.qp_type); 1354 return (IBT_QP_SRV_TYPE_INVALID); 1355 } 1356 1357 bzero(&modify_attr, sizeof (ibt_qp_info_t)); 1358 1359 /* 1360 * Can only call this function when the channel in INIT, RTS or SQD 1361 * states. 1362 */ 1363 if ((rc_chan->ch_current_state != IBT_STATE_INIT) && 1364 (rc_chan->ch_current_state != IBT_STATE_RTS) && 1365 (rc_chan->ch_current_state != IBT_STATE_SQD)) { 1366 IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: Invalid Channel " 1367 "state: 0x%X", rc_chan->ch_current_state); 1368 return (IBT_CHAN_STATE_INVALID); 1369 } 1370 1371 modify_attr.qp_state = modify_attr.qp_current_state = 1372 rc_chan->ch_current_state; 1373 modify_attr.qp_trans = rc_chan->ch_qp.qp_type; 1374 modify_attr.qp_flags = flags; 1375 1376 modify_flags &= (IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W | 1377 IBT_CEP_SET_ATOMIC); 1378 modify_flags |= IBT_CEP_SET_STATE; 1379 1380 retval = ibt_modify_qp(rc_chan, modify_flags, &modify_attr, NULL); 1381 if (retval != IBT_SUCCESS) { 1382 IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: " 1383 "failed on chan %p: %d", rc_chan, retval); 1384 } 1385 return (retval); 1386 } 1387 1388 1389 /* 1390 * Function: 1391 * ibt_set_rdma_resource 1392 * Input: 1393 * chan A previously allocated RC channel handle. 1394 * modify_flags Bitwise "or" of any of the following: 1395 * IBT_CEP_SET_RDMARA_OUT Initiator depth (rdma_ra_out) 1396 * IBT_CEP_SET_RDMARA_IN Responder Resources 1397 * (rdma_ra_in) 1398 * rdma_ra_out Outgoing RDMA Reads/Atomics 1399 * rdma_ra_in Incoming RDMA Reads/Atomics 1400 * Output: 1401 * none. 1402 * Returns: 1403 * IBT_SUCCESS 1404 * Description: 1405 * Change the number of resources to be used for incoming and outgoing 1406 * RDMA reads & Atomics. Can only be called on a previously opened 1407 * RC channel. Can only be called on a paused channel, and this will 1408 * un-pause that channel. 1409 */ 1410 ibt_status_t 1411 ibt_set_rdma_resource(ibt_channel_hdl_t chan, 1412 ibt_cep_modify_flags_t modify_flags, uint8_t rdma_ra_out, 1413 uint8_t resp_rdma_ra_out) 1414 { 1415 ibt_qp_info_t modify_attr; 1416 ibt_status_t retval; 1417 1418 IBTF_DPRINTF_L3(ibtf_qp, "ibt_set_rdma_resource(%p, 0x%x, %d, %d)", 1419 chan, modify_flags, rdma_ra_out, resp_rdma_ra_out); 1420 1421 if (chan->ch_qp.qp_type != IBT_RC_SRV) { 1422 IBTF_DPRINTF_L2(ibtf_qp, "ibt_set_rdma_resource: " 1423 "Invalid Channel type: 0x%X, Applicable only to RC Channel", 1424 chan->ch_qp.qp_type); 1425 return (IBT_CHAN_SRV_TYPE_INVALID); 1426 } 1427 1428 bzero(&modify_attr, sizeof (ibt_qp_info_t)); 1429 1430 modify_attr.qp_trans = chan->ch_qp.qp_type; 1431 modify_attr.qp_state = IBT_STATE_SQD; 1432 1433 modify_attr.qp_transport.rc.rc_rdma_ra_out = rdma_ra_out; 1434 modify_attr.qp_transport.rc.rc_rdma_ra_in = resp_rdma_ra_out; 1435 modify_flags &= (IBT_CEP_SET_RDMARA_OUT | IBT_CEP_SET_RDMARA_IN); 1436 modify_flags |= IBT_CEP_SET_STATE; 1437 1438 retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL); 1439 if (retval != IBT_SUCCESS) { 1440 IBTF_DPRINTF_L2(ibtf_qp, "ibt_set_rdma_resource: " 1441 "failed on chan %p: %d", chan, retval); 1442 } 1443 return (retval); 1444 } 1445 1446 1447 /* 1448 * Function: 1449 * ibt_change_port 1450 * Input: 1451 * rc_chan A previously allocated RC channel handle. 1452 * port_num New HCA port. 1453 * Output: 1454 * none. 1455 * Returns: 1456 * IBT_SUCCESS 1457 * Description: 1458 * Change the primary physical port of a channel. (This is done only if 1459 * HCA supports this capability). 1460 */ 1461 ibt_status_t 1462 ibt_change_port(ibt_channel_hdl_t chan, uint8_t port_num) 1463 { 1464 ibt_cep_modify_flags_t modify_flags; 1465 ibt_qp_info_t modify_attr; 1466 ibt_status_t retval; 1467 1468 IBTF_DPRINTF_L3(ibtf_qp, "ibt_change_port(%p, %d)", chan, port_num); 1469 1470 if (chan->ch_qp.qp_type != IBT_RC_SRV) { 1471 IBTF_DPRINTF_L2(ibtf_qp, "ibt_change_port: " 1472 "Invalid Channel type: 0x%X, Applicable only to RC Channel", 1473 chan->ch_qp.qp_type); 1474 return (IBT_CHAN_SRV_TYPE_INVALID); 1475 } 1476 bzero(&modify_attr, sizeof (ibt_qp_info_t)); 1477 1478 modify_attr.qp_state = IBT_STATE_SQD; 1479 modify_attr.qp_trans = chan->ch_qp.qp_type; 1480 modify_attr.qp_transport.rc.rc_path.cep_hca_port_num = port_num; 1481 1482 modify_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT; 1483 1484 retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL); 1485 if (retval != IBT_SUCCESS) { 1486 IBTF_DPRINTF_L2(ibtf_qp, "ibt_change_port: " 1487 "failed on chan %p: %d", chan, retval); 1488 } 1489 return (retval); 1490 } 1491 1492 1493 void 1494 ibtl_init_cep_states(void) 1495 { 1496 int index; 1497 int ibt_nstate_inits; 1498 1499 IBTF_DPRINTF_L3(ibtf_qp, "ibtl_init_cep_states()"); 1500 1501 ibt_nstate_inits = sizeof (ibt_cep_next_state_inits) / 1502 sizeof (ibt_cep_next_state_inits[0]); 1503 1504 /* 1505 * Initialize CEP next state table, using an indirect lookup table so 1506 * that this code isn't dependent on the ibt_cep_state_t enum values. 1507 */ 1508 for (index = 0; index < ibt_nstate_inits; index++) { 1509 ibt_cep_state_t state; 1510 1511 state = ibt_cep_next_state_inits[index].current_state; 1512 1513 ibt_cep_next_state[state].next_state = 1514 ibt_cep_next_state_inits[index].next_state; 1515 1516 ibt_cep_next_state[state].modify_flags = 1517 ibt_cep_next_state_inits[index].modify_flags; 1518 } 1519 } 1520