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