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  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 #include <sys/ib/ibtl/impl/ibtl.h>
  26 #include <sys/ib/ibtl/impl/ibtl_cm.h>
  27 
  28 /*
  29  * ibtl_qp.c
  30  *      These routines implement (most of) the verbs related to
  31  *      Queue Pairs.
  32  */
  33 
  34 /* Globals. */
  35 static char ibtf_qp[] = "ibtl";
  36 
  37 /* This table indirectly initializes the ibt_cep_next_state[] table. */
  38 typedef struct ibt_cep_next_state_s {
  39         ibt_cep_state_t         next_state;
  40         ibt_cep_modify_flags_t  modify_flags;
  41 } ibt_cep_next_state_t;
  42 
  43 struct  {
  44         ibt_cep_state_t         current_state;
  45         ibt_cep_state_t         next_state;
  46         ibt_cep_modify_flags_t  modify_flags;
  47 } ibt_cep_next_state_inits[] = {
  48         { IBT_STATE_RESET, IBT_STATE_INIT, IBT_CEP_SET_RESET_INIT},
  49         { IBT_STATE_INIT, IBT_STATE_RTR, IBT_CEP_SET_INIT_RTR},
  50         { IBT_STATE_RTR, IBT_STATE_RTS, IBT_CEP_SET_RTR_RTS}
  51 };
  52 
  53 ibt_cep_next_state_t ibt_cep_next_state[IBT_STATE_NUM];
  54 
  55 _NOTE(SCHEME_PROTECTS_DATA("unique", ibt_cep_next_state))
  56 
  57 /* The following data and functions can increase system stability. */
  58 
  59 int ibtl_qp_calls_curr;
  60 int ibtl_qp_calls_max = 128;    /* limit on # of simultaneous QP verb calls */
  61 kmutex_t ibtl_qp_mutex;
  62 kcondvar_t ibtl_qp_cv;
  63 
  64 void
  65 ibtl_qp_flow_control_enter(void)
  66 {
  67         mutex_enter(&ibtl_qp_mutex);
  68         while (ibtl_qp_calls_curr >= ibtl_qp_calls_max) {
  69                 cv_wait(&ibtl_qp_cv, &ibtl_qp_mutex);
  70         }
  71         ++ibtl_qp_calls_curr;
  72         mutex_exit(&ibtl_qp_mutex);
  73 }
  74 
  75 void
  76 ibtl_qp_flow_control_exit(void)
  77 {
  78         mutex_enter(&ibtl_qp_mutex);
  79         cv_signal(&ibtl_qp_cv);
  80         --ibtl_qp_calls_curr;
  81         mutex_exit(&ibtl_qp_mutex);
  82 }
  83 
  84 /*
  85  * Function:
  86  *      ibt_alloc_qp
  87  * Input:
  88  *      hca_hdl         HCA Handle.
  89  *      type            Specifies the type of QP to alloc in ibt_alloc_qp()
  90  *      qp_attrp        Specifies the ibt_qp_alloc_attr_t that are needed to
  91  *                      allocate a QP and transition it to the RTS state for
  92  *                      UDs and INIT state for all other QPs.
  93  * Output:
  94  *      queue_sizes_p   Returned sizes for SQ, RQ, SQ WR SGL elements & RQ
  95  *                      WR SGL elements.
  96  *      qpn_p           Returned QP Number of the allocated QP.
  97  *      ibt_qp_p        The ibt_qp_hdl_t of the allocated QP.
  98  * Returns:
  99  *      IBT_SUCCESS
 100  * Description:
 101  *      Allocate a QP with specified attributes.
 102  */
 103 ibt_status_t
 104 ibt_alloc_qp(ibt_hca_hdl_t hca_hdl, ibt_qp_type_t type,
 105     ibt_qp_alloc_attr_t *qp_attrp, ibt_chan_sizes_t *queue_sizes_p,
 106     ib_qpn_t *qpn_p, ibt_qp_hdl_t *ibt_qp_p)
 107 {
 108         ibt_status_t            retval;
 109         ibtl_channel_t          *chanp;
 110         ibt_tran_srv_t          qp_type;
 111 
 112         IBTF_DPRINTF_L3(ibtf_qp, "ibt_alloc_qp(%p, %d, %p, %p, %p, %p) ",
 113             hca_hdl, type, qp_attrp, queue_sizes_p, qpn_p, ibt_qp_p);
 114 
 115         switch (type) {
 116         case IBT_UD_RQP:
 117                 qp_type = IBT_UD_SRV;
 118                 break;
 119         case IBT_RC_RQP:
 120                 qp_type = IBT_RC_SRV;
 121                 break;
 122         case IBT_UC_RQP:
 123                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Unreliable Connected "
 124                     "Transport Type is not supported.");
 125                 *ibt_qp_p = NULL;
 126                 return (IBT_NOT_SUPPORTED);
 127         case IBT_RD_RQP:
 128                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Reliable Datagram "
 129                     "Transport Type is not supported.");
 130                 *ibt_qp_p = NULL;
 131                 return (IBT_NOT_SUPPORTED);
 132         default:
 133                 /* shouldn't happen ILLEGAL Type */
 134                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Illegal Transport Type "
 135                     "%d", type);
 136                 *ibt_qp_p = NULL;
 137                 return (IBT_QP_SRV_TYPE_INVALID);
 138         }
 139 
 140         /* Get CI CQ handles */
 141         qp_attrp->qp_ibc_scq_hdl = (qp_attrp->qp_scq_hdl == NULL) ? NULL :
 142             qp_attrp->qp_scq_hdl->cq_ibc_cq_hdl;
 143         qp_attrp->qp_ibc_rcq_hdl = (qp_attrp->qp_rcq_hdl == NULL) ? NULL :
 144             qp_attrp->qp_rcq_hdl->cq_ibc_cq_hdl;
 145 
 146         /* Get CI SRQ handle */
 147         if ((qp_attrp->qp_alloc_flags & IBT_QP_USES_SRQ) &&
 148             (qp_attrp->qp_srq_hdl != NULL))
 149                 qp_attrp->qp_ibc_srq_hdl =
 150                     qp_attrp->qp_srq_hdl->srq_ibc_srq_hdl;
 151         else
 152                 qp_attrp->qp_ibc_srq_hdl = NULL;
 153 
 154         /* Allocate Channel structure */
 155         chanp = kmem_zalloc(sizeof (*chanp), KM_SLEEP);
 156 
 157         ibtl_qp_flow_control_enter();
 158         retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_qp)(
 159             IBTL_HCA2CIHCA(hca_hdl), &chanp->ch_qp, type, qp_attrp,
 160             queue_sizes_p, qpn_p, &chanp->ch_qp.qp_ibc_qp_hdl);
 161         ibtl_qp_flow_control_exit();
 162         if (retval != IBT_SUCCESS) {
 163                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: "
 164                     "Failed to allocate QP: %d", retval);
 165                 kmem_free(chanp, sizeof (*chanp));
 166                 *ibt_qp_p = NULL;
 167                 return (retval);
 168         }
 169 
 170         /* Initialize the internal QP struct. */
 171         chanp->ch_qp.qp_type = qp_type;
 172         chanp->ch_qp.qp_hca = hca_hdl;
 173         chanp->ch_qp.qp_send_cq = qp_attrp->qp_scq_hdl;
 174         chanp->ch_qp.qp_recv_cq = qp_attrp->qp_rcq_hdl;
 175         chanp->ch_current_state = IBT_STATE_RESET;
 176         /*
 177          * The IBTA spec does not include the signal type or PD on a QP
 178          * query operation. In order to implement the "CLONE" feature
 179          * we need to cache these values.  Mostly used by TI client.
 180          */
 181         chanp->ch_qp.qp_flags = qp_attrp->qp_flags;
 182         chanp->ch_qp.qp_pd_hdl = qp_attrp->qp_pd_hdl;
 183         mutex_init(&chanp->ch_cm_mutex, NULL, MUTEX_DEFAULT, NULL);
 184         cv_init(&chanp->ch_cm_cv, NULL, CV_DEFAULT, NULL);
 185 
 186         atomic_inc_32(&hca_hdl->ha_qp_cnt);
 187 
 188         IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: SUCCESS: qp %p owned by '%s'",
 189             chanp, hca_hdl->ha_clnt_devp->clnt_name);
 190 
 191         *ibt_qp_p = chanp;
 192 
 193         return (retval);
 194 }
 195 
 196 
 197 /*
 198  * Function:
 199  *      ibt_initialize_qp
 200  * Input:
 201  *      ibt_qp          The previously allocated IBT QP Handle.
 202  *      modify_attrp    Specifies the QP Modify attributes that to transition
 203  *                      the QP to the RTS state for UDs (including special QPs)
 204  *                      and INIT state for all other QPs.
 205  * Output:
 206  *      none.
 207  * Returns:
 208  *      IBT_SUCCESS
 209  * Description:
 210  *      Transition the QP to the RTS state for UDs (including special QPs)
 211  *      and INIT state for all other QPs.
 212  */
 213 ibt_status_t
 214 ibt_initialize_qp(ibt_qp_hdl_t ibt_qp, ibt_qp_info_t *modify_attrp)
 215 {
 216         ibt_status_t            status;
 217         ibt_cep_state_t         state;
 218         ibc_hca_hdl_t           ibc_hca_hdl = IBTL_CHAN2CIHCA(ibt_qp);
 219         ibc_qp_hdl_t            ibc_qp_hdl = IBTL_CHAN2CIQP(ibt_qp);
 220         ibc_operations_t        *hca_ops_p = IBTL_CHAN2CIHCAOPS_P(ibt_qp);
 221         ibt_cep_modify_flags_t  modify_flags;
 222 
 223         IBTF_DPRINTF_L3(ibtf_qp, "ibt_initialize_qp(%p, %p)",
 224             ibt_qp, modify_attrp);
 225 
 226         /*
 227          * Validate the QP Type from the channel with QP Type from the
 228          * modify attribute struct.
 229          */
 230         if (ibt_qp->ch_qp.qp_type != modify_attrp->qp_trans) {
 231                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: "
 232                     "QP Type mismatch: Chan QP Type<%d>, Modify QP Type<%d>",
 233                     ibt_qp->ch_qp.qp_type, modify_attrp->qp_trans);
 234                 return (IBT_QP_SRV_TYPE_INVALID);
 235         }
 236         if (ibt_qp->ch_current_state != IBT_STATE_RESET) {
 237                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: "
 238                     "QP needs to be in RESET state: Chan QP State<%d>",
 239                     ibt_qp->ch_current_state);
 240                 return (IBT_CHAN_STATE_INVALID);
 241         }
 242 
 243         /*
 244          * Initialize the QP to the RTS state for UDs
 245          * and INIT state for all other QPs.
 246          */
 247         switch (modify_attrp->qp_trans) {
 248         case IBT_UD_SRV:
 249 
 250                 /*
 251                  * Bring the QP to the RTS state.
 252                  */
 253                 state = IBT_STATE_RESET;
 254                 ibtl_qp_flow_control_enter();
 255                 do {
 256                         modify_attrp->qp_current_state = state;
 257                         modify_flags = ibt_cep_next_state[state].modify_flags;
 258                         modify_attrp->qp_state = state =
 259                             ibt_cep_next_state[state].next_state;
 260 
 261                         IBTF_DPRINTF_L3(ibtf_qp, "ibt_initialize_qp: "
 262                             "modifying qp state to 0x%x", state);
 263                         status = (hca_ops_p->ibc_modify_qp)(ibc_hca_hdl,
 264                             ibc_qp_hdl, modify_flags, modify_attrp, NULL);
 265                 } while ((state != IBT_STATE_RTS) && (status == IBT_SUCCESS));
 266                 ibtl_qp_flow_control_exit();
 267 
 268                 if (status == IBT_SUCCESS) {
 269                         ibt_qp->ch_current_state = state;
 270                         ibt_qp->ch_transport.ud.ud_port_num =
 271                             modify_attrp->qp_transport.ud.ud_port;
 272                         ibt_qp->ch_transport.ud.ud_qkey =
 273                             modify_attrp->qp_transport.ud.ud_qkey;
 274                 }
 275                 break;
 276         case IBT_UC_SRV:
 277         case IBT_RD_SRV:
 278         case IBT_RC_SRV:
 279 
 280                 /*
 281                  * Bring the QP to the INIT state.
 282                  */
 283                 modify_attrp->qp_state = IBT_STATE_INIT;
 284 
 285                 ibtl_qp_flow_control_enter();
 286                 status = (hca_ops_p->ibc_modify_qp)(ibc_hca_hdl, ibc_qp_hdl,
 287                     IBT_CEP_SET_RESET_INIT, modify_attrp, NULL);
 288                 ibtl_qp_flow_control_exit();
 289                 if (status == IBT_SUCCESS)
 290                         ibt_qp->ch_current_state = IBT_STATE_INIT;
 291                 break;
 292         default:
 293                 /* shouldn't happen ILLEGAL Type */
 294                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: Illegal Type %d",
 295                     modify_attrp->qp_trans);
 296                 return (IBT_QP_SRV_TYPE_INVALID);
 297         } /* End switch */
 298 
 299         return (status);
 300 }
 301 
 302 
 303 /*
 304  * Function:
 305  *      ibt_alloc_special_qp
 306  * Input:
 307  *      hca_hdl         HCA Handle.
 308  *      type            Specifies the type of Special QP to be allocated.
 309  *      qp_attrp        Specifies the ibt_qp_alloc_attr_t that are needed to
 310  *                      allocate a special QP.
 311  * Output:
 312  *      queue_sizes_p   Returned sizes for SQ, RQ, SQ WR SGL elements & RQ
 313  *                      WR SGL elements.
 314  *      qpn_p           Returned qpn of the allocated QP.
 315  *      ibt_qp_p        The ibt_qp_hdl_t of the allocated QP.
 316  * Returns:
 317  *      IBT_SUCCESS
 318  * Description:
 319  *      Allocate a special QP with specified attributes.
 320  */
 321 ibt_status_t
 322 ibt_alloc_special_qp(ibt_hca_hdl_t hca_hdl, uint8_t port, ibt_sqp_type_t type,
 323     ibt_qp_alloc_attr_t *qp_attrp, ibt_chan_sizes_t *queue_sizes_p,
 324     ibt_qp_hdl_t *ibt_qp_p)
 325 {
 326         ibt_qp_hdl_t    chanp;
 327         ibt_status_t    retval;
 328         ibt_tran_srv_t  sqp_type;
 329 
 330         IBTF_DPRINTF_L3(ibtf_qp, "ibt_alloc_special_qp(%p, %d, %x, %p, %p, %p)",
 331             hca_hdl, port, type, qp_attrp, queue_sizes_p, ibt_qp_p);
 332 
 333         switch (type) {
 334         case IBT_SMI_SQP:
 335         case IBT_GSI_SQP:
 336                 sqp_type = IBT_UD_SRV;
 337                 break;
 338 
 339         case IBT_RAWIP_SQP:
 340                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: Raw IP "
 341                     "Transport Type is not supported.");
 342                 *ibt_qp_p = NULL;
 343                 return (IBT_NOT_SUPPORTED);
 344 
 345         case IBT_RAWETHER_SQP:
 346                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: Raw Ethernet "
 347                     "Transport Type is not supported.");
 348                 *ibt_qp_p = NULL;
 349                 return (IBT_NOT_SUPPORTED);
 350 
 351         default:
 352                 /* Shouldn't happen */
 353                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: "
 354                     "Illegal Type 0x%x", type);
 355                 *ibt_qp_p = NULL;
 356                 return (IBT_QP_SPECIAL_TYPE_INVALID);
 357         }
 358 
 359         /* convert the CQ handles for the CI */
 360         qp_attrp->qp_ibc_scq_hdl = qp_attrp->qp_scq_hdl->cq_ibc_cq_hdl;
 361         qp_attrp->qp_ibc_rcq_hdl = qp_attrp->qp_rcq_hdl->cq_ibc_cq_hdl;
 362 
 363         /* Allocate Channel structure */
 364         chanp = kmem_zalloc(sizeof (*chanp), KM_SLEEP);
 365 
 366         ibtl_qp_flow_control_enter();
 367         retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_special_qp)(
 368             IBTL_HCA2CIHCA(hca_hdl), port, &chanp->ch_qp, type, qp_attrp,
 369             queue_sizes_p, &chanp->ch_qp.qp_ibc_qp_hdl);
 370         ibtl_qp_flow_control_exit();
 371         if (retval != IBT_SUCCESS) {
 372                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: "
 373                     "Failed to allocate Special QP: %d", retval);
 374                 kmem_free(chanp, sizeof (*chanp));
 375                 *ibt_qp_p = NULL;
 376                 return (retval);
 377         }
 378 
 379         /* Initialize the internal QP struct. */
 380         chanp->ch_qp.qp_type = sqp_type;
 381         chanp->ch_qp.qp_hca = hca_hdl;
 382         chanp->ch_qp.qp_send_cq = qp_attrp->qp_scq_hdl;
 383         chanp->ch_qp.qp_recv_cq = qp_attrp->qp_rcq_hdl;
 384         chanp->ch_current_state = IBT_STATE_RESET;
 385         mutex_init(&chanp->ch_cm_mutex, NULL, MUTEX_DEFAULT, NULL);
 386         cv_init(&chanp->ch_cm_cv, NULL, CV_DEFAULT, NULL);
 387 
 388         /* Updating these variable, so that debugger shows correct values. */
 389         chanp->ch_qp.qp_flags = qp_attrp->qp_flags;
 390         chanp->ch_qp.qp_pd_hdl = qp_attrp->qp_pd_hdl;
 391 
 392         atomic_inc_32(&hca_hdl->ha_qp_cnt);
 393 
 394         *ibt_qp_p = chanp;
 395 
 396         return (retval);
 397 }
 398 
 399 
 400 /*
 401  * Function:
 402  *      ibt_flush_qp
 403  * Input:
 404  *      ibtl_qp         Handle for QP that needs to be flushed.
 405  * Output:
 406  *      none.
 407  * Returns:
 408  *      IBT_SUCCESS
 409  *      IBT_QP_HDL_INVALID
 410  * Description:
 411  *      Put the QP into error state to flush out work requests.
 412  */
 413 ibt_status_t
 414 ibt_flush_qp(ibt_qp_hdl_t ibt_qp)
 415 {
 416         ibt_qp_info_t           modify_attr;
 417         ibt_status_t            retval;
 418 
 419         IBTF_DPRINTF_L3(ibtf_qp, "ibt_flush_qp(%p)", ibt_qp);
 420 
 421         if (ibt_qp->ch_qp.qp_type == IBT_RC_SRV) {
 422                 mutex_enter(&ibtl_free_qp_mutex);
 423                 if ((ibt_qp->ch_transport.rc.rc_free_flags &
 424                     (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING)) ==
 425                     IBTL_RC_QP_CONNECTED) {
 426                         mutex_exit(&ibtl_free_qp_mutex);
 427                         IBTF_DPRINTF_L2(ibtf_qp, "ibt_flush_qp(%p): "
 428                             "called with a connected RC QP", ibt_qp);
 429                         return (IBT_CHAN_STATE_INVALID);
 430                 }
 431                 mutex_exit(&ibtl_free_qp_mutex);
 432         }
 433 
 434         bzero(&modify_attr, sizeof (ibt_qp_info_t));
 435 
 436         /*
 437          * Set the QP state to error to flush any uncompleted WRs.
 438          */
 439         modify_attr.qp_state = IBT_STATE_ERROR;
 440         modify_attr.qp_trans = ibt_qp->ch_qp.qp_type;
 441 
 442         retval = ibt_modify_qp(ibt_qp, IBT_CEP_SET_STATE, &modify_attr, NULL);
 443 
 444         if (retval != IBT_SUCCESS) {
 445                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_flush_qp: "
 446                     "failed on chan %p: %d", ibt_qp, retval);
 447         }
 448         return (retval);
 449 }
 450 
 451 
 452 /*
 453  * ibtl_cm_chan_is_opening()
 454  *
 455  *      Inform IBTL that the connection established process is in progress
 456  *      on this channel so that care need to be taken while free'ing when
 457  *      open is NOT yet complete.
 458  *
 459  *      chan    Channel Handle
 460  */
 461 void
 462 ibtl_cm_chan_is_opening(ibt_channel_hdl_t chan)
 463 {
 464         IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_opening(%p)", chan);
 465         ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
 466         mutex_enter(&ibtl_free_qp_mutex);
 467         ASSERT(chan->ch_transport.rc.rc_free_flags == 0);
 468         chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CONNECTING;
 469         mutex_exit(&ibtl_free_qp_mutex);
 470 }
 471 
 472 /*
 473  * ibtl_cm_chan_open_is_aborted()
 474  *
 475  *      Inform IBTL that the connection established on this channel has
 476  *      aborted. So undo what was done in ibtl_cm_chan_is_opening().
 477  *
 478  *      chan    Channel Handle
 479  */
 480 void
 481 ibtl_cm_chan_open_is_aborted(ibt_channel_hdl_t chan)
 482 {
 483         IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_open_is_aborted(%p)", chan);
 484         ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
 485         mutex_enter(&ibtl_free_qp_mutex);
 486         chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTING;
 487         mutex_exit(&ibtl_free_qp_mutex);
 488 }
 489 
 490 /*
 491  * ibtl_cm_chan_is_open()
 492  *
 493  *      Inform IBTL that the connection has been established on this
 494  *      channel so that a later call to ibtl_cm_chan_is_closed()
 495  *      will be required to free the QPN used by this channel.
 496  *
 497  *      chan    Channel Handle
 498  */
 499 void
 500 ibtl_cm_chan_is_open(ibt_channel_hdl_t chan)
 501 {
 502         IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_open(%p)", chan);
 503         ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
 504         mutex_enter(&ibtl_free_qp_mutex);
 505         chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTING;
 506         chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CONNECTED;
 507         mutex_exit(&ibtl_free_qp_mutex);
 508 }
 509 
 510 /*
 511  * ibtl_cm_is_chan_closing()
 512  *
 513  *      Returns 1, if the connection that has been
 514  *      started for this channel has moved to TIMEWAIT
 515  *      If not, returns 0
 516  *
 517  *      chan    Channel Handle
 518  */
 519 int
 520 ibtl_cm_is_chan_closing(ibt_channel_hdl_t chan)
 521 {
 522         IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_is_chan_closing(%p)", chan);
 523         ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
 524         mutex_enter(&ibtl_free_qp_mutex);
 525         if (chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CLOSING) {
 526                 mutex_exit(&ibtl_free_qp_mutex);
 527                 return (1);
 528         }
 529         mutex_exit(&ibtl_free_qp_mutex);
 530         return (0);
 531 }
 532 
 533 /*
 534  * ibtl_cm_is_chan_closed()
 535  *
 536  *      Returns 1, if the connection that has been
 537  *      started for this channel has completed TIMEWAIT
 538  *      If not, returns 0
 539  *
 540  *      chan    Channel Handle
 541  */
 542 int
 543 ibtl_cm_is_chan_closed(ibt_channel_hdl_t chan)
 544 {
 545         IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_is_chan_closed(%p)", chan);
 546         ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
 547         mutex_enter(&ibtl_free_qp_mutex);
 548         if (chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CLOSED) {
 549                 mutex_exit(&ibtl_free_qp_mutex);
 550                 return (1);
 551         }
 552         mutex_exit(&ibtl_free_qp_mutex);
 553         return (0);
 554 }
 555 /*
 556  * ibtl_cm_chan_is_closing()
 557  *
 558  *      Inform IBTL that the TIMEWAIT delay for the connection has been
 559  *      started for this channel so that the QP can be freed.
 560  *
 561  *      chan    Channel Handle
 562  */
 563 void
 564 ibtl_cm_chan_is_closing(ibt_channel_hdl_t chan)
 565 {
 566         IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_closing(%p)", chan);
 567         ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
 568         mutex_enter(&ibtl_free_qp_mutex);
 569         ASSERT(chan->ch_transport.rc.rc_free_flags == IBTL_RC_QP_CONNECTED);
 570         chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CLOSING;
 571         mutex_exit(&ibtl_free_qp_mutex);
 572 }
 573 /*
 574  * ibtl_cm_chan_is_closed()
 575  *
 576  *      Inform IBTL that the TIMEWAIT delay for the connection has been
 577  *      reached for this channel so that the QPN can be reused.
 578  *
 579  *      chan    Channel Handle
 580  */
 581 void
 582 ibtl_cm_chan_is_closed(ibt_channel_hdl_t chan)
 583 {
 584         ibt_status_t status;
 585         ibtl_hca_t *ibtl_hca = chan->ch_qp.qp_hca;
 586 
 587         IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_closed(%p)", chan);
 588         ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
 589         mutex_enter(&ibtl_free_qp_mutex);
 590         ASSERT((chan->ch_transport.rc.rc_free_flags &
 591             (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING)) ==
 592             (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING));
 593 
 594         chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTED;
 595         chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CLOSING;
 596         chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CLOSED;
 597 
 598         ibtl_cm_set_chan_private(chan, NULL);
 599 
 600         if ((chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_FREED) == 0) {
 601                 mutex_exit(&ibtl_free_qp_mutex);
 602                 return;
 603         }
 604         mutex_exit(&ibtl_free_qp_mutex);
 605         ibtl_qp_flow_control_enter();
 606         if ((status = (IBTL_CHAN2CIHCAOPS_P(chan)->ibc_release_qpn)
 607             (IBTL_CHAN2CIHCA(chan), chan->ch_transport.rc.rc_qpn_hdl)) ==
 608             IBT_SUCCESS) {
 609                 /* effectively, this is kmem_free(chan); */
 610                 ibtl_free_qp_async_check(&chan->ch_qp);
 611 
 612                 /* decrement ha_qpn_cnt and check for close in progress */
 613                 ibtl_close_hca_check(ibtl_hca);
 614         } else
 615                 IBTF_DPRINTF_L2(ibtf_qp, "ibtl_cm_chan_is_closed: "
 616                     "ibc_release_qpn failed: status = %d\n", status);
 617         ibtl_qp_flow_control_exit();
 618 }
 619 
 620 /*
 621  * ibtl_cm_chan_is_reused()
 622  *
 623  *      Inform IBTL that the channel is going to be re-used
 624  *      chan    Channel Handle
 625  */
 626 void
 627 ibtl_cm_chan_is_reused(ibt_channel_hdl_t chan)
 628 {
 629         IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_reused(%p)", chan);
 630         ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
 631         mutex_enter(&ibtl_free_qp_mutex);
 632         ASSERT(((chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CONNECTED) !=
 633             IBTL_RC_QP_CONNECTED));
 634 
 635         /* channel is no longer in closed state, shall be re-used */
 636         chan->ch_transport.rc.rc_free_flags = 0;
 637 
 638         mutex_exit(&ibtl_free_qp_mutex);
 639 
 640 }
 641 
 642 /*
 643  * Function:    ibt_free_qp()
 644  *
 645  * Input:       ibt_qp          Handle for Channel(QP) that needs to be freed.
 646  *
 647  * Output:      NONE.
 648  *
 649  * Returns:     IBT_SUCCESS
 650  *              IBT_QP_STATE_INVALID
 651  *              IBT_QP_HDL_INVALID
 652  *
 653  * Description:
 654  *              Free a previously allocated QP.
 655  */
 656 ibt_status_t
 657 ibt_free_qp(ibt_qp_hdl_t ibt_qp)
 658 {
 659         ibt_status_t            status;
 660         ibtl_hca_t              *ibtl_hca = ibt_qp->ch_qp.qp_hca;
 661 
 662         IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p)", ibt_qp);
 663 
 664         if (ibt_qp->ch_qp.qp_type == IBT_RC_SRV) {
 665                 ibtl_qp_flow_control_enter();
 666                 mutex_enter(&ibtl_free_qp_mutex);
 667                 if (ibt_qp->ch_transport.rc.rc_free_flags &
 668                     IBTL_RC_QP_CONNECTING) {
 669                         IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: ERROR - "
 670                             "Channel establishment is still in PROGRESS.");
 671                         mutex_exit(&ibtl_free_qp_mutex);
 672                         ibtl_qp_flow_control_exit();
 673                         return (IBT_CHAN_STATE_INVALID);
 674                 }
 675                 if (ibt_qp->ch_transport.rc.rc_free_flags &
 676                     IBTL_RC_QP_CONNECTED) {
 677                         if ((ibt_qp->ch_transport.rc.rc_free_flags &
 678                             IBTL_RC_QP_CLOSING) == 0) {
 679                                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: ERROR - "
 680                                     "need to call ibt_close_rc_channel");
 681                                 mutex_exit(&ibtl_free_qp_mutex);
 682                                 ibtl_qp_flow_control_exit();
 683                                 return (IBT_CHAN_STATE_INVALID);
 684                         }
 685                         ibt_qp->ch_transport.rc.rc_free_flags |=
 686                             IBTL_RC_QP_FREED;
 687                         status = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_free_qp)
 688                             (IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp),
 689                             IBC_FREE_QP_ONLY,
 690                             &ibt_qp->ch_transport.rc.rc_qpn_hdl);
 691                         mutex_exit(&ibtl_free_qp_mutex);
 692                         ibtl_qp_flow_control_exit();
 693 
 694                         if (status == IBT_SUCCESS) {
 695                                 mutex_enter(&ibtl_clnt_list_mutex);
 696                                 ibtl_hca->ha_qpn_cnt++;
 697                                 mutex_exit(&ibtl_clnt_list_mutex);
 698                                 atomic_dec_32(&ibtl_hca->ha_qp_cnt);
 699                                 IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p) - "
 700                                     "SUCCESS", ibt_qp);
 701                         } else
 702                                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: "
 703                                     "ibc_free_qp failed: status = %d", status);
 704                         return (status);
 705                 }
 706                 mutex_exit(&ibtl_free_qp_mutex);
 707         } else
 708                 ibtl_qp_flow_control_enter();
 709 
 710         status = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_free_qp)
 711             (IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp),
 712             IBC_FREE_QP_AND_QPN, NULL);
 713         ibtl_qp_flow_control_exit();
 714 
 715         if (status == IBT_SUCCESS) {
 716                 /* effectively, this is kmem_free(ibt_qp); */
 717                 ibtl_free_qp_async_check(&ibt_qp->ch_qp);
 718 
 719                 atomic_dec_32(&ibtl_hca->ha_qp_cnt);
 720                 IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p) - SUCCESS", ibt_qp);
 721         } else {
 722                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: "
 723                     "ibc_free_qp failed with error %d", status);
 724         }
 725 
 726         return (status);
 727 }
 728 
 729 
 730 /* helper function for ibt_query_qp */
 731 static void
 732 ibtl_fillin_sgid(ibt_cep_path_t *pathp, ibtl_hca_devinfo_t *hca_devp)
 733 {
 734         uint8_t port;
 735         uint32_t sgid_ix;
 736         ib_gid_t *sgidp;
 737 
 738         port = pathp->cep_hca_port_num;
 739         sgid_ix = pathp->cep_adds_vect.av_sgid_ix;
 740         if (port == 0 || port > hca_devp->hd_hca_attr->hca_nports ||
 741             sgid_ix >= IBTL_HDIP2SGIDTBLSZ(hca_devp)) {
 742                 pathp->cep_adds_vect.av_sgid.gid_prefix = 0;
 743                 pathp->cep_adds_vect.av_sgid.gid_guid = 0;
 744         } else {
 745                 mutex_enter(&ibtl_clnt_list_mutex);
 746                 sgidp = hca_devp->hd_portinfop[port-1].p_sgid_tbl;
 747                 pathp->cep_adds_vect.av_sgid = sgidp[sgid_ix];
 748                 mutex_exit(&ibtl_clnt_list_mutex);
 749         }
 750 }
 751 
 752 
 753 /*
 754  * Function:    ibt_query_qp
 755  *
 756  * Input:       ibt_qp                  - The IBT QP Handle.
 757  *
 758  * Output:      ibt_qp_query_attrp      - Points to a ibt_qp_query_attr_t
 759  *                                        that on return contains all the
 760  *                                        attributes of the specified qp.
 761  *
 762  * Returns:     IBT_SUCCESS
 763  *              IBT_QP_HDL_INVALID
 764  *
 765  * Description:
 766  *              Query QP attributes
 767  *
 768  */
 769 ibt_status_t
 770 ibt_query_qp(ibt_qp_hdl_t ibt_qp, ibt_qp_query_attr_t *qp_query_attrp)
 771 {
 772         ibt_status_t            retval;
 773         ibtl_hca_devinfo_t      *hca_devp;
 774         ibt_qp_info_t           *qp_infop;
 775 
 776         IBTF_DPRINTF_L3(ibtf_qp, "ibt_query_qp(%p, %p)",
 777             ibt_qp, qp_query_attrp);
 778 
 779         ibtl_qp_flow_control_enter();
 780         retval = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_query_qp(
 781             IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), qp_query_attrp));
 782         ibtl_qp_flow_control_exit();
 783         if (retval == IBT_SUCCESS) {
 784                 ibt_qp->ch_current_state = qp_query_attrp->qp_info.qp_state;
 785 
 786                 /* need to fill in sgid from port and sgid_ix for RC and UC */
 787                 hca_devp = ibt_qp->ch_qp.qp_hca->ha_hca_devp;
 788                 qp_infop = &qp_query_attrp->qp_info;
 789 
 790                 switch (qp_infop->qp_trans) {
 791                 case IBT_RC_SRV:
 792                         ibtl_fillin_sgid(&qp_infop->qp_transport.rc.rc_path,
 793                             hca_devp);
 794                         ibtl_fillin_sgid(&qp_infop->qp_transport.rc.rc_alt_path,
 795                             hca_devp);
 796                         break;
 797                 case IBT_UC_SRV:
 798                         ibtl_fillin_sgid(&qp_infop->qp_transport.uc.uc_path,
 799                             hca_devp);
 800                         ibtl_fillin_sgid(&qp_infop->qp_transport.uc.uc_alt_path,
 801                             hca_devp);
 802                         break;
 803                 }
 804         } else {
 805                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_query_qp: "
 806                     "failed on chan %p: %d", ibt_qp, retval);
 807         }
 808 
 809         return (retval);
 810 }
 811 
 812 
 813 /*
 814  * Function:
 815  *      ibt_modify_qp
 816  * Input:
 817  *      ibt_qp          The IBT QP Handle.
 818  *      flags           Specifies which attributes in ibt_qp_mod_attr_t
 819  *                      are to be modified.
 820  *      qp_attrp        Points to an ibt_qp_mod_attr_t struct that contains all
 821  *                      the attributes of the specified QP that a client is
 822  *                      allowed to modify after a QP has been allocated
 823  * Output:
 824  *      actual_sz       Returned actual queue sizes.
 825  * Returns:
 826  *      IBT_SUCCESS
 827  * Description:
 828  *      Modify the attributes of an existing QP.
 829  */
 830 ibt_status_t
 831 ibt_modify_qp(ibt_qp_hdl_t ibt_qp, ibt_cep_modify_flags_t flags,
 832     ibt_qp_info_t *modify_attrp, ibt_queue_sizes_t *actual_sz)
 833 {
 834         ibt_status_t            retval;
 835 
 836         IBTF_DPRINTF_L3(ibtf_qp, "ibt_modify_qp(%p, %d, %p, %p)",
 837             ibt_qp, flags, modify_attrp, actual_sz);
 838 
 839         ibtl_qp_flow_control_enter();
 840         retval = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_modify_qp)(
 841             IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), flags,
 842             modify_attrp, actual_sz);
 843         ibtl_qp_flow_control_exit();
 844         if (retval == IBT_SUCCESS) {
 845                 ibt_qp->ch_current_state = modify_attrp->qp_state;
 846                 if (ibt_qp->ch_qp.qp_type == IBT_UD_SRV) {
 847                         if (flags & (IBT_CEP_SET_PORT | IBT_CEP_SET_RESET_INIT))
 848                                 ibt_qp->ch_transport.ud.ud_port_num =
 849                                     modify_attrp->qp_transport.ud.ud_port;
 850                         if (flags & (IBT_CEP_SET_QKEY | IBT_CEP_SET_RESET_INIT))
 851                                 ibt_qp->ch_transport.ud.ud_qkey =
 852                                     modify_attrp->qp_transport.ud.ud_qkey;
 853                 }
 854         } else {
 855                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_qp: failed on chan %p: %d",
 856                     ibt_qp, retval);
 857 
 858                 if (retval == IBT_CHAN_STATE_INVALID) {
 859                         /* That means our cache had invalid QP state value. */
 860                         ibt_qp_query_attr_t     qp_attr;
 861 
 862                         /* Query the channel (QP) */
 863                         if (ibt_query_qp(ibt_qp, &qp_attr) == IBT_SUCCESS)
 864                                 ibt_qp->ch_current_state =
 865                                     qp_attr.qp_info.qp_state;
 866                 }
 867         }
 868         return (retval);
 869 }
 870 
 871 
 872 /*
 873  * Function:
 874  *      ibt_migrate_path
 875  * Input:
 876  *      rc_chan         A previously allocated RC channel handle.
 877  * Output:
 878  *      none.
 879  * Returns:
 880  *      IBT_SUCCESS on Success else appropriate error.
 881  * Description:
 882  *      Force the CI to use the alternate path. The alternate path becomes
 883  *      the primary path. A new alternate path should be loaded and enabled.
 884  *      Assumes that the given channel is in RTS/SQD state
 885  */
 886 ibt_status_t
 887 ibt_migrate_path(ibt_channel_hdl_t rc_chan)
 888 {
 889         ibt_status_t            retval;
 890         ibt_qp_info_t           qp_info;
 891         ibt_qp_query_attr_t     qp_attr;
 892         ibt_cep_modify_flags_t  cep_flags;
 893         int                     retries = 1;
 894 
 895         IBTF_DPRINTF_L3(ibtf_qp, "ibt_migrate_path: channel %p", rc_chan);
 896 
 897         if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
 898                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path: "
 899                     "Invalid Channel type: Applicable only to RC Channel");
 900                 return (IBT_CHAN_SRV_TYPE_INVALID);
 901         }
 902 
 903         if (rc_chan->ch_current_state != IBT_STATE_RTS &&
 904             rc_chan->ch_current_state != IBT_STATE_SQD) {
 905                 if (ibt_query_qp(rc_chan, &qp_attr) == IBT_SUCCESS) {
 906                         /* ch_current_state is fixed by ibt_query_qp */
 907                         if (rc_chan->ch_current_state != IBT_STATE_RTS &&
 908                             rc_chan->ch_current_state != IBT_STATE_SQD)
 909                                 return (IBT_CHAN_STATE_INVALID);
 910                         retries = 0;
 911                 } else /* query_qp should never really fail */
 912                         return (IBT_CHAN_STATE_INVALID);
 913         }
 914 
 915 retry:
 916         /* Call modify_qp */
 917         cep_flags = IBT_CEP_SET_MIG | IBT_CEP_SET_STATE;
 918         qp_info.qp_state = rc_chan->ch_current_state;
 919         qp_info.qp_current_state = rc_chan->ch_current_state;
 920         qp_info.qp_trans = IBT_RC_SRV;
 921         qp_info.qp_transport.rc.rc_mig_state = IBT_STATE_MIGRATED;
 922         retval = ibt_modify_qp(rc_chan, cep_flags, &qp_info, NULL);
 923 
 924         if (retval != IBT_SUCCESS) {
 925                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path:"
 926                     " ibt_modify_qp() returned = %d", retval);
 927                 if (rc_chan->ch_current_state != qp_info.qp_state &&
 928                     --retries >= 0) {
 929                         /*
 930                          * That means our cached 'state' was invalid.
 931                          * We know ibt_modify_qp() fixed it up, so it
 932                          * might be worth retrying.
 933                          */
 934                         if (rc_chan->ch_current_state != IBT_STATE_RTS &&
 935                             rc_chan->ch_current_state != IBT_STATE_SQD)
 936                                 return (IBT_CHAN_STATE_INVALID);
 937                         IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path:"
 938                             " retrying after 'state' fixed");
 939                         goto retry;
 940                 }
 941         }
 942         return (retval);
 943 }
 944 
 945 
 946 /*
 947  * Function:
 948  *      ibt_set_qp_private
 949  * Input:
 950  *      ibt_qp          The ibt_qp_hdl_t of the allocated QP.
 951  *      clnt_private    The client private data.
 952  * Output:
 953  *      none.
 954  * Returns:
 955  *      none.
 956  * Description:
 957  *      Set the client private data.
 958  */
 959 void
 960 ibt_set_qp_private(ibt_qp_hdl_t ibt_qp, void *clnt_private)
 961 {
 962         ibt_qp->ch_clnt_private = clnt_private;
 963 }
 964 
 965 
 966 /*
 967  * Function:
 968  *      ibt_get_qp_private
 969  * Input:
 970  *      ibt_qp          The ibt_qp_hdl_t of the allocated QP.
 971  * Output:
 972  *      none.
 973  * Returns:
 974  *      The client private data.
 975  * Description:
 976  *      Get the client private data.
 977  */
 978 void *
 979 ibt_get_qp_private(ibt_qp_hdl_t ibt_qp)
 980 {
 981         return (ibt_qp->ch_clnt_private);
 982 }
 983 
 984 
 985 /*
 986  * Function:
 987  *      ibt_qp_to_hca_guid
 988  * Input:
 989  *      ibt_qp          The ibt_qp_hdl_t of the allocated QP.
 990  * Output:
 991  *      none.
 992  * Returns:
 993  *      hca_guid        Returned HCA GUID on which the specified QP is
 994  *                      allocated. Valid if it is non-NULL on return.
 995  * Description:
 996  *      A helper function to retrieve HCA GUID for the specified QP.
 997  */
 998 ib_guid_t
 999 ibt_qp_to_hca_guid(ibt_qp_hdl_t ibt_qp)
