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