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