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