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