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