1000 {
1001         IBTF_DPRINTF_L3(ibtf_qp, "ibt_qp_to_hca_guid(%p)", ibt_qp);
1002 
1003         return (IBTL_HCA2HCAGUID(IBTL_CHAN2HCA(ibt_qp)));
1004 }
1005 
1006 
1007 /*
1008  * Function:
1009  *      ibt_recover_ud_qp
1010  * Input:
1011  *      ibt_qp          An QP Handle which is in SQError state.
1012  * Output:
1013  *      none.
1014  * Returns:
1015  *      IBT_SUCCESS
1016  *      IBT_QP_SRV_TYPE_INVALID
1017  *      IBT_QP_STATE_INVALID.
1018  * Description:
1019  *      Recover an UD QP which has transitioned to SQ Error state. The
1020  *      ibt_recover_ud_qp() transitions the QP from SQ Error state to
1021  *      Ready-To-Send QP state.
1022  *
1023  *      If a work request posted to a UD QP's send queue completes with an
1024  *      error (see ibt_wc_status_t), the QP gets transitioned to SQ Error state.
1025  *      In order to reuse this QP, ibt_recover_ud_qp() can be used to recover
1026  *      the QP to a usable (Ready-to-Send) state.
1027  */
1028 ibt_status_t
1029 ibt_recover_ud_qp(ibt_qp_hdl_t ibt_qp)
1030 {
1031         IBTF_DPRINTF_L3(ibtf_qp, "ibt_recover_ud_qp(%p)", ibt_qp);
1032 
1033         return (ibt_recover_ud_channel(IBTL_QP2CHAN(ibt_qp)));
1034 }
1035 
1036 
1037 /*
1038  * Function:
1039  *      ibt_recycle_ud
1040  * Input:
1041  *      ud_chan         The IBT UD QP Handle.
1042  *      various attributes
1043  *
1044  * Output:
1045  *      none
1046  * Returns:
1047  *      IBT_SUCCESS
1048  *      IBT_CHAN_SRV_TYPE_INVALID
1049  *      IBT_CHAN_STATE_INVALID
1050  *
1051  * Description:
1052  *      Revert the UD QP back to a usable state.
1053  */
1054 ibt_status_t
1055 ibt_recycle_ud(ibt_channel_hdl_t ud_chan, uint8_t hca_port_num,
1056     uint16_t pkey_ix, ib_qkey_t qkey)
1057 {
1058         ibt_qp_query_attr_t     qp_attr;
1059         ibt_status_t            retval;
1060 
1061         IBTF_DPRINTF_L3(ibtf_qp, "ibt_recycle_ud(%p, %d, %x, %x): ",
1062             ud_chan, hca_port_num, pkey_ix, qkey);
1063 
1064         if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) {
1065                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
1066                     "chan %p is not a UD channel", ud_chan);
1067                 return (IBT_CHAN_SRV_TYPE_INVALID);
1068         }
1069 
1070         retval = ibt_query_qp(ud_chan, &qp_attr);
1071         if (retval != IBT_SUCCESS) {
1072                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
1073                     "ibt_query_qp failed on chan %p: %d", ud_chan, retval);
1074                 return (retval);
1075         }
1076         if (qp_attr.qp_info.qp_state != IBT_STATE_ERROR) {
1077                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
1078                     "chan %p is in state %d (not in ERROR state)",
1079                     ud_chan, qp_attr.qp_info.qp_state);
1080                 ud_chan->ch_current_state = qp_attr.qp_info.qp_state;
1081                 return (IBT_CHAN_STATE_INVALID);
1082         }
1083 
1084         /* transition the QP from ERROR to RESET */
1085         qp_attr.qp_info.qp_state = IBT_STATE_RESET;
1086         qp_attr.qp_info.qp_trans = ud_chan->ch_qp.qp_type;
1087         retval = ibt_modify_qp(ud_chan, IBT_CEP_SET_STATE, &qp_attr.qp_info,
1088             NULL);
1089         if (retval != IBT_SUCCESS) {
1090                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
1091                     "ibt_modify_qp(ERROR=>RESET) failed on chan %p: %d",
1092                     ud_chan, retval);
1093                 return (retval);
1094         }
1095         ud_chan->ch_current_state = IBT_STATE_RESET;
1096 
1097         /* transition the QP back to RTS */
1098         qp_attr.qp_info.qp_transport.ud.ud_port = hca_port_num;
1099         qp_attr.qp_info.qp_transport.ud.ud_qkey = qkey;
1100         qp_attr.qp_info.qp_transport.ud.ud_pkey_ix = pkey_ix;
1101         retval = ibt_initialize_qp(ud_chan, &qp_attr.qp_info);
1102         if (retval != IBT_SUCCESS) {
1103                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
1104                     "ibt_initialize_qp failed on chan %p: %d", ud_chan, retval);
1105                 /* the man page says the QP should be left in ERROR state */
1106                 (void) ibt_flush_qp(ud_chan);
1107         }
1108         return (retval);
1109 }
1110 
1111 /*
1112  * Function:
1113  *      ibt_pause_sendq
1114  * Input:
1115  *      chan            The IBT QP Handle.
1116  *      modify_flags    IBT_CEP_SET_NOTHING or IBT_CEP_SET_SQD_EVENT
1117  *
1118  * Output:
1119  *      none.
1120  * Returns:
1121  *      IBT_SUCCESS
1122  *      IBT_CHAN_HDL_INVALID
1123  *      IBT_CHAN_STATE_INVALID
1124  *      IBT_INVALID_PARAM
1125  *
1126  * Description:
1127  *      Place the send queue of the specified channel into the send queue
1128  *      drained (SQD) state.
1129  *
1130  */
1131 ibt_status_t
1132 ibt_pause_sendq(ibt_channel_hdl_t chan, ibt_cep_modify_flags_t modify_flags)
1133 {
1134         ibt_qp_info_t           modify_attr;
1135         ibt_status_t            retval;
1136 
1137         IBTF_DPRINTF_L3(ibtf_qp, "ibt_pause_sendq(%p, %x)", chan, modify_flags);
1138 
1139         modify_flags &= IBT_CEP_SET_SQD_EVENT;      /* ignore other bits */
1140         modify_flags |= IBT_CEP_SET_STATE;
1141 
1142         bzero(&modify_attr, sizeof (ibt_qp_info_t));
1143         /*
1144          * Set the QP state to SQD.
1145          */
1146         modify_attr.qp_state = IBT_STATE_SQD;
1147         modify_attr.qp_trans = chan->ch_qp.qp_type;
1148 
1149         retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
1150 
1151         if (retval != IBT_SUCCESS) {
1152                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_pause_sendq: "
1153                     "failed on chan %p: %d", chan, retval);
1154         }
1155         return (retval);
1156 }
1157 
1158 
1159 /*
1160  * Function:
1161  *      ibt_unpause_sendq
1162  * Input:
1163  *      chan    The IBT Channel Handle.
1164  * Output:
1165  *      none.
1166  * Returns:
1167  *      IBT_SUCCESS
1168  *      IBT_CHAN_HDL_INVALID
1169  *      IBT_CHAN_STATE_INVALID
1170  * Description:
1171  *      Un-pauses the previously paused channel. This call will transition the
1172  *      QP from SQD to RTS state.
1173  */
1174 ibt_status_t
1175 ibt_unpause_sendq(ibt_channel_hdl_t chan)
1176 {
1177         ibt_qp_info_t           modify_attr;
1178         ibt_status_t            retval;
1179 
1180         IBTF_DPRINTF_L3(ibtf_qp, "ibt_unpause_sendq(%p)", chan);
1181 
1182         bzero(&modify_attr, sizeof (ibt_qp_info_t));
1183 
1184         /*
1185          * Set the QP state to RTS.
1186          */
1187         modify_attr.qp_current_state = IBT_STATE_SQD;
1188         modify_attr.qp_state = IBT_STATE_RTS;
1189         modify_attr.qp_trans = chan->ch_qp.qp_type;
1190 
1191         retval = ibt_modify_qp(chan, IBT_CEP_SET_STATE, &modify_attr, NULL);
1192         if (retval != IBT_SUCCESS) {
1193                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_unpause_sendq: "
1194                     "failed on chan %p: %d", chan, retval);
1195         }
1196         return (retval);
1197 }
1198 
1199 
1200 /*
1201  * Function:
1202  *      ibt_resize_queues
1203  * Input:
1204  *      chan            A previously allocated channel handle.
1205  *      flags           QP Flags
1206  *                              IBT_SEND_Q
1207  *                              IBT_RECV_Q
1208  *      request_sz      Requested new sizes.
1209  * Output:
1210  *      actual_sz       Returned actual sizes.
1211  * Returns:
1212  *      IBT_SUCCESS
1213  * Description:
1214  *      Resize the SendQ/RecvQ sizes of a channel. Can only be called on
1215  *      a previously opened channel.
1216  */
1217 ibt_status_t
1218 ibt_resize_queues(ibt_channel_hdl_t chan, ibt_qflags_t flags,
1219     ibt_queue_sizes_t *request_sz, ibt_queue_sizes_t *actual_sz)
1220 {
1221         ibt_cep_modify_flags_t  modify_flags = IBT_CEP_SET_STATE;
1222         ibt_qp_info_t           modify_attr;
1223         ibt_status_t            retval;
1224 
1225         IBTF_DPRINTF_L3(ibtf_qp, "ibt_resize_queues(%p, 0x%X, %p, %p)",
1226             chan, flags, request_sz, actual_sz);
1227 
1228         if ((flags & (IBT_SEND_Q | IBT_RECV_Q)) == 0)  {
1229                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_resize_queues: "
1230                     "Flags <0x%X> not set", flags);
1231                 return (IBT_INVALID_PARAM);
1232         }
1233 
1234         bzero(&modify_attr, sizeof (ibt_qp_info_t));
1235 
1236         modify_attr.qp_current_state = chan->ch_current_state;
1237         modify_attr.qp_trans = chan->ch_qp.qp_type;
1238         modify_attr.qp_state = chan->ch_current_state;
1239 
1240         if (flags & IBT_SEND_Q) {
1241                 modify_attr.qp_sq_sz = request_sz->qs_sq;
1242                 modify_flags |= IBT_CEP_SET_SQ_SIZE;
1243         }
1244 
1245         if (flags & IBT_RECV_Q) {
1246                 modify_attr.qp_rq_sz = request_sz->qs_rq;
1247                 modify_flags |= IBT_CEP_SET_RQ_SIZE;
1248         }
1249 
1250         retval = ibt_modify_qp(chan, modify_flags, &modify_attr, actual_sz);
1251         if (retval != IBT_SUCCESS) {
1252                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_resize_queues: "
1253                     "failed on QP %p: %d", chan, retval);
1254         }
1255 
1256         return (retval);
1257 }
1258 
1259 
1260 /*
1261  * Function:
1262  *      ibt_query_queues
1263  * Input:
1264  *      chan            A previously allocated channel handle.
1265  * Output:
1266  *      actual_sz       Returned actual sizes.
1267  * Returns:
1268  *      IBT_SUCCESS
1269  * Description:
1270  *      Query the SendQ/RecvQ sizes of a channel.
1271  */
1272 ibt_status_t
1273 ibt_query_queues(ibt_channel_hdl_t chan, ibt_queue_sizes_t *actual_sz)
1274 {
1275         ibt_status_t            retval;
1276         ibt_qp_query_attr_t     qp_query_attr;
1277 
1278         IBTF_DPRINTF_L3(ibtf_qp, "ibt_query_queues(%p)", chan);
1279 
1280         /* Perform Query QP and retrieve QP sizes. */
1281         retval = ibt_query_qp(chan, &qp_query_attr);
1282         if (retval != IBT_SUCCESS) {
1283                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_query_queues: "
1284                     "ibt_query_qp failed: qp %p: %d", chan, retval);
1285                 return (retval);
1286         }
1287 
1288         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(actual_sz->qs_rq,
1289             actual_sz->qs_sq))
1290         actual_sz->qs_sq = qp_query_attr.qp_info.qp_sq_sz;
1291         actual_sz->qs_rq = qp_query_attr.qp_info.qp_rq_sz;
1292         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(actual_sz->qs_rq,
1293             actual_sz->qs_sq))
1294         chan->ch_current_state = qp_query_attr.qp_info.qp_state;
1295 
1296         return (retval);
1297 }
1298 
1299 
1300 /*
1301  * Function:
1302  *      ibt_modify_rdma
1303  * Input:
1304  *      rc_chan         A previously allocated channel handle.
1305  *
1306  *      modify_flags    Bitwise "or" of any of the following:
1307  *                      IBT_CEP_SET_RDMA_R      Enable/Disable RDMA RD
1308  *                      IBT_CEP_SET_RDMA_W      Enable/Disable RDMA WR
1309  *                      IBT_CEP_SET_ATOMIC      Enable/Disable Atomics
1310  *
1311  *      flags           Channel End Point (CEP) Disable Flags (0 => enable).
1312  *                      IBT_CEP_NO_RDMA_RD      Disable incoming RDMA RD's
1313  *                      IBT_CEP_NO_RDMA_WR      Disable incoming RDMA WR's
1314  *                      IBT_CEP_NO_ATOMIC       Disable incoming Atomics.
1315  * Output:
1316  *      none.
1317  * Returns:
1318  *      IBT_SUCCESS
1319  *      IBT_QP_SRV_TYPE_INVALID
1320  *      IBT_CHAN_HDL_INVALID
1321  *      IBT_CHAN_ATOMICS_NOT_SUPPORTED
1322  *      IBT_CHAN_STATE_INVALID
1323  * Description:
1324  *      Enable/disable RDMA operations. To enable an operation clear the
1325  *      "disable" flag. Can call this function when the channel is in
1326  *      INIT, RTS or SQD states. If called in any other state
1327  *      IBT_CHAN_STATE_INVALID is returned. When the operation completes the
1328  *      channel state is left unchanged.
1329  */
1330 ibt_status_t
1331 ibt_modify_rdma(ibt_channel_hdl_t rc_chan,
1332     ibt_cep_modify_flags_t modify_flags, ibt_cep_flags_t flags)
1333 {
1334         ibt_status_t            retval;
1335         ibt_qp_info_t           modify_attr;
1336 
1337         IBTF_DPRINTF_L3(ibtf_qp, "ibt_modify_rdma(%p, 0x%x, 0x%x)",
1338             rc_chan, modify_flags, flags);
1339 
1340         if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
1341                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: "
1342                     "Invalid Channel type: 0x%X, Applicable only to RC Channel",
1343                     rc_chan->ch_qp.qp_type);
1344                 return (IBT_QP_SRV_TYPE_INVALID);
1345         }
1346 
1347         bzero(&modify_attr, sizeof (ibt_qp_info_t));
1348 
1349         /*
1350          * Can only call this function when the channel in INIT, RTS or SQD
1351          * states.
1352          */
1353         if ((rc_chan->ch_current_state != IBT_STATE_INIT) &&
1354             (rc_chan->ch_current_state != IBT_STATE_RTS) &&
1355             (rc_chan->ch_current_state != IBT_STATE_SQD)) {
1356                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: Invalid Channel "
1357                     "state: 0x%X", rc_chan->ch_current_state);
1358                 return (IBT_CHAN_STATE_INVALID);
1359         }
1360 
1361         modify_attr.qp_state = modify_attr.qp_current_state =
1362             rc_chan->ch_current_state;
1363         modify_attr.qp_trans = rc_chan->ch_qp.qp_type;
1364         modify_attr.qp_flags = flags;
1365 
1366         modify_flags &= (IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
1367             IBT_CEP_SET_ATOMIC);
1368         modify_flags |= IBT_CEP_SET_STATE;
1369 
1370         retval = ibt_modify_qp(rc_chan, modify_flags, &modify_attr, NULL);
1371         if (retval != IBT_SUCCESS) {
1372                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: "
1373                     "failed on chan %p: %d", rc_chan, retval);
1374         }
1375         return (retval);
1376 }
1377 
1378 
1379 /*
1380  * Function:
1381  *      ibt_set_rdma_resource
1382  * Input:
1383  *      chan            A previously allocated RC channel handle.
1384  *      modify_flags    Bitwise "or" of any of the following:
1385  *                      IBT_CEP_SET_RDMARA_OUT  Initiator depth (rdma_ra_out)
1386  *                      IBT_CEP_SET_RDMARA_IN   Responder Resources
1387  *                                              (rdma_ra_in)
1388  *      rdma_ra_out     Outgoing RDMA Reads/Atomics
1389  *      rdma_ra_in      Incoming RDMA Reads/Atomics
1390  * Output:
1391  *      none.
1392  * Returns:
1393  *      IBT_SUCCESS
1394  * Description:
1395  *      Change the number of resources to be used for incoming and outgoing
1396  *      RDMA reads & Atomics. Can only be called on a previously opened
1397  *      RC channel.  Can only be called on a paused channel, and this will
1398  *      un-pause that channel.
1399  */
1400 ibt_status_t
1401 ibt_set_rdma_resource(ibt_channel_hdl_t chan,
1402     ibt_cep_modify_flags_t modify_flags, uint8_t rdma_ra_out,
1403     uint8_t resp_rdma_ra_out)
1404 {
1405         ibt_qp_info_t           modify_attr;
1406         ibt_status_t            retval;
1407 
1408         IBTF_DPRINTF_L3(ibtf_qp, "ibt_set_rdma_resource(%p, 0x%x, %d, %d)",
1409             chan, modify_flags, rdma_ra_out, resp_rdma_ra_out);
1410 
1411         if (chan->ch_qp.qp_type != IBT_RC_SRV) {
1412                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_set_rdma_resource: "
1413                     "Invalid Channel type: 0x%X, Applicable only to RC Channel",
1414                     chan->ch_qp.qp_type);
1415                 return (IBT_CHAN_SRV_TYPE_INVALID);
1416         }
1417 
1418         bzero(&modify_attr, sizeof (ibt_qp_info_t));
1419 
1420         modify_attr.qp_trans = chan->ch_qp.qp_type;
1421         modify_attr.qp_state = IBT_STATE_SQD;
1422 
1423         modify_attr.qp_transport.rc.rc_rdma_ra_out = rdma_ra_out;
1424         modify_attr.qp_transport.rc.rc_rdma_ra_in = resp_rdma_ra_out;
1425         modify_flags &= (IBT_CEP_SET_RDMARA_OUT | IBT_CEP_SET_RDMARA_IN);
1426         modify_flags |= IBT_CEP_SET_STATE;
1427 
1428         retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
1429         if (retval != IBT_SUCCESS) {
1430                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_set_rdma_resource: "
1431                     "failed on chan %p: %d", chan, retval);
1432         }
1433         return (retval);
1434 }
1435 
1436 
1437 /*
1438  * Function:
1439  *      ibt_change_port
1440  * Input:
1441  *      rc_chan         A previously allocated RC channel handle.
1442  *      port_num        New HCA port.
1443  * Output:
1444  *      none.
1445  * Returns:
1446  *      IBT_SUCCESS
1447  * Description:
1448  *      Change the primary physical port of a channel. (This is done only if
1449  *      HCA supports this capability).
1450  */
1451 ibt_status_t
1452 ibt_change_port(ibt_channel_hdl_t chan, uint8_t port_num)
1453 {
1454         ibt_cep_modify_flags_t  modify_flags;
1455         ibt_qp_info_t           modify_attr;
1456         ibt_status_t            retval;
1457 
1458         IBTF_DPRINTF_L3(ibtf_qp, "ibt_change_port(%p, %d)", chan, port_num);
1459 
1460         if (chan->ch_qp.qp_type != IBT_RC_SRV) {
1461                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_change_port: "
1462                     "Invalid Channel type: 0x%X, Applicable only to RC Channel",
1463                     chan->ch_qp.qp_type);
1464                 return (IBT_CHAN_SRV_TYPE_INVALID);
1465         }
1466         bzero(&modify_attr, sizeof (ibt_qp_info_t));
1467 
1468         modify_attr.qp_state = IBT_STATE_SQD;
1469         modify_attr.qp_trans = chan->ch_qp.qp_type;
1470         modify_attr.qp_transport.rc.rc_path.cep_hca_port_num = port_num;
1471 
1472         modify_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT;
1473 
1474         retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
1475         if (retval != IBT_SUCCESS) {
1476                 IBTF_DPRINTF_L2(ibtf_qp, "ibt_change_port: "
1477                     "failed on chan %p: %d", chan, retval);
1478         }
1479         return (retval);
1480 }
1481 
1482 
1483 void
1484 ibtl_init_cep_states(void)
1485 {
1486         int     index;
1487         int     ibt_nstate_inits;
1488 
1489         IBTF_DPRINTF_L3(ibtf_qp, "ibtl_init_cep_states()");
1490 
1491         ibt_nstate_inits = sizeof (ibt_cep_next_state_inits) /
1492             sizeof (ibt_cep_next_state_inits[0]);
1493 
1494         /*
1495          * Initialize CEP next state table, using an indirect lookup table so
1496          * that this code isn't dependent on the ibt_cep_state_t enum values.
1497          */
1498         for (index = 0; index < ibt_nstate_inits; index++) {
1499                 ibt_cep_state_t state;
1500 
1501                 state = ibt_cep_next_state_inits[index].current_state;
1502 
1503                 ibt_cep_next_state[state].next_state =
1504                     ibt_cep_next_state_inits[index].next_state;
1505 
1506                 ibt_cep_next_state[state].modify_flags =
1507                     ibt_cep_next_state_inits[index].modify_flags;
1508         }
1509 }