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 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * tavor_qpmod.c 29 * Tavor Queue Pair Modify Routines 30 * 31 * This contains all the routines necessary to implement the Tavor 32 * ModifyQP() verb. This includes all the code for legal transitions to 33 * and from Reset, Init, RTR, RTS, SQD, SQErr, and Error. 34 */ 35 36 #include <sys/sysmacros.h> 37 #include <sys/types.h> 38 #include <sys/conf.h> 39 #include <sys/ddi.h> 40 #include <sys/sunddi.h> 41 #include <sys/modctl.h> 42 #include <sys/bitmap.h> 43 44 #include <sys/ib/adapters/tavor/tavor.h> 45 #include <sys/ib/ib_pkt_hdrs.h> 46 47 static int tavor_qp_reset2init(tavor_state_t *state, tavor_qphdl_t qp, 48 ibt_qp_info_t *info_p); 49 static int tavor_qp_init2init(tavor_state_t *state, tavor_qphdl_t qp, 50 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p); 51 static int tavor_qp_init2rtr(tavor_state_t *state, tavor_qphdl_t qp, 52 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p); 53 static int tavor_qp_rtr2rts(tavor_state_t *state, tavor_qphdl_t qp, 54 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p); 55 static int tavor_qp_rts2rts(tavor_state_t *state, tavor_qphdl_t qp, 56 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p); 57 static int tavor_qp_rts2sqd(tavor_state_t *state, tavor_qphdl_t qp, 58 ibt_cep_modify_flags_t flags); 59 static int tavor_qp_sqd2rts(tavor_state_t *state, tavor_qphdl_t qp, 60 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p); 61 static int tavor_qp_sqd2sqd(tavor_state_t *state, tavor_qphdl_t qp, 62 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p); 63 static int tavor_qp_sqerr2rts(tavor_state_t *state, tavor_qphdl_t qp, 64 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p); 65 static int tavor_qp_to_error(tavor_state_t *state, tavor_qphdl_t qp); 66 static int tavor_qp_reset2err(tavor_state_t *state, tavor_qphdl_t qp); 67 68 static uint_t tavor_check_rdma_enable_flags(ibt_cep_modify_flags_t flags, 69 ibt_qp_info_t *info_p, tavor_hw_qpc_t *qpc); 70 static int tavor_qp_validate_resp_rsrc(tavor_state_t *state, 71 ibt_qp_rc_attr_t *rc, uint_t *rra_max); 72 static int tavor_qp_validate_init_depth(tavor_state_t *state, 73 ibt_qp_rc_attr_t *rc, uint_t *sra_max); 74 static int tavor_qp_validate_mtu(tavor_state_t *state, uint_t mtu); 75 76 /* 77 * tavor_qp_modify() 78 * Context: Can be called from interrupt or base context. 79 */ 80 /* ARGSUSED */ 81 int 82 tavor_qp_modify(tavor_state_t *state, tavor_qphdl_t qp, 83 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p, 84 ibt_queue_sizes_t *actual_sz) 85 { 86 ibt_cep_state_t cur_state, mod_state; 87 ibt_cep_modify_flags_t okflags; 88 int status; 89 char *errormsg; 90 91 TAVOR_TNF_ENTER(tavor_qp_modify); 92 93 /* 94 * Lock the QP so that we can modify it atomically. After grabbing 95 * the lock, get the current QP state. We will use this current QP 96 * state to determine the legal transitions (and the checks that need 97 * to be performed.) 98 * Below you will find a case for every possible QP state. In each 99 * case we check that no flags are set which are not valid for the 100 * possible transitions from that state. If these tests pass (and if 101 * the state transition we are attempting is legal), then we call 102 * one of the helper functions. Each of these functions does some 103 * additional setup before posting a Tavor firmware command for the 104 * appropriate state transition. 105 */ 106 mutex_enter(&qp->qp_lock); 107 108 /* 109 * Verify that the transport type matches between the serv_type and the 110 * qp_trans. A caller to IBT must specify the qp_trans field as 111 * IBT_UD_SRV, IBT_RC_SRV, or IBT_UC_SRV, depending on the QP. We 112 * check here that the correct value was specified, based on our 113 * understanding of the QP serv type. 114 * 115 * Because callers specify part of a 'union' based on what QP type they 116 * think they're working with, this ensures that we do not pickup bogus 117 * data if the caller thought they were working with a different QP 118 * type. 119 */ 120 if (!(TAVOR_QP_TYPE_VALID(info_p->qp_trans, qp->qp_serv_type))) { 121 mutex_exit(&qp->qp_lock); 122 TNF_PROBE_1(tavor_qp_modify_inv_qp_trans_fail, 123 TAVOR_TNF_ERROR, "", tnf_uint, qptrans, 124 info_p->qp_trans); 125 TAVOR_TNF_EXIT(tavor_qp_modify); 126 return (IBT_QP_SRV_TYPE_INVALID); 127 } 128 129 /* 130 * If this is a transition to RTS (which is valid from RTR, RTS, 131 * SQError, and SQ Drain) then we should honor the "current QP state" 132 * specified by the consumer. This means converting the IBTF QP state 133 * in "info_p->qp_current_state" to a Tavor QP state. Otherwise, we 134 * assume that we already know the current state (i.e. whatever it was 135 * last modified to or queried as - in "qp->qp_state"). 136 */ 137 mod_state = info_p->qp_state; 138 139 if (flags & IBT_CEP_SET_RTR_RTS) { 140 cur_state = TAVOR_QP_RTR; /* Ready to Receive */ 141 142 } else if ((flags & IBT_CEP_SET_STATE) && 143 (mod_state == IBT_STATE_RTS)) { 144 145 /* Convert the current IBTF QP state to a Tavor QP state */ 146 switch (info_p->qp_current_state) { 147 case IBT_STATE_RTR: 148 cur_state = TAVOR_QP_RTR; /* Ready to Receive */ 149 break; 150 case IBT_STATE_RTS: 151 cur_state = TAVOR_QP_RTS; /* Ready to Send */ 152 break; 153 case IBT_STATE_SQE: 154 cur_state = TAVOR_QP_SQERR; /* Send Queue Error */ 155 break; 156 case IBT_STATE_SQD: 157 cur_state = TAVOR_QP_SQD; /* SQ Drained */ 158 break; 159 default: 160 mutex_exit(&qp->qp_lock); 161 TNF_PROBE_1(tavor_qp_modify_inv_currqpstate_fail, 162 TAVOR_TNF_ERROR, "", tnf_uint, qpstate, 163 info_p->qp_current_state); 164 TAVOR_TNF_EXIT(tavor_qp_modify); 165 return (IBT_QP_STATE_INVALID); 166 } 167 } else { 168 cur_state = qp->qp_state; 169 } 170 171 switch (cur_state) { 172 case TAVOR_QP_RESET: 173 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RESET_INIT | 174 IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W | 175 IBT_CEP_SET_ATOMIC | IBT_CEP_SET_PKEY_IX | 176 IBT_CEP_SET_PORT | IBT_CEP_SET_QKEY); 177 178 /* 179 * Check for attempts to modify invalid attributes from the 180 * "Reset" state 181 */ 182 if (flags & ~okflags) { 183 mutex_exit(&qp->qp_lock); 184 /* Set "status" and "errormsg" and goto failure */ 185 TAVOR_TNF_FAIL(IBT_QP_ATTR_RO, "reset: invalid flag"); 186 goto qpmod_fail; 187 } 188 189 /* 190 * Verify state transition is to either "Init", back to 191 * "Reset", or to "Error". 192 */ 193 if ((flags & IBT_CEP_SET_RESET_INIT) && 194 (flags & IBT_CEP_SET_STATE) && 195 (mod_state != IBT_STATE_INIT)) { 196 /* Invalid transition - ambiguous flags */ 197 mutex_exit(&qp->qp_lock); 198 /* Set "status" and "errormsg" and goto failure */ 199 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID, 200 "reset: ambiguous flags"); 201 goto qpmod_fail; 202 203 } else if ((flags & IBT_CEP_SET_RESET_INIT) || 204 ((flags & IBT_CEP_SET_STATE) && 205 (mod_state == IBT_STATE_INIT))) { 206 /* 207 * Attempt to transition from "Reset" to "Init" 208 */ 209 status = tavor_qp_reset2init(state, qp, info_p); 210 if (status != DDI_SUCCESS) { 211 mutex_exit(&qp->qp_lock); 212 /* Set "status"/"errormsg", goto failure */ 213 TAVOR_TNF_FAIL(status, "reset to init"); 214 goto qpmod_fail; 215 } 216 qp->qp_state = TAVOR_QP_INIT; 217 218 } else if ((flags & IBT_CEP_SET_STATE) && 219 (mod_state == IBT_STATE_RESET)) { 220 /* 221 * Attempt to transition from "Reset" back to "Reset" 222 * Nothing to do here really... just drop the lock 223 * and return success. The qp->qp_state should 224 * already be set to TAVOR_QP_RESET. 225 * 226 * Note: We return here because we do not want to fall 227 * through to the tavor_wrid_from_reset_handling() 228 * routine below (since we are not really moving 229 * _out_ of the "Reset" state. 230 */ 231 mutex_exit(&qp->qp_lock); 232 TNF_PROBE_0_DEBUG(tavor_qp_modify_rst2rst, 233 TAVOR_TNF_TRACE, ""); 234 TAVOR_TNF_EXIT(tavor_qp_modify); 235 return (DDI_SUCCESS); 236 237 } else if ((flags & IBT_CEP_SET_STATE) && 238 (mod_state == IBT_STATE_ERROR)) { 239 /* 240 * Attempt to transition from "Reset" to "Error" 241 */ 242 status = tavor_qp_reset2err(state, qp); 243 if (status != DDI_SUCCESS) { 244 mutex_exit(&qp->qp_lock); 245 /* Set "status"/"errormsg", goto failure */ 246 TAVOR_TNF_FAIL(status, "reset to error"); 247 goto qpmod_fail; 248 } 249 qp->qp_state = TAVOR_QP_ERR; 250 251 } else { 252 /* Invalid transition - return error */ 253 mutex_exit(&qp->qp_lock); 254 /* Set "status" and "errormsg" and goto failure */ 255 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID, 256 "reset: invalid transition"); 257 goto qpmod_fail; 258 } 259 260 /* 261 * Do any additional handling necessary here for the transition 262 * from the "Reset" state (e.g. re-initialize the workQ WRID 263 * lists). Note: If tavor_wrid_from_reset_handling() fails, 264 * then we attempt to transition the QP back to the "Reset" 265 * state. If that fails, then it is an indication of a serious 266 * problem (either HW or SW). So we print out a warning 267 * message and return failure. 268 */ 269 status = tavor_wrid_from_reset_handling(state, qp); 270 if (status != DDI_SUCCESS) { 271 if (tavor_qp_to_reset(state, qp) != DDI_SUCCESS) { 272 TAVOR_WARNING(state, "failed to reset QP"); 273 } 274 qp->qp_state = TAVOR_QP_RESET; 275 276 mutex_exit(&qp->qp_lock); 277 /* Set "status" and "errormsg" and goto failure */ 278 TAVOR_TNF_FAIL(status, "reset: wrid_from_reset hdl"); 279 goto qpmod_fail; 280 } 281 break; 282 283 case TAVOR_QP_INIT: 284 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_INIT_RTR | 285 IBT_CEP_SET_ADDS_VECT | IBT_CEP_SET_RDMARA_IN | 286 IBT_CEP_SET_MIN_RNR_NAK | IBT_CEP_SET_ALT_PATH | 287 IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W | 288 IBT_CEP_SET_ATOMIC | IBT_CEP_SET_PKEY_IX | 289 IBT_CEP_SET_QKEY | IBT_CEP_SET_PORT); 290 291 /* 292 * Check for attempts to modify invalid attributes from the 293 * "Init" state 294 */ 295 if (flags & ~okflags) { 296 mutex_exit(&qp->qp_lock); 297 /* Set "status" and "errormsg" and goto failure */ 298 TAVOR_TNF_FAIL(IBT_QP_ATTR_RO, "init: invalid flag"); 299 goto qpmod_fail; 300 } 301 302 /* 303 * Verify state transition is to either "RTR", back to "Init", 304 * to "Reset", or to "Error" 305 */ 306 if ((flags & IBT_CEP_SET_INIT_RTR) && 307 (flags & IBT_CEP_SET_STATE) && 308 (mod_state != IBT_STATE_RTR)) { 309 /* Invalid transition - ambiguous flags */ 310 mutex_exit(&qp->qp_lock); 311 /* Set "status" and "errormsg" and goto failure */ 312 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID, 313 "init: ambiguous flags"); 314 goto qpmod_fail; 315 316 } else if ((flags & IBT_CEP_SET_INIT_RTR) || 317 ((flags & IBT_CEP_SET_STATE) && 318 (mod_state == IBT_STATE_RTR))) { 319 /* 320 * Attempt to transition from "Init" to "RTR" 321 */ 322 status = tavor_qp_init2rtr(state, qp, flags, info_p); 323 if (status != DDI_SUCCESS) { 324 mutex_exit(&qp->qp_lock); 325 /* Set "status"/"errormsg", goto failure */ 326 TAVOR_TNF_FAIL(status, "init to rtr"); 327 goto qpmod_fail; 328 } 329 qp->qp_state = TAVOR_QP_RTR; 330 331 } else if ((flags & IBT_CEP_SET_STATE) && 332 (mod_state == IBT_STATE_INIT)) { 333 /* 334 * Attempt to transition from "Init" to "Init" 335 */ 336 status = tavor_qp_init2init(state, qp, flags, info_p); 337 if (status != DDI_SUCCESS) { 338 mutex_exit(&qp->qp_lock); 339 /* Set "status"/"errormsg", goto failure */ 340 TAVOR_TNF_FAIL(status, "init to init"); 341 goto qpmod_fail; 342 } 343 qp->qp_state = TAVOR_QP_INIT; 344 345 } else if ((flags & IBT_CEP_SET_STATE) && 346 (mod_state == IBT_STATE_RESET)) { 347 /* 348 * Attempt to transition from "Init" to "Reset" 349 */ 350 status = tavor_qp_to_reset(state, qp); 351 if (status != DDI_SUCCESS) { 352 mutex_exit(&qp->qp_lock); 353 /* Set "status"/"errormsg", goto failure */ 354 TAVOR_TNF_FAIL(status, "init to reset"); 355 goto qpmod_fail; 356 } 357 qp->qp_state = TAVOR_QP_RESET; 358 359 /* 360 * Do any additional handling necessary for the 361 * transition _to_ the "Reset" state (e.g. update the 362 * workQ WRID lists) 363 */ 364 tavor_wrid_to_reset_handling(state, qp); 365 366 } else if ((flags & IBT_CEP_SET_STATE) && 367 (mod_state == IBT_STATE_ERROR)) { 368 /* 369 * Attempt to transition from "Init" to "Error" 370 */ 371 status = tavor_qp_to_error(state, qp); 372 if (status != DDI_SUCCESS) { 373 mutex_exit(&qp->qp_lock); 374 /* Set "status"/"errormsg", goto failure */ 375 TAVOR_TNF_FAIL(status, "init to error"); 376 goto qpmod_fail; 377 } 378 qp->qp_state = TAVOR_QP_ERR; 379 380 } else { 381 /* Invalid transition - return error */ 382 mutex_exit(&qp->qp_lock); 383 /* Set "status" and "errormsg" and goto failure */ 384 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID, 385 "init: invalid transition"); 386 goto qpmod_fail; 387 } 388 break; 389 390 case TAVOR_QP_RTR: 391 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RTR_RTS | 392 IBT_CEP_SET_TIMEOUT | IBT_CEP_SET_RETRY | 393 IBT_CEP_SET_RNR_NAK_RETRY | IBT_CEP_SET_RDMARA_OUT | 394 IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W | 395 IBT_CEP_SET_ATOMIC | IBT_CEP_SET_QKEY | 396 IBT_CEP_SET_ALT_PATH | IBT_CEP_SET_MIG | 397 IBT_CEP_SET_MIN_RNR_NAK); 398 399 /* 400 * Check for attempts to modify invalid attributes from the 401 * "RTR" state 402 */ 403 if (flags & ~okflags) { 404 mutex_exit(&qp->qp_lock); 405 /* Set "status" and "errormsg" and goto failure */ 406 TAVOR_TNF_FAIL(IBT_QP_ATTR_RO, "rtr: invalid flag"); 407 goto qpmod_fail; 408 } 409 410 /* 411 * Verify state transition is to either "RTS", "Reset", 412 * or "Error" 413 */ 414 if ((flags & IBT_CEP_SET_RTR_RTS) && 415 (flags & IBT_CEP_SET_STATE) && 416 (mod_state != IBT_STATE_RTS)) { 417 /* Invalid transition - ambiguous flags */ 418 mutex_exit(&qp->qp_lock); 419 /* Set "status" and "errormsg" and goto failure */ 420 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID, 421 "reset: ambiguous flags"); 422 goto qpmod_fail; 423 424 } else if ((flags & IBT_CEP_SET_RTR_RTS) || 425 ((flags & IBT_CEP_SET_STATE) && 426 (mod_state == IBT_STATE_RTS))) { 427 /* 428 * Attempt to transition from "RTR" to "RTS" 429 */ 430 status = tavor_qp_rtr2rts(state, qp, flags, info_p); 431 if (status != DDI_SUCCESS) { 432 mutex_exit(&qp->qp_lock); 433 /* Set "status"/"errormsg", goto failure */ 434 TAVOR_TNF_FAIL(status, "rtr to rts"); 435 goto qpmod_fail; 436 } 437 qp->qp_state = TAVOR_QP_RTS; 438 439 } else if ((flags & IBT_CEP_SET_STATE) && 440 (mod_state == IBT_STATE_RESET)) { 441 /* 442 * Attempt to transition from "RTR" to "Reset" 443 */ 444 status = tavor_qp_to_reset(state, qp); 445 if (status != DDI_SUCCESS) { 446 mutex_exit(&qp->qp_lock); 447 /* Set "status"/"errormsg", goto failure */ 448 TAVOR_TNF_FAIL(status, "rtr to reset"); 449 goto qpmod_fail; 450 } 451 qp->qp_state = TAVOR_QP_RESET; 452 453 /* 454 * Do any additional handling necessary for the 455 * transition _to_ the "Reset" state (e.g. update the 456 * workQ WRID lists) 457 */ 458 tavor_wrid_to_reset_handling(state, qp); 459 460 } else if ((flags & IBT_CEP_SET_STATE) && 461 (mod_state == IBT_STATE_ERROR)) { 462 /* 463 * Attempt to transition from "RTR" to "Error" 464 */ 465 status = tavor_qp_to_error(state, qp); 466 if (status != DDI_SUCCESS) { 467 mutex_exit(&qp->qp_lock); 468 /* Set "status"/"errormsg", goto failure */ 469 TAVOR_TNF_FAIL(status, "rtr to error"); 470 goto qpmod_fail; 471 } 472 qp->qp_state = TAVOR_QP_ERR; 473 474 } else { 475 /* Invalid transition - return error */ 476 mutex_exit(&qp->qp_lock); 477 /* Set "status" and "errormsg" and goto failure */ 478 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID, 479 "rtr: invalid transition"); 480 goto qpmod_fail; 481 } 482 break; 483 484 case TAVOR_QP_RTS: 485 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RDMA_R | 486 IBT_CEP_SET_RDMA_W | IBT_CEP_SET_ATOMIC | 487 IBT_CEP_SET_QKEY | IBT_CEP_SET_ALT_PATH | 488 IBT_CEP_SET_MIG | IBT_CEP_SET_MIN_RNR_NAK | 489 IBT_CEP_SET_SQD_EVENT); 490 491 /* 492 * Check for attempts to modify invalid attributes from the 493 * "RTS" state 494 */ 495 if (flags & ~okflags) { 496 mutex_exit(&qp->qp_lock); 497 /* Set "status" and "errormsg" and goto failure */ 498 TAVOR_TNF_FAIL(IBT_QP_ATTR_RO, "rts: invalid flag"); 499 goto qpmod_fail; 500 } 501 502 /* 503 * Verify state transition is to either "RTS", "SQD", "Reset", 504 * or "Error" 505 */ 506 if ((flags & IBT_CEP_SET_STATE) && 507 (mod_state == IBT_STATE_RTS)) { 508 /* 509 * Attempt to transition from "RTS" to "RTS" 510 */ 511 status = tavor_qp_rts2rts(state, qp, flags, info_p); 512 if (status != DDI_SUCCESS) { 513 mutex_exit(&qp->qp_lock); 514 /* Set "status"/"errormsg", goto failure */ 515 TAVOR_TNF_FAIL(status, "rts to rts"); 516 goto qpmod_fail; 517 } 518 /* qp->qp_state = TAVOR_QP_RTS; */ 519 520 } else if ((flags & IBT_CEP_SET_STATE) && 521 (mod_state == IBT_STATE_SQD)) { 522 /* 523 * Attempt to transition from "RTS" to "SQD" 524 */ 525 status = tavor_qp_rts2sqd(state, qp, flags); 526 if (status != DDI_SUCCESS) { 527 mutex_exit(&qp->qp_lock); 528 /* Set "status"/"errormsg", goto failure */ 529 TAVOR_TNF_FAIL(status, "rts to sqd"); 530 goto qpmod_fail; 531 } 532 qp->qp_state = TAVOR_QP_SQD; 533 534 } else if ((flags & IBT_CEP_SET_STATE) && 535 (mod_state == IBT_STATE_RESET)) { 536 /* 537 * Attempt to transition from "RTS" to "Reset" 538 */ 539 status = tavor_qp_to_reset(state, qp); 540 if (status != DDI_SUCCESS) { 541 mutex_exit(&qp->qp_lock); 542 /* Set "status"/"errormsg", goto failure */ 543 TAVOR_TNF_FAIL(status, "rts to reset"); 544 goto qpmod_fail; 545 } 546 qp->qp_state = TAVOR_QP_RESET; 547 548 /* 549 * Do any additional handling necessary for the 550 * transition _to_ the "Reset" state (e.g. update the 551 * workQ WRID lists) 552 */ 553 tavor_wrid_to_reset_handling(state, qp); 554 555 } else if ((flags & IBT_CEP_SET_STATE) && 556 (mod_state == IBT_STATE_ERROR)) { 557 /* 558 * Attempt to transition from "RTS" to "Error" 559 */ 560 status = tavor_qp_to_error(state, qp); 561 if (status != DDI_SUCCESS) { 562 mutex_exit(&qp->qp_lock); 563 /* Set "status"/"errormsg", goto failure */ 564 TAVOR_TNF_FAIL(status, "rts to error"); 565 goto qpmod_fail; 566 } 567 qp->qp_state = TAVOR_QP_ERR; 568 569 } else { 570 /* Invalid transition - return error */ 571 mutex_exit(&qp->qp_lock); 572 /* Set "status" and "errormsg" and goto failure */ 573 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID, 574 "rts: invalid transition"); 575 goto qpmod_fail; 576 } 577 break; 578 579 case TAVOR_QP_SQERR: 580 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RDMA_R | 581 IBT_CEP_SET_RDMA_W | IBT_CEP_SET_ATOMIC | 582 IBT_CEP_SET_QKEY | IBT_CEP_SET_MIN_RNR_NAK); 583 584 /* 585 * Check for attempts to modify invalid attributes from the 586 * "SQErr" state 587 */ 588 if (flags & ~okflags) { 589 mutex_exit(&qp->qp_lock); 590 /* Set "status" and "errormsg" and goto failure */ 591 TAVOR_TNF_FAIL(IBT_QP_ATTR_RO, "sqerr: invalid flag"); 592 goto qpmod_fail; 593 } 594 595 /* 596 * Verify state transition is to either "RTS", "Reset", or 597 * "Error" 598 */ 599 if ((flags & IBT_CEP_SET_STATE) && 600 (mod_state == IBT_STATE_RTS)) { 601 /* 602 * Attempt to transition from "SQErr" to "RTS" 603 */ 604 status = tavor_qp_sqerr2rts(state, qp, flags, info_p); 605 if (status != DDI_SUCCESS) { 606 mutex_exit(&qp->qp_lock); 607 /* Set "status"/"errormsg", goto failure */ 608 TAVOR_TNF_FAIL(status, "sqerr to rts"); 609 goto qpmod_fail; 610 } 611 qp->qp_state = TAVOR_QP_RTS; 612 613 } else if ((flags & IBT_CEP_SET_STATE) && 614 (mod_state == IBT_STATE_RESET)) { 615 /* 616 * Attempt to transition from "SQErr" to "Reset" 617 */ 618 status = tavor_qp_to_reset(state, qp); 619 if (status != DDI_SUCCESS) { 620 mutex_exit(&qp->qp_lock); 621 /* Set "status"/"errormsg", goto failure */ 622 TAVOR_TNF_FAIL(status, "sqerr to reset"); 623 goto qpmod_fail; 624 } 625 qp->qp_state = TAVOR_QP_RESET; 626 627 /* 628 * Do any additional handling necessary for the 629 * transition _to_ the "Reset" state (e.g. update the 630 * workQ WRID lists) 631 */ 632 tavor_wrid_to_reset_handling(state, qp); 633 634 } else if ((flags & IBT_CEP_SET_STATE) && 635 (mod_state == IBT_STATE_ERROR)) { 636 /* 637 * Attempt to transition from "SQErr" to "Error" 638 */ 639 status = tavor_qp_to_error(state, qp); 640 if (status != DDI_SUCCESS) { 641 mutex_exit(&qp->qp_lock); 642 /* Set "status"/"errormsg", goto failure */ 643 TAVOR_TNF_FAIL(status, "sqerr to error"); 644 goto qpmod_fail; 645 } 646 qp->qp_state = TAVOR_QP_ERR; 647 648 } else { 649 /* Invalid transition - return error */ 650 mutex_exit(&qp->qp_lock); 651 /* Set "status" and "errormsg" and goto failure */ 652 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID, 653 "sqerr: invalid transition"); 654 goto qpmod_fail; 655 } 656 break; 657 658 case TAVOR_QP_SQD: 659 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_ADDS_VECT | 660 IBT_CEP_SET_ALT_PATH | IBT_CEP_SET_MIG | 661 IBT_CEP_SET_RDMARA_OUT | IBT_CEP_SET_RDMARA_IN | 662 IBT_CEP_SET_QKEY | IBT_CEP_SET_PKEY_IX | 663 IBT_CEP_SET_TIMEOUT | IBT_CEP_SET_RETRY | 664 IBT_CEP_SET_RNR_NAK_RETRY | IBT_CEP_SET_PORT | 665 IBT_CEP_SET_MIN_RNR_NAK | IBT_CEP_SET_RDMA_R | 666 IBT_CEP_SET_RDMA_W | IBT_CEP_SET_ATOMIC); 667 668 /* 669 * Check for attempts to modify invalid attributes from the 670 * "SQD" state 671 */ 672 if (flags & ~okflags) { 673 mutex_exit(&qp->qp_lock); 674 /* Set "status" and "errormsg" and goto failure */ 675 TAVOR_TNF_FAIL(IBT_QP_ATTR_RO, "sqd: invalid flag"); 676 goto qpmod_fail; 677 } 678 679 /* 680 * Verify state transition is to either "SQD", "RTS", "Reset", 681 * or "Error" 682 */ 683 684 if ((flags & IBT_CEP_SET_STATE) && 685 (mod_state == IBT_STATE_SQD)) { 686 /* 687 * Attempt to transition from "SQD" to "SQD" 688 */ 689 status = tavor_qp_sqd2sqd(state, qp, flags, info_p); 690 if (status != DDI_SUCCESS) { 691 mutex_exit(&qp->qp_lock); 692 /* Set "status"/"errormsg", goto failure */ 693 TAVOR_TNF_FAIL(status, "sqd to sqd"); 694 goto qpmod_fail; 695 } 696 qp->qp_state = TAVOR_QP_SQD; 697 698 } else if ((flags & IBT_CEP_SET_STATE) && 699 (mod_state == IBT_STATE_RTS)) { 700 /* 701 * If still draining SQ, then fail transition attempt 702 * to RTS. 703 */ 704 if (qp->qp_sqd_still_draining) { 705 mutex_exit(&qp->qp_lock); 706 /* Set "status"/"errormsg", goto failure */ 707 status = IBT_QP_STATE_INVALID; 708 TAVOR_TNF_FAIL(status, "sqd to rts; draining"); 709 goto qpmod_fail; 710 } 711 712 /* 713 * Attempt to transition from "SQD" to "RTS" 714 */ 715 status = tavor_qp_sqd2rts(state, qp, flags, info_p); 716 if (status != DDI_SUCCESS) { 717 mutex_exit(&qp->qp_lock); 718 /* Set "status"/"errormsg", goto failure */ 719 TAVOR_TNF_FAIL(status, "sqd to rts"); 720 goto qpmod_fail; 721 } 722 qp->qp_state = TAVOR_QP_RTS; 723 724 } else if ((flags & IBT_CEP_SET_STATE) && 725 (mod_state == IBT_STATE_RESET)) { 726 /* 727 * Attempt to transition from "SQD" to "Reset" 728 */ 729 status = tavor_qp_to_reset(state, qp); 730 if (status != DDI_SUCCESS) { 731 mutex_exit(&qp->qp_lock); 732 /* Set "status"/"errormsg", goto failure */ 733 TAVOR_TNF_FAIL(status, "sqd to reset"); 734 goto qpmod_fail; 735 } 736 qp->qp_state = TAVOR_QP_RESET; 737 738 /* 739 * Do any additional handling necessary for the 740 * transition _to_ the "Reset" state (e.g. update the 741 * workQ WRID lists) 742 */ 743 tavor_wrid_to_reset_handling(state, qp); 744 745 } else if ((flags & IBT_CEP_SET_STATE) && 746 (mod_state == IBT_STATE_ERROR)) { 747 /* 748 * Attempt to transition from "SQD" to "Error" 749 */ 750 status = tavor_qp_to_error(state, qp); 751 if (status != DDI_SUCCESS) { 752 mutex_exit(&qp->qp_lock); 753 /* Set "status"/"errormsg", goto failure */ 754 TAVOR_TNF_FAIL(status, "sqd to error"); 755 goto qpmod_fail; 756 } 757 qp->qp_state = TAVOR_QP_ERR; 758 759 } else { 760 /* Invalid transition - return error */ 761 mutex_exit(&qp->qp_lock); 762 /* Set "status" and "errormsg" and goto failure */ 763 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID, 764 "sqd: invalid transition"); 765 goto qpmod_fail; 766 } 767 break; 768 769 case TAVOR_QP_ERR: 770 /* 771 * Verify state transition is to either "Reset" or back to 772 * "Error" 773 */ 774 if ((flags & IBT_CEP_SET_STATE) && 775 (mod_state == IBT_STATE_RESET)) { 776 /* 777 * Attempt to transition from "Error" to "Reset" 778 */ 779 status = tavor_qp_to_reset(state, qp); 780 if (status != DDI_SUCCESS) { 781 mutex_exit(&qp->qp_lock); 782 /* Set "status"/"errormsg", goto failure */ 783 TAVOR_TNF_FAIL(status, "error to reset"); 784 goto qpmod_fail; 785 } 786 qp->qp_state = TAVOR_QP_RESET; 787 788 /* 789 * Do any additional handling necessary for the 790 * transition _to_ the "Reset" state (e.g. update the 791 * workQ WRID lists) 792 */ 793 tavor_wrid_to_reset_handling(state, qp); 794 795 } else if ((flags & IBT_CEP_SET_STATE) && 796 (mod_state == IBT_STATE_ERROR)) { 797 /* 798 * Attempt to transition from "Error" back to "Error" 799 * Nothing to do here really... just drop the lock 800 * and return success. The qp->qp_state should 801 * already be set to TAVOR_QP_ERR. 802 * 803 */ 804 mutex_exit(&qp->qp_lock); 805 TNF_PROBE_0_DEBUG(tavor_qp_modify_err2err, 806 TAVOR_TNF_TRACE, ""); 807 TAVOR_TNF_EXIT(tavor_qp_modify); 808 return (DDI_SUCCESS); 809 810 } else { 811 /* Invalid transition - return error */ 812 mutex_exit(&qp->qp_lock); 813 /* Set "status" and "errormsg" and goto failure */ 814 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID, 815 "error: invalid transition"); 816 goto qpmod_fail; 817 } 818 break; 819 820 default: 821 /* 822 * Invalid QP state. If we got here then it's a warning of 823 * a probably serious problem. So print a message and return 824 * failure 825 */ 826 mutex_exit(&qp->qp_lock); 827 TAVOR_WARNING(state, "unknown QP state in modify"); 828 /* Set "status" and "errormsg" and goto failure */ 829 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID, "invalid curr QP state"); 830 goto qpmod_fail; 831 } 832 833 mutex_exit(&qp->qp_lock); 834 TAVOR_TNF_EXIT(tavor_qp_modify); 835 return (DDI_SUCCESS); 836 837 qpmod_fail: 838 TNF_PROBE_1(tavor_qp_modify_fail, TAVOR_TNF_ERROR, "", 839 tnf_string, msg, errormsg); 840 TAVOR_TNF_EXIT(tavor_qp_modify); 841 return (status); 842 } 843 844 845 /* 846 * tavor_qp_reset2init() 847 * Context: Can be called from interrupt or base context. 848 */ 849 static int 850 tavor_qp_reset2init(tavor_state_t *state, tavor_qphdl_t qp, 851 ibt_qp_info_t *info_p) 852 { 853 tavor_hw_qpc_t *qpc; 854 ibt_qp_rc_attr_t *rc; 855 ibt_qp_ud_attr_t *ud; 856 ibt_qp_uc_attr_t *uc; 857 uint_t portnum, pkeyindx; 858 int status; 859 860 TAVOR_TNF_ENTER(tavor_qp_reset2init); 861 862 ASSERT(MUTEX_HELD(&qp->qp_lock)); 863 864 /* 865 * Grab the temporary QPC entry from QP software state 866 */ 867 qpc = &qp->qpc; 868 869 /* 870 * Fill in the common and/or Tavor-specific fields in the QPC 871 */ 872 if (qp->qp_is_special) { 873 qpc->serv_type = TAVOR_QP_MLX; 874 } else { 875 qpc->serv_type = qp->qp_serv_type; 876 } 877 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED; 878 qpc->de = TAVOR_QP_DESC_EVT_ENABLED; 879 qpc->sched_q = TAVOR_QP_SCHEDQ_GET(qp->qp_qpnum); 880 if (qp->qp_is_umap) { 881 qpc->usr_page = qp->qp_uarpg; 882 } else { 883 qpc->usr_page = 0; 884 } 885 qpc->pd = qp->qp_pdhdl->pd_pdnum; 886 qpc->wqe_baseaddr = 0; 887 qpc->wqe_lkey = qp->qp_mrhdl->mr_lkey; 888 qpc->ssc = qp->qp_sq_sigtype; 889 qpc->cqn_snd = qp->qp_sq_cqhdl->cq_cqnum; 890 qpc->rsc = TAVOR_QP_RQ_ALL_SIGNALED; 891 qpc->cqn_rcv = qp->qp_rq_cqhdl->cq_cqnum; 892 qpc->srq_en = qp->qp_srq_en; 893 894 if (qp->qp_srq_en == TAVOR_QP_SRQ_ENABLED) { 895 qpc->srq_number = qp->qp_srqhdl->srq_srqnum; 896 } else { 897 qpc->srq_number = 0; 898 } 899 900 /* 901 * Now fill in the QPC fields which are specific to transport type 902 */ 903 if (qp->qp_serv_type == TAVOR_QP_UD) { 904 ud = &info_p->qp_transport.ud; 905 906 /* Set the QKey */ 907 qpc->qkey = ud->ud_qkey; 908 909 /* Check for valid port number and fill it in */ 910 portnum = ud->ud_port; 911 if (tavor_portnum_is_valid(state, portnum)) { 912 qpc->pri_addr_path.portnum = portnum; 913 } else { 914 TNF_PROBE_1(tavor_qp_reset2init_inv_port_fail, 915 TAVOR_TNF_ERROR, "", tnf_uint, port, portnum); 916 TAVOR_TNF_EXIT(tavor_qp_reset2init); 917 return (IBT_HCA_PORT_INVALID); 918 } 919 920 /* Check for valid PKey index and fill it in */ 921 pkeyindx = ud->ud_pkey_ix; 922 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 923 qpc->pri_addr_path.pkey_indx = pkeyindx; 924 qp->qp_pkeyindx = pkeyindx; 925 } else { 926 TNF_PROBE_1(tavor_qp_reset2init_inv_pkey_fail, 927 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx, pkeyindx); 928 TAVOR_TNF_EXIT(tavor_qp_reset2init); 929 return (IBT_PKEY_IX_ILLEGAL); 930 } 931 932 } else if (qp->qp_serv_type == TAVOR_QP_RC) { 933 rc = &info_p->qp_transport.rc; 934 935 /* Set the RDMA (recv) enable/disable flags */ 936 qpc->rre = (info_p->qp_flags & IBT_CEP_RDMA_RD) ? 1 : 0; 937 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0; 938 qpc->rae = (info_p->qp_flags & IBT_CEP_ATOMIC) ? 1 : 0; 939 940 /* Check for valid port number and fill it in */ 941 portnum = rc->rc_path.cep_hca_port_num; 942 if (tavor_portnum_is_valid(state, portnum)) { 943 qpc->pri_addr_path.portnum = portnum; 944 } else { 945 TNF_PROBE_1(tavor_qp_reset2init_inv_port_fail, 946 TAVOR_TNF_ERROR, "", tnf_uint, port, portnum); 947 TAVOR_TNF_EXIT(tavor_qp_reset2init); 948 return (IBT_HCA_PORT_INVALID); 949 } 950 951 /* Check for valid PKey index and fill it in */ 952 pkeyindx = rc->rc_path.cep_pkey_ix; 953 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 954 qpc->pri_addr_path.pkey_indx = pkeyindx; 955 } else { 956 TNF_PROBE_1(tavor_qp_reset2init_inv_pkey_fail, 957 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx, pkeyindx); 958 TAVOR_TNF_EXIT(tavor_qp_reset2init); 959 return (IBT_PKEY_IX_ILLEGAL); 960 } 961 962 } else if (qp->qp_serv_type == TAVOR_QP_UC) { 963 uc = &info_p->qp_transport.uc; 964 965 /* 966 * Set the RDMA (recv) enable/disable flags. Note: RDMA Read 967 * and Atomic are ignored by default. 968 */ 969 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0; 970 971 /* Check for valid port number and fill it in */ 972 portnum = uc->uc_path.cep_hca_port_num; 973 if (tavor_portnum_is_valid(state, portnum)) { 974 qpc->pri_addr_path.portnum = portnum; 975 } else { 976 TNF_PROBE_1(tavor_qp_reset2init_inv_port_fail, 977 TAVOR_TNF_ERROR, "", tnf_uint, port, portnum); 978 TAVOR_TNF_EXIT(tavor_qp_reset2init); 979 return (IBT_HCA_PORT_INVALID); 980 } 981 982 /* Check for valid PKey index and fill it in */ 983 pkeyindx = uc->uc_path.cep_pkey_ix; 984 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 985 qpc->pri_addr_path.pkey_indx = pkeyindx; 986 } else { 987 TNF_PROBE_1(tavor_qp_reset2init_inv_pkey_fail, 988 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx, pkeyindx); 989 TAVOR_TNF_EXIT(tavor_qp_reset2init); 990 return (IBT_PKEY_IX_ILLEGAL); 991 } 992 } else { 993 /* 994 * Invalid QP transport type. If we got here then it's a 995 * warning of a probably serious problem. So print a message 996 * and return failure 997 */ 998 TAVOR_WARNING(state, "unknown QP transport type in rst2init"); 999 TNF_PROBE_0(tavor_qp_reset2init_inv_transtype_fail, 1000 TAVOR_TNF_ERROR, ""); 1001 TAVOR_TNF_EXIT(tavor_qp_reset2init); 1002 return (ibc_get_ci_failure(0)); 1003 } 1004 1005 /* 1006 * Post the RST2INIT_QP command to the Tavor firmware 1007 * 1008 * We do a TAVOR_NOSLEEP here because we are still holding the 1009 * "qp_lock". If we got raised to interrupt level by priority 1010 * inversion, we do not want to block in this routine waiting for 1011 * success. 1012 */ 1013 status = tavor_cmn_qp_cmd_post(state, RST2INIT_QP, qpc, qp->qp_qpnum, 1014 0, TAVOR_CMD_NOSLEEP_SPIN); 1015 if (status != TAVOR_CMD_SUCCESS) { 1016 cmn_err(CE_CONT, "Tavor: RST2INIT_QP command failed: %08x\n", 1017 status); 1018 TNF_PROBE_1(tavor_qp_reset2init_cmd_fail, TAVOR_TNF_ERROR, "", 1019 tnf_uint, status, status); 1020 TAVOR_TNF_EXIT(tavor_qp_reset2init); 1021 return (ibc_get_ci_failure(0)); 1022 } 1023 1024 TAVOR_TNF_EXIT(tavor_qp_reset2init); 1025 return (DDI_SUCCESS); 1026 } 1027 1028 1029 /* 1030 * tavor_qp_init2init() 1031 * Context: Can be called from interrupt or base context. 1032 */ 1033 static int 1034 tavor_qp_init2init(tavor_state_t *state, tavor_qphdl_t qp, 1035 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p) 1036 { 1037 tavor_hw_qpc_t *qpc; 1038 ibt_qp_rc_attr_t *rc; 1039 ibt_qp_ud_attr_t *ud; 1040 ibt_qp_uc_attr_t *uc; 1041 uint_t portnum, pkeyindx; 1042 uint32_t opmask = 0; 1043 int status; 1044 1045 TAVOR_TNF_ENTER(tavor_qp_init2init); 1046 1047 ASSERT(MUTEX_HELD(&qp->qp_lock)); 1048 1049 /* 1050 * Grab the temporary QPC entry from QP software state 1051 */ 1052 qpc = &qp->qpc; 1053 1054 /* 1055 * Since there are no common and/or Tavor-specific fields to be filled 1056 * in for this command, we begin with the QPC fields which are 1057 * specific to transport type. 1058 */ 1059 if (qp->qp_serv_type == TAVOR_QP_UD) { 1060 ud = &info_p->qp_transport.ud; 1061 1062 /* 1063 * If we are attempting to modify the port for this QP, then 1064 * check for valid port number and fill it in. Also set the 1065 * appropriate flag in the "opmask" parameter. 1066 */ 1067 if (flags & IBT_CEP_SET_PORT) { 1068 portnum = ud->ud_port; 1069 if (tavor_portnum_is_valid(state, portnum)) { 1070 qpc->pri_addr_path.portnum = portnum; 1071 } else { 1072 TNF_PROBE_1(tavor_qp_init2init_inv_port_fail, 1073 TAVOR_TNF_ERROR, "", tnf_uint, port, 1074 portnum); 1075 TAVOR_TNF_EXIT(tavor_qp_init2init); 1076 return (IBT_HCA_PORT_INVALID); 1077 } 1078 opmask |= TAVOR_CMD_OP_PRIM_PORT; 1079 } 1080 1081 /* 1082 * If we are attempting to modify the PKey index for this QP, 1083 * then check for valid PKey index and fill it in. Also set 1084 * the appropriate flag in the "opmask" parameter. 1085 */ 1086 if (flags & IBT_CEP_SET_PKEY_IX) { 1087 pkeyindx = ud->ud_pkey_ix; 1088 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 1089 qpc->pri_addr_path.pkey_indx = pkeyindx; 1090 opmask |= TAVOR_CMD_OP_PKEYINDX; 1091 qp->qp_pkeyindx = pkeyindx; 1092 } else { 1093 TNF_PROBE_1(tavor_qp_init2init_inv_pkey_fail, 1094 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx, 1095 pkeyindx); 1096 TAVOR_TNF_EXIT(tavor_qp_init2init); 1097 return (IBT_PKEY_IX_ILLEGAL); 1098 } 1099 } 1100 1101 /* 1102 * If we are attempting to modify the QKey for this QP, then 1103 * fill it in and set the appropriate flag in the "opmask" 1104 * parameter. 1105 */ 1106 if (flags & IBT_CEP_SET_QKEY) { 1107 qpc->qkey = ud->ud_qkey; 1108 opmask |= TAVOR_CMD_OP_QKEY; 1109 } 1110 1111 } else if (qp->qp_serv_type == TAVOR_QP_RC) { 1112 rc = &info_p->qp_transport.rc; 1113 1114 /* 1115 * If we are attempting to modify the port for this QP, then 1116 * check for valid port number and fill it in. Also set the 1117 * appropriate flag in the "opmask" parameter. 1118 */ 1119 if (flags & IBT_CEP_SET_PORT) { 1120 portnum = rc->rc_path.cep_hca_port_num; 1121 if (tavor_portnum_is_valid(state, portnum)) { 1122 qpc->pri_addr_path.portnum = portnum; 1123 } else { 1124 TNF_PROBE_1(tavor_qp_init2init_inv_port_fail, 1125 TAVOR_TNF_ERROR, "", tnf_uint, port, 1126 portnum); 1127 TAVOR_TNF_EXIT(tavor_qp_init2init); 1128 return (IBT_HCA_PORT_INVALID); 1129 } 1130 opmask |= TAVOR_CMD_OP_PRIM_PORT; 1131 } 1132 1133 /* 1134 * If we are attempting to modify the PKey index for this QP, 1135 * then check for valid PKey index and fill it in. Also set 1136 * the appropriate flag in the "opmask" parameter. 1137 */ 1138 if (flags & IBT_CEP_SET_PKEY_IX) { 1139 pkeyindx = rc->rc_path.cep_pkey_ix; 1140 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 1141 qpc->pri_addr_path.pkey_indx = pkeyindx; 1142 opmask |= TAVOR_CMD_OP_PKEYINDX; 1143 } else { 1144 TNF_PROBE_1(tavor_qp_init2init_inv_pkey_fail, 1145 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx, 1146 pkeyindx); 1147 TAVOR_TNF_EXIT(tavor_qp_init2init); 1148 return (IBT_PKEY_IX_ILLEGAL); 1149 } 1150 } 1151 1152 /* 1153 * Check if any of the flags indicate a change in the RDMA 1154 * (recv) enable/disable flags and set the appropriate flag in 1155 * the "opmask" parameter 1156 */ 1157 opmask |= tavor_check_rdma_enable_flags(flags, info_p, qpc); 1158 1159 } else if (qp->qp_serv_type == TAVOR_QP_UC) { 1160 uc = &info_p->qp_transport.uc; 1161 1162 /* 1163 * If we are attempting to modify the port for this QP, then 1164 * check for valid port number and fill it in. Also set the 1165 * appropriate flag in the "opmask" parameter. 1166 */ 1167 if (flags & IBT_CEP_SET_PORT) { 1168 portnum = uc->uc_path.cep_hca_port_num; 1169 if (tavor_portnum_is_valid(state, portnum)) { 1170 qpc->pri_addr_path.portnum = portnum; 1171 } else { 1172 TNF_PROBE_1(tavor_qp_init2init_inv_port_fail, 1173 TAVOR_TNF_ERROR, "", tnf_uint, port, 1174 portnum); 1175 TAVOR_TNF_EXIT(tavor_qp_init2init); 1176 return (IBT_HCA_PORT_INVALID); 1177 } 1178 opmask |= TAVOR_CMD_OP_PRIM_PORT; 1179 } 1180 1181 /* 1182 * If we are attempting to modify the PKey index for this QP, 1183 * then check for valid PKey index and fill it in. Also set 1184 * the appropriate flag in the "opmask" parameter. 1185 */ 1186 if (flags & IBT_CEP_SET_PKEY_IX) { 1187 pkeyindx = uc->uc_path.cep_pkey_ix; 1188 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 1189 qpc->pri_addr_path.pkey_indx = pkeyindx; 1190 opmask |= TAVOR_CMD_OP_PKEYINDX; 1191 } else { 1192 TNF_PROBE_1(tavor_qp_init2init_inv_pkey_fail, 1193 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx, 1194 pkeyindx); 1195 TAVOR_TNF_EXIT(tavor_qp_init2init); 1196 return (IBT_PKEY_IX_ILLEGAL); 1197 } 1198 } 1199 1200 /* 1201 * Check if any of the flags indicate a change in the RDMA 1202 * Write (recv) enable/disable and set the appropriate flag 1203 * in the "opmask" parameter. Note: RDMA Read and Atomic are 1204 * not valid for UC transport. 1205 */ 1206 if (flags & IBT_CEP_SET_RDMA_W) { 1207 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0; 1208 opmask |= TAVOR_CMD_OP_RWE; 1209 } 1210 } else { 1211 /* 1212 * Invalid QP transport type. If we got here then it's a 1213 * warning of a probably serious problem. So print a message 1214 * and return failure 1215 */ 1216 TAVOR_WARNING(state, "unknown QP transport type in init2init"); 1217 TNF_PROBE_0(tavor_qp_init2init_inv_transtype_fail, 1218 TAVOR_TNF_ERROR, ""); 1219 TAVOR_TNF_EXIT(tavor_qp_init2init); 1220 return (ibc_get_ci_failure(0)); 1221 } 1222 1223 /* 1224 * Post the INIT2INIT_QP command to the Tavor firmware 1225 * 1226 * We do a TAVOR_NOSLEEP here because we are still holding the 1227 * "qp_lock". If we got raised to interrupt level by priority 1228 * inversion, we do not want to block in this routine waiting for 1229 * success. 1230 */ 1231 status = tavor_cmn_qp_cmd_post(state, INIT2INIT_QP, qpc, qp->qp_qpnum, 1232 opmask, TAVOR_CMD_NOSLEEP_SPIN); 1233 if (status != TAVOR_CMD_SUCCESS) { 1234 if (status != TAVOR_CMD_BAD_QP_STATE) { 1235 cmn_err(CE_CONT, "Tavor: INIT2INIT_QP command failed: " 1236 "%08x\n", status); 1237 TNF_PROBE_1(tavor_qp_init2init_cmd_fail, 1238 TAVOR_TNF_ERROR, "", tnf_uint, status, status); 1239 TAVOR_TNF_EXIT(tavor_qp_init2init); 1240 return (ibc_get_ci_failure(0)); 1241 } else { 1242 TNF_PROBE_0(tavor_qp_init2init_inv_qpstate_fail, 1243 TAVOR_TNF_ERROR, ""); 1244 TAVOR_TNF_EXIT(tavor_qp_init2init); 1245 return (IBT_QP_STATE_INVALID); 1246 } 1247 } 1248 1249 TAVOR_TNF_EXIT(tavor_qp_init2init); 1250 return (DDI_SUCCESS); 1251 } 1252 1253 1254 /* 1255 * tavor_qp_init2rtr() 1256 * Context: Can be called from interrupt or base context. 1257 */ 1258 static int 1259 tavor_qp_init2rtr(tavor_state_t *state, tavor_qphdl_t qp, 1260 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p) 1261 { 1262 tavor_hw_qpc_t *qpc; 1263 ibt_qp_rc_attr_t *rc; 1264 ibt_qp_ud_attr_t *ud; 1265 ibt_qp_uc_attr_t *uc; 1266 tavor_hw_addr_path_t *qpc_path; 1267 ibt_adds_vect_t *adds_vect; 1268 uint_t portnum, pkeyindx, rdma_ra_in, rra_max; 1269 uint_t mtu; 1270 uint32_t opmask = 0; 1271 int status; 1272 1273 TAVOR_TNF_ENTER(tavor_qp_init2rtr); 1274 1275 ASSERT(MUTEX_HELD(&qp->qp_lock)); 1276 1277 /* 1278 * Grab the temporary QPC entry from QP software state 1279 */ 1280 qpc = &qp->qpc; 1281 1282 /* 1283 * Since there are no common and/or Tavor-specific fields to be filled 1284 * in for this command, we begin with the QPC fields which are 1285 * specific to transport type. 1286 */ 1287 if (qp->qp_serv_type == TAVOR_QP_UD) { 1288 ud = &info_p->qp_transport.ud; 1289 1290 /* 1291 * If this UD QP is also a "special QP" (QP0 or QP1), then 1292 * the MTU is 256 bytes. However, Tavor HW requires us to 1293 * set the MTU to 4 (which is the IB code for a 2K MTU). 1294 * If this is not a special QP, then we set the MTU to the 1295 * configured maximum (which defaults to 2K). Note: the 1296 * QPC "msg_max" must also be set so as to correspond with 1297 * the specified MTU value. 1298 */ 1299 if (qp->qp_is_special) { 1300 qpc->mtu = 4; 1301 } else { 1302 qpc->mtu = state->ts_cfg_profile->cp_max_mtu; 1303 } 1304 qpc->msg_max = qpc->mtu + 7; /* must equal MTU plus seven */ 1305 1306 /* 1307 * Save away the MTU value. This is used in future sqd2sqd 1308 * transitions, as the MTU must remain the same in future 1309 * changes. 1310 */ 1311 qp->qp_save_mtu = qpc->mtu; 1312 1313 /* 1314 * If we are attempting to modify the PKey index for this QP, 1315 * then check for valid PKey index and fill it in. Also set 1316 * the appropriate flag in the "opmask" parameter. 1317 */ 1318 if (flags & IBT_CEP_SET_PKEY_IX) { 1319 pkeyindx = ud->ud_pkey_ix; 1320 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 1321 qpc->pri_addr_path.pkey_indx = pkeyindx; 1322 opmask |= TAVOR_CMD_OP_PKEYINDX; 1323 qp->qp_pkeyindx = pkeyindx; 1324 } else { 1325 TNF_PROBE_1(tavor_qp_init2rtr_inv_pkey_fail, 1326 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx, 1327 pkeyindx); 1328 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1329 return (IBT_PKEY_IX_ILLEGAL); 1330 } 1331 } 1332 1333 /* 1334 * If we are attempting to modify the QKey for this QP, then 1335 * fill it in and set the appropriate flag in the "opmask" 1336 * parameter. 1337 */ 1338 if (flags & IBT_CEP_SET_QKEY) { 1339 qpc->qkey = ud->ud_qkey; 1340 opmask |= TAVOR_CMD_OP_QKEY; 1341 } 1342 1343 } else if (qp->qp_serv_type == TAVOR_QP_RC) { 1344 rc = &info_p->qp_transport.rc; 1345 qpc_path = &qpc->pri_addr_path; 1346 adds_vect = &rc->rc_path.cep_adds_vect; 1347 1348 /* 1349 * Set the common primary address path fields 1350 */ 1351 status = tavor_set_addr_path(state, adds_vect, qpc_path, 1352 TAVOR_ADDRPATH_QP, qp); 1353 if (status != DDI_SUCCESS) { 1354 TNF_PROBE_0(tavor_qp_init2rtr_setaddrpath_fail, 1355 TAVOR_TNF_ERROR, ""); 1356 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1357 return (status); 1358 } 1359 1360 /* 1361 * The following values are apparently "required" here (as 1362 * they are part of the IBA-defined "Remote Node Address 1363 * Vector"). However, they are also going to be "required" 1364 * later - at RTR2RTS_QP time. Not sure why. But we set 1365 * them here anyway. 1366 */ 1367 qpc_path->rnr_retry = rc->rc_rnr_retry_cnt; 1368 qpc->retry_cnt = rc->rc_retry_cnt; 1369 qpc_path->ack_timeout = rc->rc_path.cep_timeout; 1370 1371 /* 1372 * Setup the destination QP, recv PSN, MTU, max msg size,etc. 1373 * Note max message size is defined to be the maximum IB 1374 * allowed message size (which is 2^31 bytes). Also max 1375 * MTU is defined by HCA port properties. 1376 */ 1377 qpc->rem_qpn = rc->rc_dst_qpn; 1378 qpc->next_rcv_psn = rc->rc_rq_psn; 1379 qpc->msg_max = TAVOR_QP_LOG_MAX_MSGSZ; 1380 1381 /* 1382 * If this QP is using an SRQ, 'ric' must be set to 1. 1383 */ 1384 qpc->ric = (qp->qp_srq_en == TAVOR_QP_SRQ_ENABLED) ? 1 : 0; 1385 mtu = rc->rc_path_mtu; 1386 if (tavor_qp_validate_mtu(state, mtu) != DDI_SUCCESS) { 1387 TNF_PROBE_1(tavor_qp_init2rtr_inv_mtu_fail, 1388 TAVOR_TNF_ERROR, "", tnf_uint, mtu, mtu); 1389 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1390 return (IBT_HCA_PORT_MTU_EXCEEDED); 1391 } 1392 qpc->mtu = mtu; 1393 1394 /* 1395 * Save away the MTU value. This is used in future sqd2sqd 1396 * transitions, as the MTU must remain the same in future 1397 * changes. 1398 */ 1399 qp->qp_save_mtu = qpc->mtu; 1400 1401 /* 1402 * Though it is a "required" parameter, "min_rnr_nak" is 1403 * optionally specifiable in Tavor. So we hardcode the 1404 * optional flag here. 1405 */ 1406 qpc->min_rnr_nak = rc->rc_min_rnr_nak; 1407 opmask |= TAVOR_CMD_OP_MINRNRNAK; 1408 1409 /* 1410 * Check that the number of specified "incoming RDMA resources" 1411 * is valid. And if it is, then setup the "rra_max" and 1412 * "ra_buf_index" fields in the QPC to point to the 1413 * pre-allocated RDB resources (in DDR) 1414 */ 1415 rdma_ra_in = rc->rc_rdma_ra_in; 1416 if (tavor_qp_validate_resp_rsrc(state, rc, &rra_max) != 1417 DDI_SUCCESS) { 1418 TNF_PROBE_1(tavor_qp_init2rtr_inv_rdma_in_fail, 1419 TAVOR_TNF_ERROR, "", tnf_uint, rdma_ra_in, 1420 rdma_ra_in); 1421 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1422 return (IBT_INVALID_PARAM); 1423 } 1424 qpc->rra_max = rra_max; 1425 qpc->ra_buff_indx = qp->qp_rdb_ddraddr >> TAVOR_RDB_SIZE_SHIFT; 1426 1427 /* 1428 * If we are attempting to modify the PKey index for this QP, 1429 * then check for valid PKey index and fill it in. Also set 1430 * the appropriate flag in the "opmask" parameter. 1431 */ 1432 if (flags & IBT_CEP_SET_PKEY_IX) { 1433 pkeyindx = rc->rc_path.cep_pkey_ix; 1434 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 1435 qpc->pri_addr_path.pkey_indx = pkeyindx; 1436 opmask |= TAVOR_CMD_OP_PKEYINDX; 1437 } else { 1438 TNF_PROBE_1(tavor_qp_init2rtr_inv_pkey_fail, 1439 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx, 1440 pkeyindx); 1441 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1442 return (IBT_PKEY_IX_ILLEGAL); 1443 } 1444 } 1445 1446 /* 1447 * Check if any of the flags indicate a change in the RDMA 1448 * (recv) enable/disable flags and set the appropriate flag in 1449 * the "opmask" parameter 1450 */ 1451 opmask |= tavor_check_rdma_enable_flags(flags, info_p, qpc); 1452 1453 /* 1454 * Check for optional alternate path and fill in the 1455 * appropriate QPC fields if one is specified 1456 */ 1457 if (flags & IBT_CEP_SET_ALT_PATH) { 1458 qpc_path = &qpc->alt_addr_path; 1459 adds_vect = &rc->rc_alt_path.cep_adds_vect; 1460 1461 /* Set the common alternate address path fields */ 1462 status = tavor_set_addr_path(state, adds_vect, qpc_path, 1463 TAVOR_ADDRPATH_QP, qp); 1464 if (status != DDI_SUCCESS) { 1465 TNF_PROBE_0(tavor_qp_init2rtr_setaddrpath_fail, 1466 TAVOR_TNF_ERROR, ""); 1467 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1468 return (status); 1469 } 1470 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout; 1471 1472 /* 1473 * Copy the "RNR Retry count" value from the primary 1474 * path. Just as we did above, we need to hardcode 1475 * the optional flag here (see below). 1476 */ 1477 qpc_path->rnr_retry = rc->rc_rnr_retry_cnt; 1478 1479 /* 1480 * Check for valid alternate path port number and fill 1481 * it in 1482 */ 1483 portnum = rc->rc_alt_path.cep_hca_port_num; 1484 if (tavor_portnum_is_valid(state, portnum)) { 1485 qpc->alt_addr_path.portnum = portnum; 1486 } else { 1487 TNF_PROBE_1(tavor_qp_init2rtr_inv_altport_fail, 1488 TAVOR_TNF_ERROR, "", tnf_uint, altport, 1489 portnum); 1490 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1491 return (IBT_HCA_PORT_INVALID); 1492 } 1493 1494 /* 1495 * Check for valid alternate path PKey index and fill 1496 * it in 1497 */ 1498 pkeyindx = rc->rc_alt_path.cep_pkey_ix; 1499 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 1500 qpc->alt_addr_path.pkey_indx = pkeyindx; 1501 } else { 1502 TNF_PROBE_1(tavor_qp_init2rtr_inv_altpkey_fail, 1503 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx, 1504 pkeyindx); 1505 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1506 return (IBT_PKEY_IX_ILLEGAL); 1507 } 1508 opmask |= (TAVOR_CMD_OP_ALT_PATH | 1509 TAVOR_CMD_OP_ALT_RNRRETRY); 1510 } 1511 1512 } else if (qp->qp_serv_type == TAVOR_QP_UC) { 1513 uc = &info_p->qp_transport.uc; 1514 qpc_path = &qpc->pri_addr_path; 1515 adds_vect = &uc->uc_path.cep_adds_vect; 1516 1517 /* 1518 * Set the common primary address path fields 1519 */ 1520 status = tavor_set_addr_path(state, adds_vect, qpc_path, 1521 TAVOR_ADDRPATH_QP, qp); 1522 if (status != DDI_SUCCESS) { 1523 TNF_PROBE_0(tavor_qp_init2rtr_setaddrpath_fail, 1524 TAVOR_TNF_ERROR, ""); 1525 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1526 return (status); 1527 } 1528 1529 /* 1530 * Setup the destination QP, recv PSN, MTU, max msg size,etc. 1531 * Note max message size is defined to be the maximum IB 1532 * allowed message size (which is 2^31 bytes). Also max 1533 * MTU is defined by HCA port properties. 1534 */ 1535 qpc->rem_qpn = uc->uc_dst_qpn; 1536 qpc->next_rcv_psn = uc->uc_rq_psn; 1537 qpc->msg_max = TAVOR_QP_LOG_MAX_MSGSZ; 1538 mtu = uc->uc_path_mtu; 1539 if (tavor_qp_validate_mtu(state, mtu) != DDI_SUCCESS) { 1540 TNF_PROBE_1(tavor_qp_init2rtr_inv_mtu_fail, 1541 TAVOR_TNF_ERROR, "", tnf_uint, mtu, mtu); 1542 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1543 return (IBT_HCA_PORT_MTU_EXCEEDED); 1544 } 1545 qpc->mtu = mtu; 1546 1547 /* 1548 * Save away the MTU value. This is used in future sqd2sqd 1549 * transitions, as the MTU must remain the same in future 1550 * changes. 1551 */ 1552 qp->qp_save_mtu = qpc->mtu; 1553 1554 /* 1555 * If we are attempting to modify the PKey index for this QP, 1556 * then check for valid PKey index and fill it in. Also set 1557 * the appropriate flag in the "opmask" parameter. 1558 */ 1559 if (flags & IBT_CEP_SET_PKEY_IX) { 1560 pkeyindx = uc->uc_path.cep_pkey_ix; 1561 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 1562 qpc->pri_addr_path.pkey_indx = pkeyindx; 1563 opmask |= TAVOR_CMD_OP_PKEYINDX; 1564 } else { 1565 TNF_PROBE_1(tavor_qp_init2rtr_inv_pkey_fail, 1566 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx, 1567 pkeyindx); 1568 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1569 return (IBT_PKEY_IX_ILLEGAL); 1570 } 1571 } 1572 1573 /* 1574 * Check if any of the flags indicate a change in the RDMA 1575 * Write (recv) enable/disable and set the appropriate flag 1576 * in the "opmask" parameter. Note: RDMA Read and Atomic are 1577 * not valid for UC transport. 1578 */ 1579 if (flags & IBT_CEP_SET_RDMA_W) { 1580 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0; 1581 opmask |= TAVOR_CMD_OP_RWE; 1582 } 1583 1584 /* 1585 * Check for optional alternate path and fill in the 1586 * appropriate QPC fields if one is specified 1587 */ 1588 if (flags & IBT_CEP_SET_ALT_PATH) { 1589 qpc_path = &qpc->alt_addr_path; 1590 adds_vect = &uc->uc_alt_path.cep_adds_vect; 1591 1592 /* Set the common alternate address path fields */ 1593 status = tavor_set_addr_path(state, adds_vect, qpc_path, 1594 TAVOR_ADDRPATH_QP, qp); 1595 if (status != DDI_SUCCESS) { 1596 TNF_PROBE_0(tavor_qp_init2rtr_setaddrpath_fail, 1597 TAVOR_TNF_ERROR, ""); 1598 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1599 return (status); 1600 } 1601 1602 /* 1603 * Check for valid alternate path port number and fill 1604 * it in 1605 */ 1606 portnum = uc->uc_alt_path.cep_hca_port_num; 1607 if (tavor_portnum_is_valid(state, portnum)) { 1608 qpc->alt_addr_path.portnum = portnum; 1609 } else { 1610 TNF_PROBE_1(tavor_qp_init2rtr_inv_altport_fail, 1611 TAVOR_TNF_ERROR, "", tnf_uint, altport, 1612 portnum); 1613 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1614 return (IBT_HCA_PORT_INVALID); 1615 } 1616 1617 /* 1618 * Check for valid alternate path PKey index and fill 1619 * it in 1620 */ 1621 pkeyindx = uc->uc_alt_path.cep_pkey_ix; 1622 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 1623 qpc->alt_addr_path.pkey_indx = pkeyindx; 1624 } else { 1625 TNF_PROBE_1(tavor_qp_init2rtr_inv_altpkey_fail, 1626 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx, 1627 pkeyindx); 1628 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1629 return (IBT_PKEY_IX_ILLEGAL); 1630 } 1631 opmask |= TAVOR_CMD_OP_ALT_PATH; 1632 } 1633 } else { 1634 /* 1635 * Invalid QP transport type. If we got here then it's a 1636 * warning of a probably serious problem. So print a message 1637 * and return failure 1638 */ 1639 TAVOR_WARNING(state, "unknown QP transport type in init2rtr"); 1640 TNF_PROBE_0(tavor_qp_init2rtr_inv_transtype_fail, 1641 TAVOR_TNF_ERROR, ""); 1642 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1643 return (ibc_get_ci_failure(0)); 1644 } 1645 1646 /* 1647 * Post the INIT2RTR_QP command to the Tavor firmware 1648 * 1649 * We do a TAVOR_NOSLEEP here because we are still holding the 1650 * "qp_lock". If we got raised to interrupt level by priority 1651 * inversion, we do not want to block in this routine waiting for 1652 * success. 1653 */ 1654 status = tavor_cmn_qp_cmd_post(state, INIT2RTR_QP, qpc, qp->qp_qpnum, 1655 opmask, TAVOR_CMD_NOSLEEP_SPIN); 1656 if (status != TAVOR_CMD_SUCCESS) { 1657 if (status != TAVOR_CMD_BAD_QP_STATE) { 1658 cmn_err(CE_CONT, "Tavor: INIT2RTR_QP command failed: " 1659 "%08x\n", status); 1660 TNF_PROBE_1(tavor_qp_init2rtr_cmd_fail, 1661 TAVOR_TNF_ERROR, "", tnf_uint, status, status); 1662 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1663 return (ibc_get_ci_failure(0)); 1664 } else { 1665 TNF_PROBE_0(tavor_qp_init2rtr_inv_qpstate_fail, 1666 TAVOR_TNF_ERROR, ""); 1667 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1668 return (IBT_QP_STATE_INVALID); 1669 } 1670 } 1671 1672 TAVOR_TNF_EXIT(tavor_qp_init2rtr); 1673 return (DDI_SUCCESS); 1674 } 1675 1676 1677 /* 1678 * tavor_qp_rtr2rts() 1679 * Context: Can be called from interrupt or base context. 1680 */ 1681 static int 1682 tavor_qp_rtr2rts(tavor_state_t *state, tavor_qphdl_t qp, 1683 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p) 1684 { 1685 tavor_hw_qpc_t *qpc; 1686 ibt_qp_rc_attr_t *rc; 1687 ibt_qp_ud_attr_t *ud; 1688 ibt_qp_uc_attr_t *uc; 1689 tavor_hw_addr_path_t *qpc_path; 1690 ibt_adds_vect_t *adds_vect; 1691 uint_t portnum, pkeyindx, rdma_ra_out, sra_max; 1692 uint32_t opmask = 0; 1693 int status; 1694 1695 TAVOR_TNF_ENTER(tavor_qp_rtr2rts); 1696 1697 ASSERT(MUTEX_HELD(&qp->qp_lock)); 1698 1699 /* 1700 * Grab the temporary QPC entry from QP software state 1701 */ 1702 qpc = &qp->qpc; 1703 1704 /* 1705 * Fill in the common and/or Tavor-specific fields in the QPC 1706 */ 1707 qpc->flight_lim = TAVOR_QP_FLIGHT_LIM_UNLIMITED; 1708 1709 /* 1710 * Now fill in the QPC fields which are specific to transport type 1711 */ 1712 if (qp->qp_serv_type == TAVOR_QP_UD) { 1713 ud = &info_p->qp_transport.ud; 1714 1715 /* Set the send PSN */ 1716 qpc->next_snd_psn = ud->ud_sq_psn; 1717 1718 /* 1719 * If we are attempting to modify the QKey for this QP, then 1720 * fill it in and set the appropriate flag in the "opmask" 1721 * parameter. 1722 */ 1723 if (flags & IBT_CEP_SET_QKEY) { 1724 qpc->qkey = ud->ud_qkey; 1725 opmask |= TAVOR_CMD_OP_QKEY; 1726 } 1727 1728 } else if (qp->qp_serv_type == TAVOR_QP_RC) { 1729 rc = &info_p->qp_transport.rc; 1730 qpc_path = &qpc->pri_addr_path; 1731 1732 /* 1733 * Setup the send PSN, ACK timeout, and retry counts 1734 */ 1735 qpc->next_snd_psn = rc->rc_sq_psn; 1736 qpc_path->ack_timeout = rc->rc_path.cep_timeout; 1737 qpc_path->rnr_retry = rc->rc_rnr_retry_cnt; 1738 qpc->retry_cnt = rc->rc_retry_cnt; 1739 1740 /* 1741 * Set "ack_req_freq" based on the configuration variable 1742 */ 1743 qpc->ack_req_freq = state->ts_cfg_profile->cp_ackreq_freq; 1744 1745 /* 1746 * Check that the number of specified "outgoing RDMA resources" 1747 * is valid. And if it is, then setup the "sra_max" 1748 * appropriately 1749 */ 1750 rdma_ra_out = rc->rc_rdma_ra_out; 1751 if (tavor_qp_validate_init_depth(state, rc, &sra_max) != 1752 DDI_SUCCESS) { 1753 TNF_PROBE_1(tavor_qp_rtr2rts_inv_rdma_out_fail, 1754 TAVOR_TNF_ERROR, "", tnf_uint, rdma_ra_out, 1755 rdma_ra_out); 1756 TAVOR_TNF_EXIT(tavor_qp_rtr2rts); 1757 return (IBT_INVALID_PARAM); 1758 } 1759 qpc->sra_max = sra_max; 1760 1761 /* 1762 * Configure the QP to allow (sending of) all types of RC 1763 * traffic. Tavor hardware allows these bits to be set to 1764 * zero (thereby disabling certain outgoing RDMA types), but 1765 * we do not desire to do this. 1766 */ 1767 qpc->sre = qpc->swe = qpc->sae = 1; 1768 qpc->sic = 0; 1769 1770 /* 1771 * Check if any of the flags indicate a change in the RDMA 1772 * (recv) enable/disable flags and set the appropriate flag in 1773 * the "opmask" parameter 1774 */ 1775 opmask |= tavor_check_rdma_enable_flags(flags, info_p, qpc); 1776 1777 /* 1778 * If we are attempting to modify the path migration state for 1779 * this QP, then check for valid state and fill it in. Also 1780 * set the appropriate flag in the "opmask" parameter. 1781 */ 1782 if (flags & IBT_CEP_SET_MIG) { 1783 if (rc->rc_mig_state == IBT_STATE_MIGRATED) { 1784 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED; 1785 } else if (rc->rc_mig_state == IBT_STATE_REARMED) { 1786 qpc->pm_state = TAVOR_QP_PMSTATE_REARM; 1787 } else { 1788 TNF_PROBE_1(tavor_qp_rtr2rts_inv_mig_state_fail, 1789 TAVOR_TNF_ERROR, "", tnf_uint, mig_state, 1790 rc->rc_mig_state); 1791 TAVOR_TNF_EXIT(tavor_qp_rtr2rts); 1792 return (IBT_QP_APM_STATE_INVALID); 1793 } 1794 opmask |= TAVOR_CMD_OP_PM_STATE; 1795 } 1796 1797 /* 1798 * If we are attempting to modify the "Minimum RNR NAK" value 1799 * for this QP, then fill it in and set the appropriate flag 1800 * in the "opmask" parameter. 1801 */ 1802 if (flags & IBT_CEP_SET_MIN_RNR_NAK) { 1803 qpc->min_rnr_nak = rc->rc_min_rnr_nak; 1804 opmask |= TAVOR_CMD_OP_MINRNRNAK; 1805 } 1806 1807 /* 1808 * Check for optional alternate path and fill in the 1809 * appropriate QPC fields if one is specified 1810 */ 1811 if (flags & IBT_CEP_SET_ALT_PATH) { 1812 qpc_path = &qpc->alt_addr_path; 1813 adds_vect = &rc->rc_alt_path.cep_adds_vect; 1814 1815 /* Set the common alternate address path fields */ 1816 status = tavor_set_addr_path(state, adds_vect, qpc_path, 1817 TAVOR_ADDRPATH_QP, qp); 1818 if (status != DDI_SUCCESS) { 1819 TNF_PROBE_0(tavor_qp_rtr2rts_setaddrpath_fail, 1820 TAVOR_TNF_ERROR, ""); 1821 TAVOR_TNF_EXIT(tavor_qp_rtr2rts); 1822 return (status); 1823 } 1824 1825 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout; 1826 1827 /* 1828 * Copy the "RNR Retry count" value from the primary 1829 * path. Just as we did above, we need to hardcode 1830 * the optional flag here (see below). 1831 */ 1832 qpc_path->rnr_retry = rc->rc_rnr_retry_cnt; 1833 1834 /* 1835 * Check for valid alternate path port number and fill 1836 * it in 1837 */ 1838 portnum = rc->rc_alt_path.cep_hca_port_num; 1839 if (tavor_portnum_is_valid(state, portnum)) { 1840 qpc->alt_addr_path.portnum = portnum; 1841 } else { 1842 TNF_PROBE_1(tavor_qp_rtr2rts_inv_altport_fail, 1843 TAVOR_TNF_ERROR, "", tnf_uint, altport, 1844 portnum); 1845 TAVOR_TNF_EXIT(tavor_qp_rtr2rts); 1846 return (IBT_HCA_PORT_INVALID); 1847 } 1848 1849 /* 1850 * Check for valid alternate path PKey index and fill 1851 * it in 1852 */ 1853 pkeyindx = rc->rc_alt_path.cep_pkey_ix; 1854 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 1855 qpc->alt_addr_path.pkey_indx = pkeyindx; 1856 } else { 1857 TNF_PROBE_1(tavor_qp_rtr2rts_inv_altpkey_fail, 1858 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx, 1859 pkeyindx); 1860 TAVOR_TNF_EXIT(tavor_qp_rtr2rts); 1861 return (IBT_PKEY_IX_ILLEGAL); 1862 } 1863 opmask |= (TAVOR_CMD_OP_ALT_PATH | 1864 TAVOR_CMD_OP_ALT_RNRRETRY); 1865 } 1866 1867 } else if (qp->qp_serv_type == TAVOR_QP_UC) { 1868 uc = &info_p->qp_transport.uc; 1869 1870 /* Set the send PSN */ 1871 qpc->next_snd_psn = uc->uc_sq_psn; 1872 1873 /* 1874 * Configure the QP to allow (sending of) all types of allowable 1875 * UC traffic (i.e. RDMA Write). 1876 */ 1877 qpc->swe = 1; 1878 1879 /* 1880 * Check if any of the flags indicate a change in the RDMA 1881 * Write (recv) enable/disable and set the appropriate flag 1882 * in the "opmask" parameter. Note: RDMA Read and Atomic are 1883 * not valid for UC transport. 1884 */ 1885 if (flags & IBT_CEP_SET_RDMA_W) { 1886 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0; 1887 opmask |= TAVOR_CMD_OP_RWE; 1888 } 1889 1890 /* 1891 * If we are attempting to modify the path migration state for 1892 * this QP, then check for valid state and fill it in. Also 1893 * set the appropriate flag in the "opmask" parameter. 1894 */ 1895 if (flags & IBT_CEP_SET_MIG) { 1896 if (uc->uc_mig_state == IBT_STATE_MIGRATED) { 1897 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED; 1898 } else if (uc->uc_mig_state == IBT_STATE_REARMED) { 1899 qpc->pm_state = TAVOR_QP_PMSTATE_REARM; 1900 } else { 1901 TNF_PROBE_1(tavor_qp_rtr2rts_inv_mig_state_fail, 1902 TAVOR_TNF_ERROR, "", tnf_uint, mig_state, 1903 uc->uc_mig_state); 1904 TAVOR_TNF_EXIT(tavor_qp_rtr2rts); 1905 return (IBT_QP_APM_STATE_INVALID); 1906 } 1907 opmask |= TAVOR_CMD_OP_PM_STATE; 1908 } 1909 1910 /* 1911 * Check for optional alternate path and fill in the 1912 * appropriate QPC fields if one is specified 1913 */ 1914 if (flags & IBT_CEP_SET_ALT_PATH) { 1915 qpc_path = &qpc->alt_addr_path; 1916 adds_vect = &uc->uc_alt_path.cep_adds_vect; 1917 1918 /* Set the common alternate address path fields */ 1919 status = tavor_set_addr_path(state, adds_vect, qpc_path, 1920 TAVOR_ADDRPATH_QP, qp); 1921 if (status != DDI_SUCCESS) { 1922 TNF_PROBE_0(tavor_qp_rtr2rts_setaddrpath_fail, 1923 TAVOR_TNF_ERROR, ""); 1924 TAVOR_TNF_EXIT(tavor_qp_rtr2rts); 1925 return (status); 1926 } 1927 1928 /* 1929 * Check for valid alternate path port number and fill 1930 * it in 1931 */ 1932 portnum = uc->uc_alt_path.cep_hca_port_num; 1933 if (tavor_portnum_is_valid(state, portnum)) { 1934 qpc->alt_addr_path.portnum = portnum; 1935 } else { 1936 TNF_PROBE_1(tavor_qp_rtr2rts_inv_altport_fail, 1937 TAVOR_TNF_ERROR, "", tnf_uint, altport, 1938 portnum); 1939 TAVOR_TNF_EXIT(tavor_qp_rtr2rts); 1940 return (IBT_HCA_PORT_INVALID); 1941 } 1942 1943 /* 1944 * Check for valid alternate path PKey index and fill 1945 * it in 1946 */ 1947 pkeyindx = uc->uc_alt_path.cep_pkey_ix; 1948 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 1949 qpc->alt_addr_path.pkey_indx = pkeyindx; 1950 } else { 1951 TNF_PROBE_1(tavor_qp_rtr2rts_inv_altpkey_fail, 1952 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx, 1953 pkeyindx); 1954 TAVOR_TNF_EXIT(tavor_qp_rtr2rts); 1955 return (IBT_PKEY_IX_ILLEGAL); 1956 } 1957 opmask |= TAVOR_CMD_OP_ALT_PATH; 1958 } 1959 } else { 1960 /* 1961 * Invalid QP transport type. If we got here then it's a 1962 * warning of a probably serious problem. So print a message 1963 * and return failure 1964 */ 1965 TAVOR_WARNING(state, "unknown QP transport type in rtr2rts"); 1966 TNF_PROBE_0(tavor_qp_rtr2rts_inv_transtype_fail, 1967 TAVOR_TNF_ERROR, ""); 1968 TAVOR_TNF_EXIT(tavor_qp_rtr2rts); 1969 return (ibc_get_ci_failure(0)); 1970 } 1971 1972 /* 1973 * Post the RTR2RTS_QP command to the Tavor firmware 1974 * 1975 * We do a TAVOR_NOSLEEP here because we are still holding the 1976 * "qp_lock". If we got raised to interrupt level by priority 1977 * inversion, we do not want to block in this routine waiting for 1978 * success. 1979 */ 1980 status = tavor_cmn_qp_cmd_post(state, RTR2RTS_QP, qpc, qp->qp_qpnum, 1981 opmask, TAVOR_CMD_NOSLEEP_SPIN); 1982 if (status != TAVOR_CMD_SUCCESS) { 1983 if (status != TAVOR_CMD_BAD_QP_STATE) { 1984 cmn_err(CE_CONT, "Tavor: RTR2RTS_QP command failed: " 1985 "%08x\n", status); 1986 TNF_PROBE_1(tavor_qp_rtr2rts_cmd_fail, 1987 TAVOR_TNF_ERROR, "", tnf_uint, status, status); 1988 TAVOR_TNF_EXIT(tavor_qp_rtr2rts); 1989 return (ibc_get_ci_failure(0)); 1990 } else { 1991 TNF_PROBE_0(tavor_qp_rtr2rts_inv_qpstate_fail, 1992 TAVOR_TNF_ERROR, ""); 1993 TAVOR_TNF_EXIT(tavor_qp_rtr2rts); 1994 return (IBT_QP_STATE_INVALID); 1995 } 1996 } 1997 1998 TAVOR_TNF_EXIT(tavor_qp_rtr2rts); 1999 return (DDI_SUCCESS); 2000 } 2001 2002 2003 /* 2004 * tavor_qp_rts2rts() 2005 * Context: Can be called from interrupt or base context. 2006 */ 2007 static int 2008 tavor_qp_rts2rts(tavor_state_t *state, tavor_qphdl_t qp, 2009 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p) 2010 { 2011 tavor_hw_qpc_t *qpc; 2012 ibt_qp_rc_attr_t *rc; 2013 ibt_qp_ud_attr_t *ud; 2014 ibt_qp_uc_attr_t *uc; 2015 tavor_hw_addr_path_t *qpc_path; 2016 ibt_adds_vect_t *adds_vect; 2017 uint_t portnum, pkeyindx; 2018 uint32_t opmask = 0; 2019 int status; 2020 2021 TAVOR_TNF_ENTER(tavor_qp_rts2rts); 2022 2023 ASSERT(MUTEX_HELD(&qp->qp_lock)); 2024 2025 /* 2026 * Grab the temporary QPC entry from QP software state 2027 */ 2028 qpc = &qp->qpc; 2029 2030 /* 2031 * Since there are no common and/or Tavor-specific fields to be filled 2032 * in for this command, we begin with the QPC fields which are 2033 * specific to transport type. 2034 */ 2035 if (qp->qp_serv_type == TAVOR_QP_UD) { 2036 ud = &info_p->qp_transport.ud; 2037 2038 /* 2039 * If we are attempting to modify the QKey for this QP, then 2040 * fill it in and set the appropriate flag in the "opmask" 2041 * parameter. 2042 */ 2043 if (flags & IBT_CEP_SET_QKEY) { 2044 qpc->qkey = ud->ud_qkey; 2045 opmask |= TAVOR_CMD_OP_QKEY; 2046 } 2047 2048 } else if (qp->qp_serv_type == TAVOR_QP_RC) { 2049 rc = &info_p->qp_transport.rc; 2050 2051 /* 2052 * Check if any of the flags indicate a change in the RDMA 2053 * (recv) enable/disable flags and set the appropriate flag in 2054 * the "opmask" parameter 2055 */ 2056 opmask |= tavor_check_rdma_enable_flags(flags, info_p, qpc); 2057 2058 /* 2059 * If we are attempting to modify the path migration state for 2060 * this QP, then check for valid state and fill it in. Also 2061 * set the appropriate flag in the "opmask" parameter. 2062 */ 2063 if (flags & IBT_CEP_SET_MIG) { 2064 if (rc->rc_mig_state == IBT_STATE_MIGRATED) { 2065 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED; 2066 } else if (rc->rc_mig_state == IBT_STATE_REARMED) { 2067 qpc->pm_state = TAVOR_QP_PMSTATE_REARM; 2068 } else { 2069 TNF_PROBE_1(tavor_qp_rts2rts_inv_mig_state_fail, 2070 TAVOR_TNF_ERROR, "", tnf_uint, mig_state, 2071 rc->rc_mig_state); 2072 TAVOR_TNF_EXIT(tavor_qp_rts2rts); 2073 return (IBT_QP_APM_STATE_INVALID); 2074 } 2075 opmask |= TAVOR_CMD_OP_PM_STATE; 2076 } 2077 2078 /* 2079 * If we are attempting to modify the "Minimum RNR NAK" value 2080 * for this QP, then fill it in and set the appropriate flag 2081 * in the "opmask" parameter. 2082 */ 2083 if (flags & IBT_CEP_SET_MIN_RNR_NAK) { 2084 qpc->min_rnr_nak = rc->rc_min_rnr_nak; 2085 opmask |= TAVOR_CMD_OP_MINRNRNAK; 2086 } 2087 2088 /* 2089 * Check for optional alternate path and fill in the 2090 * appropriate QPC fields if one is specified 2091 */ 2092 if (flags & IBT_CEP_SET_ALT_PATH) { 2093 qpc_path = &qpc->alt_addr_path; 2094 adds_vect = &rc->rc_alt_path.cep_adds_vect; 2095 2096 /* Set the common alternate address path fields */ 2097 status = tavor_set_addr_path(state, adds_vect, qpc_path, 2098 TAVOR_ADDRPATH_QP, qp); 2099 if (status != DDI_SUCCESS) { 2100 TNF_PROBE_0(tavor_qp_rts2rts_setaddrpath_fail, 2101 TAVOR_TNF_ERROR, ""); 2102 TAVOR_TNF_EXIT(tavor_qp_rts2rts); 2103 return (status); 2104 } 2105 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout; 2106 2107 /* 2108 * Check for valid alternate path port number and fill 2109 * it in 2110 */ 2111 portnum = rc->rc_alt_path.cep_hca_port_num; 2112 if (tavor_portnum_is_valid(state, portnum)) { 2113 qpc->alt_addr_path.portnum = portnum; 2114 } else { 2115 TNF_PROBE_1(tavor_qp_rts2rts_inv_altport_fail, 2116 TAVOR_TNF_ERROR, "", tnf_uint, altport, 2117 portnum); 2118 TAVOR_TNF_EXIT(tavor_qp_rts2rts); 2119 return (IBT_HCA_PORT_INVALID); 2120 } 2121 2122 /* 2123 * Check for valid alternate path PKey index and fill 2124 * it in 2125 */ 2126 pkeyindx = rc->rc_alt_path.cep_pkey_ix; 2127 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 2128 qpc->alt_addr_path.pkey_indx = pkeyindx; 2129 } else { 2130 TNF_PROBE_1(tavor_qp_rts2rts_inv_altpkey_fail, 2131 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx, 2132 pkeyindx); 2133 TAVOR_TNF_EXIT(tavor_qp_rts2rts); 2134 return (IBT_PKEY_IX_ILLEGAL); 2135 } 2136 opmask |= TAVOR_CMD_OP_ALT_PATH; 2137 } 2138 2139 } else if (qp->qp_serv_type == TAVOR_QP_UC) { 2140 uc = &info_p->qp_transport.uc; 2141 2142 /* 2143 * Check if any of the flags indicate a change in the RDMA 2144 * Write (recv) enable/disable and set the appropriate flag 2145 * in the "opmask" parameter. Note: RDMA Read and Atomic are 2146 * not valid for UC transport. 2147 */ 2148 if (flags & IBT_CEP_SET_RDMA_W) { 2149 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0; 2150 opmask |= TAVOR_CMD_OP_RWE; 2151 } 2152 2153 /* 2154 * If we are attempting to modify the path migration state for 2155 * this QP, then check for valid state and fill it in. Also 2156 * set the appropriate flag in the "opmask" parameter. 2157 */ 2158 if (flags & IBT_CEP_SET_MIG) { 2159 if (uc->uc_mig_state == IBT_STATE_MIGRATED) { 2160 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED; 2161 } else if (uc->uc_mig_state == IBT_STATE_REARMED) { 2162 qpc->pm_state = TAVOR_QP_PMSTATE_REARM; 2163 } else { 2164 TNF_PROBE_1(tavor_qp_rts2rts_inv_mig_state_fail, 2165 TAVOR_TNF_ERROR, "", tnf_uint, mig_state, 2166 uc->uc_mig_state); 2167 TAVOR_TNF_EXIT(tavor_qp_rts2rts); 2168 return (IBT_QP_APM_STATE_INVALID); 2169 } 2170 opmask |= TAVOR_CMD_OP_PM_STATE; 2171 } 2172 2173 /* 2174 * Check for optional alternate path and fill in the 2175 * appropriate QPC fields if one is specified 2176 */ 2177 if (flags & IBT_CEP_SET_ALT_PATH) { 2178 qpc_path = &qpc->alt_addr_path; 2179 adds_vect = &uc->uc_alt_path.cep_adds_vect; 2180 2181 /* Set the common alternate address path fields */ 2182 status = tavor_set_addr_path(state, adds_vect, qpc_path, 2183 TAVOR_ADDRPATH_QP, qp); 2184 if (status != DDI_SUCCESS) { 2185 TNF_PROBE_0(tavor_qp_rts2rts_setaddrpath_fail, 2186 TAVOR_TNF_ERROR, ""); 2187 TAVOR_TNF_EXIT(tavor_qp_rts2rts); 2188 return (status); 2189 } 2190 2191 /* 2192 * Check for valid alternate path port number and fill 2193 * it in 2194 */ 2195 portnum = uc->uc_alt_path.cep_hca_port_num; 2196 if (tavor_portnum_is_valid(state, portnum)) { 2197 qpc->alt_addr_path.portnum = portnum; 2198 } else { 2199 TNF_PROBE_1(tavor_qp_rts2rts_inv_altport_fail, 2200 TAVOR_TNF_ERROR, "", tnf_uint, altport, 2201 portnum); 2202 TAVOR_TNF_EXIT(tavor_qp_rts2rts); 2203 return (IBT_HCA_PORT_INVALID); 2204 } 2205 2206 /* 2207 * Check for valid alternate path PKey index and fill 2208 * it in 2209 */ 2210 pkeyindx = uc->uc_alt_path.cep_pkey_ix; 2211 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 2212 qpc->alt_addr_path.pkey_indx = pkeyindx; 2213 } else { 2214 TNF_PROBE_1(tavor_qp_rts2rts_inv_altpkey_fail, 2215 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx, 2216 pkeyindx); 2217 TAVOR_TNF_EXIT(tavor_qp_rts2rts); 2218 return (IBT_PKEY_IX_ILLEGAL); 2219 } 2220 opmask |= TAVOR_CMD_OP_ALT_PATH; 2221 } 2222 } else { 2223 /* 2224 * Invalid QP transport type. If we got here then it's a 2225 * warning of a probably serious problem. So print a message 2226 * and return failure 2227 */ 2228 TAVOR_WARNING(state, "unknown QP transport type in rts2rts"); 2229 TNF_PROBE_0(tavor_qp_rts2rts_inv_transtype_fail, 2230 TAVOR_TNF_ERROR, ""); 2231 TAVOR_TNF_EXIT(tavor_qp_rts2rts); 2232 return (ibc_get_ci_failure(0)); 2233 } 2234 2235 /* 2236 * Post the RTS2RTS_QP command to the Tavor firmware 2237 * 2238 * We do a TAVOR_NOSLEEP here because we are still holding the 2239 * "qp_lock". If we got raised to interrupt level by priority 2240 * inversion, we do not want to block in this routine waiting for 2241 * success. 2242 */ 2243 status = tavor_cmn_qp_cmd_post(state, RTS2RTS_QP, qpc, qp->qp_qpnum, 2244 opmask, TAVOR_CMD_NOSLEEP_SPIN); 2245 if (status != TAVOR_CMD_SUCCESS) { 2246 if (status != TAVOR_CMD_BAD_QP_STATE) { 2247 cmn_err(CE_CONT, "Tavor: RTS2RTS_QP command failed: " 2248 "%08x\n", status); 2249 TNF_PROBE_1(tavor_qp_rts2rts_cmd_fail, 2250 TAVOR_TNF_ERROR, "", tnf_uint, status, status); 2251 TAVOR_TNF_EXIT(tavor_qp_rts2rts); 2252 return (ibc_get_ci_failure(0)); 2253 } else { 2254 TNF_PROBE_0(tavor_qp_rts2rts_inv_qpstate_fail, 2255 TAVOR_TNF_ERROR, ""); 2256 TAVOR_TNF_EXIT(tavor_qp_rts2rts); 2257 return (IBT_QP_STATE_INVALID); 2258 } 2259 } 2260 2261 TAVOR_TNF_EXIT(tavor_qp_rts2rts); 2262 return (DDI_SUCCESS); 2263 } 2264 2265 2266 /* 2267 * tavor_qp_rts2sqd() 2268 * Context: Can be called from interrupt or base context. 2269 */ 2270 static int 2271 tavor_qp_rts2sqd(tavor_state_t *state, tavor_qphdl_t qp, 2272 ibt_cep_modify_flags_t flags) 2273 { 2274 int status; 2275 2276 TAVOR_TNF_ENTER(tavor_qp_rts2sqd); 2277 2278 ASSERT(MUTEX_HELD(&qp->qp_lock)); 2279 2280 /* 2281 * Set a flag to indicate whether or not the consumer is interested 2282 * in receiving the SQ drained event. Since we are going to always 2283 * request hardware generation of the SQD event, we use the value in 2284 * "qp_forward_sqd_event" to determine whether or not to pass the event 2285 * to the IBTF or to silently consume it. 2286 */ 2287 qp->qp_forward_sqd_event = (flags & IBT_CEP_SET_SQD_EVENT) ? 1 : 0; 2288 2289 /* 2290 * Post the RTS2SQD_QP command to the Tavor firmware 2291 * 2292 * We do a TAVOR_NOSLEEP here because we are still holding the 2293 * "qp_lock". If we got raised to interrupt level by priority 2294 * inversion, we do not want to block in this routine waiting for 2295 * success. 2296 */ 2297 status = tavor_cmn_qp_cmd_post(state, RTS2SQD_QP, NULL, qp->qp_qpnum, 2298 0, TAVOR_CMD_NOSLEEP_SPIN); 2299 if (status != TAVOR_CMD_SUCCESS) { 2300 if (status != TAVOR_CMD_BAD_QP_STATE) { 2301 cmn_err(CE_CONT, "Tavor: RTS2SQD_QP command failed: " 2302 "%08x\n", status); 2303 TNF_PROBE_1(tavor_qp_rts2sqd_cmd_fail, 2304 TAVOR_TNF_ERROR, "", tnf_uint, status, status); 2305 TAVOR_TNF_EXIT(tavor_qp_rts2sqd); 2306 return (ibc_get_ci_failure(0)); 2307 } else { 2308 TNF_PROBE_0(tavor_qp_rts2sqd_inv_qpstate_fail, 2309 TAVOR_TNF_ERROR, ""); 2310 TAVOR_TNF_EXIT(tavor_qp_rts2sqd); 2311 return (IBT_QP_STATE_INVALID); 2312 } 2313 } 2314 2315 /* 2316 * Mark the current QP state as "SQ Draining". This allows us to 2317 * distinguish between the two underlying states in SQD. (see QueryQP() 2318 * code in tavor_qp.c) 2319 */ 2320 qp->qp_sqd_still_draining = 1; 2321 2322 TAVOR_TNF_EXIT(tavor_qp_rts2sqd); 2323 return (DDI_SUCCESS); 2324 } 2325 2326 2327 /* 2328 * tavor_qp_sqd2rts() 2329 * Context: Can be called from interrupt or base context. 2330 */ 2331 static int 2332 tavor_qp_sqd2rts(tavor_state_t *state, tavor_qphdl_t qp, 2333 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p) 2334 { 2335 tavor_hw_qpc_t *qpc; 2336 ibt_qp_rc_attr_t *rc; 2337 ibt_qp_ud_attr_t *ud; 2338 ibt_qp_uc_attr_t *uc; 2339 tavor_hw_addr_path_t *qpc_path; 2340 ibt_adds_vect_t *adds_vect; 2341 uint_t portnum, pkeyindx; 2342 uint32_t opmask = 0; 2343 int status; 2344 2345 TAVOR_TNF_ENTER(tavor_qp_sqd2rts); 2346 2347 ASSERT(MUTEX_HELD(&qp->qp_lock)); 2348 2349 /* 2350 * Grab the temporary QPC entry from QP software state 2351 */ 2352 qpc = &qp->qpc; 2353 2354 /* 2355 * Since there are no common and/or Tavor-specific fields to be filled 2356 * in for this command, we begin with the QPC fields which are 2357 * specific to transport type. 2358 */ 2359 if (qp->qp_serv_type == TAVOR_QP_UD) { 2360 ud = &info_p->qp_transport.ud; 2361 2362 /* 2363 * If we are attempting to modify the QKey for this QP, then 2364 * fill it in and set the appropriate flag in the "opmask" 2365 * parameter. 2366 */ 2367 if (flags & IBT_CEP_SET_QKEY) { 2368 qpc->qkey = ud->ud_qkey; 2369 opmask |= TAVOR_CMD_OP_QKEY; 2370 } 2371 2372 } else if (qp->qp_serv_type == TAVOR_QP_RC) { 2373 rc = &info_p->qp_transport.rc; 2374 2375 /* 2376 * Check if any of the flags indicate a change in the RDMA 2377 * (recv) enable/disable flags and set the appropriate flag in 2378 * the "opmask" parameter 2379 */ 2380 opmask |= tavor_check_rdma_enable_flags(flags, info_p, qpc); 2381 2382 /* 2383 * If we are attempting to modify the path migration state for 2384 * this QP, then check for valid state and fill it in. Also 2385 * set the appropriate flag in the "opmask" parameter. 2386 */ 2387 if (flags & IBT_CEP_SET_MIG) { 2388 if (rc->rc_mig_state == IBT_STATE_MIGRATED) { 2389 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED; 2390 } else if (rc->rc_mig_state == IBT_STATE_REARMED) { 2391 qpc->pm_state = TAVOR_QP_PMSTATE_REARM; 2392 } else { 2393 TNF_PROBE_1(tavor_qp_sqd2rts_inv_mig_state_fail, 2394 TAVOR_TNF_ERROR, "", tnf_uint, mig_state, 2395 rc->rc_mig_state); 2396 TAVOR_TNF_EXIT(tavor_qp_sqd2rts); 2397 return (IBT_QP_APM_STATE_INVALID); 2398 } 2399 opmask |= TAVOR_CMD_OP_PM_STATE; 2400 } 2401 2402 /* 2403 * Check for optional alternate path and fill in the 2404 * appropriate QPC fields if one is specified 2405 */ 2406 if (flags & IBT_CEP_SET_ALT_PATH) { 2407 qpc_path = &qpc->alt_addr_path; 2408 adds_vect = &rc->rc_alt_path.cep_adds_vect; 2409 2410 /* Set the common alternate address path fields */ 2411 status = tavor_set_addr_path(state, adds_vect, qpc_path, 2412 TAVOR_ADDRPATH_QP, qp); 2413 if (status != DDI_SUCCESS) { 2414 TNF_PROBE_0(tavor_qp_sqd2rts_setaddrpath_fail, 2415 TAVOR_TNF_ERROR, ""); 2416 TAVOR_TNF_EXIT(tavor_qp_sqd2rts); 2417 return (status); 2418 } 2419 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout; 2420 2421 /* 2422 * Check for valid alternate path port number and fill 2423 * it in 2424 */ 2425 portnum = rc->rc_alt_path.cep_hca_port_num; 2426 if (tavor_portnum_is_valid(state, portnum)) { 2427 qpc->alt_addr_path.portnum = portnum; 2428 } else { 2429 TNF_PROBE_1(tavor_qp_sqd2rts_inv_altport_fail, 2430 TAVOR_TNF_ERROR, "", tnf_uint, altport, 2431 portnum); 2432 TAVOR_TNF_EXIT(tavor_qp_sqd2rts); 2433 return (IBT_HCA_PORT_INVALID); 2434 } 2435 2436 /* 2437 * Check for valid alternate path PKey index and fill 2438 * it in 2439 */ 2440 pkeyindx = rc->rc_alt_path.cep_pkey_ix; 2441 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 2442 qpc->alt_addr_path.pkey_indx = pkeyindx; 2443 } else { 2444 TNF_PROBE_1(tavor_qp_sqd2rts_inv_altpkey_fail, 2445 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx, 2446 pkeyindx); 2447 TAVOR_TNF_EXIT(tavor_qp_sqd2rts); 2448 return (IBT_PKEY_IX_ILLEGAL); 2449 } 2450 opmask |= TAVOR_CMD_OP_ALT_PATH; 2451 } 2452 2453 /* 2454 * If we are attempting to modify the "Minimum RNR NAK" value 2455 * for this QP, then fill it in and set the appropriate flag 2456 * in the "opmask" parameter. 2457 */ 2458 if (flags & IBT_CEP_SET_MIN_RNR_NAK) { 2459 qpc->min_rnr_nak = rc->rc_min_rnr_nak; 2460 opmask |= TAVOR_CMD_OP_MINRNRNAK; 2461 } 2462 2463 } else if (qp->qp_serv_type == TAVOR_QP_UC) { 2464 uc = &info_p->qp_transport.uc; 2465 2466 /* 2467 * Check if any of the flags indicate a change in the RDMA 2468 * Write (recv) enable/disable and set the appropriate flag 2469 * in the "opmask" parameter. Note: RDMA Read and Atomic are 2470 * not valid for UC transport. 2471 */ 2472 if (flags & IBT_CEP_SET_RDMA_W) { 2473 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0; 2474 opmask |= TAVOR_CMD_OP_RWE; 2475 } 2476 2477 /* 2478 * If we are attempting to modify the path migration state for 2479 * this QP, then check for valid state and fill it in. Also 2480 * set the appropriate flag in the "opmask" parameter. 2481 */ 2482 if (flags & IBT_CEP_SET_MIG) { 2483 if (uc->uc_mig_state == IBT_STATE_MIGRATED) { 2484 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED; 2485 } else if (uc->uc_mig_state == IBT_STATE_REARMED) { 2486 qpc->pm_state = TAVOR_QP_PMSTATE_REARM; 2487 } else { 2488 TNF_PROBE_1(tavor_qp_sqd2rts_inv_mig_state_fail, 2489 TAVOR_TNF_ERROR, "", tnf_uint, mig_state, 2490 uc->uc_mig_state); 2491 TAVOR_TNF_EXIT(tavor_qp_sqd2rts); 2492 return (IBT_QP_APM_STATE_INVALID); 2493 } 2494 opmask |= TAVOR_CMD_OP_PM_STATE; 2495 } 2496 2497 /* 2498 * Check for optional alternate path and fill in the 2499 * appropriate QPC fields if one is specified 2500 */ 2501 if (flags & IBT_CEP_SET_ALT_PATH) { 2502 qpc_path = &qpc->alt_addr_path; 2503 adds_vect = &uc->uc_alt_path.cep_adds_vect; 2504 2505 /* Set the common alternate address path fields */ 2506 status = tavor_set_addr_path(state, adds_vect, qpc_path, 2507 TAVOR_ADDRPATH_QP, qp); 2508 if (status != DDI_SUCCESS) { 2509 TNF_PROBE_0(tavor_qp_sqd2rts_setaddrpath_fail, 2510 TAVOR_TNF_ERROR, ""); 2511 TAVOR_TNF_EXIT(tavor_qp_sqd2rts); 2512 return (status); 2513 } 2514 2515 /* 2516 * Check for valid alternate path port number and fill 2517 * it in 2518 */ 2519 portnum = uc->uc_alt_path.cep_hca_port_num; 2520 if (tavor_portnum_is_valid(state, portnum)) { 2521 qpc->alt_addr_path.portnum = portnum; 2522 } else { 2523 TNF_PROBE_1(tavor_qp_sqd2rts_inv_altport_fail, 2524 TAVOR_TNF_ERROR, "", tnf_uint, altport, 2525 portnum); 2526 TAVOR_TNF_EXIT(tavor_qp_sqd2rts); 2527 return (IBT_HCA_PORT_INVALID); 2528 } 2529 2530 /* 2531 * Check for valid alternate path PKey index and fill 2532 * it in 2533 */ 2534 pkeyindx = uc->uc_alt_path.cep_pkey_ix; 2535 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 2536 qpc->alt_addr_path.pkey_indx = pkeyindx; 2537 } else { 2538 TNF_PROBE_1(tavor_qp_sqd2rts_inv_altpkey_fail, 2539 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx, 2540 pkeyindx); 2541 TAVOR_TNF_EXIT(tavor_qp_sqd2rts); 2542 return (IBT_PKEY_IX_ILLEGAL); 2543 } 2544 opmask |= TAVOR_CMD_OP_ALT_PATH; 2545 } 2546 } else { 2547 /* 2548 * Invalid QP transport type. If we got here then it's a 2549 * warning of a probably serious problem. So print a message 2550 * and return failure 2551 */ 2552 TAVOR_WARNING(state, "unknown QP transport type in sqd2rts"); 2553 TNF_PROBE_0(tavor_qp_sqd2rts_inv_transtype_fail, 2554 TAVOR_TNF_ERROR, ""); 2555 TAVOR_TNF_EXIT(tavor_qp_sqd2rts); 2556 return (ibc_get_ci_failure(0)); 2557 } 2558 2559 /* 2560 * Post the SQD2RTS_QP command to the Tavor firmware 2561 * 2562 * We do a TAVOR_NOSLEEP here because we are still holding the 2563 * "qp_lock". If we got raised to interrupt level by priority 2564 * inversion, we do not want to block in this routine waiting for 2565 * success. 2566 */ 2567 status = tavor_cmn_qp_cmd_post(state, SQD2RTS_QP, qpc, qp->qp_qpnum, 2568 opmask, TAVOR_CMD_NOSLEEP_SPIN); 2569 if (status != TAVOR_CMD_SUCCESS) { 2570 if (status != TAVOR_CMD_BAD_QP_STATE) { 2571 cmn_err(CE_CONT, "Tavor: SQD2RTS_QP command failed: " 2572 "%08x\n", status); 2573 TNF_PROBE_1(tavor_qp_sqd2rts_cmd_fail, 2574 TAVOR_TNF_ERROR, "", tnf_uint, status, status); 2575 TAVOR_TNF_EXIT(tavor_qp_sqd2rts); 2576 return (ibc_get_ci_failure(0)); 2577 } else { 2578 TNF_PROBE_0(tavor_qp_sqd2rts_inv_qpstate_fail, 2579 TAVOR_TNF_ERROR, ""); 2580 TAVOR_TNF_EXIT(tavor_qp_sqd2rts); 2581 return (IBT_QP_STATE_INVALID); 2582 } 2583 } 2584 2585 TAVOR_TNF_EXIT(tavor_qp_sqd2rts); 2586 return (DDI_SUCCESS); 2587 } 2588 2589 2590 /* 2591 * tavor_qp_sqd2sqd() 2592 * Context: Can be called from interrupt or base context. 2593 */ 2594 static int 2595 tavor_qp_sqd2sqd(tavor_state_t *state, tavor_qphdl_t qp, 2596 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p) 2597 { 2598 tavor_hw_qpc_t *qpc; 2599 ibt_qp_rc_attr_t *rc; 2600 ibt_qp_ud_attr_t *ud; 2601 ibt_qp_uc_attr_t *uc; 2602 tavor_hw_addr_path_t *qpc_path; 2603 ibt_adds_vect_t *adds_vect; 2604 uint_t portnum, pkeyindx, rdma_ra_out, rdma_ra_in; 2605 uint_t rra_max, sra_max; 2606 uint32_t opmask = 0; 2607 int status; 2608 2609 TAVOR_TNF_ENTER(tavor_qp_sqd2sqd); 2610 2611 ASSERT(MUTEX_HELD(&qp->qp_lock)); 2612 2613 /* 2614 * Grab the temporary QPC entry from QP software state 2615 */ 2616 qpc = &qp->qpc; 2617 2618 /* 2619 * Since there are no common and/or Tavor-specific fields to be filled 2620 * in for this command, we begin with the QPC fields which are 2621 * specific to transport type. 2622 */ 2623 if (qp->qp_serv_type == TAVOR_QP_UD) { 2624 ud = &info_p->qp_transport.ud; 2625 2626 /* 2627 * If we are attempting to modify the PKey index for this QP, 2628 * then check for valid PKey index and fill it in. Also set 2629 * the appropriate flag in the "opmask" parameter. 2630 */ 2631 if (flags & IBT_CEP_SET_PKEY_IX) { 2632 pkeyindx = ud->ud_pkey_ix; 2633 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 2634 qpc->pri_addr_path.pkey_indx = pkeyindx; 2635 opmask |= TAVOR_CMD_OP_PKEYINDX; 2636 qp->qp_pkeyindx = pkeyindx; 2637 } else { 2638 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_pkey_fail, 2639 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx, 2640 pkeyindx); 2641 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 2642 return (IBT_PKEY_IX_ILLEGAL); 2643 } 2644 } 2645 2646 /* 2647 * If we are attempting to modify the QKey for this QP, then 2648 * fill it in and set the appropriate flag in the "opmask" 2649 * parameter. 2650 */ 2651 if (flags & IBT_CEP_SET_QKEY) { 2652 qpc->qkey = ud->ud_qkey; 2653 opmask |= TAVOR_CMD_OP_QKEY; 2654 } 2655 2656 } else if (qp->qp_serv_type == TAVOR_QP_RC) { 2657 rc = &info_p->qp_transport.rc; 2658 2659 /* 2660 * Check if any of the flags indicate a change in the RDMA 2661 * (recv) enable/disable flags and set the appropriate flag in 2662 * the "opmask" parameter 2663 */ 2664 opmask |= tavor_check_rdma_enable_flags(flags, info_p, qpc); 2665 2666 /* 2667 * Check for optional primary path and fill in the 2668 * appropriate QPC fields if one is specified 2669 */ 2670 if (flags & IBT_CEP_SET_ADDS_VECT) { 2671 qpc_path = &qpc->pri_addr_path; 2672 adds_vect = &rc->rc_path.cep_adds_vect; 2673 2674 /* Set the common primary address path fields */ 2675 status = tavor_set_addr_path(state, adds_vect, qpc_path, 2676 TAVOR_ADDRPATH_QP, qp); 2677 if (status != DDI_SUCCESS) { 2678 TNF_PROBE_0(tavor_qp_sqd2sqd_setaddrpath_fail, 2679 TAVOR_TNF_ERROR, ""); 2680 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 2681 return (status); 2682 } 2683 qpc_path->rnr_retry = rc->rc_rnr_retry_cnt; 2684 qpc_path->ack_timeout = rc->rc_path.cep_timeout; 2685 qpc->retry_cnt = rc->rc_retry_cnt; 2686 2687 /* 2688 * MTU changes as part of sqd2sqd are not allowed. 2689 * Simply keep the same MTU value here, stored in the 2690 * qphdl from init2rtr time. 2691 */ 2692 qpc->mtu = qp->qp_save_mtu; 2693 2694 opmask |= (TAVOR_CMD_OP_PRIM_PATH | 2695 TAVOR_CMD_OP_RETRYCNT | TAVOR_CMD_OP_ACKTIMEOUT | 2696 TAVOR_CMD_OP_PRIM_RNRRETRY); 2697 } 2698 2699 /* 2700 * If we are attempting to modify the path migration state for 2701 * this QP, then check for valid state and fill it in. Also 2702 * set the appropriate flag in the "opmask" parameter. 2703 */ 2704 if (flags & IBT_CEP_SET_MIG) { 2705 if (rc->rc_mig_state == IBT_STATE_MIGRATED) { 2706 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED; 2707 } else if (rc->rc_mig_state == IBT_STATE_REARMED) { 2708 qpc->pm_state = TAVOR_QP_PMSTATE_REARM; 2709 } else { 2710 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_mig_state_fail, 2711 TAVOR_TNF_ERROR, "", tnf_uint, mig_state, 2712 rc->rc_mig_state); 2713 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 2714 return (IBT_QP_APM_STATE_INVALID); 2715 } 2716 opmask |= TAVOR_CMD_OP_PM_STATE; 2717 } 2718 2719 /* 2720 * If we are attempting to modify the PKey index for this QP, 2721 * then check for valid PKey index and fill it in. Also set 2722 * the appropriate flag in the "opmask" parameter. 2723 */ 2724 if (flags & IBT_CEP_SET_PKEY_IX) { 2725 pkeyindx = rc->rc_path.cep_pkey_ix; 2726 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 2727 qpc->pri_addr_path.pkey_indx = pkeyindx; 2728 opmask |= TAVOR_CMD_OP_PKEYINDX; 2729 } else { 2730 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_pkey_fail, 2731 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx, 2732 pkeyindx); 2733 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 2734 return (IBT_PKEY_IX_ILLEGAL); 2735 } 2736 } 2737 2738 /* 2739 * If we are attempting to modify the port for this QP, then 2740 * check for valid port number and fill it in. Also set the 2741 * appropriate flag in the "opmask" parameter. 2742 */ 2743 if (flags & IBT_CEP_SET_PORT) { 2744 portnum = rc->rc_path.cep_hca_port_num; 2745 if (tavor_portnum_is_valid(state, portnum)) { 2746 qpc->pri_addr_path.portnum = portnum; 2747 } else { 2748 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_port_fail, 2749 TAVOR_TNF_ERROR, "", tnf_uint, port, 2750 portnum); 2751 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 2752 return (IBT_HCA_PORT_INVALID); 2753 } 2754 opmask |= TAVOR_CMD_OP_PRIM_PORT; 2755 } 2756 2757 /* 2758 * Check for optional alternate path and fill in the 2759 * appropriate QPC fields if one is specified 2760 */ 2761 if (flags & IBT_CEP_SET_ALT_PATH) { 2762 qpc_path = &qpc->alt_addr_path; 2763 adds_vect = &rc->rc_alt_path.cep_adds_vect; 2764 2765 /* Set the common alternate address path fields */ 2766 status = tavor_set_addr_path(state, adds_vect, qpc_path, 2767 TAVOR_ADDRPATH_QP, qp); 2768 if (status != DDI_SUCCESS) { 2769 TNF_PROBE_0(tavor_qp_sqd2sqd_setaddrpath_fail, 2770 TAVOR_TNF_ERROR, ""); 2771 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 2772 return (status); 2773 } 2774 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout; 2775 2776 /* 2777 * Check for valid alternate path port number and fill 2778 * it in 2779 */ 2780 portnum = rc->rc_alt_path.cep_hca_port_num; 2781 if (tavor_portnum_is_valid(state, portnum)) { 2782 qpc->alt_addr_path.portnum = portnum; 2783 } else { 2784 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_altport_fail, 2785 TAVOR_TNF_ERROR, "", tnf_uint, altport, 2786 portnum); 2787 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 2788 return (IBT_HCA_PORT_INVALID); 2789 } 2790 2791 /* 2792 * Check for valid alternate path PKey index and fill 2793 * it in 2794 */ 2795 pkeyindx = rc->rc_alt_path.cep_pkey_ix; 2796 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 2797 qpc->alt_addr_path.pkey_indx = pkeyindx; 2798 } else { 2799 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_altpkey_fail, 2800 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx, 2801 pkeyindx); 2802 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 2803 return (IBT_PKEY_IX_ILLEGAL); 2804 } 2805 opmask |= TAVOR_CMD_OP_ALT_PATH; 2806 } 2807 2808 /* 2809 * If we are attempting to modify the number of "outgoing 2810 * RDMA resources" for this QP, then check for valid value and 2811 * fill it in. Also set the appropriate flag in the "opmask" 2812 * parameter. 2813 */ 2814 if (flags & IBT_CEP_SET_RDMARA_OUT) { 2815 rdma_ra_out = rc->rc_rdma_ra_out; 2816 if (tavor_qp_validate_init_depth(state, rc, 2817 &sra_max) != DDI_SUCCESS) { 2818 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_rdma_out_fail, 2819 TAVOR_TNF_ERROR, "", tnf_uint, rdma_ra_out, 2820 rdma_ra_out); 2821 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 2822 return (IBT_INVALID_PARAM); 2823 } 2824 qpc->sra_max = sra_max; 2825 opmask |= TAVOR_CMD_OP_SRA_SET; 2826 } 2827 2828 /* 2829 * If we are attempting to modify the number of "incoming 2830 * RDMA resources" for this QP, then check for valid value and 2831 * update the "rra_max" and "ra_buf_index" fields in the QPC to 2832 * point to the pre-allocated RDB resources (in DDR). Also set 2833 * the appropriate flag in the "opmask" parameter. 2834 */ 2835 if (flags & IBT_CEP_SET_RDMARA_IN) { 2836 rdma_ra_in = rc->rc_rdma_ra_in; 2837 if (tavor_qp_validate_resp_rsrc(state, rc, 2838 &rra_max) != DDI_SUCCESS) { 2839 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_rdma_in_fail, 2840 TAVOR_TNF_ERROR, "", tnf_uint, rdma_ra_in, 2841 rdma_ra_in); 2842 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 2843 return (IBT_INVALID_PARAM); 2844 } 2845 qpc->rra_max = rra_max; 2846 qpc->ra_buff_indx = qp->qp_rdb_ddraddr >> 2847 TAVOR_RDB_SIZE_SHIFT; 2848 opmask |= TAVOR_CMD_OP_RRA_SET; 2849 } 2850 2851 /* 2852 * If we are attempting to modify the "Local Ack Timeout" value 2853 * for this QP, then fill it in and set the appropriate flag in 2854 * the "opmask" parameter. 2855 */ 2856 if (flags & IBT_CEP_SET_TIMEOUT) { 2857 qpc_path = &qpc->pri_addr_path; 2858 qpc_path->ack_timeout = rc->rc_path.cep_timeout; 2859 opmask |= TAVOR_CMD_OP_ACKTIMEOUT; 2860 } 2861 2862 /* 2863 * If we are attempting to modify the "Retry Count" for this QP, 2864 * then fill it in and set the appropriate flag in the "opmask" 2865 * parameter. 2866 */ 2867 if (flags & IBT_CEP_SET_RETRY) { 2868 qpc->retry_cnt = rc->rc_retry_cnt; 2869 opmask |= TAVOR_CMD_OP_PRIM_RNRRETRY; 2870 } 2871 2872 /* 2873 * If we are attempting to modify the "RNR Retry Count" for this 2874 * QP, then fill it in and set the appropriate flag in the 2875 * "opmask" parameter. 2876 */ 2877 if (flags & IBT_CEP_SET_RNR_NAK_RETRY) { 2878 qpc_path = &qpc->pri_addr_path; 2879 qpc_path->rnr_retry = rc->rc_rnr_retry_cnt; 2880 opmask |= TAVOR_CMD_OP_RETRYCNT; 2881 } 2882 2883 /* 2884 * If we are attempting to modify the "Minimum RNR NAK" value 2885 * for this QP, then fill it in and set the appropriate flag 2886 * in the "opmask" parameter. 2887 */ 2888 if (flags & IBT_CEP_SET_MIN_RNR_NAK) { 2889 qpc->min_rnr_nak = rc->rc_min_rnr_nak; 2890 opmask |= TAVOR_CMD_OP_MINRNRNAK; 2891 } 2892 2893 } else if (qp->qp_serv_type == TAVOR_QP_UC) { 2894 uc = &info_p->qp_transport.uc; 2895 2896 /* 2897 * Check if any of the flags indicate a change in the RDMA 2898 * Write (recv) enable/disable and set the appropriate flag 2899 * in the "opmask" parameter. Note: RDMA Read and Atomic are 2900 * not valid for UC transport. 2901 */ 2902 if (flags & IBT_CEP_SET_RDMA_W) { 2903 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0; 2904 opmask |= TAVOR_CMD_OP_RWE; 2905 } 2906 2907 /* 2908 * Check for optional primary path and fill in the 2909 * appropriate QPC fields if one is specified 2910 */ 2911 if (flags & IBT_CEP_SET_ADDS_VECT) { 2912 qpc_path = &qpc->pri_addr_path; 2913 adds_vect = &uc->uc_path.cep_adds_vect; 2914 2915 /* Set the common primary address path fields */ 2916 status = tavor_set_addr_path(state, adds_vect, qpc_path, 2917 TAVOR_ADDRPATH_QP, qp); 2918 if (status != DDI_SUCCESS) { 2919 TNF_PROBE_0(tavor_qp_sqd2sqd_setaddrpath_fail, 2920 TAVOR_TNF_ERROR, ""); 2921 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 2922 return (status); 2923 } 2924 2925 /* 2926 * MTU changes as part of sqd2sqd are not allowed. 2927 * Simply keep the same MTU value here, stored in the 2928 * qphdl from init2rtr time. 2929 */ 2930 qpc->mtu = qp->qp_save_mtu; 2931 2932 opmask |= TAVOR_CMD_OP_PRIM_PATH; 2933 } 2934 2935 /* 2936 * If we are attempting to modify the path migration state for 2937 * this QP, then check for valid state and fill it in. Also 2938 * set the appropriate flag in the "opmask" parameter. 2939 */ 2940 if (flags & IBT_CEP_SET_MIG) { 2941 if (uc->uc_mig_state == IBT_STATE_MIGRATED) { 2942 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED; 2943 } else if (uc->uc_mig_state == IBT_STATE_REARMED) { 2944 qpc->pm_state = TAVOR_QP_PMSTATE_REARM; 2945 } else { 2946 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_mig_state_fail, 2947 TAVOR_TNF_ERROR, "", tnf_uint, mig_state, 2948 uc->uc_mig_state); 2949 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 2950 return (IBT_QP_APM_STATE_INVALID); 2951 } 2952 opmask |= TAVOR_CMD_OP_PM_STATE; 2953 } 2954 2955 /* 2956 * If we are attempting to modify the PKey index for this QP, 2957 * then check for valid PKey index and fill it in. Also set 2958 * the appropriate flag in the "opmask" parameter. 2959 */ 2960 if (flags & IBT_CEP_SET_PKEY_IX) { 2961 pkeyindx = uc->uc_path.cep_pkey_ix; 2962 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 2963 qpc->pri_addr_path.pkey_indx = pkeyindx; 2964 opmask |= TAVOR_CMD_OP_PKEYINDX; 2965 } else { 2966 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_pkey, 2967 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx, 2968 pkeyindx); 2969 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 2970 return (IBT_PKEY_IX_ILLEGAL); 2971 } 2972 } 2973 2974 /* 2975 * Check for optional alternate path and fill in the 2976 * appropriate QPC fields if one is specified 2977 */ 2978 if (flags & IBT_CEP_SET_ALT_PATH) { 2979 qpc_path = &qpc->alt_addr_path; 2980 adds_vect = &uc->uc_alt_path.cep_adds_vect; 2981 2982 /* Set the common alternate address path fields */ 2983 status = tavor_set_addr_path(state, adds_vect, qpc_path, 2984 TAVOR_ADDRPATH_QP, qp); 2985 if (status != DDI_SUCCESS) { 2986 TNF_PROBE_0(tavor_qp_sqd2sqd_setaddrpath_fail, 2987 TAVOR_TNF_ERROR, ""); 2988 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 2989 return (status); 2990 } 2991 2992 /* 2993 * Check for valid alternate path port number and fill 2994 * it in 2995 */ 2996 portnum = uc->uc_alt_path.cep_hca_port_num; 2997 if (tavor_portnum_is_valid(state, portnum)) { 2998 qpc->alt_addr_path.portnum = portnum; 2999 } else { 3000 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_altport_fail, 3001 TAVOR_TNF_ERROR, "", tnf_uint, altport, 3002 portnum); 3003 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 3004 return (IBT_HCA_PORT_INVALID); 3005 } 3006 3007 /* 3008 * Check for valid alternate path PKey index and fill 3009 * it in 3010 */ 3011 pkeyindx = uc->uc_alt_path.cep_pkey_ix; 3012 if (tavor_pkeyindex_is_valid(state, pkeyindx)) { 3013 qpc->alt_addr_path.pkey_indx = pkeyindx; 3014 } else { 3015 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_altpkey_fail, 3016 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx, 3017 pkeyindx); 3018 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 3019 return (IBT_PKEY_IX_ILLEGAL); 3020 } 3021 opmask |= TAVOR_CMD_OP_ALT_PATH; 3022 } 3023 } else { 3024 /* 3025 * Invalid QP transport type. If we got here then it's a 3026 * warning of a probably serious problem. So print a message 3027 * and return failure 3028 */ 3029 TAVOR_WARNING(state, "unknown QP transport type in sqd2sqd"); 3030 TNF_PROBE_0(tavor_qp_sqd2sqd_inv_transtype_fail, 3031 TAVOR_TNF_ERROR, ""); 3032 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 3033 return (ibc_get_ci_failure(0)); 3034 } 3035 3036 /* 3037 * Post the SQD2SQD_QP command to the Tavor firmware 3038 * 3039 * We do a TAVOR_NOSLEEP here because we are still holding the 3040 * "qp_lock". If we got raised to interrupt level by priority 3041 * inversion, we do not want to block in this routine waiting for 3042 * success. 3043 */ 3044 status = tavor_cmn_qp_cmd_post(state, SQD2SQD_QP, qpc, qp->qp_qpnum, 3045 opmask, TAVOR_CMD_NOSLEEP_SPIN); 3046 if (status != TAVOR_CMD_SUCCESS) { 3047 if (status != TAVOR_CMD_BAD_QP_STATE) { 3048 cmn_err(CE_CONT, "Tavor: SQD2SQD_QP command failed: " 3049 "%08x\n", status); 3050 TNF_PROBE_1(tavor_qp_sqd2sqd_cmd_fail, 3051 TAVOR_TNF_ERROR, "", tnf_uint, status, status); 3052 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 3053 return (ibc_get_ci_failure(0)); 3054 } else { 3055 TNF_PROBE_0(tavor_qp_sqd2sqd_inv_qpstate_fail, 3056 TAVOR_TNF_ERROR, ""); 3057 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 3058 return (IBT_QP_STATE_INVALID); 3059 } 3060 } 3061 3062 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd); 3063 return (DDI_SUCCESS); 3064 } 3065 3066 3067 /* 3068 * tavor_qp_sqerr2rts() 3069 * Context: Can be called from interrupt or base context. 3070 */ 3071 static int 3072 tavor_qp_sqerr2rts(tavor_state_t *state, tavor_qphdl_t qp, 3073 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p) 3074 { 3075 tavor_hw_qpc_t *qpc; 3076 ibt_qp_ud_attr_t *ud; 3077 uint32_t opmask = 0; 3078 int status; 3079 3080 TAVOR_TNF_ENTER(tavor_qp_sqerr2rts); 3081 3082 ASSERT(MUTEX_HELD(&qp->qp_lock)); 3083 3084 /* 3085 * Grab the temporary QPC entry from QP software state 3086 */ 3087 qpc = &qp->qpc; 3088 3089 /* 3090 * Since there are no common and/or Tavor-specific fields to be filled 3091 * in for this command, we begin with the QPC fields which are 3092 * specific to transport type. 3093 */ 3094 if (qp->qp_serv_type == TAVOR_QP_UD) { 3095 ud = &info_p->qp_transport.ud; 3096 3097 /* 3098 * If we are attempting to modify the QKey for this QP, then 3099 * fill it in and set the appropriate flag in the "opmask" 3100 * parameter. 3101 */ 3102 if (flags & IBT_CEP_SET_QKEY) { 3103 qpc->qkey = ud->ud_qkey; 3104 opmask |= TAVOR_CMD_OP_QKEY; 3105 } 3106 3107 } else if (qp->qp_serv_type == TAVOR_QP_UC) { 3108 3109 /* 3110 * Check if any of the flags indicate a change in the RDMA 3111 * Write (recv) enable/disable and set the appropriate flag 3112 * in the "opmask" parameter. Note: RDMA Read and Atomic are 3113 * not valid for UC transport. 3114 */ 3115 if (flags & IBT_CEP_SET_RDMA_W) { 3116 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0; 3117 opmask |= TAVOR_CMD_OP_RWE; 3118 } 3119 } else { 3120 /* 3121 * Invalid QP transport type. If we got here then it's a 3122 * warning of a probably serious problem. So print a message 3123 * and return failure 3124 */ 3125 TAVOR_WARNING(state, "unknown QP transport type in sqerr2rts"); 3126 TNF_PROBE_0(tavor_qp_sqerr2rts_inv_transtype_fail, 3127 TAVOR_TNF_ERROR, ""); 3128 TAVOR_TNF_EXIT(tavor_qp_sqerr2rts); 3129 return (ibc_get_ci_failure(0)); 3130 } 3131 3132 /* 3133 * Post the SQERR2RTS_QP command to the Tavor firmware 3134 * 3135 * We do a TAVOR_NOSLEEP here because we are still holding the 3136 * "qp_lock". If we got raised to interrupt level by priority 3137 * inversion, we do not want to block in this routine waiting for 3138 * success. 3139 */ 3140 status = tavor_cmn_qp_cmd_post(state, SQERR2RTS_QP, qpc, qp->qp_qpnum, 3141 opmask, TAVOR_CMD_NOSLEEP_SPIN); 3142 if (status != TAVOR_CMD_SUCCESS) { 3143 if (status != TAVOR_CMD_BAD_QP_STATE) { 3144 cmn_err(CE_CONT, "Tavor: SQERR2RTS_QP command failed: " 3145 "%08x\n", status); 3146 TNF_PROBE_1(tavor_qp_sqerr2rts_cmd_fail, 3147 TAVOR_TNF_ERROR, "", tnf_uint, status, status); 3148 TAVOR_TNF_EXIT(tavor_qp_sqerr2rts); 3149 return (ibc_get_ci_failure(0)); 3150 } else { 3151 TNF_PROBE_0(tavor_qp_sqerr2rts_inv_qpstate_fail, 3152 TAVOR_TNF_ERROR, ""); 3153 TAVOR_TNF_EXIT(tavor_qp_sqerr2rts); 3154 return (IBT_QP_STATE_INVALID); 3155 } 3156 } 3157 3158 TAVOR_TNF_EXIT(tavor_qp_sqerr2rts); 3159 return (DDI_SUCCESS); 3160 } 3161 3162 3163 /* 3164 * tavor_qp_to_error() 3165 * Context: Can be called from interrupt or base context. 3166 */ 3167 static int 3168 tavor_qp_to_error(tavor_state_t *state, tavor_qphdl_t qp) 3169 { 3170 int status; 3171 3172 TAVOR_TNF_ENTER(tavor_qp_to_error); 3173 3174 ASSERT(MUTEX_HELD(&qp->qp_lock)); 3175 3176 /* 3177 * Post the TOERR_QP command to the Tavor firmware 3178 * 3179 * We do a TAVOR_NOSLEEP here because we are still holding the 3180 * "qp_lock". If we got raised to interrupt level by priority 3181 * inversion, we do not want to block in this routine waiting for 3182 * success. 3183 */ 3184 status = tavor_cmn_qp_cmd_post(state, TOERR_QP, NULL, qp->qp_qpnum, 3185 0, TAVOR_CMD_NOSLEEP_SPIN); 3186 if (status != TAVOR_CMD_SUCCESS) { 3187 cmn_err(CE_CONT, "Tavor: TOERR_QP command failed: %08x\n", 3188 status); 3189 TNF_PROBE_1(tavor_qp_to_error_cmd_fail, 3190 TAVOR_TNF_ERROR, "", tnf_uint, status, status); 3191 TAVOR_TNF_EXIT(tavor_qp_to_error); 3192 return (ibc_get_ci_failure(0)); 3193 } 3194 3195 TAVOR_TNF_EXIT(tavor_qp_to_error); 3196 return (DDI_SUCCESS); 3197 } 3198 3199 3200 /* 3201 * tavor_qp_to_reset() 3202 * Context: Can be called from interrupt or base context. 3203 */ 3204 int 3205 tavor_qp_to_reset(tavor_state_t *state, tavor_qphdl_t qp) 3206 { 3207 tavor_hw_qpc_t *qpc; 3208 int status; 3209 3210 TAVOR_TNF_ENTER(tavor_qp_to_reset); 3211 3212 ASSERT(MUTEX_HELD(&qp->qp_lock)); 3213 3214 /* 3215 * Grab the temporary QPC entry from QP software state 3216 */ 3217 qpc = &qp->qpc; 3218 3219 /* 3220 * Post the TORST_QP command to the Tavor firmware 3221 * 3222 * We do a TAVOR_NOSLEEP here because we are still holding the 3223 * "qp_lock". If we got raised to interrupt level by priority 3224 * inversion, we do not want to block in this routine waiting for 3225 * success. 3226 */ 3227 status = tavor_cmn_qp_cmd_post(state, TORST_QP, qpc, qp->qp_qpnum, 3228 0, TAVOR_CMD_NOSLEEP_SPIN); 3229 if (status != TAVOR_CMD_SUCCESS) { 3230 cmn_err(CE_CONT, "Tavor: TORST_QP command failed: %08x\n", 3231 status); 3232 TNF_PROBE_1(tavor_qp_to_reset_cmd_fail, 3233 TAVOR_TNF_ERROR, "", tnf_uint, status, status); 3234 TAVOR_TNF_EXIT(tavor_qp_to_reset); 3235 return (ibc_get_ci_failure(0)); 3236 } 3237 3238 TAVOR_TNF_EXIT(tavor_qp_to_reset); 3239 return (DDI_SUCCESS); 3240 } 3241 3242 3243 /* 3244 * tavor_qp_reset2err() 3245 * Context: Can be called from interrupt or base context. 3246 */ 3247 static int 3248 tavor_qp_reset2err(tavor_state_t *state, tavor_qphdl_t qp) 3249 { 3250 tavor_hw_qpc_t *qpc; 3251 int status; 3252 3253 TAVOR_TNF_ENTER(tavor_qp_reset2err); 3254 3255 ASSERT(MUTEX_HELD(&qp->qp_lock)); 3256 3257 /* 3258 * In order to implement the transition from "Reset" directly to the 3259 * "Error" state, it is necessary to first give ownership of the QP 3260 * context to the Tavor hardware. This is accomplished by transitioning 3261 * the QP to "Init" as an intermediate step and then, immediately 3262 * transitioning to "Error". 3263 * 3264 * When this function returns success, the QP context will be owned by 3265 * the Tavor hardware and will be in the "Error" state. 3266 */ 3267 3268 /* 3269 * Grab the temporary QPC entry from QP software state 3270 */ 3271 qpc = &qp->qpc; 3272 3273 /* 3274 * Fill in the common and/or Tavor-specific fields in the QPC 3275 */ 3276 if (qp->qp_is_special) { 3277 qpc->serv_type = TAVOR_QP_MLX; 3278 } else { 3279 qpc->serv_type = qp->qp_serv_type; 3280 } 3281 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED; 3282 qpc->de = TAVOR_QP_DESC_EVT_ENABLED; 3283 qpc->sched_q = TAVOR_QP_SCHEDQ_GET(qp->qp_qpnum); 3284 if (qp->qp_is_umap) { 3285 qpc->usr_page = qp->qp_uarpg; 3286 } else { 3287 qpc->usr_page = 0; 3288 } 3289 qpc->pd = qp->qp_pdhdl->pd_pdnum; 3290 qpc->wqe_baseaddr = 0; 3291 qpc->wqe_lkey = qp->qp_mrhdl->mr_lkey; 3292 qpc->ssc = qp->qp_sq_sigtype; 3293 qpc->cqn_snd = qp->qp_sq_cqhdl->cq_cqnum; 3294 qpc->rsc = TAVOR_QP_RQ_ALL_SIGNALED; 3295 qpc->cqn_rcv = qp->qp_rq_cqhdl->cq_cqnum; 3296 qpc->srq_en = qp->qp_srq_en; 3297 3298 if (qp->qp_srq_en == TAVOR_QP_SRQ_ENABLED) { 3299 qpc->srq_number = qp->qp_srqhdl->srq_srqnum; 3300 } else { 3301 qpc->srq_number = 0; 3302 } 3303 3304 /* 3305 * Now fill in the QPC fields which are specific to transport type 3306 */ 3307 if (qp->qp_serv_type == TAVOR_QP_UD) { 3308 /* Set the UD parameters to an invalid default */ 3309 qpc->qkey = 0; 3310 qpc->pri_addr_path.portnum = 1; 3311 qpc->pri_addr_path.pkey_indx = 0; 3312 3313 } else if (qp->qp_serv_type == TAVOR_QP_RC) { 3314 /* Set the RC parameters to invalid default */ 3315 qpc->rre = 0; 3316 qpc->rwe = 0; 3317 qpc->rae = 0; 3318 qpc->pri_addr_path.portnum = 1; 3319 qpc->pri_addr_path.pkey_indx = 0; 3320 3321 } else if (qp->qp_serv_type == TAVOR_QP_UC) { 3322 /* Set the UC parameters to invalid default */ 3323 qpc->rwe = 0; 3324 qpc->pri_addr_path.portnum = 1; 3325 qpc->pri_addr_path.pkey_indx = 0; 3326 3327 } else { 3328 /* 3329 * Invalid QP transport type. If we got here then it's a 3330 * warning of a probably serious problem. So print a message 3331 * and return failure 3332 */ 3333 TAVOR_WARNING(state, "unknown QP transport type in rst2err"); 3334 TNF_PROBE_0(tavor_qp_reset2err_inv_transtype_fail, 3335 TAVOR_TNF_ERROR, ""); 3336 TAVOR_TNF_EXIT(tavor_qp_reset2err); 3337 return (ibc_get_ci_failure(0)); 3338 } 3339 3340 /* 3341 * Post the RST2INIT_QP command to the Tavor firmware 3342 * 3343 * We do a TAVOR_NOSLEEP here because we are still holding the 3344 * "qp_lock". If we got raised to interrupt level by priority 3345 * inversion, we do not want to block in this routine waiting for 3346 * success. 3347 */ 3348 status = tavor_cmn_qp_cmd_post(state, RST2INIT_QP, qpc, qp->qp_qpnum, 3349 0, TAVOR_CMD_NOSLEEP_SPIN); 3350 if (status != TAVOR_CMD_SUCCESS) { 3351 cmn_err(CE_CONT, "Tavor: RST2INIT_QP command failed: %08x\n", 3352 status); 3353 TNF_PROBE_1(tavor_qp_reset2err_rst2init_cmd_fail, 3354 TAVOR_TNF_ERROR, "", tnf_uint, status, status); 3355 TAVOR_TNF_EXIT(tavor_qp_reset2err); 3356 return (ibc_get_ci_failure(0)); 3357 } 3358 3359 /* 3360 * Now post the TOERR_QP command to the Tavor firmware 3361 * 3362 * We still do a TAVOR_NOSLEEP here because we are still holding the 3363 * "qp_lock". Note: If this fails (which it really never should), 3364 * it indicates a serious problem in the HW or SW. We try to move 3365 * the QP back to the "Reset" state if possible and print a warning 3366 * message if not. In any case, we return an error here. 3367 */ 3368 status = tavor_cmn_qp_cmd_post(state, TOERR_QP, NULL, qp->qp_qpnum, 3369 0, TAVOR_CMD_NOSLEEP_SPIN); 3370 if (status != TAVOR_CMD_SUCCESS) { 3371 cmn_err(CE_CONT, "Tavor: TOERR_QP command failed: %08x\n", 3372 status); 3373 if (tavor_qp_to_reset(state, qp) != DDI_SUCCESS) { 3374 TAVOR_WARNING(state, "failed to reset QP context"); 3375 } 3376 TNF_PROBE_1(tavor_qp_reset2err_toerr_cmd_fail, 3377 TAVOR_TNF_ERROR, "", tnf_uint, status, status); 3378 TAVOR_TNF_EXIT(tavor_qp_reset2err); 3379 return (ibc_get_ci_failure(0)); 3380 } 3381 3382 TAVOR_TNF_EXIT(tavor_qp_reset2err); 3383 return (DDI_SUCCESS); 3384 } 3385 3386 3387 /* 3388 * tavor_check_rdma_enable_flags() 3389 * Context: Can be called from interrupt or base context. 3390 */ 3391 static uint_t 3392 tavor_check_rdma_enable_flags(ibt_cep_modify_flags_t flags, 3393 ibt_qp_info_t *info_p, tavor_hw_qpc_t *qpc) 3394 { 3395 uint_t opmask = 0; 3396 3397 if (flags & IBT_CEP_SET_RDMA_R) { 3398 qpc->rre = (info_p->qp_flags & IBT_CEP_RDMA_RD) ? 1 : 0; 3399 opmask |= TAVOR_CMD_OP_RRE; 3400 } 3401 3402 if (flags & IBT_CEP_SET_RDMA_W) { 3403 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0; 3404 opmask |= TAVOR_CMD_OP_RWE; 3405 } 3406 3407 if (flags & IBT_CEP_SET_ATOMIC) { 3408 qpc->rae = (info_p->qp_flags & IBT_CEP_ATOMIC) ? 1 : 0; 3409 opmask |= TAVOR_CMD_OP_RAE; 3410 } 3411 3412 return (opmask); 3413 } 3414 3415 /* 3416 * tavor_qp_validate_resp_rsrc() 3417 * Context: Can be called from interrupt or base context. 3418 */ 3419 static int 3420 tavor_qp_validate_resp_rsrc(tavor_state_t *state, ibt_qp_rc_attr_t *rc, 3421 uint_t *rra_max) 3422 { 3423 uint_t rdma_ra_in; 3424 3425 rdma_ra_in = rc->rc_rdma_ra_in; 3426 3427 /* 3428 * Check if number of responder resources is too large. Return an 3429 * error if it is 3430 */ 3431 if (rdma_ra_in > state->ts_cfg_profile->cp_hca_max_rdma_in_qp) { 3432 return (IBT_INVALID_PARAM); 3433 } 3434 3435 /* 3436 * If the number of responder resources is too small, round it up. 3437 * Then find the next highest power-of-2 3438 */ 3439 if (rdma_ra_in == 0) { 3440 rdma_ra_in = 1; 3441 } 3442 if (ISP2(rdma_ra_in)) { 3443 *rra_max = highbit(rdma_ra_in) - 1; 3444 } else { 3445 *rra_max = highbit(rdma_ra_in); 3446 } 3447 return (DDI_SUCCESS); 3448 } 3449 3450 3451 /* 3452 * tavor_qp_validate_init_depth() 3453 * Context: Can be called from interrupt or base context. 3454 */ 3455 static int 3456 tavor_qp_validate_init_depth(tavor_state_t *state, ibt_qp_rc_attr_t *rc, 3457 uint_t *sra_max) 3458 { 3459 uint_t rdma_ra_out; 3460 3461 rdma_ra_out = rc->rc_rdma_ra_out; 3462 3463 /* 3464 * Check if requested initiator depth is too large. Return an error 3465 * if it is 3466 */ 3467 if (rdma_ra_out > state->ts_cfg_profile->cp_hca_max_rdma_out_qp) { 3468 return (IBT_INVALID_PARAM); 3469 } 3470 3471 /* 3472 * If the requested initiator depth is too small, round it up. 3473 * Then find the next highest power-of-2 3474 */ 3475 if (rdma_ra_out == 0) { 3476 rdma_ra_out = 1; 3477 } 3478 if (ISP2(rdma_ra_out)) { 3479 *sra_max = highbit(rdma_ra_out) - 1; 3480 } else { 3481 *sra_max = highbit(rdma_ra_out); 3482 } 3483 return (DDI_SUCCESS); 3484 } 3485 3486 3487 /* 3488 * tavor_qp_validate_mtu() 3489 * Context: Can be called from interrupt or base context. 3490 */ 3491 static int 3492 tavor_qp_validate_mtu(tavor_state_t *state, uint_t mtu) 3493 { 3494 /* 3495 * Check for invalid MTU values (i.e. zero or any value larger than 3496 * the HCA's port maximum). 3497 */ 3498 if ((mtu == 0) || (mtu > state->ts_cfg_profile->cp_max_mtu)) { 3499 return (IBT_HCA_PORT_MTU_EXCEEDED); 3500 } 3501 return (DDI_SUCCESS); 3502 } 3503