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