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