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