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/mgt/ibcm/ibcm_impl.h>
  26 #include <sys/callb.h>
  27 
  28 /*
  29  * ibcm_sm.c
  30  *      These routines implement the CM state machine (both ACTIVE and PASSIVE)
  31  *
  32  * Points to Note :
  33  *
  34  * o  CM uses one ibcm_hca_info_t entry per HCA  to store all the
  35  *    connection state data belonging to that HCA in the AVL trees, etc.,
  36  *
  37  * o  There is one state structure per RC, referenced from three AVL trees
  38  *    ie. the HCA active AVL tree, and the HCA passive AVL tree and HCA
  39  *    passive comid tree
  40  *
  41  * o  SIDR state structures are stored in a linked list
  42  *
  43  * o  The term statep generally refers to RC, until explicitly mentioned
  44  *    in the notes below
  45  *
  46  * o  Any thread that may access statep increments the ref_cnt. This ensures
  47  *    that statep is not deleted when it is still being accessed and modified
  48  *    by other threads
  49  *
  50  * o  Any thread that may want to search the AVL tree(s) holds the hca state
  51  *    table reader lock. If it shall insert/delete a new state structure, then
  52  *    the lock held is writer lock.
  53  *
  54  * o  Incrementing and Decrementing the ref_cnt can happen only after acquiring
  55  *    statep mutex
  56  *
  57  * o  Deleting a statep can happen only by acquiring the hca state writer lock
  58  *    and statep mutex and if ref_cnt is zero.
  59  *
  60  * o  Statep mutexes are used to decrease the hca state table lock holding
  61  *    times. thus increasing more number of threads that can access hca
  62  *    global data structures
  63  *
  64  * o  Statep mutexes cannot be hold for long time. They are primarily used to
  65  *    check the state of statep, change it and exit the lock. Other threads
  66  *    checking this statep find statep's new state, and may exit without
  67  *    further processing (as the statep->state has changed).
  68  *
  69  * o  Statep mutex must be held while setting and unsetting the timer id
  70  *    values and during untimeout
  71  *
  72  * Re-stating, the overall purpose of these various locks are:
  73  *   - Minimize the time state table locks are held
  74  *   - Writer locks are held only while inserting/deleting into trees,
  75  *      so multiple readers can traverse data structures in parallel
  76  *   - Minimize the time statep mutex held, so other threads entering the same
  77  *      statep mutex are not held for long
  78  *
  79  * The CM state machine logic ensures that the statep is valid and exists
  80  * when timeout callback (ibcm_timeout_cb) is called. This is ensured by
  81  * cancelling timeouts on state changes, where appropriate
  82  *
  83  *
  84  * The timeout processing is handled in the context in which the
  85  * timeout callback is invoked.
  86  *
  87  * The CM STATE MACHINE logic flow:
  88  *
  89  * On an incoming MAD:-
  90  *
  91  * IBMF -> ibcm_process_incoming_mad
  92  *      Verify and branch to one of the below connection state routines.
  93  *      The callback arg from ibmf has the pointer to ibcm_hca_info_t
  94  *
  95  * 1. INCOMING REQ MAD
  96  *
  97  *      Acquire hca state table WRITER lock
  98  *      Do lookup in passive AVL tree by remote qpn and remote hca guid
  99  *
 100  *      If (new lookup)
 101  *
 102  *        create new statep, initialize key fields
 103  *        obtain new local com id, insert into hca state AVL tree
 104  *        release hca state table WRITER lock
 105  *
 106  *        Initialize remaining fields
 107  *        If invalid service id,
 108  *              send a REJ reply,
 109  *              decr ref_cnt holding state mutex
 110  *        If existing peer conn, check guids, and break the tie
 111  *        Call the cep state transition function
 112  *        Send an RTU/REJ reply
 113  *        Check and handle for any incoming REJ's during REQ RCVD state
 114  *
 115  *    else if (existing lookup)
 116  *
 117  *        increment refcnt holding state mutex
 118  *        release hca state table WRITER lock
 119  *
 120  *        re-acquire the statep mutex
 121  *        if (statep->state is REP SENT/REJ SENT/ MRA SENT)
 122  *              resend the mad
 123  *        else if established
 124  *              handle the stale detection
 125  *        else
 126  *              drop the mad (no processing required)
 127  *        decr statep->ref_cnt, release state mutex
 128  *
 129  *
 130  * 2. INCOMING REP MAD
 131  *
 132  *    Acquire hca state READER lock
 133  *    Do lookup in hca state tree by local com id
 134  *    Release hca state table READER lock
 135  *
 136  *    if lookup does not exist
 137  *       return
 138  *
 139  *    if look up exists
 140  *       incr statep->ref_cnt holding state mutex
 141  *
 142  *    acquire the statep lock
 143  *    if (state == ESTABLISHED or REJ SENt or MRA REP SENT)
 144  *        resend the MAD
 145  *        release state mutex, cancel req sent timer
 146  *        decrement ref_cnt holding the statep lock
 147  *        return
 148  *
 149  *    if (state == REQ_SENT or REP_WAIT)
 150  *        first, change state to REP_RCVD
 151  *        release statep lock
 152  *        cancel timers
 153  *        lookup in the passive tree by remote qpn and remote hca guid
 154  *        if entry already exists
 155  *               handle the stale detection
 156  *        else
 157  *              add to the passive tree
 158  *
 159  *        Initialize fields of statep
 160  *        Call the qp state transition function
 161  *        Post RTU/REJ reply
 162  *        Acquire the state mutex
 163  *        decrement the ref cnt
 164  *        release the statep lock
 165  *
 166  * 3. INCOMING MRA
 167  *
 168  *      Acquire hca state table READER lock
 169  *      Do lookup in active hca state tree by local com id
 170  *      Release hca state table READER lock
 171  *
 172  *      If lookup does not exist
 173  *              return
 174  *
 175  *      if look up exists
 176  *               incr statep->ref_cnt holding state mutex
 177  *
 178  *      acquire state mutex
 179  *      if (state is REQ_SENT or REP_SENT)
 180  *        change state to REP WAIT or MRA REP RCVD
 181  *        release state mutex
 182  *        cancel the current timer
 183  *
 184  *        reacquire state mutex
 185  *        if (state is REP_WAIT or MRA_REP_RCVD)
 186  *              set new timer, using service timeout for the first timeout
 187  *    decr ref cnt, release state mutex
 188  *
 189  * 4. INCOMING RTU
 190  *
 191  *      Acquire hca state table READER lock
 192  *      Do lookup in active hca state tree by local com id
 193  *      Release hca state table READER lock
 194  *
 195  *      If lookup does not exist
 196  *              return
 197  *
 198  *       if look up exists
 199  *               incr statep->ref_cnt holding state mutex
 200  *
 201  *      acquire statep mutex
 202  *      if (state == REP_SENT or MRA REP RCVD))
 203  *        change state to ESTABLISHED
 204  *        release statep mutex
 205  *        cancel timer
 206  *
 207  *        Change QP state
 208  *
 209  *        acquire the statep mutex
 210  *      decrement the ref count
 211  *      release statep mutex
 212  *
 213  * 5. INCOMING REJ
 214  *
 215  *      Acquire hca state table READER lock
 216  *      Do lookup in active hca state tree by local com id
 217  *      Release hca state table READER lock
 218  *
 219  *      If lookup does not exist
 220  *              return
 221  *
 222  *      if look up exists
 223  *               incr statep->ref_cnt holding state mutex
 224  *
 225  *      if (state == REQ RCVD or REP RCVD MRA_SENT or MRA_REP_SNET)
 226  *        set statep->delete = true
 227  *        decrement the ref_cnt
 228  *        release statep mutex;
 229  *
 230  *    else if (state == REQ_SENT or REP SENT or MRA REP Rcvd)
 231  *       state = IBCM_STATE_DELETE
 232  *       Cancel running timers
 233  *       decrement the ref_cnt
 234  *       release state mutex
 235  *       Call the client QP handler
 236  *       delete the state data
 237  *
 238  * 6. INCOMING DREQ
 239  *
 240  *      Acquire hca state table READER lock
 241  *      Do lookup in active hca state tree by local com id
 242  *      Release hca state table READER lock
 243  *
 244  *      If lookup does not exist
 245  *              return
 246  *
 247  *      if look up exists
 248  *               incr statep->ref_cnt holding state mutex
 249  *
 250  *      acquire state mutex
 251  *      if (state is ESTABLISHED/DREQ SENT/TIMEWAIT)
 252  *        if state is ESTABLISHED/DREQ SENT,
 253  *              change state to DREQ RECVD
 254  *              start timers
 255  *
 256  *    send DREP reply
 257  *    decr ref_cnt
 258  *    release state mutex
 259  *
 260  * 7.  Incoming DREP
 261  *
 262  *      Acquire hca state table READER lock
 263  *      Do lookup in active hca state tree by local com id
 264  *      Release hca state table READER lock
 265  *
 266  *      If lookup does not exist
 267  *              return
 268  *
 269  *      if look up exists
 270  *               incr statep->ref_cnt holding state mutex
 271  *
 272  *      acquire state mutex
 273  *      if state is DREQ_SENT
 274  *        change state to DREP_RCVD
 275  *        cancel timer
 276  *        change state to TIMEWAIT
 277  *        set timewait timer
 278  *    decr ref_cnt
 279  *    release state mutex
 280  *
 281  * 8. Timeout handler
 282  *
 283  *  (for states REQ SENT/REP SENT/REJ SENT/DREQ SENT/DREP SENT/TIMEWAIT)
 284  *
 285  *       acquire the statep mutex
 286  *
 287  *       if (set state != stored_state)
 288  *          The thread that changed the state is responsible for any cleanup
 289  *          decrement ref cnt
 290  *          release statep mutex
 291  *          return
 292  *       else if (statep's state == REJ SENT)
 293  *              change state to DELETE
 294  *              decrement ref cnt
 295  *              release statep mutex
 296  *              delete statep
 297  *              return
 298  *       else if (state == TIME WAIT)
 299  *              do the time wait state processing
 300  *              decrement ref cnt
 301  *              change state to DELETE
 302  *              release statep mutex
 303  *              delete statep, and also QP
 304  *       else if (remaining retry cnt > 0)
 305  *              resend the mad
 306  *              decrement ref cnt
 307  *              release statep mutex
 308  *       else if (state == rep sent or req sent or mra rep rcvd or rep wait)
 309  *              (retry counter expired)
 310  *              change state to REJ SENT (No one shall delete in REJ SENT)
 311  *              decrement the ref_cnt
 312  *              release the statep mutex
 313  *              Post REJ MAD
 314  *              cv_signal anyone blocking
 315  *              Invoke client handler
 316  *       else if state == DREQ_SENT
 317  *              change state to TIME WAIT
 318  *              decrement the ref cnt
 319  *              set a timer for time wait time
 320  *              release the statep mutex
 321  *
 322  *
 323  * SIDR processing
 324  *
 325  * 9. INCOMING SIDR_REQ MAD
 326  *
 327  *    Figure out LID/GID
 328  *    Do lookup in SIDR LIST based on LID, GID, grh_exists and req_id
 329  *    increment ud_statep->ud_ref_cnt
 330  *
 331  *    If (new lookup)
 332  *
 333  *        validate service id, and the create new statep,
 334  *        initialize key fields
 335  *        do a lookup based on service id
 336  *        if service_id_lookup returns exists
 337  *              set sidr_status to QPN_VALID
 338  *        else
 339  *              set sidr_status to SID_INVALID
 340  *        post SIDR_REP mad
 341  *        decr ud_statep->ud_ref_cnt, release ud_state_mutex
 342  *
 343  *    else if (existing lookup)
 344  *
 345  *        if (ud_statep->ud_state is SIDR_REP_SENT)
 346  *              resend the mad
 347  *
 348  *        decr ud_statep->ud_ref_cnt, release ud_state_mutex
 349  *
 350  *
 351  * 10. INCOMING SIDR_REP MAD
 352  *
 353  *    Figure out LID/GID
 354  *    Do lookup in SIDR LIST based on LID, GID, grh_exists and req_id
 355  *    increment ud_statep->ud_ref_cnt
 356  *
 357  *    if look up doesn't exists
 358  *        return
 359  *
 360  *    if (state == SIDR_REQ_SENT)
 361  *        first, change state to SIDR_REP_RCVD
 362  *        release statep lock
 363  *        cancel timers
 364  *        cv_signal anyone blocking
 365  *        release the statep lock
 366  *        extract return args
 367  *        destroy the statep
 368  *
 369  * 11. Timeout handler
 370  *
 371  *  (for states SIDR_REQ_SENT/SIDR_REP_SENT)
 372  *
 373  *       acquire the statep mutex
 374  *
 375  *       if (statep's state == SIDR_REP_SENT SENT)
 376  *              change state to DELETE
 377  *              decrement ref cnt
 378  *              release statep mutex
 379  *              delete statep
 380  *              return
 381  *       else if (remaining retry cnt > 0 and state is SIDR_REQ_SENT)
 382  *              resend the mad
 383  *              decrement ref cnt
 384  *              release statep mutex
 385  *       else if (state == SIDR_REQ_SENT)
 386  *              (retry counter expired)
 387  *              change state to DELETE
 388  *              decrement the ref_cnt
 389  *              the statep mutex
 390  *              cv_signal anyone blocking
 391  *              Invoke client handler
 392  *              delete statep
 393  */
 394 
 395 /* Function prototypes */
 396 static void             ibcm_set_primary_adds_vect(ibcm_state_data_t *,
 397                             ibt_adds_vect_t *, ibcm_req_msg_t *);
 398 static void             ibcm_set_alt_adds_vect(ibcm_state_data_t *,
 399                             ibt_adds_vect_t *, ibcm_req_msg_t *);
 400 static ibt_status_t     ibcm_set_primary_cep_path(ibcm_state_data_t *,
 401                             ibt_cep_path_t *, ibcm_req_msg_t *);
 402 static ibt_status_t     ibcm_set_alt_cep_path(ibcm_state_data_t *,
 403                             ibt_cep_path_t *, ibcm_req_msg_t *);
 404 static ibt_status_t     ibcm_invoke_qp_modify(ibcm_state_data_t *,
 405                             ibcm_req_msg_t *, ibcm_rep_msg_t *);
 406 static ibt_status_t     ibcm_invoke_rtu_qp_modify(ibcm_state_data_t *,
 407                             ib_time_t, ibcm_rep_msg_t *);
 408 static ibcm_status_t    ibcm_sidr_req_ud_handler(ibcm_ud_state_data_t *,
 409                             ibcm_sidr_req_msg_t *, ibcm_mad_addr_t *,
 410                             ibt_sidr_status_t *);
 411 static void             ibcm_sidr_rep_ud_handler(ibcm_ud_state_data_t *,
 412                             ibcm_sidr_rep_msg_t *);
 413 static void             ibcm_handler_conn_fail(ibcm_state_data_t *,
 414                             uint8_t cf_code, uint8_t cf_msg,
 415                             ibt_cm_reason_t rej_reason, uint8_t *,
 416                             ibt_priv_data_len_t);
 417 static void             ibcm_build_n_post_rej_mad(uint8_t *input_madp,
 418                             ib_com_id_t, ibcm_mad_addr_t *, int, uint16_t);
 419 static void             ibcm_post_drep_mad(ibcm_state_data_t *);
 420 
 421 static ibcm_status_t    ibcm_verify_req_gids_and_svcid(
 422                             ibcm_state_data_t *statep,
 423                             ibcm_req_msg_t *cm_req_msgp);
 424 
 425 static void             ibcm_timeout_client_cb(ibcm_state_data_t *statep);
 426 static void             ibcm_ud_timeout_client_cb(
 427                             ibcm_ud_state_data_t *ud_statep);
 428 
 429 static void             ibcm_process_dreq_timeout(ibcm_state_data_t *statep);
 430 
 431 static void             ibcm_fill_adds_from_lap(ibt_adds_vect_t *adds,
 432                             ibcm_lap_msg_t *lap_msg, ibcm_mode_t mode);
 433 
 434 static void             ibcm_post_stored_apr_mad(ibcm_state_data_t *statep,
 435                             uint8_t *input_madp);
 436 
 437 static ibcm_status_t    ibcm_set_qp_from_apr(ibcm_state_data_t *statep,
 438                             ibcm_lap_msg_t *lap_msg);
 439 
 440 static boolean_t        ibcm_compare_prim_alt_paths(ibt_adds_vect_t *prim,
 441                             ibt_adds_vect_t *alt);
 442 
 443 static void             ibcm_process_get_classport_info(ibcm_hca_info_t *hcap,
 444                             uint8_t *input_madp, ibcm_mad_addr_t *cm_mad_addr);
 445 
 446 static void             ibcm_decode_classport_info(ibcm_hca_info_t *hcap,
 447                             uint8_t *input_madp, ibcm_mad_addr_t *cm_mad_addr);
 448 
 449 static void             ibcm_post_rej_ver_mismatch(uint8_t *input_madp,
 450                             ibcm_mad_addr_t *cm_mad_addr);
 451 
 452 static void             ibcm_init_clp_to_mad(ibcm_classportinfo_msg_t *clp,
 453                             ibt_redirect_info_t *rinfo);
 454 
 455 static void             ibcm_init_clp_from_mad(ibcm_classportinfo_msg_t *clp,
 456                             ibt_redirect_info_t *rinfo);
 457 
 458 static void             ibcm_copy_addl_rej(ibcm_state_data_t *statep,
 459                             ibcm_rej_msg_t *rej_msgp,
 460                             ibt_cm_conn_failed_t *failed);
 461 
 462 static void             ibcm_return_open_data(ibcm_state_data_t *statep,
 463                             ibcm_rep_msg_t *rep_msgp,
 464                             ibt_cm_reason_t reject_reason);
 465 
 466 /* limit the number of taskq threads to handle received MADs. */
 467 int ibcm_recv_tasks = 0;
 468 int ibcm_max_recv_tasks = 24;
 469 int ibcm_recv_timeouts = 0;
 470 
 471 /*
 472  * Tunable MAX MRA Service Timeout value in MicroSECONDS.
 473  *      0 - Tunable parameter not used.
 474  *
 475  *      Ex:   60000000 - Max MRA Service Delay is 60 Seconds.
 476  */
 477 clock_t ibcm_mra_service_timeout_max = 0;
 478 
 479 #ifdef  DEBUG
 480 
 481 static void                     print_modify_qp(char *prefix,
 482                                     ibt_qp_hdl_t ibt_qp,
 483                                     ibt_cep_modify_flags_t flags,
 484                                     ibt_qp_info_t *qp_attr);
 485 #endif
 486 
 487 /*      Warlock annotations */
 488 
 489 _NOTE(READ_ONLY_DATA(ibt_arej_info_u))
 490 
 491 /*
 492  * ibcm_process_incoming_mad:
 493  *      The CM callback that is invoked by IBMF, when a valid CM MAD arrives
 494  *      on any of the registered ibmf handles by CM.
 495  *
 496  *      It is assumed that the incoming MAD (except for incoming REQ) belongs
 497  *      to a connection on the HCA, on which the MAD is received.
 498  *      The IBMF callback arg specifies ibcm_hca_info_t
 499  *
 500  * NOTE: IBMF always invokes ibcm_recv_cb() in a taskq. CM does some memory
 501  * allocations and invoke ibcm_sm_funcs_tbl[i]() in the same taskq.
 502  *
 503  * INPUTS:
 504  *      ibmf_handle     - IBMF Handle
 505  *      args            - from IBMF. Is a ptr to ibcm_hca_info_t
 506  *      status          - Callback status. Is mostly IBMF_SUCCESS
 507  *      madbuf          - IBMF allocated MAD buffer (CM should free it)
 508  *      madaddr         - IBMF MAD's address
 509  *      grhvalid        - If GRH is valid or not
 510  *
 511  * RETURN VALUES: NONE
 512  */
 513 void
 514 ibcm_process_incoming_mad(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
 515     void *args)
 516 {
 517         uint8_t                 method;         /* Method type in MAD hdr */
 518         ib_mad_hdr_t            *in_mad_hdr;    /* Incoming MAD's header */
 519         ibcm_hca_info_t         *hcap;          /* pointer to HCA entry */
 520         ibcm_port_info_t        *portp;
 521         ibcm_mad_addr_t         *cm_mad_addr;   /* MAD address information */
 522         ibcm_event_type_t       attr_id;        /* Attribute ID in MAD hdr */
 523         ibcm_mad_addr_t         loc_mad_addr;   /* MAD address information */
 524         ibcm_qp_list_t          *cm_qp_entry;
 525         int                     ibmf_status;
 526 
 527 
 528         /* Noticed that IBMF always calls with IBMF_SUCCESS, but still check */
 529         if (msgp->im_msg_status != IBMF_SUCCESS) {
 530                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
 531                     "bad status %x", msgp->im_msg_status);
 532                 /* IBMF allocates Input MAD, so free it here */
 533                 if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) !=
 534                     IBMF_SUCCESS)
 535                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
 536                             "ibmf_free_msg failed %d", ibmf_status);
 537                 return;
 538         }
 539 
 540         /* Get the HCA entry pointer */
 541         cm_qp_entry = (ibcm_qp_list_t *)args;
 542 
 543         IBTF_DPRINTF_L5(cmlog, "ibcm_process_incoming_mad: ibmf_hdl %p "
 544             "msg %p args %p", ibmf_handle, msgp, args);
 545 
 546 #ifdef  DEBUG
 547         if (ibcm_test_mode > 1)
 548                 ibcm_query_qp(ibmf_handle, cm_qp_entry->qp_cm);
 549 #endif
 550 
 551         portp = cm_qp_entry->qp_port;
 552         hcap = portp->port_hcap;
 553 
 554         IBTF_DPRINTF_L4(cmlog, "ibcm_process_incoming_mad: CM MAD on "
 555             "port %d", portp->port_num);
 556 
 557         /* Increment hca ref cnt, if HCA is in attached state, else fail */
 558         if (ibcm_inc_hca_acc_cnt(hcap) != IBCM_SUCCESS) {
 559                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
 560                     "hca not in attach state");
 561                 /* IBMF allocates Input MAD, and ibcm free's it */
 562                 if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) !=
 563                     IBMF_SUCCESS)
 564                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
 565                             "ibmf_free_msg failed %d", ibmf_status);
 566                 return;
 567         }
 568 
 569         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cm_mad_addr))
 570 
 571         /* allocate memory for internal MAD address buffer */
 572         cm_mad_addr = &loc_mad_addr;
 573         bzero(cm_mad_addr, sizeof (ibcm_mad_addr_t));
 574 
 575         cm_mad_addr->port_num = portp->port_num;
 576 
 577         /* initialize cm_mad_addr field(s) */
 578         in_mad_hdr = msgp->im_msgbufs_recv.im_bufs_mad_hdr;
 579 
 580         if (in_mad_hdr->MgmtClass != MAD_MGMT_CLASS_COMM_MGT) {
 581                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
 582                     "bad mgmt class %x", in_mad_hdr->MgmtClass);
 583                 if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) !=
 584                     IBMF_SUCCESS)
 585                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
 586                             "ibmf_free_msg failed %d", ibmf_status);
 587                 ibcm_dec_hca_acc_cnt(hcap);
 588                 return;
 589         }
 590 
 591         cm_mad_addr->rcvd_addr = msgp->im_local_addr;
 592         if (msgp->im_msg_flags & IBMF_MSG_FLAGS_GLOBAL_ADDRESS) {
 593                 cm_mad_addr->grh_hdr = msgp->im_global_addr;
 594                 cm_mad_addr->grh_exists = B_TRUE;
 595                 IBTF_DPRINTF_L3(cmlog, "ibcm_process_incoming_mad: "
 596                     "CM recv GID GUID %llX sender GID GUID %llX",
 597                     msgp->im_global_addr.ig_recver_gid.gid_guid,
 598                     msgp->im_global_addr.ig_sender_gid.gid_guid);
 599         }
 600 
 601         /* Save IBMF handle and ibmf qp related information */
 602         cm_mad_addr->ibmf_hdl = ibmf_handle;
 603         cm_mad_addr->cm_qp_entry = cm_qp_entry;
 604 
 605         /* IBMF does not initialize ia_p_key for non-QP1's */
 606         if (cm_qp_entry->qp_cm != IBMF_QP_HANDLE_DEFAULT)
 607                 cm_mad_addr->rcvd_addr.ia_p_key = cm_qp_entry->qp_pkey;
 608 
 609         if (cm_mad_addr->rcvd_addr.ia_p_key & 0x8000)
 610                 IBTF_DPRINTF_L5(cmlog, "ibcm_process_incoming_mad: PKEY %x",
 611                     cm_mad_addr->rcvd_addr.ia_p_key);
 612         else
 613                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: CM MAD "
 614                     "arrived from limited PKEY %x",
 615                     cm_mad_addr->rcvd_addr.ia_p_key);
 616 
 617         /* Retrieve the method and Attr-Id from generic mad header */
 618         method = in_mad_hdr->R_Method;
 619         attr_id = b2h16(in_mad_hdr->AttributeID);
 620 
 621         IBTF_DPRINTF_L4(cmlog, "ibcm_process_incoming_mad: "
 622             "Method %x Attribute %x", method, attr_id);
 623 
 624         if (in_mad_hdr->ClassVersion != IBCM_MAD_CLASS_VERSION) {
 625 
 626                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
 627                     "unsupported ibcm class version %x",
 628                     in_mad_hdr->ClassVersion);
 629 
 630                 if (attr_id == (IBCM_INCOMING_REQ + IBCM_ATTR_BASE_ID))
 631                         ibcm_post_rej_ver_mismatch(
 632                             (uint8_t *)IBCM_IN_HDRP(msgp), cm_mad_addr);
 633 
 634                 if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) !=
 635                     IBMF_SUCCESS)
 636                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
 637                             "ibmf_free_msg failed %d", ibmf_status);
 638                 ibcm_dec_hca_acc_cnt(hcap);
 639                 return;
 640         }
 641 
 642         IBTF_DPRINTF_L4(cmlog, "ibcm_process_incoming_mad: "
 643             "Transaction Id 0x%llX", b2h64(in_mad_hdr->TransactionID));
 644 
 645 #ifdef  DEBUG
 646         ibcm_decode_tranid(b2h64(in_mad_hdr->TransactionID), NULL);
 647 #endif
 648 
 649         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cm_mad_addr))
 650 
 651         /*
 652          * The following are valid combination of Method type
 653          * and attribute id in the received MAD :-
 654          *      o ClassPortInfo with Get method
 655          *      o CM messages with Send method
 656          */
 657         if ((attr_id == MAD_ATTR_ID_CLASSPORTINFO) &&
 658             ((method == MAD_METHOD_GET) ||
 659             (method == MAD_METHOD_GET_RESPONSE))) {
 660                 if (method == MAD_METHOD_GET)
 661                         ibcm_process_get_classport_info(hcap,
 662                             (uint8_t *)IBCM_IN_HDRP(msgp), cm_mad_addr);
 663                 else if (method == MAD_METHOD_GET_RESPONSE)
 664                         ibcm_decode_classport_info(hcap,
 665                             (uint8_t *)IBCM_IN_HDRP(msgp), cm_mad_addr);
 666         } else if ((attr_id >= IBCM_ATTR_BASE_ID) &&
 667             (attr_id < (IBCM_ATTR_BASE_ID + IBCM_MAX_EVENTS)) &&
 668             (method == MAD_METHOD_SEND)) {
 669 
 670                 attr_id -= IBCM_ATTR_BASE_ID;   /* figure out CM message id */
 671 
 672                 ASSERT(msgp->im_msgbufs_recv.im_bufs_mad_hdr != NULL);
 673 
 674                 /* Call the CM process connection state function */
 675                 ibcm_sm_funcs_tbl[attr_id](hcap,
 676                     (uint8_t *)IBCM_IN_HDRP(msgp), cm_mad_addr);
 677         } else {
 678                 /*
 679                  * Any other combination of method and attribute are invalid,
 680                  * hence drop the MAD
 681                  */
 682                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
 683                     "unknown Method %x or Attribute %x", method, attr_id);
 684         }
 685 
 686         /* decrement the hcap access reference count */
 687         ibcm_dec_hca_acc_cnt(hcap);
 688 
 689         /* ASSERT(NO_LOCKS_HELD); */
 690 
 691         /* free up ibmf msgp  */
 692         if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) != IBMF_SUCCESS)
 693                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
 694                     "ibmf_free_msg failed %d", ibmf_status);
 695 }
 696 
 697 /*
 698  * Structure to carry the arguments from ibcm_recv_cb() to
 699  * ibcm_recv_incoming_mad() via taskq_dispatch
 700  */
 701 typedef struct ibcm_taskq_args_s {
 702         ibmf_handle_t   tq_ibmf_handle;
 703         ibmf_msg_t      *tq_ibmf_msgp;
 704         void            *tq_args;
 705 } ibcm_taskq_args_t;
 706 
 707 #define IBCM_RECV_MAX   128
 708 ibcm_taskq_args_t ibcm_recv_array[IBCM_RECV_MAX + 1];
 709 int ibcm_get, ibcm_put;
 710 int ibcm_recv_total;
 711 int ibcm_recv_queued;
 712 
 713 _NOTE(READ_ONLY_DATA(ibcm_taskq_args_t))
 714 
 715 static int
 716 ibcm_recv_dequeue(ibmf_handle_t *ibmf_handlep, ibmf_msg_t **msgpp, void **argsp)
 717 {
 718         ibcm_taskq_args_t *tq;
 719 
 720         if (ibcm_put == ibcm_get)
 721                 return (0);
 722 
 723         if (++ibcm_get >= IBCM_RECV_MAX)
 724                 ibcm_get = 0;
 725         tq = ibcm_recv_array + ibcm_get;
 726         *ibmf_handlep = tq->tq_ibmf_handle;
 727         *msgpp = tq->tq_ibmf_msgp;
 728         *argsp = tq->tq_args;
 729         return (1);
 730 }
 731 
 732 static int
 733 ibcm_recv_enqueue(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp, void *args)
 734 {
 735         int next;
 736         ibcm_taskq_args_t *tq;
 737 
 738         ASSERT(MUTEX_HELD(&ibcm_recv_mutex));
 739         next = ibcm_put + 1;
 740         if (next >= IBCM_RECV_MAX)
 741                 next = 0;
 742         if (next != ibcm_get) {
 743                 ibcm_recv_queued++;
 744                 ibcm_put = next;
 745                 tq = ibcm_recv_array + next;
 746                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tq))
 747                 tq->tq_ibmf_handle = ibmf_handle;
 748                 tq->tq_ibmf_msgp = msgp;
 749                 tq->tq_args = args;
 750                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*tq))
 751                 return (1);
 752         } else {
 753                 return (0);
 754         }
 755 }
 756 
 757 void
 758 ibcm_drop_msg(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp)
 759 {
 760         int ibmf_status;
 761 
 762         IBTF_DPRINTF_L2(cmlog, "ibcm_drop_msg: discarding MAD");
 763 
 764         if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) != IBMF_SUCCESS)
 765                 IBTF_DPRINTF_L2(cmlog, "ibcm_drop_msg: "
 766                     "ibmf_free_msg failed %d", ibmf_status);
 767 }
 768 
 769 /*
 770  * Processing done in taskq thread.
 771  *
 772  * Calls ibcm_process_incoming_mad with all function arguments extracted
 773  * from args.  Afterwards, check for queued requests.
 774  */
 775 static void
 776 ibcm_recv_task(void *args)
 777 {
 778         ibcm_taskq_args_t *taskq_args;
 779         ibmf_handle_t ibmf_handle;
 780         ibmf_msg_t *msgp;
 781 
 782         taskq_args = (ibcm_taskq_args_t *)args;
 783 
 784         IBTF_DPRINTF_L4(cmlog, "ibcm_recv_task: Processing incoming MAD"
 785             " via taskq");
 786 
 787         ibcm_process_incoming_mad(taskq_args->tq_ibmf_handle,
 788             taskq_args->tq_ibmf_msgp, taskq_args->tq_args);
 789 
 790         kmem_free(taskq_args, sizeof (ibcm_taskq_args_t));
 791 
 792         /* process queued entries before giving up this thread */
 793         mutex_enter(&ibcm_recv_mutex);
 794         while (ibcm_recv_dequeue(&ibmf_handle, &msgp, &args)) {
 795                 mutex_exit(&ibcm_recv_mutex);
 796                 ibcm_process_incoming_mad(ibmf_handle, msgp, args);
 797                 mutex_enter(&ibcm_recv_mutex);
 798         }
 799         --ibcm_recv_tasks;
 800         mutex_exit(&ibcm_recv_mutex);
 801 }
 802 
 803 static void
 804 ibcm_recv_timeout_cb(void *args)
 805 {
 806         ibcm_taskq_args_t *tq = (ibcm_taskq_args_t *)args;
 807         int rv = 1;
 808 
 809         mutex_enter(&ibcm_recv_mutex);
 810         ibcm_recv_timeouts--;
 811         if (ibcm_recv_tasks == 0) {
 812                 ibcm_recv_tasks++;
 813                 mutex_exit(&ibcm_recv_mutex);
 814                 if (taskq_dispatch(ibcm_taskq, ibcm_recv_task, tq,
 815                     TQ_NOQUEUE | TQ_NOSLEEP) == 0) {
 816                         mutex_enter(&ibcm_recv_mutex);
 817                         if (--ibcm_recv_tasks == 0) {
 818                                 (void) timeout(ibcm_recv_timeout_cb, tq, 1);
 819                                 ibcm_recv_timeouts++;
 820                         } else {
 821                                 rv = ibcm_recv_enqueue(tq->tq_ibmf_handle,
 822                                     tq->tq_ibmf_msgp, tq->tq_args);
 823                                 kmem_free(tq, sizeof (*tq));
 824                         }
 825                         mutex_exit(&ibcm_recv_mutex);
 826                 }
 827         } else {
 828                 /*
 829                  * one or more taskq threads are running now
 830                  * so just try to enqueue this one.
 831                  */
 832                 rv = ibcm_recv_enqueue(tq->tq_ibmf_handle,
 833                     tq->tq_ibmf_msgp, tq->tq_args);
 834                 kmem_free(tq, sizeof (*tq));
 835                 mutex_exit(&ibcm_recv_mutex);
 836         }
 837         if (rv == 0)
 838                 ibcm_drop_msg(tq->tq_ibmf_handle, tq->tq_ibmf_msgp);
 839 }
 840 
 841 /*
 842  * Dispatch to taskq if we're not using many, else just queue it
 843  * and have the taskq thread pick it up.  Return 0 if we're dropping it.
 844  */
 845 static int
 846 ibcm_recv_add_one(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp, void *args)
 847 {
 848         int rv;
 849         ibcm_taskq_args_t *tq;
 850 
 851         mutex_enter(&ibcm_recv_mutex);
 852         ibcm_recv_total++;
 853         if (ibcm_recv_tasks >= ibcm_max_recv_tasks) { /* just queue this one */
 854                 rv = ibcm_recv_enqueue(ibmf_handle, msgp, args);
 855                 mutex_exit(&ibcm_recv_mutex);
 856                 return (rv);
 857         } else {
 858                 ibcm_recv_tasks++; /* dispatch this one to a taskq thread */
 859                 mutex_exit(&ibcm_recv_mutex);
 860                 tq = kmem_alloc(sizeof (*tq), KM_NOSLEEP);
 861                 if (tq == NULL) {
 862                         mutex_enter(&ibcm_recv_mutex);
 863                         if (--ibcm_recv_tasks > 0)
 864                                 rv = ibcm_recv_enqueue(ibmf_handle, msgp, args);
 865                         else    /* don't enqueue if no threads are running */
 866                                 rv = 0;
 867                         mutex_exit(&ibcm_recv_mutex);
 868                         return (rv);
 869                 }
 870                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tq))
 871                 tq->tq_ibmf_handle = ibmf_handle;
 872                 tq->tq_ibmf_msgp = msgp;
 873                 tq->tq_args = args;
 874                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*tq))
 875                 if (taskq_dispatch(ibcm_taskq, ibcm_recv_task, tq,
 876                     TQ_NOQUEUE | TQ_NOSLEEP) == 0) {    /* dispatch failed */
 877                         mutex_enter(&ibcm_recv_mutex);
 878                         if (--ibcm_recv_tasks == 0) {
 879                                 /* try the dispatch again, after a tick */
 880                                 (void) timeout(ibcm_recv_timeout_cb, tq, 1);
 881                                 ibcm_recv_timeouts++;
 882                                 rv = 1; /* indicate success */
 883                         } else {
 884                                 rv = ibcm_recv_enqueue(ibmf_handle, msgp, args);
 885                                 kmem_free(tq, sizeof (*tq));
 886                         }
 887                         mutex_exit(&ibcm_recv_mutex);
 888                         return (rv);
 889                 } else {
 890                         return (1);
 891                 }
 892         }
 893 }
 894 
 895 /*
 896  * ibcm_recv_cb:
 897  *      The CM callback that is invoked by IBMF, when a valid CM MAD arrives
 898  *      on any of the registered ibmf handles by CM.
 899  *
 900  * INPUTS:
 901  *      ibmf_handle     - IBMF Handle
 902  *      msgp            - IBMF msg containing the MAD (allocated by IBMF)
 903  *      args            - Ptr to ibcm_hca_info_t
 904  *
 905  * RETURN VALUES: NONE
 906  */
 907 void
 908 ibcm_recv_cb(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp, void *args)
 909 {
 910         if (ibcm_recv_add_one(ibmf_handle, msgp, args) == 0)
 911                 ibcm_drop_msg(ibmf_handle, msgp);
 912 }
 913 
 914 /*
 915  * ibcm_process_req_msg:
 916  *      PASSIVE SIDE CM
 917  *      Called from ibcm_process_incoming_mad on reception of a REQ message
 918  *
 919  * Description:
 920  *      If it a new REQ (not duplicate)
 921  *              creates a new state structure in passive connection mode
 922  *              populate state structure fields
 923  *              inserts state structure in hca active and passive trees
 924  *              validates service id
 925  *              validates primary and alternate lid/gid in REQ,
 926  *              calls QP state transition function
 927  *              generates REP/REJ response
 928  *              stores the response MAD in state structure for future re-sends
 929  *              initializes timers as required
 930  *      If a duplicate REQ, action depends upon current state in the state
 931  *      structure
 932  *
 933  * INPUTS:
 934  *      hcap            - HCA entry ptr
 935  *      input_madp      - CM MAD that is input to this function
 936  *      cm_mad_addr     - Address information for the MAD
 937  *
 938  * RETURN VALUE:
 939  *      NONE
 940  */
 941 void
 942 ibcm_process_req_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
 943     ibcm_mad_addr_t *cm_mad_addr)
 944 {
 945         ibt_priv_data_len_t     arej_info_len = 0;
 946         ib_qpn_t                remote_qpn;
 947         ib_guid_t               remote_hca_guid;
 948         ib_com_id_t             remote_comid;
 949         ib_com_id_t             local_comid;
 950         ibcm_status_t           state_lookup_status;
 951         ibcm_status_t           comid_lookup_status;
 952         ibcm_status_t           response;
 953         ibcm_req_msg_t          *req_msgp =
 954             (ibcm_req_msg_t *)&input_madp[IBCM_MAD_HDR_SIZE];
 955         ibt_cm_reason_t         reject_reason = IBT_CM_SUCCESS;
 956         ibcm_state_data_t       *statep;
 957         ibcm_state_data_t       *stale_statep = NULL;
 958         ibcm_status_t           svc_gid_check;
 959         uint32_t                psn24_timeout5_retry3;
 960         ibt_tran_srv_t          trans;
 961 
 962         IBTF_DPRINTF_L5(cmlog, "ibcm_process_req_msg(%p, %p, %p)",
 963             hcap, input_madp, cm_mad_addr);
 964 
 965         /*
 966          * Lookup for an existing state structure or create a new state struct
 967          * If there is no entry, the lookup function also allocates a new
 968          * state structure and inserts in the table, initializes remote qpn
 969          * and hca guid from REQ
 970          */
 971         remote_hca_guid = b2h64(req_msgp->req_local_ca_guid);
 972         remote_qpn = b2h32(req_msgp->req_local_qpn_plus) >> 8;
 973         remote_comid = b2h32(req_msgp->req_local_comm_id);
 974 
 975         IBCM_DUMP_RAW_MSG((uchar_t *)input_madp);
 976 
 977         IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: remote_comid = %x"
 978             " remote_qpn = %x", remote_comid, remote_qpn);
 979 
 980         IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: remote_hcaguid = %llX",
 981             remote_hca_guid);
 982 
 983         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
 984 
 985 new_req:
 986         /* allocate the local_comid before proceeding */
 987         if (ibcm_alloc_comid(hcap, &local_comid) != IBCM_SUCCESS) {
 988                 ibcm_build_n_post_rej_mad(input_madp,
 989                     b2h32(req_msgp->req_local_comm_id), cm_mad_addr,
 990                     IBT_CM_FAILURE_REQ, IBT_CM_NO_RESC);
 991                 return;
 992         }
 993 
 994         /* allocate ibcm_state_data_t before grabbing the WRITER lock */
 995         statep = kmem_zalloc(sizeof (*statep), KM_SLEEP);
 996 
 997         rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
 998 
 999         /* NOTE that only a writer lock is held here */
1000 
1001         state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_REQ,
1002             local_comid, remote_qpn, remote_hca_guid, hcap, &statep);
1003 
1004         if (state_lookup_status == IBCM_LOOKUP_NEW) {
1005                 /* seeing the REQ request for the first time */
1006 
1007                 mutex_enter(&statep->state_mutex);
1008                 /* Release the state table lock */
1009                 rw_exit(&hcap->hca_state_rwlock);
1010 
1011                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: New statep 0x%p"
1012                     " created", statep);
1013 
1014                 psn24_timeout5_retry3 = b2h32(req_msgp->req_starting_psn_plus);
1015 
1016                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
1017 
1018                 /* if ibmf msg allocation fails, delete the statep */
1019                 if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl,
1020                     &statep->stored_msg, MAD_METHOD_SEND) != IBT_SUCCESS) {
1021 
1022                         IBCM_REF_CNT_DECR(statep);
1023                         statep->state = IBCM_STATE_DELETE;
1024                         mutex_exit(&statep->state_mutex);
1025                         /* HCA res cnt decremented via ibcm_delete_state_data */
1026                         ibcm_inc_hca_res_cnt(hcap);
1027                         ibcm_delete_state_data(statep);
1028                         return;
1029                 }
1030 
1031                 /* Allocate dreq_msg buf to be used during teardown. */
1032                 if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl,
1033                     &statep->dreq_msg, MAD_METHOD_SEND) != IBT_SUCCESS) {
1034 
1035                         IBCM_REF_CNT_DECR(statep);
1036                         statep->state = IBCM_STATE_DELETE;
1037                         mutex_exit(&statep->state_mutex);
1038                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_msg: "
1039                             "statep 0x%p: Failed to allocate dreq_msg", statep);
1040 
1041                         /* HCA res cnt decremented via ibcm_delete_state_data */
1042                         ibcm_inc_hca_res_cnt(hcap);
1043                         ibcm_delete_state_data(statep);
1044                         return;
1045                 }
1046 
1047                 /* initialize some "statep" fields */
1048                 statep->mode         = IBCM_PASSIVE_MODE;
1049                 statep->hcap         = hcap;
1050                 statep->remote_comid = remote_comid;
1051                 statep->svcid                = b2h64(req_msgp->req_svc_id);
1052                 statep->local_qp_rnr_cnt =
1053                     req_msgp->req_mtu_plus & 0x7;
1054 
1055                 /*
1056                  * get the remote_ack_delay, etc.
1057                  */
1058                 statep->remote_ack_delay =
1059                     ibt_ib2usec(req_msgp->req_primary_localtime_plus >> 3);
1060                 statep->cep_retry_cnt = psn24_timeout5_retry3 & 0x7;
1061 
1062                 /*
1063                  * get the req_max_cm_retries
1064                  */
1065                 statep->max_cm_retries = req_msgp->req_max_cm_retries_plus >> 4;
1066                 statep->remaining_retry_cnt = statep->max_cm_retries;
1067 
1068                 /* Approximate pkt life time for now */
1069                 statep->pkt_life_time = statep->remote_ack_delay/2;
1070 
1071                 /* Passive side timer is set to LocalCMRespTime in REQ */
1072                 statep->timer_value =
1073                     ibt_ib2usec(psn24_timeout5_retry3 >> 3 & 0x1f);
1074 
1075                 statep->starting_psn = psn24_timeout5_retry3 >> 8;
1076 
1077                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: statep 0x%p "
1078                     "active cep timeout(usec) = %u",
1079                     statep, statep->remote_ack_delay);
1080                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: "
1081                     "passive timer(usec) = %u", statep->timer_value);
1082                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: "
1083                     "approx pkt lt(usec)= %u ", statep->pkt_life_time);
1084                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: "
1085                     "max cm retries %u", statep->max_cm_retries);
1086 
1087                 /* The reply ie., REP/REJ transaction id copied from REQ */
1088                 IBCM_OUT_HDRP(statep->stored_msg)->TransactionID =
1089                     ((ib_mad_hdr_t *)(input_madp))->TransactionID;
1090 
1091                 /*
1092                  * Initialize the stale clock. Any other REQ
1093                  * messages on this statep are considered as duplicate
1094                  * if they arrive within stale clock
1095                  * ibcm_adj_btime is used to offset for retry REQ's
1096                  * arriving  just after expected retry clock
1097                  */
1098                 statep->stale_clock = gethrtime() +
1099                     (hrtime_t)(ibcm_adj_btime  * 1000000000) +
1100                     (hrtime_t)statep->remote_ack_delay *
1101                     (statep->max_cm_retries * (1000 / 2));
1102 
1103                 mutex_exit(&statep->state_mutex);
1104 
1105                 ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_REQ);
1106 
1107                 /* Increment the hca's resource count */
1108                 ibcm_inc_hca_res_cnt(hcap);
1109 
1110                 ibcm_build_reply_mad_addr(cm_mad_addr,
1111                     &statep->stored_reply_addr);
1112 
1113                 if (statep->stored_reply_addr.cm_qp_entry == NULL) {
1114 
1115                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_msg: "
1116                             "statep 0x%p cm_qp_entry alloc failed", statep);
1117 
1118                         /*
1119                          * Not much choice. CM MADs cannot go on QP1, not even
1120                          * REJ. Hence delete state data and go away silently.
1121                          * The remote will timeout after repeated attempts
1122                          */
1123                         mutex_enter(&statep->state_mutex);
1124                         IBCM_REF_CNT_DECR(statep);
1125                         statep->state = IBCM_STATE_DELETE;
1126                         mutex_exit(&statep->state_mutex);
1127 
1128                         ibcm_delete_state_data(statep);
1129                         return;
1130                 }
1131 
1132                 stale_statep = statep;
1133                 rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
1134                 comid_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_REQ_STALE,
1135                     remote_comid, 0, remote_hca_guid, hcap, &stale_statep);
1136                 rw_exit(&hcap->hca_state_rwlock);
1137 
1138                 if (comid_lookup_status == IBCM_LOOKUP_EXISTS) {
1139 
1140                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_msg: "
1141                             "dup comid %x stale_statep 0x%p statep 0x%p",
1142                             remote_comid, stale_statep, statep);
1143 
1144                         ibcm_insert_trace(stale_statep,
1145                             IBCM_TRACE_STALE_DETECT);
1146 
1147                         /* Send a REJ with duplicate com id */
1148                         ibcm_post_rej_mad(statep, IBT_CM_DUP_COM_ID,
1149                             IBT_CM_FAILURE_REQ, NULL, 0);
1150 
1151                         /*
1152                          * Don't free the ibmf msg, if stale_statep is not in
1153                          * ESTABLISHED state, because probability is very less.
1154                          * ibmf msg shall be deleted along with statep
1155                          */
1156 
1157                         /*
1158                          * if stale_statep is in established state, process
1159                          * stale connection handling on stale_statep
1160                          */
1161                         mutex_enter(&stale_statep->state_mutex);
1162                         if (stale_statep->state == IBCM_STATE_ESTABLISHED) {
1163 
1164                                 stale_statep->state =
1165                                     IBCM_STATE_TRANSIENT_DREQ_SENT;
1166                                 stale_statep->stale = B_TRUE;
1167 
1168                                 /* Cancel pending ibt_set_alt_path */
1169                                 ibcm_sync_lapr_idle(stale_statep);
1170                                 /* The above call releases the state mutex */
1171 
1172                                 if (stale_statep->dreq_msg == NULL)
1173                                         (void) ibcm_alloc_out_msg(stale_statep->
1174                                             stored_reply_addr.ibmf_hdl,
1175                                             &stale_statep->dreq_msg,
1176                                             MAD_METHOD_SEND);
1177 
1178                                 /*
1179                                  * Spec says, post DREQ MAD on the stale
1180                                  * channel. This moves channel into timewait
1181                                  */
1182                                 if (stale_statep->dreq_msg != NULL) {
1183                                         ibcm_post_dreq_mad(stale_statep);
1184                                         mutex_enter(&stale_statep->state_mutex);
1185                                 } else {
1186                                         mutex_enter(&stale_statep->state_mutex);
1187                                         /* Set it back to original state. */
1188                                         stale_statep->state =
1189                                             IBCM_STATE_ESTABLISHED;
1190                                         cv_broadcast(
1191                                             &stale_statep->block_mad_cv);
1192                                 }
1193                         }
1194 
1195                         IBCM_REF_CNT_DECR(stale_statep);
1196                         mutex_exit(&stale_statep->state_mutex);
1197 
1198                         mutex_enter(&statep->state_mutex);
1199                         IBCM_REF_CNT_DECR(statep);
1200                         mutex_exit(&statep->state_mutex);
1201                         return;
1202                 }
1203 
1204                 /* If unknown service type, just post a REJ */
1205                 trans = ((uint8_t *)&req_msgp->req_remote_eecn_plus)[3] >> 1 &
1206                     0x3;
1207                 if ((trans != IBT_RC_SRV) && (trans != IBT_UC_SRV) &&
1208                     (trans != IBT_RD_SRV)) {
1209 
1210                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_msg: "
1211                             "statep 0x%p invalid transport type %x", statep,
1212                             trans);
1213 
1214                         /* Send a REJ with invalid transport type */
1215                         ibcm_post_rej_mad(statep, IBT_CM_INVALID_SRV_TYPE,
1216                             IBT_CM_FAILURE_REQ, NULL, 0);
1217 
1218                         mutex_enter(&statep->state_mutex);
1219                         IBCM_REF_CNT_DECR(statep);
1220                         mutex_exit(&statep->state_mutex);
1221                         return;
1222                 }
1223 
1224                 /* Validate the gids, lids and service id */
1225                 svc_gid_check = ibcm_verify_req_gids_and_svcid(statep,
1226                     req_msgp);
1227 
1228                 if (svc_gid_check == IBCM_FAILURE) {
1229 
1230                         IBTF_DPRINTF_L3(cmlog, "ibcm_process_req_msg: Either "
1231                             "gid or sid invalid for statep 0x%p", statep);
1232                         mutex_enter(&statep->state_mutex);
1233                         IBCM_REF_CNT_DECR(statep);
1234                         mutex_exit(&statep->state_mutex);
1235 
1236                         /* REJ posted from ibcm_verify_req_gids_and_svcid */
1237                         return;
1238                 }
1239 
1240                 /* Call the QP state transition processing function */
1241                 response = ibcm_cep_state_req(statep, req_msgp,
1242                     &reject_reason, &arej_info_len);
1243 
1244                 /* If defer, return holding the statep ref cnt */
1245                 if (response == IBCM_DEFER) {
1246                         IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: "
1247                             "statep %0xp client returned DEFER response",
1248                             statep);
1249                         return;
1250                 }
1251 
1252                 /* statep ref cnt decremented in the func below */
1253                 ibcm_handle_cep_req_response(statep, response,
1254                     reject_reason, arej_info_len);
1255 
1256                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
1257 
1258                 return;
1259 
1260         } else {
1261                 rw_exit(&hcap->hca_state_rwlock);
1262                 ibcm_free_comid(hcap, local_comid);
1263         }
1264 
1265         if (state_lookup_status == IBCM_LOOKUP_EXISTS) {
1266                 hrtime_t        cur_time;
1267 
1268                 mutex_enter(&statep->state_mutex);
1269 
1270                 /*
1271                  * There is an existing state structure entry
1272                  * with the same active comid
1273                  * Resending REP MAD is necessary only for REP/REJ/MRA Sent
1274                  * states
1275                  * Any other state implies the active has already received
1276                  * the REP/REJ response, and this REQ is an old MAD popping
1277                  * out of the fabric, hence no resend is required
1278                  */
1279                 cur_time = gethrtime();
1280 
1281                 if ((remote_comid == statep->remote_comid) &&
1282                     (IBCM_OUT_HDRP(statep->stored_msg)->TransactionID ==
1283                     ((ib_mad_hdr_t *)(input_madp))->TransactionID) &&
1284                     (cur_time <= statep->stale_clock)) {
1285 
1286                         ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_REQ);
1287 
1288                         if (statep->state == IBCM_STATE_REP_SENT)
1289                                 ibcm_resend_rep_mad(statep);
1290                         else if (statep->state == IBCM_STATE_REJ_SENT)
1291                                 ibcm_resend_rej_mad(statep);
1292                         else if (statep->state == IBCM_STATE_MRA_SENT)
1293                                 ibcm_resend_mra_mad(statep);
1294 
1295                         /* decrementing ref cnt and returning from below */
1296 
1297                 } else if ((statep->state == IBCM_STATE_REJ_SENT) &&
1298                     remote_comid != statep->remote_comid) {
1299                         timeout_id_t            timer_val;
1300 
1301                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_msg: "
1302                             "statep 0x%p being retired, REMOTE_QPN %x",
1303                             statep, remote_qpn);
1304                         /*
1305                          * OK, this is reuse of the QPN on the active side
1306                          * that was not connected last time.  This REQ is
1307                          * considered NEW.  We delete the statep here,
1308                          * then start over from the top.
1309                          */
1310                         statep->state = IBCM_STATE_DELETE;
1311                         timer_val = statep->timerid;
1312                         statep->timerid = 0;
1313                         mutex_exit(&statep->state_mutex);
1314                         if (timer_val)
1315                                 (void) untimeout(timer_val);
1316                         IBCM_REF_CNT_DECR(statep);
1317                         ibcm_delete_state_data(statep);
1318                         goto new_req;
1319 
1320                 /*
1321                  * The statep is stale in the following cases :-
1322                  *  1) if incoming REQ's comid's doesn't match with what is
1323                  *      stored in statep
1324                  *  2) incoming REQ's local comid matches with statep's
1325                  *      remote comid, but the REQ is for a new connection.
1326                  *      This is verified that by comparing the current time
1327                  *      with stale clock in statep
1328                  */
1329                 } else {
1330                         /* This is a stale connection on passive side */
1331 
1332                         ibcm_insert_trace(statep, IBCM_TRACE_STALE_DETECT);
1333 
1334                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_msg: "
1335                             "stale detected statep %p state %x",
1336                             statep, statep->state);
1337 
1338                         IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: "
1339                             "cur_time 0x%llX stale_clock 0x%llX", cur_time,
1340                             statep->stale_clock);
1341 
1342                         if (statep->state == IBCM_STATE_ESTABLISHED) {
1343 
1344                                 statep->state = IBCM_STATE_TRANSIENT_DREQ_SENT;
1345                                 statep->stale = B_TRUE;
1346 
1347                                 /* Cancel pending ibt_set_alt_path */
1348                                 ibcm_sync_lapr_idle(statep);
1349                                 /* The above call releases the state mutex */
1350 
1351                                 if (statep->dreq_msg == NULL)
1352                                         (void) ibcm_alloc_out_msg(
1353                                             statep->stored_reply_addr.ibmf_hdl,
1354                                             &statep->dreq_msg, MAD_METHOD_SEND);
1355 
1356                                 /*
1357                                  * Spec says, post DREQ MAD on the stale
1358                                  * channel. This moves channel into timewait
1359                                  */
1360                                 if (statep->dreq_msg != NULL)
1361                                         ibcm_post_dreq_mad(statep);
1362                                 else {
1363                                         mutex_enter(&statep->state_mutex);
1364                                         statep->state = IBCM_STATE_ESTABLISHED;
1365                                         cv_broadcast(&statep->block_mad_cv);
1366                                         mutex_exit(&statep->state_mutex);
1367                                 }
1368                         } else {
1369                                 /*
1370                                  * If not in established state, the CM
1371                                  * protocol would timeout and delete the
1372                                  * statep that is stale, eventually
1373                                  */
1374                                 mutex_exit(&statep->state_mutex);
1375                         }
1376 
1377                         /* Post a REJ MAD to the incoming REQ's sender */
1378                         ibcm_build_n_post_rej_mad(input_madp,
1379                             b2h32(req_msgp->req_local_comm_id),
1380                             cm_mad_addr, IBT_CM_FAILURE_REQ, IBT_CM_CONN_STALE);
1381 
1382                         mutex_enter(&statep->state_mutex);
1383                 }
1384                 IBCM_REF_CNT_DECR(statep); /* decrement the ref count */
1385                 mutex_exit(&statep->state_mutex);
1386         }
1387 }
1388 
1389 /*
1390  * ibcm_handle_cep_req_response:
1391  *      Processes the response from ibcm_cep_state_req. Called holding a
1392  *      statep ref cnt. The statep ref cnt is decremented before returning.
1393  */
1394 void
1395 ibcm_handle_cep_req_response(ibcm_state_data_t *statep, ibcm_status_t response,
1396     ibt_cm_reason_t reject_reason, uint8_t arej_info_len)
1397 {
1398         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
1399 
1400         if (response == IBCM_SEND_REP)
1401                 ibcm_post_rep_mad(statep);
1402         else {
1403                 ASSERT(response == IBCM_SEND_REJ);
1404                 IBTF_DPRINTF_L4(cmlog, "ibcm_handle_cep_req_response: statep %p"
1405                     " posting REJ reject_reason = %d", statep, reject_reason);
1406 
1407                 ibcm_post_rej_mad(statep,
1408                     reject_reason, IBT_CM_FAILURE_REQ,
1409                     NULL, arej_info_len);
1410         }
1411 
1412         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
1413 
1414         mutex_enter(&statep->state_mutex);
1415         IBCM_REF_CNT_DECR(statep);
1416         mutex_exit(&statep->state_mutex);
1417 }
1418 
1419 
1420 /*
1421  * ibcm_process_rep_msg:
1422  *      ACTIVE SIDE CM
1423  *      Called from ibcm_process_incoming_mad on reception of a REP message
1424  *
1425  * INPUTS:
1426  *      hcap            - HCA entry pointer
1427  *      input_madp      - CM MAD that is input to this function
1428  *      cm_mad_addr     - Address information for the MAD
1429  *
1430  * RETURN VALUE:        NONE
1431  */
1432 void
1433 ibcm_process_rep_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
1434     ibcm_mad_addr_t *cm_mad_addr)
1435 {
1436         ibt_priv_data_len_t     arej_info_len = 0;
1437         ib_com_id_t             local_comid;
1438         timeout_id_t            timer_val;
1439         ibcm_status_t           lookup_status;  /* state lookup status */
1440         ibcm_status_t           stale_lookup_status;
1441         ibcm_status_t           stale_comid_lookup_status;
1442         ibcm_status_t           response;
1443         ibcm_rep_msg_t          *rep_msgp;      /* Response REP mesg */
1444         ibt_cm_reason_t         reject_reason;
1445         ibcm_state_data_t       *statep = NULL;
1446         ibcm_state_data_t       *stale_qpn = NULL;
1447         ibcm_state_data_t       *stale_comid = NULL;
1448         ib_guid_t               remote_ca_guid;
1449 
1450         IBTF_DPRINTF_L3(cmlog, "ibcm_process_rep_msg:");
1451 
1452         /* Lookup for an existing state structure */
1453         rep_msgp = (ibcm_rep_msg_t *)(&input_madp[IBCM_MAD_HDR_SIZE]);
1454 
1455         IBCM_DUMP_RAW_MSG((uchar_t *)input_madp);
1456 
1457         IBTF_DPRINTF_L5(cmlog, "ibcm_process_rep_msg: active comid: %x",
1458             rep_msgp->rep_remote_comm_id);
1459 
1460         local_comid = b2h32(rep_msgp->rep_remote_comm_id);
1461 
1462         /* lookup message holding a reader lock */
1463         rw_enter(&hcap->hca_state_rwlock, RW_READER);
1464         lookup_status = ibcm_lookup_msg(IBCM_INCOMING_REP, local_comid, 0, 0,
1465             hcap, &statep);
1466         rw_exit(&hcap->hca_state_rwlock);
1467 
1468         IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: lkup status %x, "
1469             "statep 0x%p active comid %x", lookup_status, statep, local_comid);
1470 
1471         if (lookup_status == IBCM_LOOKUP_FAIL) {
1472                 ibcm_build_n_post_rej_mad(input_madp,
1473                     b2h32(rep_msgp->rep_local_comm_id), cm_mad_addr,
1474                     IBT_CM_FAILURE_REP, IBT_CM_INVALID_CID);
1475 
1476                 return;
1477         }
1478 
1479         /* if transaction id is not as expected, drop the REP mad */
1480         if (IBCM_OUT_HDRP(statep->stored_msg)->TransactionID !=
1481             ((ib_mad_hdr_t *)(input_madp))->TransactionID) {
1482 
1483                 IBTF_DPRINTF_L3(cmlog, "ibcm_process_rep_msg: statep 0x%p, "
1484                     "An REP MAD with tid expected 0x%llX tid found 0x%llX ",
1485                     statep,
1486                     b2h64(IBCM_OUT_HDRP(statep->stored_msg)->TransactionID),
1487                     b2h64(((ib_mad_hdr_t *)(input_madp))->TransactionID));
1488 
1489                 mutex_enter(&statep->state_mutex);
1490                 IBCM_REF_CNT_DECR(statep);
1491                 mutex_exit(&statep->state_mutex);
1492                 return;
1493         }
1494 
1495         ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_REP);
1496 
1497         /* grab mutex first */
1498         mutex_enter(&statep->state_mutex);
1499 
1500         /*
1501          * There is a state structure entry with active comid
1502          * First, handle the re-send cases
1503          * The resend routines below release the state mutex
1504          */
1505         if (statep->state == IBCM_STATE_ESTABLISHED ||
1506             statep->state == IBCM_STATE_DREQ_SENT)
1507                 ibcm_resend_rtu_mad(statep);
1508         else if (statep->state == IBCM_STATE_REJ_SENT)
1509                 ibcm_resend_rej_mad(statep);
1510         else if (statep->state == IBCM_STATE_MRA_REP_SENT)
1511                 ibcm_resend_mra_mad(statep);
1512         else if ((statep->state == IBCM_STATE_REQ_SENT) ||
1513             (statep->state == IBCM_STATE_REP_WAIT)) {
1514 
1515                 /* change state */
1516                 statep->state = IBCM_STATE_REP_RCVD;
1517                 statep->clnt_proceed = IBCM_BLOCK;
1518                 statep->local_qp_rnr_cnt =
1519                     rep_msgp->rep_rnr_retry_cnt_plus >> 5;
1520 
1521                 /* cancel the REQ timer */
1522                 if (statep->timerid != 0) {
1523                         timer_val = statep->timerid;
1524                         statep->timerid = 0;
1525                         mutex_exit(&statep->state_mutex);
1526                         (void) untimeout(timer_val);
1527                 } else {
1528                         mutex_exit(&statep->state_mutex);
1529                 }
1530 
1531                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
1532 
1533                 /* Initialize the remote destination QPN for further MADs */
1534                 statep->stored_reply_addr.rcvd_addr.ia_remote_qno =
1535                     cm_mad_addr->rcvd_addr.ia_remote_qno;
1536                 statep->remote_qpn = b2h32(rep_msgp->rep_local_qpn_plus) >> 8;
1537                 statep->remote_comid = b2h32(rep_msgp->rep_local_comm_id);
1538                 bcopy(rep_msgp->rep_local_ca_guid, &remote_ca_guid,
1539                     sizeof (ib_guid_t));
1540                 statep->remote_hca_guid = b2h64(remote_ca_guid);
1541 
1542                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: statep 0x%p "
1543                     "passive cid = %x passive qpn = %x", statep,
1544                     statep->remote_comid, statep->remote_qpn);
1545 
1546                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: statep 0x%p "
1547                     "passive hcaguid = %llX", statep, statep->remote_hca_guid);
1548 
1549                 stale_qpn = statep;
1550                 stale_comid = statep;
1551 
1552                 /* Handle stale connection detection on active side */
1553                 rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
1554 
1555                 stale_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_REP_STALE,
1556                     0, statep->remote_qpn, statep->remote_hca_guid, hcap,
1557                     &stale_qpn);
1558 
1559                 stale_comid_lookup_status = ibcm_lookup_msg(
1560                     IBCM_INCOMING_REQ_STALE, statep->remote_comid, 0,
1561                     statep->remote_hca_guid, hcap, &stale_comid);
1562 
1563                 rw_exit(&hcap->hca_state_rwlock);
1564 
1565                 /*
1566                  * Check for other side reusing QPN that was attempted
1567                  * to be used, but somehow we sent a REJ.
1568                  */
1569                 mutex_enter(&stale_qpn->state_mutex);
1570                 if ((stale_lookup_status == IBCM_LOOKUP_EXISTS) &&
1571                     (stale_comid_lookup_status != IBCM_LOOKUP_EXISTS) &&
1572                     (stale_qpn->state == IBCM_STATE_REJ_SENT)) {
1573 
1574                         timeout_id_t            timer_val;
1575 
1576                         IBTF_DPRINTF_L3(cmlog, "ibcm_process_rep_msg: "
1577                             "statep 0x%p being retired, REMOTE_QPN %x",
1578                             stale_qpn, statep->remote_qpn);
1579                         /*
1580                          * OK, this is reuse of the QPN on the active side
1581                          * that was not connected last time.  This REQ is
1582                          * considered NEW.  We delete the statep here,
1583                          * then start over from the top.
1584                          */
1585                         stale_qpn->state = IBCM_STATE_DELETE;
1586                         timer_val = stale_qpn->timerid;
1587                         stale_qpn->timerid = 0;
1588                         mutex_exit(&stale_qpn->state_mutex);
1589                         if (timer_val)
1590                                 (void) untimeout(timer_val);
1591                         IBCM_REF_CNT_DECR(stale_qpn);
1592                         ibcm_delete_state_data(stale_qpn);
1593                         stale_qpn = statep;
1594                         rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
1595                         stale_lookup_status = ibcm_lookup_msg(
1596                             IBCM_INCOMING_REP_STALE, 0, statep->remote_qpn,
1597                             statep->remote_hca_guid, hcap, &stale_qpn);
1598                         rw_exit(&hcap->hca_state_rwlock);
1599                         /* OK to continue now */
1600                 } else
1601                         mutex_exit(&stale_qpn->state_mutex);
1602 
1603                 /*
1604                  * lookup exists implies that there is already an entry with
1605                  * the remote qpn/comid and remote hca guid
1606                  */
1607                 if ((stale_lookup_status == IBCM_LOOKUP_EXISTS) ||
1608                     (stale_comid_lookup_status == IBCM_LOOKUP_EXISTS)) {
1609 
1610                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_rep_msg: "
1611                             "statep 0x%p stale detected "
1612                             "qpn_lkup %d comid_lkup %d", statep,
1613                             stale_lookup_status, stale_comid_lookup_status);
1614 
1615                         /* Disassociate statep and QP */
1616                         IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
1617 
1618                         if (stale_lookup_status == IBCM_LOOKUP_EXISTS)
1619                                 reject_reason = IBT_CM_CONN_STALE;
1620                         else
1621                                 reject_reason = IBT_CM_DUP_COM_ID;
1622 
1623                         ibcm_handler_conn_fail(statep,
1624                             IBT_CM_FAILURE_REJ_SENT, IBT_CM_FAILURE_REP,
1625                             reject_reason,
1626                             IBCM_REJ_PRIV(statep->stored_msg),
1627                             IBT_REJ_PRIV_DATA_SZ);
1628 
1629                         /* Send a REJ with stale reason for statep */
1630                         ibcm_post_rej_mad(statep, reject_reason,
1631                             IBT_CM_FAILURE_REP, NULL, 0);
1632 
1633                         /* Now let's handle the logic for stale connections */
1634                         /* If in established state, stale_statep is stale */
1635                         if (stale_lookup_status == IBCM_LOOKUP_EXISTS) {
1636 
1637                                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_rep_msg: "
1638                                     "state_qpn 0x%p stale QPN detected "
1639                                     "state %X", stale_qpn, stale_qpn->state);
1640 
1641                                 ibcm_insert_trace(stale_qpn,
1642                                     IBCM_TRACE_STALE_DETECT);
1643 
1644                                 mutex_enter(&stale_qpn->state_mutex);
1645                                 if (stale_qpn->state ==
1646                                     IBCM_STATE_ESTABLISHED) {
1647                                         /* change state to DREQ sent */
1648                                         stale_qpn->state =
1649                                             IBCM_STATE_TRANSIENT_DREQ_SENT;
1650                                         stale_qpn->stale = B_TRUE;
1651 
1652                                         /* wait for/cancel pending LAP/APR */
1653                                         ibcm_sync_lapr_idle(stale_qpn);
1654                                         /* above call releases state mutex */
1655 
1656                                         if (stale_qpn->dreq_msg == NULL)
1657                                                 (void) ibcm_alloc_out_msg(
1658                                                     stale_qpn->
1659                                                     stored_reply_addr.ibmf_hdl,
1660                                                     &stale_qpn->dreq_msg,
1661                                                     MAD_METHOD_SEND);
1662 
1663                                         if (stale_qpn->dreq_msg != NULL) {
1664                                                 ibcm_post_dreq_mad(stale_qpn);
1665                                                 mutex_enter(
1666                                                     &stale_qpn->state_mutex);
1667                                         } else {
1668                                                 mutex_enter(
1669                                                     &stale_qpn->state_mutex);
1670                                                 stale_qpn->state =
1671                                                     IBCM_STATE_ESTABLISHED;
1672                                                 cv_broadcast(
1673                                                     &stale_qpn->block_mad_cv);
1674                                         }
1675                                 }
1676                                 IBCM_REF_CNT_DECR(stale_qpn);
1677                                 mutex_exit(&stale_qpn->state_mutex);
1678                         }
1679 
1680                         if (stale_comid_lookup_status == IBCM_LOOKUP_EXISTS) {
1681 
1682                                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_rep_msg: "
1683                                     "state_comid 0x%p stale COMID detected "
1684                                     "state %X", stale_comid,
1685                                     stale_comid->state);
1686 
1687                                 mutex_enter(&stale_comid->state_mutex);
1688                                 if (!((stale_lookup_status ==
1689                                     IBCM_LOOKUP_EXISTS) &&
1690                                     (stale_qpn == stale_comid)) &&
1691                                     (stale_comid->state ==
1692                                     IBCM_STATE_ESTABLISHED)) {
1693 
1694                                         ibcm_insert_trace(stale_comid,
1695                                             IBCM_TRACE_STALE_DETECT);
1696 
1697                                         /* change state to DREQ sent */
1698                                         stale_comid->state =
1699                                             IBCM_STATE_TRANSIENT_DREQ_SENT;
1700                                         stale_comid->stale = B_TRUE;
1701 
1702                                         /* wait for/cancel pending LAP/APR */
1703                                         ibcm_sync_lapr_idle(stale_comid);
1704 
1705                                         /* above call releases state mutex */
1706 
1707                                         if (stale_comid->dreq_msg == NULL)
1708                                                 (void) ibcm_alloc_out_msg(
1709                                                     stale_comid->
1710                                                     stored_reply_addr.ibmf_hdl,
1711                                                     &stale_comid->dreq_msg,
1712                                                     MAD_METHOD_SEND);
1713 
1714                                         if (stale_comid->dreq_msg != NULL) {
1715                                                 ibcm_post_dreq_mad(stale_comid);
1716                                                 mutex_enter(
1717                                                     &stale_comid->state_mutex);
1718                                         } else {
1719                                                 mutex_enter(
1720                                                     &stale_comid->state_mutex);
1721                                                 stale_comid->state =
1722                                                     IBCM_STATE_ESTABLISHED;
1723                                                 cv_broadcast(
1724                                                     &stale_comid->block_mad_cv);
1725                                         }
1726                                 }
1727                                 IBCM_REF_CNT_DECR(stale_comid);
1728                                 mutex_exit(&stale_comid->state_mutex);
1729                         }
1730                         ibcm_return_open_data(statep, rep_msgp, reject_reason);
1731                         return;
1732                 }
1733 
1734                 /*
1735                  * No need to handle out of memory conditions as we called
1736                  * ibcm_lookup_msg() with IBT_CHAN_BLOCKING flags.
1737                  */
1738                 ASSERT(stale_lookup_status == IBCM_LOOKUP_NEW);
1739 
1740                 /* Initialize the remote ack delay */
1741                 statep->remote_ack_delay =
1742                     ibt_ib2usec(rep_msgp->rep_target_delay_plus >> 3);
1743 
1744                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: statep 0x%p"
1745                     " passive hca_ack_delay= %x ", statep,
1746                     statep->remote_ack_delay);
1747 
1748                 response = ibcm_cep_state_rep(statep, rep_msgp,
1749                     &reject_reason, &arej_info_len);
1750 
1751                 if (response == IBCM_DEFER) {
1752                         IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: "
1753                             "statep 0x%p client returned DEFER response",
1754                             statep);
1755                         return;
1756                 }
1757                 ibcm_handle_cep_rep_response(statep, response,
1758                     reject_reason, arej_info_len, rep_msgp);
1759 
1760                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
1761 
1762                 return;
1763 
1764         } else if (statep->state == IBCM_STATE_DELETE) {
1765 
1766                 mutex_exit(&statep->state_mutex);
1767                 ibcm_build_n_post_rej_mad(input_madp,
1768                     b2h32(rep_msgp->rep_local_comm_id), cm_mad_addr,
1769                     IBT_CM_FAILURE_REP, IBT_CM_INVALID_CID);
1770                 mutex_enter(&statep->state_mutex);
1771         } else {
1772 
1773 #ifdef DEBUG
1774                 if (ibcm_test_mode > 0)
1775                         if (statep->state == IBCM_STATE_REP_RCVD)
1776                                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_rep_msg: "
1777                                     "REP re-send from passive for statep 0x%p"
1778                                     " in state %d", statep, statep->state);
1779                         else
1780                                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_rep_msg: "
1781                                     "Unexpected REP for statep 0x%p in "
1782                                     "state %d", statep, statep->state);
1783 #endif
1784         }
1785         /* decrement ref count and return for LOOKUP_EXISTS */
1786         IBCM_REF_CNT_DECR(statep);
1787         mutex_exit(&statep->state_mutex);
1788 
1789 }
1790 
1791 /*
1792  * ibcm_handle_cep_req_response:
1793  *      Processes the response from ibcm_cep_state_rep. Called holding a
1794  *      statep ref cnt. The statep ref cnt is decremented before returning.
1795  */
1796 void
1797 ibcm_handle_cep_rep_response(ibcm_state_data_t *statep, ibcm_status_t response,
1798     ibt_cm_reason_t reject_reason, uint8_t arej_info_len,
1799     ibcm_rep_msg_t *rep_msgp)
1800 {
1801         /* wait until the send completion callback is invoked for REQ post */
1802         mutex_enter(&statep->state_mutex);
1803         while (statep->send_mad_flags & IBCM_REQ_POST_BUSY)
1804                 cv_wait(&statep->block_mad_cv, &statep->state_mutex);
1805         mutex_exit(&statep->state_mutex);
1806 
1807         if (response == IBCM_SEND_RTU) {
1808                 /* if connection aborted, return */
1809                 if (ibcm_post_rtu_mad(statep) != IBCM_SUCCESS) {
1810                         mutex_enter(&statep->state_mutex);
1811                         IBCM_REF_CNT_DECR(statep);
1812                         mutex_exit(&statep->state_mutex);
1813                         return;
1814                 }
1815 
1816                 /*
1817                  * Call client handler with cm event  IBT_CM_EVENT_CONN_EST to
1818                  * indicate RTU posted
1819                  */
1820                 ibcm_cep_send_rtu(statep);
1821         } else {
1822                 IBTF_DPRINTF_L4(cmlog, "ibcm_handle_cep_rep_response: statep %p"
1823                     " posting REJ reject_reason = %d", statep, reject_reason);
1824 
1825                 ASSERT(response == IBCM_SEND_REJ);
1826                 ibcm_post_rej_mad(statep, reject_reason, IBT_CM_FAILURE_REP,
1827                     NULL, arej_info_len);
1828         }
1829 
1830         ibcm_return_open_data(statep, rep_msgp, reject_reason);
1831 }
1832 
1833 /*
1834  * ibcm_return_open_data:
1835  *      Initializes the ibt_open_rc_channel return data. The statep ref cnt is
1836  *      decremented before returning.
1837  */
1838 static void
1839 ibcm_return_open_data(ibcm_state_data_t *statep, ibcm_rep_msg_t *rep_msgp,
1840     ibt_cm_reason_t reject_reason)
1841 {
1842         /* signal waiting CV - blocking in ibt_open_channel() */
1843         if (statep->open_return_data != NULL) {
1844                 if (statep->open_return_data->rc_priv_data_len > 0)
1845                         bcopy(rep_msgp->rep_private_data,
1846                             statep->open_return_data->rc_priv_data,
1847                             statep->open_return_data->rc_priv_data_len);
1848                 statep->open_return_data->rc_rdma_ra_in =
1849                     rep_msgp->rep_initiator_depth;
1850                 statep->open_return_data->rc_rdma_ra_out =
1851                     rep_msgp->rep_resp_resources;
1852                 statep->open_return_data->rc_failover_status =
1853                     rep_msgp->rep_target_delay_plus >> 1 & 3;
1854                 statep->open_return_data->rc_status = reject_reason;
1855 
1856                 mutex_enter(&statep->state_mutex);
1857                 statep->open_done = B_TRUE;
1858                 cv_broadcast(&statep->block_client_cv);
1859         } else mutex_enter(&statep->state_mutex);
1860 
1861         /* decrement ref count and return for LOOKUP_EXISTS */
1862         IBCM_REF_CNT_DECR(statep);
1863         mutex_exit(&statep->state_mutex);
1864 }
1865 
1866 
1867 /*
1868  * ibcm_process_mra_msg:
1869  *      Called from ibcm_process_incoming_mad on reception of a MRA message
1870  *
1871  *      Cancels existing timer, and sets a new timer based on timeout
1872  *      value from MRA message. The remaining retry count of statep is
1873  *      not changed, and timer value for the remaining retry timers is
1874  *      also not changed
1875  *
1876  * INPUTS:
1877  *      hcap            - HCA entry pointer
1878  *      input_madp      - CM MAD that is input to this function
1879  *      cm_mad_addr     - Address information for the MAD
1880  *
1881  * RETURN VALUE:        NONE
1882  */
1883 void
1884 ibcm_process_mra_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
1885     ibcm_mad_addr_t *cm_mad_addr)
1886 {
1887         ibcm_status_t           state_lookup_status;
1888         ibcm_mra_msg_t          *mra_msgp =
1889             (ibcm_mra_msg_t *)(&input_madp[IBCM_MAD_HDR_SIZE]);
1890         ibcm_state_data_t       *statep = NULL;
1891         uint8_t                 mra_msg;
1892 
1893         IBTF_DPRINTF_L4(cmlog, "ibcm_process_mra_msg:");
1894 
1895         /* Lookup for an existing state structure (as a READER) */
1896         rw_enter(&hcap->hca_state_rwlock, RW_READER);
1897         state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_MRA,
1898             b2h32(mra_msgp->mra_remote_comm_id), 0, 0, hcap, &statep);
1899         rw_exit(&hcap->hca_state_rwlock);
1900 
1901         /* if state doesn't exist just return */
1902         if (state_lookup_status != IBCM_LOOKUP_EXISTS) {
1903                 ibcm_build_n_post_rej_mad(input_madp,
1904                     b2h32(mra_msgp->mra_local_comm_id), cm_mad_addr,
1905                     IBT_CM_FAILURE_UNKNOWN, IBT_CM_INVALID_CID);
1906                 return;
1907         }
1908 
1909         if (IBCM_OUT_HDRP(statep->stored_msg)->TransactionID !=
1910             ((ib_mad_hdr_t *)(input_madp))->TransactionID) {
1911                 mutex_enter(&statep->state_mutex);
1912                 IBCM_REF_CNT_DECR(statep);
1913                 mutex_exit(&statep->state_mutex);
1914                 IBTF_DPRINTF_L3(cmlog, "ibcm_process_mra_msg: statep 0x%p "
1915                     "MRA MAD with tid expected 0x%llX tid found 0x%llX "
1916                     "com id 0x%x arrived", statep,
1917                     b2h64(IBCM_OUT_HDRP(statep->stored_msg)->TransactionID),
1918                     b2h64(((ib_mad_hdr_t *)(input_madp))->TransactionID),
1919                     b2h32(mra_msgp->mra_local_comm_id));
1920                 return;
1921         }
1922 
1923         ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_MRA);
1924 
1925         mutex_enter(&statep->state_mutex);
1926 
1927         /*
1928          * Only allow for REQ/REP "mra_msg_typ" ONLY
1929          * (to validate MRA message received)?
1930          */
1931         mra_msg = mra_msgp->mra_message_type_plus >> 6;
1932         if ((mra_msg != IBT_CM_MRA_TYPE_REQ) &&
1933             (mra_msg != IBT_CM_MRA_TYPE_REP) &&
1934             (mra_msg != IBT_CM_MRA_TYPE_LAP)) {
1935 
1936                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_mra_msg: statep 0x%p "
1937                     "Unexpected MRA MSG Type %x", statep, mra_msg);
1938                 IBCM_REF_CNT_DECR(statep);
1939                 mutex_exit(&statep->state_mutex);
1940                 return;
1941         }
1942 
1943         if ((statep->state == IBCM_STATE_REQ_SENT) ||
1944             (statep->state == IBCM_STATE_REP_SENT) ||
1945             ((statep->state == IBCM_STATE_ESTABLISHED) &&
1946             (statep->ap_state == IBCM_AP_STATE_LAP_SENT))) {
1947                 timeout_id_t    timer_val = statep->timerid;
1948                 clock_t         service_timeout;
1949 
1950                 if (statep->state == IBCM_STATE_REQ_SENT) {
1951                         mra_msg = IBT_CM_MRA_TYPE_REQ;
1952                         statep->state = IBCM_STATE_REP_WAIT;
1953                 } else if (statep->state == IBCM_STATE_REP_SENT) {
1954                         mra_msg = IBT_CM_MRA_TYPE_REP;
1955                         statep->state = IBCM_STATE_MRA_REP_RCVD;
1956                 } else { /* statep->state == IBCM_STATE_LAP_SENT */
1957                         mra_msg = IBT_CM_MRA_TYPE_LAP;
1958                         statep->ap_state = IBCM_AP_STATE_MRA_LAP_RCVD;
1959                 }
1960 
1961                 /* cancel the timer */
1962                 statep->timerid = 0;
1963                 mutex_exit(&statep->state_mutex);
1964 
1965                 (void) untimeout(timer_val);
1966 
1967                 service_timeout =
1968                     ibt_ib2usec(mra_msgp->mra_service_timeout_plus >> 3);
1969 
1970                 /*
1971                  * If tunable MAX MRA Service Timeout parameter is set, then
1972                  * verify whether the requested timer value exceeds the MAX
1973                  * value and reset the timer value to the MAX value.
1974                  */
1975                 if (ibcm_mra_service_timeout_max &&
1976                     ibcm_mra_service_timeout_max < service_timeout) {
1977                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_mra_msg: "
1978                             "Unexpected MRA Service Timeout value (%ld), Max "
1979                             "allowed is (%ld)", service_timeout,
1980                             ibcm_mra_service_timeout_max);
1981                         service_timeout = ibcm_mra_service_timeout_max;
1982                 }
1983 
1984                 /*
1985                  * Invoke client handler to pass the MRA private data
1986                  */
1987                 if (statep->cm_handler != NULL) {
1988                         ibt_cm_event_t  event;
1989 
1990                         bzero(&event, sizeof (event));
1991 
1992                         event.cm_type = IBT_CM_EVENT_MRA_RCV;
1993                         event.cm_channel = statep->channel;
1994                         event.cm_session_id = NULL;
1995                         event.cm_priv_data = mra_msgp->mra_private_data;
1996                         event.cm_priv_data_len = IBT_MRA_PRIV_DATA_SZ;
1997 
1998                         event.cm_event.mra.mra_msg_type = mra_msg;
1999 
2000                         event.cm_event.mra.mra_service_time = service_timeout;
2001 
2002                         /* Client cannot return private data */
2003                         (void) statep->cm_handler(statep->state_cm_private,
2004                             &event, NULL, NULL, 0);
2005                 }
2006 
2007                 /*
2008                  * Must re-check state, as an RTU could have come
2009                  * after the above mutex_exit and mutex_enter below
2010                  */
2011                 mutex_enter(&statep->state_mutex);
2012                 if ((statep->state == IBCM_STATE_REP_WAIT) ||
2013                     (statep->state == IBCM_STATE_MRA_REP_RCVD) ||
2014                     (statep->ap_state == IBCM_AP_STATE_MRA_LAP_RCVD)) {
2015 
2016                         statep->remaining_retry_cnt = statep->max_cm_retries;
2017 
2018                         /*
2019                          * The timeout interval is changed only for the first
2020                          * retry.  The later retries use the timeout from
2021                          * statep->timer_value
2022                          */
2023                         statep->timer_stored_state = statep->state;
2024                         statep->timer_value = statep->pkt_life_time +
2025                             service_timeout;
2026                         statep->timerid = IBCM_TIMEOUT(statep,
2027                             statep->timer_value);
2028                 }
2029 
2030         } else if (statep->state == IBCM_STATE_DELETE) {
2031 
2032                 mutex_exit(&statep->state_mutex);
2033                 ibcm_build_n_post_rej_mad(input_madp,
2034                     b2h32(mra_msgp->mra_local_comm_id), cm_mad_addr,
2035                     IBT_CM_FAILURE_UNKNOWN, IBT_CM_INVALID_CID);
2036                 mutex_enter(&statep->state_mutex);
2037         } else {
2038 
2039 #ifdef DEBUG
2040                 if (ibcm_test_mode > 0)
2041                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_mra_msg: "
2042                             "Unexpected mra for statep 0x%p in state %d",
2043                             statep, statep->state);
2044 #endif
2045         }
2046 
2047         IBCM_REF_CNT_DECR(statep);
2048         mutex_exit(&statep->state_mutex);
2049 }
2050 
2051 
2052 /*
2053  * ibcm_process_rtu_msg:
2054  *      Called from ibcm_process_incoming_mad on reception of a RTU message
2055  *
2056  *      Changes connection state to established if in REP SENT state
2057  *
2058  * INPUTS:
2059  *      hcap            - HCA entry pointer
2060  *      input_madp      - CM MAD that is input to this function
2061  *      cm_mad_addr     - Address information for the MAD
2062  *
2063  * RETURN VALUE:        NONE
2064  */
2065 void
2066 ibcm_process_rtu_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
2067     ibcm_mad_addr_t *cm_mad_addr)
2068 {
2069         timeout_id_t            timer_val;
2070         ibcm_status_t           status;
2071         ibcm_rtu_msg_t          *rtu_msg =
2072             (ibcm_rtu_msg_t *)(&input_madp[IBCM_MAD_HDR_SIZE]);
2073         ibcm_state_data_t       *statep = NULL;
2074 
2075         IBTF_DPRINTF_L4(cmlog, "ibcm_process_rtu_msg:");
2076 
2077         /* Lookup for an existing state structure - using a reader lock */
2078         rw_enter(&hcap->hca_state_rwlock, RW_READER);
2079         status = ibcm_lookup_msg(IBCM_INCOMING_RTU,
2080             b2h32(rtu_msg->rtu_remote_comm_id), 0, 0, hcap, &statep);
2081         rw_exit(&hcap->hca_state_rwlock);
2082 
2083         /* if state doesn't exist just return */
2084         if (status != IBCM_LOOKUP_EXISTS) {
2085                 ibcm_build_n_post_rej_mad(input_madp,
2086                     b2h32(rtu_msg->rtu_local_comm_id), cm_mad_addr,
2087                     IBT_CM_FAILURE_UNKNOWN, IBT_CM_INVALID_CID);
2088                 return;
2089         }
2090 
2091         if (IBCM_OUT_HDRP(statep->stored_msg)->TransactionID !=
2092             ((ib_mad_hdr_t *)(input_madp))->TransactionID) {
2093                 mutex_enter(&statep->state_mutex);
2094                 IBCM_REF_CNT_DECR(statep);
2095                 mutex_exit(&statep->state_mutex);
2096                 IBTF_DPRINTF_L3(cmlog, "ibcm_process_rtu_msg: statep 0x%p "
2097                     "An RTU MAD with tid expected 0x%llX tid found 0x%llX "
2098                     "com id 0x%x arrived", statep,
2099                     b2h64(IBCM_OUT_HDRP(statep->stored_msg)->TransactionID),
2100                     b2h64(((ib_mad_hdr_t *)(input_madp))->TransactionID),
2101                     b2h32(rtu_msg->rtu_remote_comm_id));
2102                 return;
2103         }
2104 
2105         ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_RTU);
2106 
2107         mutex_enter(&statep->state_mutex);
2108 
2109         if ((statep->state == IBCM_STATE_REP_SENT) ||
2110             (statep->state == IBCM_STATE_MRA_REP_RCVD)) {
2111 
2112                 /* transient until ibt_modify_qp succeeds to RTS */
2113                 statep->state = IBCM_STATE_TRANSIENT_ESTABLISHED;
2114 
2115                 timer_val = statep->timerid;
2116                 statep->timerid = 0;
2117                 mutex_exit(&statep->state_mutex);
2118 
2119                 (void) untimeout(timer_val);
2120 
2121                 ibcm_cep_state_rtu(statep, rtu_msg);
2122 
2123                 mutex_enter(&statep->state_mutex);
2124 
2125         } else if (statep->state == IBCM_STATE_REJ_SENT) {
2126                 ibcm_resend_rej_mad(statep);
2127         } else if (statep->state == IBCM_STATE_DELETE) {
2128 
2129                 mutex_exit(&statep->state_mutex);
2130                 ibcm_build_n_post_rej_mad(input_madp,
2131                     b2h32(rtu_msg->rtu_local_comm_id), cm_mad_addr,
2132                     IBT_CM_FAILURE_UNKNOWN, IBT_CM_INVALID_CID);
2133                 mutex_enter(&statep->state_mutex);
2134         } else {
2135 
2136 #ifdef DEBUG
2137                 if ((ibcm_test_mode > 0) &&
2138                     (statep->state != IBCM_STATE_ESTABLISHED))
2139                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_rtu_msg: "
2140                             "Unexpected rtu for statep 0x%p in state %d",
2141                             statep, statep->state);
2142 #endif
2143         }
2144 
2145         IBCM_REF_CNT_DECR(statep);
2146         mutex_exit(&statep->state_mutex);
2147 }
2148 
2149 
2150 /*
2151  * ibcm_process_rej_msg:
2152  *      Called from ibcm_process_incoming_mad on reception of a REJ message.
2153  *
2154  * INPUTS:
2155  *      hcap            - HCA entry pointer
2156  *      input_madp      - CM MAD that is input to this function
2157  *      cm_mad_addr     - Address information for the MAD
2158  *
2159  * RETURN VALUE:        NONE
2160  */
2161 /* ARGSUSED */
2162 void
2163 ibcm_process_rej_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
2164     ibcm_mad_addr_t *cm_mad_addr)
2165 {
2166         ibcm_status_t           state_lookup_status;
2167         ibcm_rej_msg_t          *rej_msg =
2168             (ibcm_rej_msg_t *)(&input_madp[IBCM_MAD_HDR_SIZE]);
2169         ibcm_state_data_t       *statep = NULL;
2170         ib_guid_t               remote_hca_guid;
2171         ibcm_conn_state_t       rej_state;
2172 
2173         IBTF_DPRINTF_L4(cmlog, "ibcm_process_rej_msg:");
2174 
2175         /* Lookup for an existing state structure */
2176         rw_enter(&hcap->hca_state_rwlock, RW_READER);    /* grab READER lock */
2177 
2178         if ((b2h32(rej_msg->rej_remote_comm_id) == 0) &&
2179             ((rej_msg->rej_reject_info_len_plus >> 1) >= sizeof (ib_guid_t)) &&
2180             (b2h16(rej_msg->rej_rejection_reason) == IBT_CM_TIMEOUT)) {
2181                 bcopy(rej_msg->rej_addl_rej_info, &remote_hca_guid,
2182                     sizeof (ib_guid_t));
2183                 remote_hca_guid = b2h64(remote_hca_guid);
2184 
2185                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_rej_msg: "
2186                     "hca guid in REJ's ARI =  %llX", remote_hca_guid);
2187 
2188                 state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_REJ_RCOMID,
2189                     b2h32(rej_msg->rej_local_comm_id), 0, remote_hca_guid,
2190                     hcap, &statep);
2191         } else
2192                 state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_REJ,
2193                     b2h32(rej_msg->rej_remote_comm_id), 0, 0, hcap, &statep);
2194 
2195         rw_exit(&hcap->hca_state_rwlock);
2196 
2197 
2198         /* if state doesn't exist just return */
2199         if (state_lookup_status != IBCM_LOOKUP_EXISTS) {
2200 
2201                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_rej_msg: no statep with "
2202                     "local com id %x remote com id %x reason %d",
2203                     b2h32(rej_msg->rej_remote_comm_id),
2204                     b2h32(rej_msg->rej_local_comm_id),
2205                     b2h16(rej_msg->rej_rejection_reason));
2206 
2207                 /* Do NOT respond with invalid comid REJ */
2208                 return;
2209         }
2210 
2211         IBTF_DPRINTF_L2(cmlog, "ibcm_process_rej_msg: statep 0x%p INCOMING_REJ",
2212             statep);
2213         ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_REJ);
2214         if (ibcm_enable_trace & 2)
2215                 ibcm_dump_conn_trace(statep);
2216 
2217         mutex_enter(&statep->state_mutex);
2218 
2219         rej_state = statep->state;
2220 
2221         if ((statep->state == IBCM_STATE_REP_SENT) ||
2222             (statep->state == IBCM_STATE_REQ_SENT) ||
2223             (statep->state == IBCM_STATE_REP_WAIT) ||
2224             (statep->state == IBCM_STATE_MRA_REP_RCVD)) {
2225                 timeout_id_t    timer_val = statep->timerid;
2226 
2227                 statep->state = IBCM_STATE_DELETE;
2228 
2229                 /* cancel the REQ/REP timer */
2230                 if (timer_val != 0) {
2231                         statep->timerid = 0;
2232                         mutex_exit(&statep->state_mutex);
2233 
2234                         (void) untimeout(timer_val);
2235                 } else {
2236                         mutex_exit(&statep->state_mutex);
2237                 }
2238 
2239                 /*
2240                  * Call the QP state transition processing function
2241                  * NOTE: Input MAD is the REJ received, there is no output MAD
2242                  */
2243                 ibcm_cep_state_rej(statep, rej_msg, rej_state);
2244 
2245                 /* signal waiting CV - blocking in ibt_open_channel() */
2246                 if (statep->open_return_data != NULL) {
2247                         statep->open_return_data->rc_status =
2248                             b2h16(rej_msg->rej_rejection_reason);
2249 
2250                         if (statep->open_return_data->rc_priv_data_len > 0)
2251                                 bcopy(rej_msg->rej_private_data,
2252                                     statep->open_return_data->rc_priv_data,
2253                                     min(
2254                                     statep->open_return_data->rc_priv_data_len,
2255                                     IBT_REJ_PRIV_DATA_SZ));
2256                         mutex_enter(&statep->state_mutex);
2257                         statep->open_done = B_TRUE;
2258                         cv_broadcast(&statep->block_client_cv);
2259                 } else {
2260                         mutex_enter(&statep->state_mutex);
2261                 }
2262 
2263                 IBCM_REF_CNT_DECR(statep);
2264                 mutex_exit(&statep->state_mutex);
2265 
2266                 /* Now delete the statep */
2267                 ibcm_delete_state_data(statep);
2268 
2269         } else if ((statep->state == IBCM_STATE_ESTABLISHED) &&
2270             (statep->mode == IBCM_ACTIVE_MODE)) {
2271 
2272                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_rej_msg: statep 0x%p "
2273                     "REJ in established state", statep);
2274 
2275                 statep->state = IBCM_STATE_TIMEWAIT;
2276 
2277                 /* wait for/cancel pending LAP/APR, release state mutex */
2278                 ibcm_sync_lapr_idle(statep);
2279 
2280                 /* wait until client is informed CONN EST event */
2281                 mutex_enter(&statep->state_mutex);
2282                 while (statep->cep_in_rts == IBCM_BLOCK)
2283                         cv_wait(&statep->block_mad_cv, &statep->state_mutex);
2284                 mutex_exit(&statep->state_mutex);
2285 
2286                 /*
2287                  * Call the QP state transition processing function
2288                  * NOTE: Input MAD is the REJ received, there is no output MAD
2289                  */
2290                 ibcm_cep_state_rej_est(statep);
2291 
2292                 /*
2293                  * Start the timewait state timer, as connection is in
2294                  * established state
2295                  */
2296 
2297                 /*
2298                  * For passive side CM set it to remote_ack_delay
2299                  * For active side CM add the pkt_life_time * 2
2300                  */
2301                 mutex_enter(&statep->state_mutex);
2302                 statep->timer_value = statep->remote_ack_delay;
2303                 /* statep->mode == IBCM_ACTIVE_MODE) */
2304                 statep->timer_value += (2 * statep->pkt_life_time);
2305 
2306                 statep->remaining_retry_cnt = 0;
2307                 statep->timer_stored_state = statep->state;
2308 
2309                 statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
2310 
2311                 IBCM_REF_CNT_DECR(statep);
2312                 mutex_exit(&statep->state_mutex);
2313 
2314         } else if (((statep->state == IBCM_STATE_REQ_RCVD) ||
2315             (statep->state == IBCM_STATE_REP_RCVD) ||
2316             (statep->state == IBCM_STATE_MRA_SENT) ||
2317             (statep->state == IBCM_STATE_MRA_REP_SENT)) &&
2318             (b2h16(rej_msg->rej_rejection_reason) == IBT_CM_TIMEOUT)) {
2319 
2320                 if (statep->abort_flag == IBCM_ABORT_INIT)
2321                         statep->abort_flag = IBCM_ABORT_REJ;
2322 
2323                 IBCM_REF_CNT_DECR(statep);
2324                 mutex_exit(&statep->state_mutex);
2325         } else {
2326 
2327 #ifdef DEBUG
2328                 if ((ibcm_test_mode > 0) &&
2329                     (statep->state != IBCM_STATE_DELETE))
2330                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_rej_msg: "
2331                             "Unexpected rej for statep 0x%p in state %d",
2332                             statep, statep->state);
2333 #endif
2334                 IBCM_REF_CNT_DECR(statep);
2335                 mutex_exit(&statep->state_mutex);
2336         }
2337 }
2338 
2339 
2340 /*
2341  * ibcm_process_dreq_msg:
2342  *      Processes incoming DREQ message on active/passive side
2343  *
2344  * INPUTS:
2345  *      hcap            - HCA entry pointer
2346  *      input_madp      - CM MAD that is input to this function
2347  *      cm_mad_addr     - Address information for the MAD
2348  *
2349  * RETURN VALUE:        NONE
2350  */
2351 /*ARGSUSED*/
2352 void
2353 ibcm_process_dreq_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
2354     ibcm_mad_addr_t *cm_mad_addr)
2355 {
2356         void                    *priv_data = NULL;
2357         ibcm_status_t           state_lookup_status;
2358         ib_qpn_t                local_qpn;
2359         ibcm_dreq_msg_t         *dreq_msgp =
2360             (ibcm_dreq_msg_t *)(&input_madp[IBCM_MAD_HDR_SIZE]);
2361         ibcm_state_data_t       *statep = NULL;
2362         uint8_t                 close_event_type;
2363         ibt_cm_status_t         cb_status;
2364 
2365         IBTF_DPRINTF_L4(cmlog, "ibcm_process_dreq_msg:");
2366 
2367         /* Lookup for an existing state structure */
2368         rw_enter(&hcap->hca_state_rwlock, RW_READER);
2369 
2370         state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_DREQ,
2371             b2h32(dreq_msgp->dreq_remote_comm_id), 0, 0, hcap, &statep);
2372         rw_exit(&hcap->hca_state_rwlock);
2373 
2374         local_qpn = b2h32(dreq_msgp->dreq_remote_qpn_eecn_plus) >> 8;
2375 
2376         if (state_lookup_status != IBCM_LOOKUP_EXISTS) {
2377                 IBTF_DPRINTF_L3(cmlog, "ibcm_process_dreq_msg: no statep with"
2378                     "com id %x", b2h32(dreq_msgp->dreq_remote_comm_id));
2379                 /* implies a bogus message */
2380                 return;
2381         }
2382 
2383         IBTF_DPRINTF_L4(cmlog, "ibcm_process_dreq_msg: statep 0x%p "
2384             "lookup status %x dreq qpn = %x", statep, state_lookup_status,
2385             local_qpn);
2386 
2387         /*
2388          * Local QPN check is necessary. There could be a DREQ from
2389          * a remote stale connection processing with the same com id, but
2390          * not intended for this statep
2391          */
2392         mutex_enter(&statep->state_mutex);
2393         if ((statep->local_qpn != local_qpn) ||
2394             (statep->remote_comid != b2h32(dreq_msgp->dreq_local_comm_id))) {
2395 
2396                 IBTF_DPRINTF_L3(cmlog, "ibcm_process_dreq_msg:"
2397                     "statep->local_qpn = %x qpn in dreq = %x"
2398                     "statep->remote_comid = %x local comid in dreq = %x",
2399                     statep->local_qpn, local_qpn, statep->remote_comid,
2400                     b2h32(dreq_msgp->dreq_local_comm_id));
2401 
2402                 IBCM_REF_CNT_DECR(statep);
2403                 mutex_exit(&statep->state_mutex);
2404                 return;
2405         }
2406         /*
2407          * If another thread is processing a copy of this same DREQ,
2408          * bail out here.
2409          */
2410         if (statep->state == IBCM_STATE_TRANSIENT_DREQ_SENT ||
2411             statep->drep_in_progress) {
2412                 IBCM_REF_CNT_DECR(statep);
2413                 mutex_exit(&statep->state_mutex);
2414                 return;
2415         }
2416         switch (statep->state) {
2417         case IBCM_STATE_ESTABLISHED:
2418         case IBCM_STATE_DREQ_SENT:
2419         case IBCM_STATE_TIMEWAIT:
2420                 break;
2421         default:
2422                 /* All other states ignore DREQ */
2423                 IBCM_REF_CNT_DECR(statep);
2424                 mutex_exit(&statep->state_mutex);
2425                 return;
2426         }
2427         statep->drep_in_progress = 1;
2428 
2429         /*
2430          * If drep msg wasn't really required, it shall be deleted finally
2431          * when statep goes away
2432          */
2433         if (statep->drep_msg == NULL) {
2434                 mutex_exit(&statep->state_mutex);
2435                 if (ibcm_alloc_out_msg(statep->stored_reply_addr.ibmf_hdl,
2436                     &statep->drep_msg, MAD_METHOD_SEND) != IBT_SUCCESS) {
2437                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_dreq_msg: "
2438                             "statep 0x%p ibcm_alloc_out_msg failed", statep);
2439                         mutex_enter(&statep->state_mutex);
2440                         statep->drep_in_progress = 0;
2441                         IBCM_REF_CNT_DECR(statep);
2442                         mutex_exit(&statep->state_mutex);
2443                         return;
2444                 }
2445                 mutex_enter(&statep->state_mutex);
2446         }
2447 
2448         if (statep->state == IBCM_STATE_TRANSIENT_DREQ_SENT) {
2449                 IBCM_REF_CNT_DECR(statep);
2450                 statep->drep_in_progress = 0;
2451                 mutex_exit(&statep->state_mutex);
2452                 return;
2453         }
2454 
2455         /*
2456          * Need to generate drep, as time wait can be reached either by an
2457          * outgoing dreq or an incoming dreq
2458          */
2459         if ((statep->state == IBCM_STATE_ESTABLISHED) ||
2460             (statep->state == IBCM_STATE_DREQ_SENT)) {
2461                 timeout_id_t    timer_val = statep->timerid;
2462 
2463                 if (statep->state == IBCM_STATE_DREQ_SENT) {
2464                         statep->state = IBCM_STATE_DREQ_RCVD;
2465                         statep->timerid = 0;
2466                         ibcm_close_done(statep, 0);
2467                         mutex_exit(&statep->state_mutex);
2468 
2469                         close_event_type = IBT_CM_CLOSED_DUP;
2470                         if (timer_val != 0) {
2471                                 /* Cancel the timer set for DREP reception */
2472                                 (void) untimeout(timer_val);
2473                         }
2474                 } else {        /* In ESTABLISHED State */
2475                         boolean_t       is_ofuv = statep->is_this_ofuv_chan;
2476 
2477                         statep->state = IBCM_STATE_DREQ_RCVD;
2478                         statep->clnt_proceed = IBCM_BLOCK;
2479 
2480                         /* Cancel or wait for LAP/APR to complete */
2481                         ibcm_sync_lapr_idle(statep);
2482                         /* The above function releases the state mutex */
2483 
2484                         /* wait until client knows CONN EST event */
2485                         mutex_enter(&statep->state_mutex);
2486                         while (statep->cep_in_rts == IBCM_BLOCK)
2487                                 cv_wait(&statep->block_mad_cv,
2488                                     &statep->state_mutex);
2489                         mutex_exit(&statep->state_mutex);
2490 
2491                         close_event_type = IBT_CM_CLOSED_DREQ_RCVD;
2492                         /* Move CEP to error state */
2493                         if (is_ofuv == B_FALSE) /* Skip for OFUV channel */
2494                                 (void) ibcm_cep_to_error_state(statep);
2495                 }
2496                 mutex_enter(&statep->state_mutex);
2497                 statep->drep_in_progress = 0;
2498 
2499                 IBCM_OUT_HDRP(statep->drep_msg)->TransactionID =
2500                     ((ib_mad_hdr_t *)(input_madp))->TransactionID;
2501 
2502                 priv_data = &(((ibcm_drep_msg_t *)
2503                     IBCM_OUT_MSGP(statep->drep_msg))->drep_private_data[0]);
2504 
2505                 if (statep->close_ret_status)
2506                         *statep->close_ret_status = close_event_type;
2507 
2508                 if (statep->close_nocb_state != IBCM_FAIL) {
2509                         ibtl_cm_chan_is_closing(statep->channel);
2510                         statep->close_nocb_state = IBCM_BLOCK;
2511                 }
2512                 mutex_exit(&statep->state_mutex);
2513 
2514                 /*
2515                  * if close_nocb_state is IBCM_FAIL, then cm_handler is NULL
2516                  * if close_nocb_state is IBCM_BLOCK, client cannot go away
2517                  */
2518                 if (statep->cm_handler != NULL) {
2519                         ibt_cm_event_t          event;
2520                         ibt_cm_return_args_t    ret_args;
2521 
2522                         bzero(&event, sizeof (event));
2523                         bzero(&ret_args, sizeof (ret_args));
2524 
2525                         event.cm_type = IBT_CM_EVENT_CONN_CLOSED;
2526                         event.cm_channel = statep->channel;
2527                         event.cm_session_id = statep;
2528                         event.cm_priv_data = dreq_msgp->dreq_private_data;
2529                         event.cm_priv_data_len = IBT_DREQ_PRIV_DATA_SZ;
2530                         event.cm_event.closed = close_event_type;
2531 
2532                         ibcm_insert_trace(statep,
2533                             IBCM_TRACE_CALLED_CONN_CLOSE_EVENT);
2534 
2535                         cb_status = statep->cm_handler(statep->state_cm_private,
2536                             &event, &ret_args, priv_data,
2537                             IBT_DREP_PRIV_DATA_SZ);
2538 
2539                         ibcm_insert_trace(statep,
2540                             IBCM_TRACE_RET_CONN_CLOSE_EVENT);
2541 
2542                         if (cb_status == IBT_CM_DEFER) {
2543                                 mutex_enter(&statep->state_mutex);
2544                                 statep->clnt_proceed =
2545                                     IBCM_UNBLOCK;
2546                                 cv_broadcast(&statep->block_client_cv);
2547                                 mutex_exit(&statep->state_mutex);
2548 
2549                                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_dreq_msg:"
2550                                     " statep 0x%p client returned DEFER "
2551                                     "response", statep);
2552                                 return;
2553                         }
2554                 }
2555 
2556                 /* fail/resume any blocked cm api call */
2557                 mutex_enter(&statep->state_mutex);
2558 
2559                 /* Signal for cm proceed api */
2560                 statep->clnt_proceed = IBCM_FAIL;
2561 
2562                 /* Signal for close with no callbacks */
2563                 statep->close_nocb_state = IBCM_FAIL;
2564 
2565                 /* Signal any waiting close channel thread */
2566                 statep->close_done = B_TRUE;
2567 
2568                 cv_broadcast(&statep->block_client_cv);
2569                 mutex_exit(&statep->state_mutex);
2570 
2571                 ibcm_handle_cep_dreq_response(statep, NULL, 0);
2572 
2573         } else if (statep->state == IBCM_STATE_TIMEWAIT) {
2574                 statep->drep_in_progress = 0;
2575                 if (statep->send_mad_flags & IBCM_DREP_POST_BUSY) {
2576                         IBCM_REF_CNT_DECR(statep);
2577                         mutex_exit(&statep->state_mutex);
2578                         return;
2579                 }
2580                 statep->send_mad_flags |= IBCM_DREP_POST_BUSY;
2581 
2582                 /* Release statep mutex before posting the MAD */
2583                 mutex_exit(&statep->state_mutex);
2584 
2585                 IBCM_OUT_HDRP(statep->drep_msg)->TransactionID =
2586                     ((ib_mad_hdr_t *)(input_madp))->TransactionID;
2587 
2588                 ibcm_post_drep_mad(statep);
2589                 /* ref cnt decremented in ibcm_post_drep_complete */
2590         } else {
2591 #ifdef DEBUG
2592                 if ((ibcm_test_mode > 0) &&
2593                     (statep->state != IBCM_STATE_DELETE))
2594                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_dreq_msg: "
2595                             "Unexpected dreq for statep 0x%p in state %d",
2596                             statep, statep->state);
2597 #endif
2598                 IBCM_REF_CNT_DECR(statep);
2599                 statep->drep_in_progress = 0;
2600                 mutex_exit(&statep->state_mutex);
2601         }
2602 }
2603 
2604 /*
2605  * ibcm_handle_cep_dreq_response:
2606  *      Processes the response from client handler for an incoming DREQ.
2607  *      The statep ref cnt is decremented before returning.
2608  */
2609 void
2610 ibcm_handle_cep_dreq_response(ibcm_state_data_t *statep, void *priv_data,
2611     ibt_priv_data_len_t priv_data_len)
2612 {
2613         if ((priv_data != NULL) && (priv_data_len > 0))
2614                 bcopy(priv_data,
2615                     &(((ibcm_drep_msg_t *)
2616                     IBCM_OUT_MSGP(statep->drep_msg))->drep_private_data[0]),
2617                     min(priv_data_len, IBT_DREP_PRIV_DATA_SZ));
2618 
2619         ibcm_post_drep_mad(statep);
2620 }
2621 
2622 
2623 /*
2624  * ibcm_post_dreq_mad:
2625  *      Posts a DREQ MAD
2626  * Post DREQ now for TIMEWAIT state and DREQ_RCVD
2627  *
2628  * INPUTS:
2629  *      statep          - state pointer
2630  *
2631  * RETURN VALUE:
2632  *      NONE
2633  */
2634 void
2635 ibcm_post_dreq_mad(void *vstatep)
2636 {
2637         ibcm_state_data_t       *statep = vstatep;
2638         ibcm_dreq_msg_t         *dreq_msgp;
2639 
2640         ASSERT(statep->dreq_msg != NULL);
2641 
2642         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dreq_msgp))
2643 
2644         /* Fill in the DREQ message */
2645         dreq_msgp = (ibcm_dreq_msg_t *)IBCM_OUT_MSGP(statep->dreq_msg);
2646         dreq_msgp->dreq_local_comm_id = h2b32(statep->local_comid);
2647         dreq_msgp->dreq_remote_comm_id = h2b32(statep->remote_comid);
2648         dreq_msgp->dreq_remote_qpn_eecn_plus = h2b32(statep->remote_qpn << 8);
2649 
2650         IBCM_OUT_HDRP(statep->dreq_msg)->AttributeID =
2651             h2b16(IBCM_INCOMING_DREQ + IBCM_ATTR_BASE_ID);
2652 
2653         /* wait until client knows CONN EST event */
2654         mutex_enter(&statep->state_mutex);
2655         while (statep->cep_in_rts == IBCM_BLOCK)
2656                 cv_wait(&statep->block_mad_cv, &statep->state_mutex);
2657         mutex_exit(&statep->state_mutex);
2658 
2659         /* Transition QP/EEC state to ERROR state */
2660         (void) ibcm_cep_to_error_state(statep);
2661 
2662         IBCM_OUT_HDRP(statep->dreq_msg)->TransactionID =
2663             h2b64(ibcm_generate_tranid(IBCM_INCOMING_DREQ, statep->local_comid,
2664             0));
2665 
2666         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*dreq_msgp))
2667 
2668         /* post the first DREQ via timeout callback */
2669         mutex_enter(&statep->state_mutex);
2670 
2671         statep->state = IBCM_STATE_DREQ_SENT;
2672         cv_broadcast(&statep->block_mad_cv);
2673 
2674         statep->timer_stored_state = statep->state;
2675         /* client cannot specify more than 16 retries */
2676         statep->timer_value = statep->remote_ack_delay;
2677         if (statep->mode == IBCM_ACTIVE_MODE) {
2678                 statep->timer_value += (2 * statep->pkt_life_time);
2679         }
2680         statep->remaining_retry_cnt = statep->max_cm_retries + 1;
2681         statep->timerid = IBCM_TIMEOUT(statep, 0);
2682         mutex_exit(&statep->state_mutex);
2683 }
2684 
2685 /*
2686  * ibcm_post_drep_mad:
2687  *      Posts a DREP MAD
2688  * Post DREP now for TIMEWAIT state and DREQ_RCVD
2689  *
2690  * INPUTS:
2691  *      statep          - state pointer
2692  *
2693  * RETURN VALUE:
2694  *      NONE
2695  */
2696 static void
2697 ibcm_post_drep_mad(ibcm_state_data_t *statep)
2698 {
2699         ibcm_drep_msg_t *drep_msgp;
2700 
2701         drep_msgp = (ibcm_drep_msg_t *)IBCM_OUT_MSGP(statep->drep_msg);
2702 
2703         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*drep_msgp))
2704 
2705         IBTF_DPRINTF_L4(cmlog, "ibcm_post_drep_mad:");
2706 
2707         /* Fill up DREP fields */
2708         drep_msgp->drep_local_comm_id = h2b32(statep->local_comid);
2709         drep_msgp->drep_remote_comm_id = h2b32(statep->remote_comid);
2710         IBCM_OUT_HDRP(statep->drep_msg)->AttributeID =
2711             h2b16(IBCM_INCOMING_DREP + IBCM_ATTR_BASE_ID);
2712 
2713         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*drep_msgp))
2714 
2715         ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_DREP);
2716 
2717         /* Post the DREP MAD now.  */
2718         ibcm_post_rc_mad(statep, statep->drep_msg, ibcm_post_drep_complete,
2719             statep);
2720 }
2721 
2722 /*
2723  * ibcm_process_drep_msg:
2724  *      Processes incoming DREP message on active/passive side
2725  *
2726  * INPUTS:
2727  *      hcap            - HCA entry pointer
2728  *      input_madp      - CM MAD that is input to this function
2729  *      cm_mad_addr     - Address information for the MAD
2730  *
2731  * RETURN VALUE: NONE
2732  */
2733 /* ARGSUSED */
2734 void
2735 ibcm_process_drep_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
2736     ibcm_mad_addr_t *cm_mad_addr)
2737 {
2738         ibcm_status_t           state_lookup_status;
2739         ibcm_drep_msg_t         *drep_msgp =
2740             (ibcm_drep_msg_t *)(&input_madp[IBCM_MAD_HDR_SIZE]);
2741         ibcm_state_data_t       *statep = NULL;
2742 
2743         IBTF_DPRINTF_L4(cmlog, "ibcm_process_drep_msg:");
2744 
2745         /* Lookup for an existing state structure */
2746         rw_enter(&hcap->hca_state_rwlock, RW_READER);
2747 
2748         state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_DREP,
2749             b2h32(drep_msgp->drep_remote_comm_id), 0, 0, hcap, &statep);
2750         rw_exit(&hcap->hca_state_rwlock);
2751 
2752         if (state_lookup_status != IBCM_LOOKUP_EXISTS) {
2753                 IBTF_DPRINTF_L3(cmlog, "ibcm_process_drep_msg: no statep with"
2754                     "com id %x", b2h32(drep_msgp->drep_remote_comm_id));
2755                 return;
2756         }
2757 
2758         /* if transaction id is not as expected, drop the DREP mad */
2759         if (IBCM_OUT_HDRP(statep->dreq_msg)->TransactionID !=
2760             ((ib_mad_hdr_t *)(input_madp))->TransactionID) {
2761                 mutex_enter(&statep->state_mutex);
2762                 IBCM_REF_CNT_DECR(statep);
2763                 mutex_exit(&statep->state_mutex);
2764                 IBTF_DPRINTF_L3(cmlog, "ibcm_process_drep_msg: statep 0x%p "
2765                     "DREP with tid expected 0x%llX tid found 0x%llX", statep,
2766                     b2h64(IBCM_OUT_HDRP(statep->dreq_msg)->TransactionID),
2767                     b2h64(((ib_mad_hdr_t *)(input_madp))->TransactionID));
2768                 return;
2769         }
2770 
2771         ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_DREP);
2772 
2773         mutex_enter(&statep->state_mutex);
2774 
2775         if (statep->state == IBCM_STATE_DREQ_SENT) {
2776                 timeout_id_t    timer_val = statep->timerid;
2777 
2778                 statep->state = IBCM_STATE_DREP_RCVD;
2779 
2780                 statep->timerid = 0;
2781                 mutex_exit(&statep->state_mutex);
2782                 (void) untimeout(timer_val);
2783 
2784                 if (statep->stale == B_TRUE)
2785                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_drep_msg: "
2786                             "statep 0x%p Unexpected DREP received for a stale "
2787                             "DREQ sent", statep);
2788 
2789                 mutex_enter(&statep->state_mutex);
2790                 /* allow free qp, if close channel with NOCALLBACKS didn't */
2791                 if (statep->close_nocb_state != IBCM_FAIL) {
2792                         ibtl_cm_chan_is_closing(statep->channel);
2793                         statep->close_nocb_state = IBCM_BLOCK;
2794                 }
2795                 mutex_exit(&statep->state_mutex);
2796 
2797                 /* if close_nocb_state is IBCM_FAIL, then cm_handler is NULL */
2798                 if (statep->cm_handler != NULL) {
2799                         ibt_cm_event_t          event;
2800                         ibt_cm_return_args_t    ret_args;
2801 
2802                         bzero(&event, sizeof (event));
2803                         bzero(&ret_args, sizeof (ret_args));
2804 
2805                         event.cm_type = IBT_CM_EVENT_CONN_CLOSED;
2806                         event.cm_channel = statep->channel;
2807                         event.cm_session_id = NULL;
2808 
2809                         if (statep->stale == B_TRUE) {
2810                                 event.cm_event.closed = IBT_CM_CLOSED_STALE;
2811                                 event.cm_priv_data = NULL;
2812                                 event.cm_priv_data_len = 0;
2813                         } else {
2814                                 event.cm_event.closed = IBT_CM_CLOSED_DREP_RCVD;
2815                                 event.cm_priv_data =
2816                                     drep_msgp->drep_private_data;
2817                                 event.cm_priv_data_len = IBT_DREP_PRIV_DATA_SZ;
2818                         }
2819 
2820                         ibcm_insert_trace(statep,
2821                             IBCM_TRACE_CALLED_CONN_CLOSE_EVENT);
2822 
2823                         (void) statep->cm_handler(statep->state_cm_private,
2824                             &event, &ret_args, NULL, 0);
2825 
2826                         ibcm_insert_trace(statep,
2827                             IBCM_TRACE_RET_CONN_CLOSE_EVENT);
2828                 }
2829 
2830                 /* copy the private to close channel, if specified */
2831                 if ((statep->close_ret_priv_data != NULL) &&
2832                     (statep->close_ret_priv_data_len != NULL) &&
2833                     (*statep->close_ret_priv_data_len > 0)) {
2834                         bcopy(drep_msgp->drep_private_data,
2835                             statep->close_ret_priv_data,
2836                             min(*statep->close_ret_priv_data_len,
2837                             IBT_DREP_PRIV_DATA_SZ));
2838                 }
2839 
2840                 mutex_enter(&statep->state_mutex);
2841                 if (statep->close_ret_status)
2842                         *statep->close_ret_status = IBT_CM_CLOSED_DREP_RCVD;
2843                 /* signal waiting CV - blocking in ibt_close_channel() */
2844                 statep->close_done = B_TRUE;
2845 
2846                 /* signal any blocked close channels with no callbacks */
2847                 statep->close_nocb_state = IBCM_FAIL;
2848 
2849                 cv_broadcast(&statep->block_client_cv);
2850 
2851                 /* Set the timer wait state timer */
2852                 statep->state = statep->timer_stored_state =
2853                     IBCM_STATE_TIMEWAIT;
2854                 ibcm_close_done(statep, 0);
2855 
2856                 statep->remaining_retry_cnt = 0;
2857                 /*
2858                  * For passive side CM set it to remote_ack_delay
2859                  * For active side CM add the pkt_life_time * 2
2860                  */
2861                 statep->timer_value = statep->remote_ack_delay;
2862                 if (statep->mode == IBCM_ACTIVE_MODE) {
2863                         statep->timer_value += (2 * statep->pkt_life_time);
2864                 }
2865 
2866                 /* start TIMEWAIT processing */
2867                 statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
2868         }
2869 
2870         /* There is no processing required for other states */
2871         IBCM_REF_CNT_DECR(statep);
2872         mutex_exit(&statep->state_mutex);
2873 }
2874 
2875 /*
2876  * Following are the routines used to resend various CM MADs as a response to
2877  * incoming MADs
2878  */
2879 void
2880 ibcm_resend_rtu_mad(ibcm_state_data_t *statep)
2881 {
2882         ASSERT(MUTEX_HELD(&statep->state_mutex));
2883 
2884         IBTF_DPRINTF_L3(cmlog, "ibcm_resend_rtu_mad statep %p ", statep);
2885 
2886         /* don't care, if timer is running or not. Timer may be from LAP */
2887 
2888         if (!(statep->send_mad_flags & IBCM_RTU_POST_BUSY)) {
2889                 statep->send_mad_flags |= IBCM_RTU_POST_BUSY;
2890                 IBCM_REF_CNT_INCR(statep);      /* for non-blocking RTU post */
2891                 mutex_exit(&statep->state_mutex);
2892 
2893                 ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_RTU);
2894 
2895                 ibcm_post_rc_mad(statep, statep->stored_msg,
2896                     ibcm_post_rtu_complete, statep);
2897                 mutex_enter(&statep->state_mutex);
2898         }
2899         /* ref cnt is decremented in ibcm_post_rtu_complete */
2900 }
2901 
2902 void
2903 ibcm_resend_rej_mad(ibcm_state_data_t *statep)
2904 {
2905         timeout_id_t            timer_val = statep->timerid;
2906 
2907         ASSERT(MUTEX_HELD(&statep->state_mutex));
2908 
2909         IBTF_DPRINTF_L3(cmlog, "ibcm_resend_rej_mad statep %p ", statep);
2910 
2911         /* It's a too fast of a REQ or REP */
2912         if (timer_val == 0)
2913                 return;
2914 
2915         statep->timerid = 0;
2916         if (!(statep->send_mad_flags & IBCM_REJ_POST_BUSY)) {
2917                 statep->send_mad_flags |= IBCM_REJ_POST_BUSY;
2918                 IBCM_REF_CNT_INCR(statep);      /* for nonblocking REJ post */
2919                 mutex_exit(&statep->state_mutex);
2920                 (void) untimeout(timer_val);
2921 
2922                 ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_REJ);
2923                 if (ibcm_enable_trace & 2)
2924                         ibcm_dump_conn_trace(statep);
2925                 else
2926                         IBTF_DPRINTF_L2(cmlog, "ibcm_resend_rej_mad statep %p "
2927                             "OUTGOING_REJ", statep);
2928 
2929                 ibcm_post_rc_mad(statep, statep->stored_msg,
2930                     ibcm_post_rej_complete, statep);
2931                 mutex_enter(&statep->state_mutex);
2932         }
2933         /* return, holding the state mutex */
2934 }
2935 
2936 void
2937 ibcm_resend_rep_mad(ibcm_state_data_t *statep)
2938 {
2939         timeout_id_t            timer_val = statep->timerid;
2940 
2941         ASSERT(MUTEX_HELD(&statep->state_mutex));
2942 
2943         IBTF_DPRINTF_L3(cmlog, "ibcm_resend_rep_mad statep %p ", statep);
2944 
2945         /* REP timer that is set by ibcm_post_rep_mad */
2946         if (timer_val != 0) {
2947                 /* Re-start REP timeout */
2948                 statep->remaining_retry_cnt = statep->max_cm_retries;
2949                 if (!(statep->send_mad_flags & IBCM_REP_POST_BUSY)) {
2950                         statep->send_mad_flags |= IBCM_REP_POST_BUSY;
2951                         /* for nonblocking REP post */
2952                         IBCM_REF_CNT_INCR(statep);
2953                         mutex_exit(&statep->state_mutex);
2954 
2955                         ibcm_insert_trace(statep, IBCM_TRACE_OUT_REP_RETRY);
2956 
2957                         ibcm_post_rc_mad(statep, statep->stored_msg,
2958                             ibcm_resend_post_rep_complete, statep);
2959                         mutex_enter(&statep->state_mutex);
2960                 }
2961         }
2962 
2963         /*
2964          * else, timer is not yet set by ibcm_post_rep_mad. This is too fast
2965          * of a REQ being re-transmitted.
2966          */
2967 }
2968 
2969 void
2970 ibcm_resend_mra_mad(ibcm_state_data_t *statep)
2971 {
2972         ASSERT(MUTEX_HELD(&statep->state_mutex));
2973 
2974         IBTF_DPRINTF_L3(cmlog, "ibcm_resend_mra_mad statep %p ", statep);
2975 
2976         if (statep->send_mad_flags & IBCM_MRA_POST_BUSY)
2977                 return;
2978 
2979         statep->send_mad_flags |= IBCM_MRA_POST_BUSY;
2980 
2981         statep->mra_time = gethrtime();
2982         IBCM_REF_CNT_INCR(statep);      /* for non-blocking MRA post */
2983         /* Exit the statep mutex, before sending the MAD */
2984         mutex_exit(&statep->state_mutex);
2985 
2986         ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_MRA);
2987 
2988         /* Always resend the response MAD to the original reply destination */
2989         ibcm_post_rc_mad(statep, statep->mra_msg, ibcm_post_mra_complete,
2990             statep);
2991 
2992         mutex_enter(&statep->state_mutex);
2993 
2994         /* return, holding the state mutex */
2995 }
2996 
2997 
2998 /*
2999  * ibcm_post_rej_mad:
3000  *      Posts a REJ MAD and starts timer
3001  *
3002  * INPUTS:
3003  *      statep          - state pointer
3004  *      which_msg       - which message is being MRAed
3005  *      reject_reason   - Rejection reason See Section 12.6.7.2 rev1.0a IB Spec
3006  *      addl_rej_info   - Additional rej Information
3007  *      arej_info_len   - Additional rej Info length
3008  *
3009  * RETURN VALUE:
3010  *      NONE
3011  * Notes
3012  *  There is no need to hold the statep->mutex and call ibcm_post_rej_mad
3013  *  REJ can be posted either in IBCM_STATE_REQ_RCVD or IBCM_STATE_REP_RCVD
3014  *  In these states, there is no timer active, and an incoming REJ shall
3015  *  not modify the state or cancel timers
3016  *  An incoming REJ doesn't affect statep in state = IBCM_STATE_REJ_SENT/BUSY
3017  */
3018 void
3019 ibcm_post_rej_mad(ibcm_state_data_t *statep, ibt_cm_reason_t reject_reason,
3020     int which_msg, void *addl_rej_info, ibt_priv_data_len_t arej_info_len)
3021 {
3022         ibcm_rej_msg_t  *rej_msg =
3023             (ibcm_rej_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
3024 
3025         /* Message printed if connection gets REJed */
3026         IBTF_DPRINTF_L3(cmlog, "ibcm_post_rej_mad: "
3027             "statep = %p, reject_reason = %d", statep, reject_reason);
3028 
3029         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msg))
3030 
3031         /* Initialize rej_msg fields */
3032         rej_msg->rej_local_comm_id = h2b32(statep->local_comid);
3033         rej_msg->rej_remote_comm_id = h2b32(statep->remote_comid);
3034         rej_msg->rej_msg_type_plus = (which_msg & 0x3) << 6;
3035         rej_msg->rej_reject_info_len_plus = arej_info_len << 1;
3036         rej_msg->rej_rejection_reason = h2b16((uint16_t)reject_reason);
3037 
3038         if ((arej_info_len != 0) && (addl_rej_info != NULL))
3039                 bcopy(addl_rej_info, rej_msg->rej_addl_rej_info, arej_info_len);
3040 
3041         IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
3042             h2b16(IBCM_INCOMING_REJ + IBCM_ATTR_BASE_ID);
3043 
3044         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msg))
3045 
3046         mutex_enter(&statep->state_mutex);
3047 
3048         /* signal any waiting close channels with blocking or no callbacks  */
3049         statep->close_done = B_TRUE;
3050         statep->close_nocb_state = IBCM_FAIL;
3051 
3052         cv_signal(&statep->block_client_cv);
3053 
3054         statep->timer_stored_state = statep->state = IBCM_STATE_REJ_SENT;
3055         statep->send_mad_flags |= IBCM_REJ_POST_BUSY;
3056 
3057         IBCM_REF_CNT_INCR(statep); /* for non-blocking post */
3058         mutex_exit(&statep->state_mutex);
3059 
3060         ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_REJ);
3061         if (ibcm_enable_trace & 2)
3062                 ibcm_dump_conn_trace(statep);
3063         else
3064                 IBTF_DPRINTF_L2(cmlog, "ibcm_post_rej_mad statep %p "
3065                     "OUTGOING_REJ", statep);
3066 
3067         ibcm_post_rc_mad(statep, statep->stored_msg, ibcm_post_rej_complete,
3068             statep);
3069 }
3070 
3071 
3072 /*
3073  * ibcm_build_n_post_rej_mad:
3074  *      Builds and posts a REJ MAD for "reject_reason"
3075  *      Doesn't set a timer, and doesn't need statep
3076  *
3077  * INPUTS:
3078  *      input_madp      - Incoming MAD
3079  *      remote_comid    - Local comid in the message being rejected
3080  *      cm_mad_addr     - Address information for the MAD to be posted
3081  *      which_msg       - REJ message type ie., REJ for REQ/REP
3082  *
3083  * RETURN VALUE:
3084  *      NONE
3085  */
3086 static void
3087 ibcm_build_n_post_rej_mad(uint8_t *input_madp, ib_com_id_t remote_comid,
3088     ibcm_mad_addr_t *cm_mad_addr, int which_msg, uint16_t reject_reason)
3089 {
3090         ibcm_rej_msg_t  *rej_msg;
3091         ibmf_msg_t      *cm_rej_msg;
3092         ibcm_mad_addr_t rej_reply_addr;
3093 
3094         IBTF_DPRINTF_L3(cmlog, "ibcm_build_n_post_rej_mad: "
3095             "remote_comid: %x reject_reason %d", remote_comid, reject_reason);
3096 
3097         if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg,
3098             MAD_METHOD_SEND) != IBT_SUCCESS) {
3099                 IBTF_DPRINTF_L2(cmlog, "ibcm_build_n_post_rej_mad: "
3100                     "ibcm_alloc_out_msg failed");
3101                 return;
3102         }
3103 
3104         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msg))
3105 
3106         IBCM_OUT_HDRP(cm_rej_msg)->TransactionID =
3107             ((ib_mad_hdr_t *)(input_madp))->TransactionID;
3108 
3109         /* Initialize rej_msg fields */
3110         rej_msg = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(cm_rej_msg);
3111         rej_msg->rej_local_comm_id = 0;
3112         rej_msg->rej_remote_comm_id = h2b32(remote_comid);
3113         rej_msg->rej_msg_type_plus = (which_msg & 0x3) << 6;
3114         rej_msg->rej_reject_info_len_plus = 0;
3115         rej_msg->rej_rejection_reason = h2b16(reject_reason);
3116 
3117         IBCM_OUT_HDRP(cm_rej_msg)->AttributeID =
3118             h2b16(IBCM_INCOMING_REJ + IBCM_ATTR_BASE_ID);
3119 
3120         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msg))
3121 
3122         ibcm_build_reply_mad_addr(cm_mad_addr, &rej_reply_addr);
3123 
3124         if (rej_reply_addr.cm_qp_entry != NULL) {
3125                 (void) ibcm_post_mad(cm_rej_msg, &rej_reply_addr, NULL, NULL);
3126                 ibcm_release_qp(rej_reply_addr.cm_qp_entry);
3127         }
3128 
3129         (void) ibcm_free_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg);
3130 }
3131 
3132 /* posts a REJ for an incoming REQ with unsupported class version */
3133 
3134 static void
3135 ibcm_post_rej_ver_mismatch(uint8_t *input_madp, ibcm_mad_addr_t *cm_mad_addr)
3136 {
3137         ibcm_req_msg_t  *req_msgp =
3138             (ibcm_req_msg_t *)&input_madp[IBCM_MAD_HDR_SIZE];
3139         ibcm_rej_msg_t  *rej_msg;
3140         ibmf_msg_t      *cm_rej_msg;
3141         ibcm_mad_addr_t rej_reply_addr;
3142 
3143         IBTF_DPRINTF_L3(cmlog, "ibcm_post_rej_ver_mismatch: remote comid %x",
3144             b2h32(req_msgp->req_local_comm_id));
3145 
3146         if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg,
3147             MAD_METHOD_SEND) != IBT_SUCCESS) {
3148                 IBTF_DPRINTF_L2(cmlog, "ibcm_post_rej_ver_mismatch: "
3149                     "ibcm_alloc_out_msg failed");
3150                 return;
3151         }
3152 
3153         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msg))
3154 
3155         IBCM_OUT_HDRP(cm_rej_msg)->TransactionID =
3156             ((ib_mad_hdr_t *)(input_madp))->TransactionID;
3157 
3158         /* Initialize rej_msg fields */
3159         rej_msg = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(cm_rej_msg);
3160         rej_msg->rej_local_comm_id = 0;
3161         rej_msg->rej_remote_comm_id = req_msgp->req_local_comm_id;
3162         rej_msg->rej_msg_type_plus = IBT_CM_FAILURE_REQ << 6;
3163         rej_msg->rej_rejection_reason = h2b16(IBT_CM_CLASS_NO_SUPPORT);
3164         rej_msg->rej_reject_info_len_plus = 1 << 1;
3165         rej_msg->rej_addl_rej_info[0] = IBCM_MAD_CLASS_VERSION;
3166 
3167         IBCM_OUT_HDRP(cm_rej_msg)->AttributeID =
3168             h2b16(IBCM_INCOMING_REJ + IBCM_ATTR_BASE_ID);
3169         IBCM_OUT_HDRP(cm_rej_msg)->Status = h2b16(MAD_STATUS_BAD_VERSION);
3170 
3171         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msg))
3172 
3173         ibcm_build_reply_mad_addr(cm_mad_addr, &rej_reply_addr);
3174         if (rej_reply_addr.cm_qp_entry != NULL) {
3175                 (void) ibcm_post_mad(cm_rej_msg, &rej_reply_addr, NULL, NULL);
3176                 ibcm_release_qp(rej_reply_addr.cm_qp_entry);
3177         }
3178         (void) ibcm_free_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg);
3179 }
3180 
3181 
3182 /*
3183  * ibcm_post_rep_mad:
3184  *      Posts a REP MAD and starts timer
3185  *
3186  * INPUTS:
3187  *      statep          - state pointer
3188  *
3189  * RETURN VALUE:
3190  *      NONE
3191  */
3192 void
3193 ibcm_post_rep_mad(ibcm_state_data_t *statep)
3194 {
3195         ibcm_rep_msg_t  *rep_msgp =
3196             (ibcm_rep_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
3197         ibmf_msg_t      *mra_msg = NULL;
3198         boolean_t       ret = B_FALSE;
3199 
3200         IBTF_DPRINTF_L4(cmlog, "ibcm_post_rep_mad: statep 0x%p", statep);
3201 
3202         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rep_msgp))
3203 
3204         /*
3205          * All other REP fields, other that the 2 below, are filled in
3206          * the ibcm_cep_state_req() function.
3207          */
3208         rep_msgp->rep_local_comm_id = h2b32(statep->local_comid);
3209         rep_msgp->rep_remote_comm_id = h2b32(statep->remote_comid);
3210         IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
3211             h2b16(IBCM_INCOMING_REP + IBCM_ATTR_BASE_ID);
3212 
3213         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rep_msgp))
3214 
3215         /*
3216          * Changing state and attempt to delete the mra msg must be done
3217          * together holding the state_mutex
3218          */
3219         mutex_enter(&statep->state_mutex);
3220 
3221         /* Now, attempt to delete the mra_msg, if there is one allocated */
3222         if (statep->mra_msg != NULL) {
3223                 if (!(statep->send_mad_flags & IBCM_MRA_POST_BUSY)) {
3224                         mra_msg = statep->mra_msg;
3225                         statep->mra_msg = NULL;
3226                 } else statep->delete_mra_msg = B_TRUE;
3227         }
3228 
3229         if (statep->abort_flag == IBCM_ABORT_CLIENT) {
3230                 statep->state = IBCM_STATE_ABORTED;
3231                 mutex_exit(&statep->state_mutex);
3232                 ibcm_process_abort(statep);
3233 
3234                 /* Now post a REJ MAD, rej reason consumer abort */
3235                 ibcm_post_rej_mad(statep, IBT_CM_CONSUMER, IBT_CM_FAILURE_REQ,
3236                     NULL, 0);
3237                 ret = B_TRUE;
3238         } else if (statep->abort_flag & IBCM_ABORT_REJ) {
3239 
3240                 statep->state = IBCM_STATE_DELETE;
3241                 mutex_exit(&statep->state_mutex);
3242 
3243                 ibcm_process_abort(statep);
3244                 ibcm_delete_state_data(statep);
3245                 ret = B_TRUE;
3246         } else {
3247 
3248                 statep->state = statep->timer_stored_state =
3249                     IBCM_STATE_REP_SENT;
3250                 statep->remaining_retry_cnt = statep->max_cm_retries;
3251                 statep->send_mad_flags |= IBCM_REP_POST_BUSY;
3252                 IBCM_REF_CNT_INCR(statep);      /* for nonblocking REP Post */
3253                 mutex_exit(&statep->state_mutex);
3254         }
3255 
3256         if (mra_msg != NULL)
3257                 (void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl,
3258                     &mra_msg);
3259         if (ret == B_TRUE)
3260                 return;
3261 
3262         ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_REP);
3263 
3264         ibcm_post_rc_mad(statep, statep->stored_msg, ibcm_post_rep_complete,
3265             statep);
3266 }
3267 
3268 
3269 /*
3270  * ibcm_post_rtu_mad:
3271  *      From active side post RTU MAD
3272  *
3273  * INPUTS:
3274  *      statep          - state pointer
3275  *
3276  * RETURN VALUE: NONE
3277  *
3278  * NOTE: No timer set after posting RTU
3279  */
3280 ibcm_status_t
3281 ibcm_post_rtu_mad(ibcm_state_data_t *statep)
3282 {
3283         ibcm_rtu_msg_t  *rtu_msg;
3284         ibmf_msg_t      *mra_msg = NULL;
3285         boolean_t       ret = B_FALSE;
3286 
3287         IBTF_DPRINTF_L4(cmlog, "ibcm_post_rtu_mad: statep 0x%p", statep);
3288 
3289         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rtu_msg))
3290 
3291         rtu_msg = (ibcm_rtu_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
3292 
3293         rtu_msg->rtu_local_comm_id = h2b32(statep->local_comid);
3294         rtu_msg->rtu_remote_comm_id = h2b32(statep->remote_comid);
3295         IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
3296             h2b16(IBCM_INCOMING_RTU + IBCM_ATTR_BASE_ID);
3297 
3298         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rtu_msg))
3299 
3300         mutex_enter(&statep->state_mutex);
3301 
3302         /* Now, attempt to delete the mra_msg, if there is one allocated */
3303         if (statep->mra_msg != NULL) {
3304                 if (!(statep->send_mad_flags & IBCM_MRA_POST_BUSY)) {
3305                         mra_msg = statep->mra_msg;
3306                         statep->mra_msg = NULL;
3307                 } else statep->delete_mra_msg = B_TRUE;
3308         }
3309 
3310         if (statep->abort_flag == IBCM_ABORT_CLIENT) {
3311                 statep->state = IBCM_STATE_ABORTED;
3312                 mutex_exit(&statep->state_mutex);
3313 
3314                 ibcm_process_abort(statep);
3315 
3316                 /* Now post a REJ MAD */
3317                 ibcm_post_rej_mad(statep, IBT_CM_CONSUMER, IBT_CM_FAILURE_REP,
3318                     NULL, 0);
3319                 ret = B_TRUE;
3320         } else if (statep->abort_flag & IBCM_ABORT_REJ) {
3321                 statep->state = IBCM_STATE_DELETE;
3322                 mutex_exit(&statep->state_mutex);
3323 
3324                 ibcm_process_abort(statep);
3325                 ibcm_delete_state_data(statep);
3326                 ret = B_TRUE;
3327         } else {
3328                 statep->state = IBCM_STATE_ESTABLISHED;
3329                 ibtl_cm_chan_is_open(statep->channel);
3330                 statep->send_mad_flags |= IBCM_RTU_POST_BUSY;
3331                 IBCM_REF_CNT_INCR(statep);      /* for nonblocking RTU post */
3332                 mutex_exit(&statep->state_mutex);
3333         }
3334 
3335         if (mra_msg != NULL)
3336                 (void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl,
3337                     &mra_msg);
3338 
3339         if (ret == B_TRUE)      /* Abort case, no RTU posted */
3340                 return (IBCM_FAILURE);
3341 
3342         ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_RTU);
3343 
3344         ibcm_post_rc_mad(statep, statep->stored_msg, ibcm_post_rtu_complete,
3345             statep);
3346         return (IBCM_SUCCESS);
3347 }
3348 
3349 
3350 /*
3351  * ibcm_process_abort:
3352  *      Processes abort, if client requested abort connection attempt
3353  *
3354  * INPUTS:
3355  *      statep  - pointer to ibcm_state_data_t is passed
3356  *
3357  * RETURN VALUES: None
3358  */
3359 void
3360 ibcm_process_abort(ibcm_state_data_t *statep)
3361 {
3362         IBTF_DPRINTF_L3(cmlog, "ibcm_process_abort: statep 0x%p", statep);
3363 
3364         /* move CEP to error state, before calling client handler */
3365         (void) ibcm_cep_to_error_state(statep);
3366 
3367         /* Now disassociate the link between statep and qp */
3368         IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
3369 
3370         /* invoke cm handler, for non-blocking open/close rc channel calls */
3371         if (statep->cm_handler) { /* cannot be NULL, but still .. */
3372                 ibt_cm_event_t          event;
3373                 ibt_cm_return_args_t    ret_args;
3374 
3375                 bzero(&event, sizeof (event));
3376                 bzero(&ret_args, sizeof (ret_args));
3377 
3378                 if (statep->abort_flag & IBCM_ABORT_REJ)
3379                         ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_RCV,
3380                             IBT_CM_FAILURE_UNKNOWN, IBT_CM_TIMEOUT, NULL, 0);
3381                 else {
3382                         ibcm_path_cache_purge();
3383 
3384                         event.cm_type = IBT_CM_EVENT_CONN_CLOSED;
3385                         event.cm_channel = statep->channel;
3386                         event.cm_event.closed = IBT_CM_CLOSED_ABORT;
3387 
3388                         ibcm_insert_trace(statep,
3389                             IBCM_TRACE_CALLED_CONN_CLOSE_EVENT);
3390 
3391                         if (statep->channel)
3392                                 ibtl_cm_chan_open_is_aborted(statep->channel);
3393 
3394                         (void) statep->cm_handler(statep->state_cm_private,
3395                             &event, &ret_args, NULL, 0);
3396 
3397                         ibcm_insert_trace(statep,
3398                             IBCM_TRACE_RET_CONN_CLOSE_EVENT);
3399 
3400                         mutex_enter(&statep->state_mutex);
3401                         ibcm_open_done(statep);
3402                         mutex_exit(&statep->state_mutex);
3403                 }
3404         }
3405 
3406         /*
3407          * Unblock an ibt_open_rc_channel called in a blocking mode, though
3408          * it is an unlikely scenario
3409          */
3410         mutex_enter(&statep->state_mutex);
3411 
3412         statep->cm_retries++; /* cause connection trace to be printed */
3413         statep->open_done = B_TRUE;
3414         statep->close_done = B_TRUE;
3415         statep->close_nocb_state = IBCM_FAIL; /* sanity sake */
3416 
3417         if (statep->open_return_data != NULL) {
3418                 /* REJ came first, and then client aborted connection */
3419                 if (statep->abort_flag & IBCM_ABORT_REJ)
3420                         statep->open_return_data->rc_status = IBT_CM_TIMEOUT;
3421                 else statep->open_return_data->rc_status = IBT_CM_ABORT;
3422         }
3423 
3424         cv_broadcast(&statep->block_client_cv);
3425         mutex_exit(&statep->state_mutex);
3426         if (ibcm_enable_trace != 0)
3427                 ibcm_dump_conn_trace(statep);
3428 }
3429 
3430 /*
3431  * ibcm_timeout_cb:
3432  *      Called when the timer expires
3433  *
3434  * INPUTS:
3435  *      arg     - ibcm_state_data_t is passed
3436  *
3437  * RETURN VALUES: NONE
3438  */
3439 void
3440 ibcm_timeout_cb(void *arg)
3441 {
3442         ibcm_state_data_t       *statep = (ibcm_state_data_t *)arg;
3443 
3444         mutex_enter(&statep->state_mutex);
3445 
3446         /*
3447          * The blocking operations are handled in a separate thread.
3448          * All other non-blocking operations, including ibmf non-blocking
3449          * posts are done from timeout context
3450          */
3451 
3452         if ((statep->timer_stored_state != statep->state) ||
3453             ((statep->timer_stored_state == IBCM_STATE_ESTABLISHED) &&
3454             (statep->ap_state != statep->timer_stored_ap_state))) {
3455                 mutex_exit(&statep->state_mutex);
3456                 return;
3457         }
3458 
3459         IBTF_DPRINTF_L3(cmlog, "ibcm_timeout_cb: statep 0x%p state %x "
3460             "ap_state %x", statep, statep->state, statep->ap_state);
3461 
3462         /* Processing depends upon current state */
3463 
3464         if (statep->state == IBCM_STATE_REJ_SENT) {
3465                 statep->state = IBCM_STATE_DELETE;
3466                 mutex_exit(&statep->state_mutex);
3467 
3468                 /* Deallocate the CM state structure */
3469                 ibcm_delete_state_data(statep);
3470                 return;
3471 
3472         } else if (statep->state == IBCM_STATE_TIMEWAIT) {
3473                 statep->state = IBCM_STATE_DELETE;
3474 
3475                 /* TIME_WAIT timer expired, so cleanup */
3476                 mutex_exit(&statep->state_mutex);
3477 
3478                 if (statep->channel)
3479                         ibtl_cm_chan_is_closed(statep->channel);
3480 
3481                 if (statep->recycle_arg) {
3482                         struct ibcm_taskq_recycle_arg_s *recycle_arg;
3483 
3484                         recycle_arg = statep->recycle_arg;
3485 
3486                         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(
3487                             statep->recycle_arg))
3488                         statep->recycle_arg = NULL;
3489                         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
3490 
3491                         /* if possible, do not slow down calling recycle func */
3492                         if (taskq_dispatch(ibcm_taskq, ibcm_process_rc_recycle,
3493                             recycle_arg, TQ_NOQUEUE | TQ_NOSLEEP) == 0) {
3494 
3495                                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(
3496                                     statep->recycle_arg))
3497                                 statep->recycle_arg = recycle_arg;
3498                                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(
3499                                     statep->recycle_arg))
3500                                 ibcm_add_tlist(statep);
3501                                 return;
3502                         }
3503                 }
3504 
3505                 ibcm_delete_state_data(statep);
3506                 return;
3507         } else if (statep->remaining_retry_cnt > 0) {
3508                 ibcm_conn_state_t       stored_state;
3509                 ibcm_ap_state_t         stored_ap_state;
3510 
3511                 statep->remaining_retry_cnt--;
3512                 IBTF_DPRINTF_L3(cmlog, "ibcm_timeout_cb: statep 0x%p "
3513                     "attr-id= 0x%x, retries remaining = 0x%x", statep,
3514                     b2h16(IBCM_OUT_HDRP(statep->stored_msg)->AttributeID),
3515                     statep->remaining_retry_cnt);
3516 
3517                 /*
3518                  * REP could be resent, either because of timeout or an
3519                  * incoming REQ. Any other MAD below can be resent, because
3520                  * of timeout only, hence send_mad_flag manipulation not
3521                  * required for those cases.
3522                  * If REP is already being retransmitted, then just set the
3523                  * timer and return. Else post REP in non-blocking mode
3524                  */
3525                 if (statep->timer_stored_state == IBCM_STATE_REP_SENT) {
3526                         if (statep->send_mad_flags & IBCM_REP_POST_BUSY) {
3527                                 statep->timerid = IBCM_TIMEOUT(statep,
3528                                     statep->timer_value);
3529                                 mutex_exit(&statep->state_mutex);
3530                                 ibcm_insert_trace(statep,
3531                                     IBCM_TRACE_TIMEOUT_REP);
3532                                 return;
3533                         }
3534 
3535                         /*
3536                          * Set REP  busy flag, so any incoming REQ's will not
3537                          * initiate new REP transmissions
3538                          */
3539                         statep->send_mad_flags |= IBCM_REP_POST_BUSY;
3540 
3541                 /* Since REQ/RTU/REJ on active side use same MAD, synchronize */
3542                 } else if (statep->timer_stored_state == IBCM_STATE_REQ_SENT) {
3543                         ASSERT((statep->send_mad_flags & IBCM_REQ_POST_BUSY)
3544                             == 0);
3545                         statep->send_mad_flags |= IBCM_REQ_POST_BUSY;
3546                 }
3547 
3548                 IBCM_REF_CNT_INCR(statep);      /* for non-blocking post */
3549                 stored_state = statep->timer_stored_state;
3550                 stored_ap_state = statep->timer_stored_ap_state;
3551                 mutex_exit(&statep->state_mutex);
3552 
3553                 /* Post REQ MAD in non-blocking mode */
3554                 if (stored_state == IBCM_STATE_REQ_SENT) {
3555                         ibcm_insert_trace(statep, IBCM_TRACE_OUT_REQ_RETRY);
3556                         ibcm_post_rc_mad(statep, statep->stored_msg,
3557                             ibcm_post_req_complete, statep);
3558                 /* Post REQ MAD in non-blocking mode */
3559                 } else if (stored_state == IBCM_STATE_REP_WAIT) {
3560                         ibcm_insert_trace(statep, IBCM_TRACE_OUT_REQ_RETRY);
3561                         ibcm_post_rc_mad(statep, statep->stored_msg,
3562                             ibcm_post_rep_wait_complete, statep);
3563                 /* Post REP MAD in non-blocking mode */
3564                 } else if (stored_state == IBCM_STATE_REP_SENT) {
3565                         ibcm_insert_trace(statep, IBCM_TRACE_OUT_REP_RETRY);
3566                         ibcm_post_rc_mad(statep, statep->stored_msg,
3567                             ibcm_post_rep_complete, statep);
3568                 /* Post REP MAD in non-blocking mode */
3569                 } else if (stored_state == IBCM_STATE_MRA_REP_RCVD) {
3570                         ibcm_insert_trace(statep, IBCM_TRACE_OUT_REP_RETRY);
3571                         mutex_enter(&statep->state_mutex);
3572                         statep->mra_time = gethrtime();
3573                         mutex_exit(&statep->state_mutex);
3574                         ibcm_post_rc_mad(statep, statep->stored_msg,
3575                             ibcm_post_mra_rep_complete, statep);
3576                 /* Post DREQ MAD in non-blocking mode */
3577                 } else if (stored_state == IBCM_STATE_DREQ_SENT) {
3578                         mutex_enter(&statep->state_mutex);
3579                         if (statep->remaining_retry_cnt ==
3580                             statep->max_cm_retries)
3581                                 ibcm_insert_trace(statep,
3582                                     IBCM_TRACE_OUTGOING_DREQ);
3583                         else {
3584                                 ibcm_insert_trace(statep,
3585                                     IBCM_TRACE_OUT_DREQ_RETRY);
3586                                 statep->cm_retries++;
3587                                 ibcm_close_done(statep, 0);
3588                         }
3589                         mutex_exit(&statep->state_mutex);
3590                         ibcm_post_rc_mad(statep, statep->dreq_msg,
3591                             ibcm_post_dreq_complete, statep);
3592                 /* post LAP MAD in non-blocking mode */
3593                 } else if (stored_ap_state == IBCM_AP_STATE_LAP_SENT) {
3594                         ibcm_insert_trace(statep, IBCM_TRACE_OUT_LAP_RETRY);
3595                         ibcm_post_rc_mad(statep, statep->lapr_msg,
3596                             ibcm_post_lap_complete, statep);
3597                 /* post LAP MAD in non-blocking mode */
3598                 } else if (stored_ap_state == IBCM_AP_STATE_MRA_LAP_RCVD) {
3599                         ibcm_insert_trace(statep, IBCM_TRACE_OUT_LAP_RETRY);
3600                         mutex_enter(&statep->state_mutex);
3601                         statep->mra_time = gethrtime();
3602                         mutex_exit(&statep->state_mutex);
3603                         ibcm_post_rc_mad(statep, statep->lapr_msg,
3604                             ibcm_post_mra_lap_complete, statep);
3605                 }
3606                 return;
3607 
3608         } else if ((statep->state == IBCM_STATE_REQ_SENT) ||
3609             (statep->state == IBCM_STATE_REP_SENT) ||
3610             (statep->state == IBCM_STATE_MRA_REP_RCVD) ||
3611             (statep->state == IBCM_STATE_REP_WAIT)) {
3612 
3613                 /*
3614                  * MAX retries reached, send a REJ to the remote,
3615                  * and close the connection
3616                  */
3617                 statep->timedout_state = statep->state;
3618                 statep->state = IBCM_STATE_TIMED_OUT;
3619 
3620                 IBTF_DPRINTF_L3(cmlog, "ibcm_timeout_cb: "
3621                     "max retries done for statep 0x%p", statep);
3622                 statep->cm_retries++; /* cause conn trace to print */
3623                 mutex_exit(&statep->state_mutex);
3624 
3625                 if ((statep->timedout_state == IBCM_STATE_REP_SENT) ||
3626                     (statep->timedout_state == IBCM_STATE_MRA_REP_RCVD))
3627                         (void) ibcm_cep_to_error_state(statep);
3628 
3629                 /* Disassociate statep from QP */
3630                 IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
3631 
3632                 /*
3633                  * statep is in REJ SENT state, the only way to get deleted is
3634                  * the timeout callback that is set after posting REJ
3635                  * The thread processing is required where cm handler is
3636                  * specified
3637                  */
3638 
3639                 if (statep->cm_handler != NULL) {
3640                         /* Attach the statep to timeout list */
3641                         ibcm_add_tlist(statep);
3642                 } else {
3643                         ib_guid_t local_hca_guid;
3644 
3645                         mutex_enter(&statep->state_mutex);
3646 
3647                         /*
3648                          * statep->open_return_data is set for blocking
3649                          * No handler specified, hence signal blocked
3650                          * ibt_open_rc_channel from here
3651                          */
3652                         if (statep->open_return_data != NULL) {
3653                                 statep->open_return_data->rc_status =
3654                                     IBT_CM_TIMEOUT;
3655                                 statep->open_done = B_TRUE;
3656                                 cv_broadcast(&statep->block_client_cv);
3657                         }
3658 
3659                         mutex_exit(&statep->state_mutex);
3660 
3661                         local_hca_guid = h2b64(statep->local_hca_guid);
3662                         ibcm_post_rej_mad(statep, IBT_CM_TIMEOUT,
3663                             (statep->timedout_state == IBCM_STATE_REP_SENT ||
3664                             statep->timedout_state == IBCM_STATE_MRA_REP_RCVD) ?
3665                             IBT_CM_FAILURE_REP: IBT_CM_FAILURE_REQ,
3666                             &local_hca_guid, sizeof (ib_guid_t));
3667                 }
3668 
3669         } else if ((statep->ap_state == IBCM_AP_STATE_LAP_SENT) ||
3670             (statep->ap_state == IBCM_AP_STATE_MRA_LAP_RCVD)) {
3671 
3672                 IBTF_DPRINTF_L4(cmlog, "ibcm_timeout_cb: statep 0x%p "
3673                     "LAP timed out",  statep);
3674                 statep->timedout_state = statep->state;
3675                 /*
3676                  * This state setting ensures that the processing of DREQ is
3677                  * sequentialized, once this ap_state is set. If statep is
3678                  * attached to timeout list, it cannot be re-attached as long
3679                  * as in this state
3680                  */
3681                 statep->ap_state = IBCM_AP_STATE_TIMED_OUT;
3682                 ibcm_open_done(statep);
3683 
3684                 if (statep->cm_handler != NULL) {
3685                         /* Attach statep to timeout list - thread handling */
3686                         ibcm_add_tlist(statep);
3687                 } else if (statep->ap_return_data != NULL) {
3688                         /*
3689                          * statep->ap_return_data is initialized for blocking in
3690                          * ibt_set_alt_path(), signal the waiting CV
3691                          */
3692                         statep->ap_return_data->ap_status = IBT_CM_AP_TIMEOUT;
3693                         statep->ap_done = B_TRUE;
3694                         cv_broadcast(&statep->block_client_cv);
3695 
3696                         statep->ap_state = IBCM_AP_STATE_IDLE;
3697                         /* Wake up threads waiting for LAP/APR to complete */
3698                         cv_broadcast(&statep->block_mad_cv);
3699                 }
3700                 mutex_exit(&statep->state_mutex);
3701 
3702         } else if (statep->state == IBCM_STATE_DREQ_SENT) {
3703 
3704                 statep->timedout_state = statep->state;
3705                 statep->state = IBCM_STATE_TIMED_OUT;
3706 
3707                 /*
3708                  * The logic below is necessary, for a race situation between
3709                  * ibt_close_rc_channel with no callbacks option and CM's
3710                  * internal stale connection handling on the same connection
3711                  */
3712                 if (statep->close_nocb_state != IBCM_FAIL) {
3713                         ASSERT(statep->close_nocb_state == IBCM_UNBLOCK);
3714                         ibtl_cm_chan_is_closing(statep->channel);
3715                         statep->close_nocb_state = IBCM_BLOCK;
3716                 }
3717 
3718                 mutex_exit(&statep->state_mutex);
3719 
3720                 /*
3721                  * If cm handler is specified, then invoke handler for
3722                  * the DREQ timeout
3723                  */
3724                 if (statep->cm_handler != NULL) {
3725                         ibcm_add_tlist(statep);
3726                         return;
3727                 }
3728 
3729                 ibcm_process_dreq_timeout(statep);
3730         } else {
3731 
3732 #ifdef DEBUG
3733                 if (ibcm_test_mode > 0)
3734                         IBTF_DPRINTF_L2(cmlog, "ibcm_timeout_cb: "
3735                             "Unexpected unhandled timeout  for statep 0x%p "
3736                             "state %d", statep, statep->state);
3737 #endif
3738                 mutex_exit(&statep->state_mutex);
3739         }
3740 }
3741 
3742 /*
3743  * Following are set of ibmf send callback routines that are used when posting
3744  * various CM MADs in non-blocking post mode
3745  */
3746 
3747 /*ARGSUSED*/
3748 void
3749 ibcm_post_req_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp, void *args)
3750 {
3751         ibcm_state_data_t       *statep = (ibcm_state_data_t *)args;
3752 
3753         IBTF_DPRINTF_L4(cmlog, "ibcm_post_req_complete statep %p ", statep);
3754 
3755         mutex_enter(&statep->state_mutex);
3756         ibcm_flow_dec(statep->post_time, "REQ");
3757         ibcm_insert_trace(statep, IBCM_TRACE_REQ_POST_COMPLETE);
3758 
3759         statep->send_mad_flags &= ~IBCM_REQ_POST_BUSY;
3760 
3761         /* signal any waiting threads for REQ MAD to become available */
3762         cv_signal(&statep->block_mad_cv);
3763 
3764         if (statep->state == IBCM_STATE_REQ_SENT)
3765                 statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
3766 
3767         IBCM_REF_CNT_DECR(statep);
3768         mutex_exit(&statep->state_mutex);
3769 }
3770 
3771 /*ARGSUSED*/
3772 void
3773 ibcm_post_rep_wait_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3774     void *args)
3775 {
3776         ibcm_state_data_t       *statep = (ibcm_state_data_t *)args;
3777 
3778         IBTF_DPRINTF_L4(cmlog, "ibcm_post_rep_wait_complete statep %p", statep);
3779 
3780         mutex_enter(&statep->state_mutex);
3781         ibcm_flow_dec(statep->post_time, "REQ_RETRY");
3782         ibcm_insert_trace(statep, IBCM_TRACE_REQ_POST_COMPLETE);
3783         if (statep->state == IBCM_STATE_REP_WAIT)
3784                 statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
3785         IBCM_REF_CNT_DECR(statep);
3786         mutex_exit(&statep->state_mutex);
3787 }
3788 
3789 /*ARGSUSED*/
3790 void
3791 ibcm_post_rep_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp, void *args)
3792 {
3793         ibcm_state_data_t       *statep = (ibcm_state_data_t *)args;
3794 
3795         IBTF_DPRINTF_L4(cmlog, "ibcm_post_rep_complete statep %p", statep);
3796 
3797         mutex_enter(&statep->state_mutex);
3798         ibcm_flow_dec(statep->post_time, "REP");
3799         ibcm_insert_trace(statep, IBCM_TRACE_REP_POST_COMPLETE);
3800         statep->send_mad_flags &= ~IBCM_REP_POST_BUSY;
3801         if (statep->state == IBCM_STATE_REP_SENT)
3802                 statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
3803         IBCM_REF_CNT_DECR(statep);
3804         mutex_exit(&statep->state_mutex);
3805 }
3806 
3807 /*ARGSUSED*/
3808 void
3809 ibcm_resend_post_rep_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3810     void *args)
3811 {
3812         ibcm_state_data_t       *statep = (ibcm_state_data_t *)args;
3813 
3814         IBTF_DPRINTF_L4(cmlog, "ibcm_resend_post_rep_complete(%p)", statep);
3815 
3816         mutex_enter(&statep->state_mutex);
3817         ibcm_flow_dec(statep->post_time, "REP_RETRY");
3818         ibcm_insert_trace(statep, IBCM_TRACE_REP_POST_COMPLETE);
3819         statep->send_mad_flags &= ~IBCM_REP_POST_BUSY;
3820 
3821         /* No new timeout is set for resending a REP MAD for an incoming REQ */
3822         IBCM_REF_CNT_DECR(statep);
3823         mutex_exit(&statep->state_mutex);
3824 }
3825 
3826 /*ARGSUSED*/
3827 void
3828 ibcm_post_mra_rep_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3829     void *args)
3830 {
3831         ibcm_state_data_t       *statep = (ibcm_state_data_t *)args;
3832 
3833         IBTF_DPRINTF_L4(cmlog, "ibcm_post_mra_rep_complete statep %p", statep);
3834 
3835         mutex_enter(&statep->state_mutex);
3836         ibcm_flow_dec(statep->mra_time, "MRA_REP");
3837         ibcm_insert_trace(statep, IBCM_TRACE_REP_POST_COMPLETE);
3838         if (statep->state == IBCM_STATE_MRA_REP_RCVD)
3839                 statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
3840         IBCM_REF_CNT_DECR(statep);
3841         mutex_exit(&statep->state_mutex);
3842 }
3843 
3844 
3845 /*ARGSUSED*/
3846 void
3847 ibcm_post_mra_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3848     void *args)
3849 {
3850         ibcm_state_data_t       *statep = (ibcm_state_data_t *)args;
3851 
3852         IBTF_DPRINTF_L4(cmlog, "ibcm_post_mra_complete statep %p", statep);
3853 
3854         mutex_enter(&statep->state_mutex);
3855         ibcm_flow_dec(statep->mra_time, "MRA");
3856         ibcm_insert_trace(statep, IBCM_TRACE_MRA_POST_COMPLETE);
3857 
3858         if (statep->delete_mra_msg == B_TRUE) {
3859                 ibmf_msg_t      *mra_msg;
3860 
3861                 mra_msg = statep->mra_msg;
3862                 statep->mra_msg = NULL;
3863                 mutex_exit(&statep->state_mutex);
3864                 (void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl,
3865                     &mra_msg);
3866                 mutex_enter(&statep->state_mutex);
3867         }
3868         statep->send_mad_flags &= ~IBCM_MRA_POST_BUSY;
3869         IBCM_REF_CNT_DECR(statep);
3870         mutex_exit(&statep->state_mutex);
3871 }
3872 
3873 /*ARGSUSED*/
3874 void
3875 ibcm_post_dreq_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp, void *args)
3876 {
3877         ibcm_state_data_t       *statep = (ibcm_state_data_t *)args;
3878 
3879         IBTF_DPRINTF_L4(cmlog, "ibcm_post_dreq_complete statep %p", statep);
3880 
3881         mutex_enter(&statep->state_mutex);
3882         ibcm_flow_dec(statep->post_time, "DREQ");
3883         ibcm_insert_trace(statep, IBCM_TRACE_DREQ_POST_COMPLETE);
3884         if (statep->state == IBCM_STATE_DREQ_SENT)
3885                 statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
3886         ibcm_close_done(statep, 1);
3887         IBCM_REF_CNT_DECR(statep);
3888         mutex_exit(&statep->state_mutex);
3889 }
3890 
3891 /*ARGSUSED*/
3892 void
3893 ibcm_post_lap_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp, void *args)
3894 {
3895         ibcm_state_data_t       *statep = (ibcm_state_data_t *)args;
3896 
3897         IBTF_DPRINTF_L4(cmlog, "ibcm_post_lap_complete statep %p", statep);
3898 
3899         mutex_enter(&statep->state_mutex);
3900         ibcm_flow_dec(statep->post_time, "LAP");
3901         ibcm_insert_trace(statep, IBCM_TRACE_LAP_POST_COMPLETE);
3902         if (statep->ap_state == IBCM_AP_STATE_LAP_SENT)
3903                 statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
3904         IBCM_REF_CNT_DECR(statep);
3905         mutex_exit(&statep->state_mutex);
3906 }
3907 
3908 /*ARGSUSED*/
3909 void
3910 ibcm_post_mra_lap_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3911     void *args)
3912 {
3913         ibcm_state_data_t       *statep = (ibcm_state_data_t *)args;
3914 
3915         IBTF_DPRINTF_L4(cmlog, "ibcm_post_mra_lap_complete statep %p", statep);
3916 
3917         mutex_enter(&statep->state_mutex);
3918         ibcm_flow_dec(statep->mra_time, "MRA_LAP");
3919         ibcm_insert_trace(statep, IBCM_TRACE_LAP_POST_COMPLETE);
3920         if (statep->ap_state == IBCM_AP_STATE_MRA_LAP_RCVD)
3921                 statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
3922         IBCM_REF_CNT_DECR(statep);
3923         mutex_exit(&statep->state_mutex);
3924 }
3925 
3926 /*ARGSUSED*/
3927 void
3928 ibcm_post_rej_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3929     void *args)
3930 {
3931         ibcm_state_data_t       *statep = (ibcm_state_data_t *)args;
3932 
3933         IBTF_DPRINTF_L4(cmlog, "ibcm_post_rej_complete statep %p", statep);
3934 
3935         mutex_enter(&statep->state_mutex);
3936         ibcm_flow_dec(statep->post_time, "REJ");
3937         ibcm_insert_trace(statep, IBCM_TRACE_REJ_POST_COMPLETE);
3938         statep->send_mad_flags &= ~IBCM_REJ_POST_BUSY;
3939         if (statep->state == IBCM_STATE_REJ_SENT) {
3940                 statep->remaining_retry_cnt = 0;
3941 
3942                 /* wait until all possible retransmits of REQ/REP happened */
3943                 statep->timerid = IBCM_TIMEOUT(statep,
3944                     statep->timer_value * statep->max_cm_retries);
3945         }
3946 
3947         IBCM_REF_CNT_DECR(statep);
3948         mutex_exit(&statep->state_mutex);
3949 }
3950 
3951 /*ARGSUSED*/
3952 void
3953 ibcm_post_rtu_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3954     void *args)
3955 {
3956         ibcm_state_data_t       *statep = (ibcm_state_data_t *)args;
3957 
3958         IBTF_DPRINTF_L4(cmlog, "ibcm_post_rtu_complete statep %p", statep);
3959 
3960         mutex_enter(&statep->state_mutex);
3961         ibcm_flow_dec(statep->post_time, "RTU");
3962         ibcm_insert_trace(statep, IBCM_TRACE_RTU_POST_COMPLETE);
3963         statep->send_mad_flags &= ~IBCM_RTU_POST_BUSY;
3964         IBCM_REF_CNT_DECR(statep);
3965         ibcm_open_done(statep);
3966         mutex_exit(&statep->state_mutex);
3967 }
3968 
3969 /*ARGSUSED*/
3970 void
3971 ibcm_post_apr_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3972     void *args)
3973 {
3974         ibcm_state_data_t       *statep = (ibcm_state_data_t *)args;
3975 
3976         IBTF_DPRINTF_L4(cmlog, "ibcm_post_apr_complete statep %p", statep);
3977 
3978         mutex_enter(&statep->state_mutex);
3979         ibcm_flow_dec(statep->post_time, "APR");
3980         ibcm_insert_trace(statep, IBCM_TRACE_APR_POST_COMPLETE);
3981         /* As long as one APR mad in transit, no retransmits are allowed */
3982         statep->ap_state = IBCM_AP_STATE_IDLE;
3983 
3984         /* unblock any DREQ threads and close channels */
3985         cv_broadcast(&statep->block_mad_cv);
3986         IBCM_REF_CNT_DECR(statep); /* decrement the ref count */
3987         mutex_exit(&statep->state_mutex);
3988 
3989 }
3990 
3991 /*ARGSUSED*/
3992 void
3993 ibcm_post_stored_apr_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3994     void *args)
3995 {
3996         ibmf_msg_t      *ibmf_apr_msg = (ibmf_msg_t *)args;
3997 
3998         IBTF_DPRINTF_L4(cmlog, "ibcm_post_stored_apr_complete args %p", args);
3999 
4000         ibcm_flow_dec(0, "APR_RESEND");
4001         (void) ibcm_free_out_msg(ibmf_handle, &ibmf_apr_msg);
4002 }
4003 
4004 /*ARGSUSED*/
4005 void
4006 ibcm_post_drep_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
4007     void *args)
4008 {
4009         ibcm_state_data_t       *statep = (ibcm_state_data_t *)args;
4010 
4011         IBTF_DPRINTF_L4(cmlog, "ibcm_post_drep_complete statep %p", statep);
4012 
4013         mutex_enter(&statep->state_mutex);
4014         ibcm_flow_dec(statep->post_time, "DREP");
4015         ibcm_insert_trace(statep, IBCM_TRACE_DREP_POST_COMPLETE);
4016         statep->send_mad_flags &= ~IBCM_REJ_POST_BUSY;
4017 
4018         if (statep->state == IBCM_STATE_DREQ_RCVD) {
4019 
4020                 ibcm_close_done(statep, 1);
4021                 statep->state = IBCM_STATE_TIMEWAIT;
4022 
4023                 /*
4024                  * For passive side CM set it to remote_ack_delay
4025                  * For active side CM add the pkt_life_time * 2
4026                  */
4027                 statep->timer_value = statep->remote_ack_delay;
4028                 if (statep->mode == IBCM_ACTIVE_MODE)
4029                         statep->timer_value += (2 * statep->pkt_life_time);
4030                 statep->remaining_retry_cnt = 0;
4031                 statep->timer_stored_state = statep->state;
4032                 statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
4033         }
4034 
4035         IBCM_REF_CNT_DECR(statep);
4036         mutex_exit(&statep->state_mutex);
4037 }
4038 
4039 /*ARGSUSED*/
4040 void
4041 ibcm_post_sidr_rep_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
4042     void *args)
4043 {
4044         ibcm_ud_state_data_t    *ud_statep = (ibcm_ud_state_data_t *)args;
4045 
4046         IBTF_DPRINTF_L4(cmlog, "ibcm_post_sidr_rep_complete ud_statep %p",
4047             ud_statep);
4048 
4049         ibcm_flow_dec(0, "SIDR_REP");
4050         mutex_enter(&ud_statep->ud_state_mutex);
4051         ud_statep->ud_send_mad_flags &= ~IBCM_SREP_POST_BUSY;
4052         ud_statep->ud_remaining_retry_cnt = 0;
4053         if (ud_statep->ud_state == IBCM_STATE_SIDR_REP_SENT)
4054                 ud_statep->ud_timerid = IBCM_UD_TIMEOUT(ud_statep,
4055                     ud_statep->ud_timer_value);
4056         IBCM_UD_REF_CNT_DECR(ud_statep);
4057         mutex_exit(&ud_statep->ud_state_mutex);
4058 
4059 }
4060 
4061 /*ARGSUSED*/
4062 void
4063 ibcm_post_sidr_req_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
4064     void *args)
4065 {
4066         ibcm_ud_state_data_t    *ud_statep = (ibcm_ud_state_data_t *)args;
4067 
4068         IBTF_DPRINTF_L4(cmlog, "ibcm_post_sidr_req_complete ud_statep %p",
4069             ud_statep);
4070 
4071         ibcm_flow_dec(0, "SIDR_REQ");
4072         mutex_enter(&ud_statep->ud_state_mutex);
4073         if (ud_statep->ud_state == IBCM_STATE_SIDR_REQ_SENT)
4074                 ud_statep->ud_timerid = IBCM_UD_TIMEOUT(ud_statep,
4075                     ud_statep->ud_timer_value);
4076         IBCM_UD_REF_CNT_DECR(ud_statep);
4077         mutex_exit(&ud_statep->ud_state_mutex);
4078 
4079 }
4080 
4081 /*
4082  * ibcm_process_dreq_timeout:
4083  *      Called when the timer expires on DREP
4084  *
4085  * INPUTS:
4086  *      arg     - ibcm_state_data_t is passed
4087  *
4088  * RETURN VALUES: NONE
4089  */
4090 void
4091 ibcm_process_dreq_timeout(ibcm_state_data_t *statep)
4092 {
4093         mutex_enter(&statep->state_mutex);
4094 
4095         /* Max retries reached, move to the time wait state */
4096         statep->state = statep->timer_stored_state =
4097             IBCM_STATE_TIMEWAIT;
4098         ibcm_close_done(statep, 0);
4099 
4100         /* Set the TIME_WAIT state timer value */
4101         statep->timer_value = statep->remote_ack_delay;
4102         if (statep->mode == IBCM_ACTIVE_MODE) {
4103                 statep->timer_value += (2 * statep->pkt_life_time);
4104         }
4105 
4106         statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
4107 
4108         if (statep->close_ret_status)
4109                 if (statep->stale == B_TRUE)
4110                         *statep->close_ret_status = IBT_CM_CLOSED_STALE;
4111                 else *statep->close_ret_status = IBT_CM_CLOSED_DREQ_TIMEOUT;
4112 
4113         /* signal waiting CVs - blocking in ibt_close_channel() */
4114         statep->close_done = B_TRUE;
4115         if (statep->close_ret_priv_data_len != NULL)
4116                 *statep->close_ret_priv_data_len = 0;
4117 
4118         /* unblock any close channel with no callbacks option */
4119         statep->close_nocb_state = IBCM_FAIL;
4120 
4121         cv_broadcast(&statep->block_client_cv);
4122         mutex_exit(&statep->state_mutex);
4123 }
4124 
4125 /*
4126  * ibcm_add_tlist:
4127  *      Adds the given RC statep to timeout list
4128  *
4129  * INPUTS:
4130  *      arg     - ibcm_state_data_t is passed
4131  *
4132  * RETURN VALUES: NONE
4133  */
4134 void
4135 ibcm_add_tlist(ibcm_state_data_t *statep)
4136 {
4137         mutex_enter(&ibcm_timeout_list_lock);
4138 
4139         statep->timeout_next = NULL;
4140         if (ibcm_timeout_list_hdr == NULL) {
4141                 ibcm_timeout_list_hdr = statep;
4142         } else {
4143                 ibcm_timeout_list_tail->timeout_next = statep;
4144         }
4145 
4146         ibcm_timeout_list_tail = statep;
4147 
4148         cv_signal(&ibcm_timeout_list_cv);
4149 
4150         mutex_exit(&ibcm_timeout_list_lock);
4151         IBTF_DPRINTF_L3(cmlog, "ibcm_add_tlist: "
4152             "attached state = %p to timeout list", statep);
4153 }
4154 
4155 void
4156 ibcm_run_tlist_thread(void)
4157 {
4158         mutex_enter(&ibcm_timeout_list_lock);
4159         cv_signal(&ibcm_timeout_list_cv);
4160         mutex_exit(&ibcm_timeout_list_lock);
4161 }
4162 
4163 /*
4164  * ibcm_add_ud_tlist:
4165  *      Adds the given UD statep to timeout list
4166  *
4167  * INPUTS:
4168  *      arg     - ibcm_ud_state_data_t is passed
4169  *
4170  * RETURN VALUES: NONE
4171  */
4172 void
4173 ibcm_add_ud_tlist(ibcm_ud_state_data_t *ud_statep)
4174 {
4175         mutex_enter(&ibcm_timeout_list_lock);
4176 
4177         ud_statep->ud_timeout_next = NULL;
4178         if (ibcm_ud_timeout_list_hdr == NULL) {
4179                 ibcm_ud_timeout_list_hdr = ud_statep;
4180         } else {
4181                 ibcm_ud_timeout_list_tail->ud_timeout_next = ud_statep;
4182         }
4183 
4184         ibcm_ud_timeout_list_tail = ud_statep;
4185 
4186         cv_signal(&ibcm_timeout_list_cv);
4187 
4188         mutex_exit(&ibcm_timeout_list_lock);
4189         IBTF_DPRINTF_L3(cmlog, "ibcm_add_ud_tlist: "
4190             "attached state = %p to ud timeout list", ud_statep);
4191 }
4192 
4193 /*
4194  * ibcm_process_tlist:
4195  *      Thread that processes all the RC and UD statep's from
4196  *      the appropriate lists
4197  *
4198  * INPUTS:
4199  *      NONE
4200  *
4201  * RETURN VALUES: NONE
4202  */
4203 void
4204 ibcm_process_tlist()
4205 {
4206         ibcm_state_data_t       *statep;
4207         ibcm_ud_state_data_t    *ud_statep;
4208         callb_cpr_t             cprinfo;
4209 
4210         IBTF_DPRINTF_L5(cmlog, "ibcm_process_tlist: thread started");
4211 
4212         mutex_enter(&ibcm_timeout_list_lock);
4213 
4214         CALLB_CPR_INIT(&cprinfo, &ibcm_timeout_list_lock, callb_generic_cpr,
4215             "ibcm_process_tlist");
4216 
4217         for (;;) {
4218                 if (ibcm_timeout_list_flags & IBCM_TIMEOUT_THREAD_EXIT) {
4219                         /* The thread needs to exit */
4220                         cv_signal(&ibcm_timeout_thread_done_cv);
4221                         break;
4222                 }
4223                 mutex_exit(&ibcm_timeout_list_lock);
4224                 ibcm_check_for_opens();
4225                 ibcm_check_for_async_close();
4226                 mutex_enter(&ibcm_timeout_list_lock);
4227 
4228                 /* First, handle pending RC statep's, followed by UD's */
4229                 if (ibcm_timeout_list_hdr != NULL) {
4230                         statep = ibcm_timeout_list_hdr;
4231                         ibcm_timeout_list_hdr = statep->timeout_next;
4232 
4233                         if (ibcm_timeout_list_hdr == NULL)
4234                                 ibcm_timeout_list_tail = NULL;
4235 
4236                         statep->timeout_next = NULL;
4237 
4238                         mutex_exit(&ibcm_timeout_list_lock);
4239                         IBTF_DPRINTF_L3(cmlog, "ibcm_process_tlist: "
4240                             "scheduling state = %p", statep);
4241                         ibcm_timeout_client_cb(statep);
4242                         mutex_enter(&ibcm_timeout_list_lock);
4243                 } else if (ibcm_ud_timeout_list_hdr != NULL) {
4244                         ud_statep = ibcm_ud_timeout_list_hdr;
4245                         ibcm_ud_timeout_list_hdr = ud_statep->ud_timeout_next;
4246 
4247                         if (ibcm_ud_timeout_list_hdr == NULL)
4248                                 ibcm_ud_timeout_list_tail = NULL;
4249 
4250                         ud_statep->ud_timeout_next = NULL;
4251 
4252                         mutex_exit(&ibcm_timeout_list_lock);
4253                         IBTF_DPRINTF_L3(cmlog, "ibcm_process_tlist: "
4254                             "ud scheduling state = %p", ud_statep);
4255                         ibcm_ud_timeout_client_cb(ud_statep);
4256                         mutex_enter(&ibcm_timeout_list_lock);
4257                 } else {
4258                         CALLB_CPR_SAFE_BEGIN(&cprinfo);
4259                         cv_wait(&ibcm_timeout_list_cv, &ibcm_timeout_list_lock);
4260                         CALLB_CPR_SAFE_END(&cprinfo, &ibcm_timeout_list_lock);
4261                 }
4262         }
4263 
4264 #ifndef __lock_lint
4265         CALLB_CPR_EXIT(&cprinfo);   /* mutex_exit */
4266 #endif
4267 }
4268 
4269 
4270 /*
4271  * ibcm_timeout_client_cb:
4272  *      Called from timeout thread processing
4273  *      Primary purpose is to call client handler
4274  *
4275  * INPUTS:
4276  *      arg     - ibcm_state_data_t is passed
4277  *
4278  * RETURN VALUES: NONE
4279  */
4280 void
4281 ibcm_timeout_client_cb(ibcm_state_data_t *statep)
4282 {
4283         mutex_enter(&statep->state_mutex);
4284 
4285         if ((statep->state == IBCM_STATE_DELETE) &&
4286             (statep->recycle_arg != NULL)) {
4287                 struct ibcm_taskq_recycle_arg_s *recycle_arg;
4288 
4289                 recycle_arg = statep->recycle_arg;
4290                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
4291                 statep->recycle_arg = NULL;
4292                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
4293                 mutex_exit(&statep->state_mutex);
4294                 (void) ibcm_process_rc_recycle(recycle_arg);
4295                 ibcm_delete_state_data(statep);
4296                 return;
4297         }
4298 
4299         if ((statep->state == IBCM_STATE_DELETE) &&
4300             (statep->delete_state_data == B_TRUE)) {
4301                 mutex_exit(&statep->state_mutex);
4302                 ibcm_dealloc_state_data(statep);
4303                 return;
4304         }
4305 
4306         /* Else, it must be in TIMEOUT state, do the necessary processing */
4307         if (statep->state == IBCM_STATE_TIMED_OUT) {
4308                 void            *data;
4309                 uint8_t         cf_msg;
4310                 ib_guid_t       local_hca_guid;
4311 
4312                 mutex_exit(&statep->state_mutex);
4313 
4314                 if (statep->timedout_state == IBCM_STATE_DREQ_SENT) {
4315                         ibt_cm_event_t          event;
4316                         ibt_cm_return_args_t    ret_args;
4317 
4318                         bzero(&event, sizeof (event));
4319                         bzero(&ret_args, sizeof (ret_args));
4320 
4321                         event.cm_type = IBT_CM_EVENT_CONN_CLOSED;
4322                         event.cm_channel = statep->channel;
4323                         event.cm_session_id = NULL;
4324                         event.cm_priv_data = NULL;
4325                         event.cm_priv_data_len = 0;
4326 
4327                         if (statep->stale == B_TRUE)
4328                                 event.cm_event.closed = IBT_CM_CLOSED_STALE;
4329                         else event.cm_event.closed = IBT_CM_CLOSED_DREQ_TIMEOUT;
4330 
4331                         /*
4332                          * cm handler cannot be non-NULL, as that check is
4333                          * already made in ibcm_timeout_cb
4334                          */
4335                         ibcm_insert_trace(statep,
4336                             IBCM_TRACE_CALLED_CONN_CLOSE_EVENT);
4337 
4338                         (void) statep->cm_handler(statep->state_cm_private,
4339                             &event, &ret_args, NULL, 0);
4340 
4341                         ibcm_insert_trace(statep,
4342                             IBCM_TRACE_RET_CONN_CLOSE_EVENT);
4343 
4344                         ibcm_process_dreq_timeout(statep);
4345                         return;
4346                 }
4347 
4348                 data = ((ibcm_rej_msg_t *)
4349                     IBCM_OUT_MSGP(statep->stored_msg))->rej_private_data;
4350 
4351                 if ((statep->timedout_state == IBCM_STATE_REQ_SENT) ||
4352                     (statep->timedout_state == IBCM_STATE_REP_WAIT)) {
4353                         cf_msg = IBT_CM_FAILURE_REQ;
4354                 } else {
4355                         ASSERT(
4356                             (statep->timedout_state == IBCM_STATE_REP_SENT) ||
4357                             (statep->timedout_state ==
4358                             IBCM_STATE_MRA_REP_RCVD));
4359                         cf_msg = IBT_CM_FAILURE_REP;
4360                 }
4361 
4362                 /*
4363                  * Invoke the CM handler w/ event IBT_CM_EVENT_TIMEOUT
4364                  * This callback happens for only active non blocking or
4365                  * passive client
4366                  */
4367                 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_TIMEOUT,
4368                     cf_msg, IBT_CM_TIMEOUT, data, IBT_REJ_PRIV_DATA_SZ);
4369 
4370                 /* signal the blocked ibt_open_rc_channel */
4371                 mutex_enter(&statep->state_mutex);
4372 
4373                 /*
4374                  * statep->open_return_data is set for blocking
4375                  * signal the blocked ibt_open_rc_channel
4376                  */
4377                 if (statep->open_return_data != NULL) {
4378                         statep->open_return_data->rc_status = IBT_CM_TIMEOUT;
4379                         statep->open_done = B_TRUE;
4380                         cv_broadcast(&statep->block_client_cv);
4381                 }
4382 
4383                 mutex_exit(&statep->state_mutex);
4384 
4385                 local_hca_guid = h2b64(statep->local_hca_guid);
4386                 ibcm_post_rej_mad(statep, IBT_CM_TIMEOUT,
4387                     IBT_CM_FAILURE_UNKNOWN, &local_hca_guid,
4388                     sizeof (ib_guid_t));
4389         } else if (statep->ap_state == IBCM_AP_STATE_TIMED_OUT) {
4390 
4391                 mutex_exit(&statep->state_mutex);
4392 
4393                 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_TIMEOUT,
4394                     IBT_CM_FAILURE_LAP, IBT_CM_TIMEOUT, NULL, 0);
4395 
4396                 /* Now wake up threads waiting for LAP/APR to complete */
4397                 mutex_enter(&statep->state_mutex);
4398                 /*
4399                  * statep->ap_return_data is initialized for blocking in
4400                  * ibt_set_alt_path(), signal the waiting CV
4401                  */
4402                 if (statep->ap_return_data != NULL) {
4403                         statep->ap_return_data->ap_status = IBT_CM_AP_TIMEOUT;
4404                         statep->ap_done = B_TRUE;
4405                         cv_broadcast(&statep->block_client_cv);
4406                 }
4407                 statep->ap_state = IBCM_AP_STATE_IDLE;
4408                 cv_broadcast(&statep->block_mad_cv);
4409                 mutex_exit(&statep->state_mutex);
4410         } else {
4411                 IBTF_DPRINTF_L2(cmlog, "ibcm_timeout_client_cb "
4412                     "Unexpected else path statep %p state %d ap_state %d",
4413                     statep, statep->state, statep->ap_state);
4414                 mutex_exit(&statep->state_mutex);
4415 
4416         }
4417 }
4418 
4419 /*
4420  * ibcm_ud_timeout_client_cb:
4421  *      Called from UD timeout thread processing
4422  *      Primary purpose is to call client handler
4423  *
4424  * INPUTS:
4425  *      arg     - ibcm_ud_state_data_t is passed
4426  *
4427  * RETURN VALUES: NONE
4428  */
4429 void
4430 ibcm_ud_timeout_client_cb(ibcm_ud_state_data_t *ud_statep)
4431 {
4432         ibt_cm_ud_event_t       ud_event;
4433 
4434         mutex_enter(&ud_statep->ud_state_mutex);
4435 
4436         if ((ud_statep->ud_state == IBCM_STATE_DELETE) &&
4437             (ud_statep->ud_delete_state_data == B_TRUE)) {
4438 
4439                 mutex_exit(&ud_statep->ud_state_mutex);
4440                 ibcm_dealloc_ud_state_data(ud_statep);
4441                 return;
4442         } else
4443                 mutex_exit(&ud_statep->ud_state_mutex);
4444 
4445         /* Fill in ibt_cm_ud_event_t */
4446         ud_event.cm_type = IBT_CM_UD_EVENT_SIDR_REP;
4447         ud_event.cm_session_id = NULL;
4448         ud_event.cm_event.sidr_rep.srep_status = IBT_CM_SREP_TIMEOUT;
4449 
4450         (void) ud_statep->ud_cm_handler(ud_statep->ud_state_cm_private,
4451             &ud_event, NULL, NULL, 0);
4452 
4453         /* Delete UD state data now, finally done with it */
4454         ibcm_delete_ud_state_data(ud_statep);
4455 }
4456 
4457 
4458 /*
4459  * ibcm_process_sidr_req_msg:
4460  *      This call processes an incoming SIDR REQ
4461  *
4462  * INPUTS:
4463  *      hcap            - HCA entry pointer
4464  *      input_madp      - Incoming CM SIDR REQ MAD
4465  *      cm_mad_addr     - Address information for the MAD to be posted
4466  *
4467  * RETURN VALUE:
4468  *      NONE
4469  */
4470 void
4471 ibcm_process_sidr_req_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
4472     ibcm_mad_addr_t *cm_mad_addr)
4473 {
4474         ib_gid_t                gid;
4475         ib_lid_t                lid;
4476         uint32_t                req_id;
4477         ibcm_status_t           state_lookup_status;
4478         ibcm_status_t           cm_status;
4479         ibt_sidr_status_t       sidr_status;
4480         ibcm_svc_info_t         *svc_infop;
4481         ibcm_svc_bind_t         *svc_bindp;
4482         ibcm_svc_bind_t         *tmp_bindp;
4483         ibcm_sidr_req_msg_t     *sidr_reqp = (ibcm_sidr_req_msg_t *)
4484             (&input_madp[IBCM_MAD_HDR_SIZE]);
4485         ibcm_ud_state_data_t    *ud_statep = NULL;
4486         ibcm_sidr_srch_t        srch_sidr;
4487         ib_pkey_t               pkey;
4488         uint8_t                 port_num;
4489         ib_guid_t               hca_guid;
4490 
4491         IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_req_msg:");
4492 
4493         hca_guid = hcap->hca_guid;
4494         port_num = cm_mad_addr->port_num;
4495 
4496         /* Figure out LID, GID, RequestId for svc_id lookup */
4497         lid = cm_mad_addr->rcvd_addr.ia_remote_lid;
4498         req_id = b2h32(sidr_reqp->sidr_req_request_id);
4499         pkey = b2h16(sidr_reqp->sidr_req_pkey);
4500         if (cm_mad_addr->grh_exists == B_TRUE)
4501                 gid = cm_mad_addr->grh_hdr.ig_sender_gid;
4502         else
4503                 gid.gid_prefix = gid.gid_guid = 0;
4504 
4505         /*
4506          * Lookup for an existing state structure
4507          * - if lookup fails it creates a new ud_state struct
4508          * No need to hold a lock across the call to ibcm_find_sidr_entry() as
4509          * the list lock is held in that function to find the matching entry.
4510          */
4511 
4512         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(srch_sidr))
4513 
4514         srch_sidr.srch_lid = lid;
4515         srch_sidr.srch_gid = gid;
4516         srch_sidr.srch_grh_exists = cm_mad_addr->grh_exists;
4517         srch_sidr.srch_req_id = req_id;
4518         srch_sidr.srch_mode = IBCM_PASSIVE_MODE;
4519 
4520         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(srch_sidr))
4521 
4522         rw_enter(&hcap->hca_sidr_list_lock, RW_WRITER);
4523         state_lookup_status = ibcm_find_sidr_entry(&srch_sidr, hcap, &ud_statep,
4524             IBCM_FLAG_LOOKUP_AND_ADD);
4525         rw_exit(&hcap->hca_sidr_list_lock);
4526 
4527         IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_req_msg: ud_statep 0x%p "
4528             "lookup status %x", ud_statep, state_lookup_status);
4529 
4530         if (state_lookup_status == IBCM_LOOKUP_NEW) {
4531 
4532                 /* Increment hca's resource count */
4533                 ibcm_inc_hca_res_cnt(hcap);
4534 
4535                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ud_statep))
4536 
4537                 /*
4538                  * Allocate CM MAD for a response
4539                  * This MAD is deallocated on state structure delete
4540                  * and re-used for all outgoing MADs for this connection.
4541                  * If MAD allocation fails, delete the ud statep
4542                  */
4543                 if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl,
4544                     &ud_statep->ud_stored_msg, MAD_METHOD_SEND) !=
4545                     IBT_SUCCESS) {
4546                         mutex_enter(&ud_statep->ud_state_mutex);
4547                         IBCM_UD_REF_CNT_DECR(ud_statep);
4548                         mutex_exit(&ud_statep->ud_state_mutex);
4549                         ibcm_delete_ud_state_data(ud_statep);
4550                         return;
4551                 }
4552 
4553                 /* Lookup for service */
4554                 ud_statep->ud_svc_id = b2h64(sidr_reqp->sidr_req_service_id);
4555                 ud_statep->ud_state  = IBCM_STATE_SIDR_REQ_RCVD;
4556                 ud_statep->ud_clnt_proceed = IBCM_BLOCK;
4557 
4558                 mutex_enter(&ibcm_svc_info_lock);
4559 
4560                 svc_infop = ibcm_find_svc_entry(ud_statep->ud_svc_id);
4561 
4562                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_req_msg: "
4563                     " ud_statep 0x%p svc_info %p", ud_statep, svc_infop);
4564 
4565                 /*
4566                  * No need to hold the ud state mutex, as no other thread
4567                  * modifies ud statep in IBCM_STATE_SIDR_REQ_RCVD state
4568                  */
4569 
4570                 if (svc_infop != NULL) {
4571                         /* find the "bind" entry that enables this port */
4572 
4573                         svc_bindp = NULL;
4574                         tmp_bindp = svc_infop->svc_bind_list;
4575                         while (tmp_bindp) {
4576                                 if (tmp_bindp->sbind_hcaguid == hca_guid &&
4577                                     tmp_bindp->sbind_port == port_num) {
4578                                         if (gid.gid_guid ==
4579                                             tmp_bindp->sbind_gid.gid_guid &&
4580                                             gid.gid_prefix ==
4581                                             tmp_bindp->sbind_gid.gid_prefix) {
4582                                                 /* a really good match */
4583                                                 svc_bindp = tmp_bindp;
4584                                                 if (pkey ==
4585                                                     tmp_bindp->sbind_pkey)
4586                                                         /* absolute best */
4587                                                         break;
4588                                         } else if (svc_bindp == NULL) {
4589                                                 /* port match => a good match */
4590                                                 svc_bindp = tmp_bindp;
4591                                         }
4592                                 }
4593                                 tmp_bindp = tmp_bindp->sbind_link;
4594                         }
4595                         if (svc_bindp == NULL) {
4596                                 svc_infop = NULL;
4597                         }
4598                 }
4599 
4600                 IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->TransactionID =
4601                     ((ib_mad_hdr_t *)(input_madp))->TransactionID;
4602 
4603                 ibcm_build_reply_mad_addr(cm_mad_addr,
4604                     &ud_statep->ud_stored_reply_addr);
4605 
4606                 if (ud_statep->ud_stored_reply_addr.cm_qp_entry == NULL) {
4607 
4608                         mutex_exit(&ibcm_svc_info_lock);
4609 
4610                         /* Not much choice. CM MADs cannot go on QP1 */
4611                         mutex_enter(&ud_statep->ud_state_mutex);
4612                         IBCM_UD_REF_CNT_DECR(ud_statep);
4613                         ud_statep->ud_state = IBCM_STATE_DELETE;
4614                         mutex_exit(&ud_statep->ud_state_mutex);
4615 
4616                         ibcm_delete_ud_state_data(ud_statep);
4617                         return;
4618                 }
4619 
4620                 if (svc_infop == NULL || svc_infop->svc_ud_handler == NULL) {
4621                         /*
4622                          * Don't have a record of Service ID in CM's
4623                          * internal list registered at this gid/lid.
4624                          * So, send out Service ID not supported SIDR REP msg
4625                          */
4626                         sidr_status = IBT_CM_SREP_SID_INVALID;
4627                 } else {
4628                         ud_statep->ud_cm_handler = svc_infop->svc_ud_handler;
4629                         ud_statep->ud_state_cm_private =
4630                             svc_bindp->sbind_cm_private;
4631                         IBCM_SVC_INCR(svc_infop);
4632                         mutex_exit(&ibcm_svc_info_lock);
4633 
4634                         /* Call Client's UD handler */
4635                         cm_status = ibcm_sidr_req_ud_handler(ud_statep,
4636                             sidr_reqp, cm_mad_addr, &sidr_status);
4637 
4638                         mutex_enter(&ibcm_svc_info_lock);
4639                         IBCM_SVC_DECR(svc_infop);
4640                 }
4641 
4642                 mutex_exit(&ibcm_svc_info_lock);
4643 
4644                 if (cm_status == IBCM_DEFER) {
4645                         IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_req_msg: "
4646                             "ud_statep 0x%p client returned DEFER response",
4647                             ud_statep);
4648                         return;
4649                 }
4650 
4651                 ibcm_post_sidr_rep_mad(ud_statep, sidr_status);
4652 
4653                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ud_statep))
4654 
4655                 mutex_enter(&ud_statep->ud_state_mutex);
4656                 IBCM_UD_REF_CNT_DECR(ud_statep);
4657                 mutex_exit(&ud_statep->ud_state_mutex);
4658         } else {
4659                 ASSERT(state_lookup_status == IBCM_LOOKUP_EXISTS);
4660 
4661                 mutex_enter(&ud_statep->ud_state_mutex);
4662 
4663                 if (ud_statep->ud_state == IBCM_STATE_SIDR_REP_SENT)
4664                         ibcm_resend_srep_mad(ud_statep);
4665 
4666                 IBCM_UD_REF_CNT_DECR(ud_statep);
4667                 mutex_exit(&ud_statep->ud_state_mutex);
4668         }
4669 }
4670 
4671 
4672 /*
4673  * ibcm_process_sidr_rep_msg:
4674  *      This call processes an incoming SIDR REP
4675  *
4676  * INPUTS:
4677  *      hcap            - HCA entry pointer
4678  *      input_madp      - incoming CM SIDR REP MAD
4679  *      cm_mad_addr     - Address information for the MAD to be posted
4680  *
4681  * RETURN VALUE:
4682  *      NONE
4683  */
4684 void
4685 ibcm_process_sidr_rep_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
4686     ibcm_mad_addr_t *cm_mad_addr)
4687 {
4688         ib_lid_t                lid;
4689         ib_gid_t                gid;
4690         ibcm_status_t           status;
4691         ib_svc_id_t             tmp_svc_id;
4692         ibcm_sidr_rep_msg_t     *sidr_repp = (ibcm_sidr_rep_msg_t *)
4693             (&input_madp[IBCM_MAD_HDR_SIZE]);
4694         ibcm_ud_state_data_t    *ud_statep = NULL;
4695         ibcm_sidr_srch_t        srch_sidr;
4696 
4697         IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_rep_msg:");
4698 
4699         lid = cm_mad_addr->rcvd_addr.ia_local_lid;
4700         if (cm_mad_addr->grh_exists == B_TRUE)
4701                 gid = cm_mad_addr->grh_hdr.ig_recver_gid;
4702         else
4703                 gid.gid_prefix = gid.gid_guid = 0;
4704 
4705         IBTF_DPRINTF_L3(cmlog, "ibcm_process_sidr_rep_msg: QPN rcvd = %x",
4706             h2b32(sidr_repp->sidr_rep_qpn_plus) >> 8);
4707 
4708         /*
4709          * Lookup for an existing state structure.
4710          * No need to hold a lock as ibcm_find_sidr_entry() holds the
4711          * list lock to find the matching entry.
4712          */
4713         IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_rep: lid=%x, (%llX, %llX), "
4714             "grh = %x, id = %x", lid, gid.gid_prefix, gid.gid_guid,
4715             cm_mad_addr->grh_exists, sidr_repp->sidr_rep_request_id);
4716 
4717         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(srch_sidr))
4718 
4719         srch_sidr.srch_lid = lid;
4720         srch_sidr.srch_gid = gid;
4721         srch_sidr.srch_grh_exists = cm_mad_addr->grh_exists;
4722         srch_sidr.srch_req_id = b2h32(sidr_repp->sidr_rep_request_id);
4723         srch_sidr.srch_mode = IBCM_ACTIVE_MODE;
4724 
4725         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(srch_sidr))
4726 
4727         rw_enter(&hcap->hca_sidr_list_lock, RW_READER);
4728         status = ibcm_find_sidr_entry(&srch_sidr, hcap, &ud_statep,
4729             IBCM_FLAG_LOOKUP);
4730         rw_exit(&hcap->hca_sidr_list_lock);
4731 
4732         IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_rep_msg: ud_statep 0x%p "
4733             "find sidr entry status = %x", ud_statep, status);
4734 
4735         if (status != IBCM_LOOKUP_EXISTS) {
4736                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_rep_msg: "
4737                     "No matching ud_statep for SIDR REP");
4738                 return;
4739         }
4740 
4741         if (IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->TransactionID !=
4742             ((ib_mad_hdr_t *)(input_madp))->TransactionID) {
4743                 mutex_enter(&ud_statep->ud_state_mutex);
4744                 IBCM_UD_REF_CNT_DECR(ud_statep);
4745                 mutex_exit(&ud_statep->ud_state_mutex);
4746                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_rep_msg: "
4747                     "ud_statep 0x%p. A SIDR REP MAD with tid expected 0x%llX "
4748                     "tid found 0x%llX req_id %x arrived", ud_statep,
4749                     b2h64(
4750                     IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->TransactionID),
4751                     b2h64(((ib_mad_hdr_t *)(input_madp))->TransactionID),
4752                     b2h32(sidr_repp->sidr_rep_request_id));
4753                 return;
4754         }
4755 
4756         mutex_enter(&ud_statep->ud_state_mutex);
4757 
4758         /*
4759          * We need to check service ID received against the one sent?
4760          * If they don't match just return.
4761          */
4762         bcopy(sidr_repp->sidr_rep_service_id, &tmp_svc_id, sizeof (tmp_svc_id));
4763         bcopy(&tmp_svc_id, sidr_repp->sidr_rep_service_id, sizeof (tmp_svc_id));
4764         if (ud_statep->ud_svc_id != b2h64(tmp_svc_id)) {
4765                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_rep_msg: "
4766                     "ud_statep -0x%p svcids do not match %llx %llx",
4767                     ud_statep, ud_statep->ud_svc_id, b2h64(tmp_svc_id));
4768 
4769                 IBCM_UD_REF_CNT_DECR(ud_statep);
4770                 mutex_exit(&ud_statep->ud_state_mutex);
4771                 return;
4772         }
4773 
4774         if (ud_statep->ud_state == IBCM_STATE_SIDR_REQ_SENT) {
4775                 timeout_id_t    timer_val = ud_statep->ud_timerid;
4776 
4777                 ud_statep->ud_state = IBCM_STATE_SIDR_REP_RCVD;
4778                 ud_statep->ud_timerid = 0;
4779                 mutex_exit(&ud_statep->ud_state_mutex);
4780 
4781                 /* Cancel timer set after sending SIDR REQ */
4782                 (void) untimeout(timer_val);
4783 
4784                 /*
4785                  * Call Client's UD handler
4786                  */
4787                 ibcm_sidr_rep_ud_handler(ud_statep, sidr_repp);
4788 
4789                 mutex_enter(&ud_statep->ud_state_mutex);
4790 
4791                 ud_statep->ud_state = IBCM_STATE_DELETE;
4792 
4793                 /*
4794                  * ud_statep->ud_return_data is initialized for blocking in
4795                  * ibt_ud_get_dqpn(). Initialize its fields and
4796                  * signal the blocking call in ibt_ud_get_dqpn().
4797                  */
4798                 if (ud_statep->ud_return_data != NULL) {
4799                         /* get rep_qpn and rep_status */
4800                         ibt_priv_data_len_t len;
4801 
4802                         /* Copy the SIDR private data */
4803                         len = min(ud_statep->ud_return_data->ud_priv_data_len,
4804                             IBT_SIDR_REP_PRIV_DATA_SZ);
4805 
4806                         if ((ud_statep->ud_return_data->ud_priv_data != NULL) &&
4807                             (len > 0)) {
4808                                 bcopy(sidr_repp->sidr_rep_private_data,
4809                                     ud_statep->ud_return_data->ud_priv_data,
4810                                     len);
4811                         }
4812 
4813                         /* get status first */
4814                         ud_statep->ud_return_data->ud_status =
4815                             sidr_repp->sidr_rep_rep_status;
4816 
4817                         if (ud_statep->ud_return_data->ud_status ==
4818                             IBT_CM_SREP_QPN_VALID) {
4819                                 ud_statep->ud_return_data->ud_dqpn =
4820                                     h2b32(sidr_repp->sidr_rep_qpn_plus) >> 8;
4821                                 ud_statep->ud_return_data->ud_qkey =
4822                                     b2h32(sidr_repp->sidr_rep_qkey);
4823                         }
4824 
4825                         ud_statep->ud_blocking_done = B_TRUE;
4826                         cv_broadcast(&ud_statep->ud_block_client_cv);
4827                 }
4828 
4829                 IBCM_UD_REF_CNT_DECR(ud_statep);
4830                 mutex_exit(&ud_statep->ud_state_mutex);
4831 
4832                 /* Delete UD state data now, finally done with it */
4833                 ibcm_delete_ud_state_data(ud_statep);
4834         } else {
4835                 IBTF_DPRINTF_L3(cmlog, "ibcm_process_sidr_rep_msg: "
4836                     "ud state is = 0x%x", ud_statep->ud_state);
4837                 IBCM_UD_REF_CNT_DECR(ud_statep);
4838                 mutex_exit(&ud_statep->ud_state_mutex);
4839         }
4840 }
4841 
4842 
4843 /*
4844  * ibcm_post_sidr_rep_mad:
4845  *      This call posts a SIDR REP MAD
4846  *
4847  * INPUTS:
4848  *      ud_statep       - pointer to ibcm_ud_state_data_t
4849  *      status          - Status information
4850  *
4851  * RETURN VALUE: NONE
4852  */
4853 void
4854 ibcm_post_sidr_rep_mad(ibcm_ud_state_data_t *ud_statep,
4855     ibt_sidr_status_t status)
4856 {
4857         ib_svc_id_t             tmp_svc_id;
4858         ibcm_sidr_rep_msg_t     *sidr_repp =
4859             (ibcm_sidr_rep_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg);
4860         clock_t                 timer_value;
4861 
4862         IBTF_DPRINTF_L5(cmlog, "ibcm_post_sidr_rep_mad:");
4863 
4864         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_repp))
4865 
4866         IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->AttributeID =
4867             h2b16(IBCM_INCOMING_SIDR_REP + IBCM_ATTR_BASE_ID);
4868 
4869         /*
4870          * Initialize SIDR REP message. (Other fields were
4871          * already filled up in ibcm_sidr_req_ud_handler()
4872          */
4873         sidr_repp->sidr_rep_request_id = h2b32(ud_statep->ud_req_id);
4874         tmp_svc_id = h2b64(ud_statep->ud_svc_id);
4875         bcopy(&tmp_svc_id, sidr_repp->sidr_rep_service_id, sizeof (tmp_svc_id));
4876 
4877         sidr_repp->sidr_rep_rep_status = (uint8_t)status;
4878 
4879         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sidr_repp))
4880 
4881         /* post the SIDR REP MAD */
4882         ibcm_post_ud_mad(ud_statep, ud_statep->ud_stored_msg, NULL, NULL);
4883 
4884         timer_value = ibt_ib2usec(ibcm_max_sidr_rep_store_time);
4885         /*
4886          * Hold the statep lock, as a SIDR REQ may come in after setting state
4887          * but before timeout. This can result in a dangling timeout ie.,
4888          * the incoming SIDR REQ would be unable to cancel this timeout
4889          */
4890         mutex_enter(&ud_statep->ud_state_mutex);
4891 
4892         ud_statep->ud_remaining_retry_cnt = 1;
4893         ud_statep->ud_timer_value = timer_value;
4894 
4895         ud_statep->ud_timer_stored_state = ud_statep->ud_state =
4896             IBCM_STATE_SIDR_REP_SENT;
4897         ud_statep->ud_timerid = IBCM_UD_TIMEOUT(ud_statep,
4898             ud_statep->ud_timer_value);
4899 
4900         mutex_exit(&ud_statep->ud_state_mutex);
4901 }
4902 
4903 
4904 /*
4905  * ibcm_sidr_timeout_cb:
4906  *      Called when the timer expires on SIDR request
4907  *
4908  * INPUTS:
4909  *      arg     -       ibcm_ud_state_data_t with all the info
4910  *
4911  * RETURN VALUE: NONE
4912  */
4913 void
4914 ibcm_sidr_timeout_cb(void *arg)
4915 {
4916         ibcm_ud_state_data_t    *ud_statep = (ibcm_ud_state_data_t *)arg;
4917 
4918         mutex_enter(&ud_statep->ud_state_mutex);
4919         ud_statep->ud_timerid = 0;
4920 
4921         IBTF_DPRINTF_L3(cmlog, "ibcm_sidr_timeout_cb: ud_statep 0x%p "
4922             "state = 0x%x", ud_statep, ud_statep->ud_state);
4923 
4924         /* Processing depends upon current state */
4925         if (ud_statep->ud_state == IBCM_STATE_SIDR_REP_SENT) {
4926                 ud_statep->ud_state = IBCM_STATE_DELETE;
4927 
4928                 mutex_exit(&ud_statep->ud_state_mutex);
4929 
4930                 /* Deallocate the CM state structure */
4931                 ibcm_delete_ud_state_data(ud_statep);
4932 
4933         } else if ((ud_statep->ud_remaining_retry_cnt > 0) &&
4934             (ud_statep->ud_state == IBCM_STATE_SIDR_REQ_SENT)) {
4935 
4936                 ud_statep->ud_remaining_retry_cnt--;
4937                 IBCM_UD_REF_CNT_INCR(ud_statep); /* for non-blocking post */
4938                 IBTF_DPRINTF_L4(cmlog, "ibcm_sidr_timeout_cb: "
4939                     "ud_statep = %p, retries remaining = 0x%x",
4940                     ud_statep, ud_statep->ud_remaining_retry_cnt);
4941                 mutex_exit(&ud_statep->ud_state_mutex);
4942 
4943                 /* Post mad in non blocking mode */
4944                 ibcm_post_ud_mad(ud_statep, ud_statep->ud_stored_msg,
4945                     ibcm_post_sidr_req_complete, ud_statep);
4946 
4947         } else if (ud_statep->ud_state == IBCM_STATE_SIDR_REQ_SENT) {
4948 
4949                 /* This is on SIDR REQ Sender side processing */
4950 
4951                 /* set state to IBCM_STATE_DELETE */
4952                 ud_statep->ud_state = IBCM_STATE_DELETE;
4953 
4954                 /*
4955                  * retry counter expired, clean up
4956                  *
4957                  * Invoke the client/server handler with a "status" of
4958                  * IBT_CM_SREP_TIMEOUT.
4959                  */
4960 
4961                 if (ud_statep->ud_return_data != NULL) {
4962                         ud_statep->ud_return_data->ud_status =
4963                             IBT_CM_SREP_TIMEOUT;
4964                         ud_statep->ud_blocking_done = B_TRUE;
4965                         cv_broadcast(&ud_statep->ud_block_client_cv);
4966                 }
4967 
4968                 mutex_exit(&ud_statep->ud_state_mutex);
4969 
4970                 /* Invoke the client handler in a separate thread */
4971                 if (ud_statep->ud_cm_handler != NULL) {
4972                         /* UD state data is delete in timeout thread */
4973                         ibcm_add_ud_tlist(ud_statep);
4974                         return;
4975                 }
4976 
4977                 /* Delete UD state data now, finally done with it */
4978                 ibcm_delete_ud_state_data(ud_statep);
4979         } else {
4980 
4981 #ifdef DEBUG
4982                 if (ibcm_test_mode > 0)
4983                         IBTF_DPRINTF_L2(cmlog, "ibcm_sidr_timeout_cb: "
4984                             "Nop timeout  for ud_statep 0x%p in ud_state %d",
4985                             ud_statep, ud_statep->ud_state);
4986 #endif
4987                 mutex_exit(&ud_statep->ud_state_mutex);
4988         }
4989 }
4990 
4991 
4992 /*
4993  * ibcm_resend_srep_mad:
4994  *      Called on a duplicate incoming SIDR REQ on server side
4995  *      Posts the stored MAD from ud state structure using ud_stored_reply_addr
4996  *      Cancels any running timer, and then re-starts the timer
4997  *      This routine must be called with state structure table lock held
4998  *
4999  * INPUTS:
5000  *      ud_statep       -       ibcm_ud_state_data_t
5001  *
5002  * RETURN VALUE: NONE
5003  */
5004 void
5005 ibcm_resend_srep_mad(ibcm_ud_state_data_t *ud_statep)
5006 {
5007         timeout_id_t            timer_val;
5008 
5009         ASSERT(MUTEX_HELD(&ud_statep->ud_state_mutex));
5010 
5011         IBTF_DPRINTF_L3(cmlog, "ibcm_resend_srep_mad: ud_statep 0x%p",
5012             ud_statep);
5013 
5014         if (ud_statep->ud_send_mad_flags & IBCM_SREP_POST_BUSY)
5015                 return;
5016 
5017         ud_statep->ud_send_mad_flags |= IBCM_SREP_POST_BUSY;
5018 
5019         /* for nonblocking SIDR REP Post */
5020         IBCM_UD_REF_CNT_INCR(ud_statep);
5021 
5022         /* Cancel currently running timer */
5023         timer_val = ud_statep->ud_timerid;
5024 
5025         if (ud_statep->ud_timerid != 0) {
5026                 ud_statep->ud_timerid = 0;
5027                 mutex_exit(&ud_statep->ud_state_mutex);
5028                 (void) untimeout(timer_val);
5029         } else {
5030                 mutex_exit(&ud_statep->ud_state_mutex);
5031         }
5032 
5033         /* Always resend the response MAD to the original reply destination */
5034         ibcm_post_ud_mad(ud_statep, ud_statep->ud_stored_msg,
5035             ibcm_post_sidr_rep_complete, ud_statep);
5036 
5037         mutex_enter(&ud_statep->ud_state_mutex);
5038 }
5039 
5040 
5041 /*
5042  * ibcm_build_reply_mad_addr:
5043  *      Forms the reply MAD address based on "incoming mad addr" that is
5044  *      supplied as an arg.
5045  *
5046  *      Swaps the source and destination gids in ib_grh_t
5047  *
5048  * INPUTS:
5049  * inp_mad_addr:        Address information in the incoming MAD
5050  * out_mad_addr:        Derived address for the reply MAD
5051  *                      The reply MAD address is derived based
5052  *                      address information of incoming CM MAD
5053  * RETURN VALUE: NONE
5054  */
5055 void
5056 ibcm_build_reply_mad_addr(ibcm_mad_addr_t *inp_mad_addr,
5057     ibcm_mad_addr_t *out_mad_addr)
5058 {
5059         IBTF_DPRINTF_L5(cmlog, "ibcm_build_reply_mad_addr:");
5060 
5061         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*out_mad_addr))
5062 
5063         bcopy(inp_mad_addr, out_mad_addr, sizeof (ibcm_mad_addr_t));
5064 
5065         /* Swap the GIDs in the GRH */
5066         if (inp_mad_addr->grh_exists == B_TRUE) {
5067                 ib_gid_t sgid = inp_mad_addr->grh_hdr.ig_sender_gid;
5068 
5069                 /* swap the SGID and DGID */
5070                 out_mad_addr->grh_hdr.ig_sender_gid =
5071                     inp_mad_addr->grh_hdr.ig_recver_gid;
5072                 out_mad_addr->grh_hdr.ig_recver_gid = sgid;
5073         }
5074 
5075         /*
5076          * CM posts response MAD on a new/existing internal QP on the same port
5077          * and pkey
5078          */
5079         out_mad_addr->cm_qp_entry =
5080             ibcm_find_qp(inp_mad_addr->cm_qp_entry->qp_port->port_hcap,
5081             inp_mad_addr->port_num, inp_mad_addr->rcvd_addr.ia_p_key);
5082 
5083         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*out_mad_addr))
5084 }
5085 
5086 
5087 /*
5088  * ibcm_post_rc_mad
5089  *      Posts a CM MAD associated with a RC statep
5090  *
5091  * INPUTS:
5092  * statep       : RC statep associated with the post
5093  * msgp         : CM MAD to be posted
5094  * post_cb      : non-NULL callback address implies non-blocking post
5095  * args         : Args to ibmf send callback
5096  *
5097  * RETURN VALUE: based on ibmf_send_mad
5098  */
5099 void
5100 ibcm_post_rc_mad(ibcm_state_data_t *statep, ibmf_msg_t *msgp,
5101     ibmf_msg_cb_t post_cb, void *args)
5102 {
5103         ibt_status_t    status;
5104 
5105         mutex_enter(&statep->state_mutex);
5106         statep->post_time = gethrtime();
5107         mutex_exit(&statep->state_mutex);
5108         status = ibcm_post_mad(msgp, &statep->stored_reply_addr, post_cb,
5109             args);
5110         if ((status != IBT_SUCCESS) && (post_cb != NULL))
5111                 /* Call ibmf callback directly */
5112                 (*post_cb)(NULL, msgp, args);
5113 }
5114 
5115 
5116 /*
5117  * ibcm_post_ud_mad
5118  *      Posts a CM MAD associated with a UD statep
5119  *
5120  * INPUTS:
5121  * ud_statep    : UD statep associated with the post
5122  * msgp         : CM MAD to be posted
5123  * post_cb      : non-NULL callback address implies non-blocking post
5124  * args         : Args to ibmf send callback
5125  *
5126  * RETURN VALUE: based on ibmf_send_mad
5127  */
5128 void
5129 ibcm_post_ud_mad(ibcm_ud_state_data_t *ud_statep, ibmf_msg_t *msgp,
5130     ibmf_msg_cb_t ud_post_cb, void *args)
5131 {
5132         ibt_status_t    status;
5133         status = ibcm_post_mad(msgp, &ud_statep->ud_stored_reply_addr,
5134             ud_post_cb, args);
5135         if ((status != IBT_SUCCESS) && (ud_post_cb != NULL))
5136                 /* Call ibmf callback directly */
5137                 (*ud_post_cb)(NULL, msgp, args);
5138 }
5139 
5140 /*
5141  * ibcm_post_mad:
5142  *      Posts CM MAD using IBMF in blocking mode
5143  *
5144  * INPUTS:
5145  * msgp         : CM MAD to be posted
5146  * cm_mad_addr  : Address information for the MAD to be posted
5147  * post_cb      : non-NULL callback address implies non-blocking post
5148  * args         : Args to ibmf send callback
5149  *
5150  * RETURN VALUE: based on ibmf_send_mad
5151  */
5152 ibt_status_t
5153 ibcm_post_mad(ibmf_msg_t *msgp, ibcm_mad_addr_t *cm_mad_addr,
5154     ibmf_msg_cb_t post_cb, void *args)
5155 {
5156         int     post_status;
5157 
5158         IBTF_DPRINTF_L5(cmlog, "ibcm_post_mad: "
5159             "ibmf_msg_t = %p, cm_madd_adr = %p", msgp, cm_mad_addr);
5160 
5161         IBTF_DPRINTF_L4(cmlog, "ibcm_post_mad: dlid = %x, d_qno= %x",
5162             cm_mad_addr->rcvd_addr.ia_remote_lid,
5163             cm_mad_addr->rcvd_addr.ia_remote_qno);
5164         IBTF_DPRINTF_L4(cmlog, "ibcm_post_mad: p_key = %x, q_key = %x, "
5165             "sl = %x, grh_exists = %x",
5166             cm_mad_addr->rcvd_addr.ia_p_key, cm_mad_addr->rcvd_addr.ia_q_key,
5167             cm_mad_addr->rcvd_addr.ia_service_level, cm_mad_addr->grh_exists);
5168 
5169         /* Copy local addressing info */
5170         msgp->im_local_addr = cm_mad_addr->rcvd_addr;
5171 
5172         /* Copy global/GRH addressing info */
5173         if (cm_mad_addr->grh_exists == B_TRUE)
5174                 msgp->im_global_addr = cm_mad_addr->grh_hdr;
5175 
5176         if (post_cb)
5177                 ibcm_flow_inc();
5178         post_status = ibmf_msg_transport(
5179             cm_mad_addr->ibmf_hdl, cm_mad_addr->cm_qp_entry->qp_cm, msgp,
5180             NULL, post_cb, args, 0);
5181         if (post_status != IBMF_SUCCESS) {
5182                 IBTF_DPRINTF_L2(cmlog, "ibcm_post_mad: ibmf_msg_transport "
5183                     "failed: status %d, cb = %p", post_status, post_cb);
5184                 /* Analyze the reason for failure */
5185                 return (ibcm_ibmf_analyze_error(post_status));
5186         }
5187 
5188         return (IBT_SUCCESS);
5189 }
5190 
5191 
5192 /*
5193  * ibcm_process_get_classport_info:
5194  *      Get classportinfo
5195  *
5196  * INPUTS:
5197  *      hcap            - HCA entry pointer
5198  *      input_madp      - Input MAD pointer
5199  *      cm_mad_addr     - Address information for the MAD to be posted
5200  *
5201  * RETURN VALUE: NONE
5202  */
5203 static void
5204 ibcm_process_get_classport_info(ibcm_hca_info_t *hcap, uint8_t *input_madp,
5205     ibcm_mad_addr_t *cm_mad_addr)
5206 {
5207         ibmf_msg_t              *msgp;
5208 
5209         IBTF_DPRINTF_L5(cmlog, "ibcm_process_get_classport_info: (%p, %p, %p)",
5210             hcap, input_madp, cm_mad_addr);
5211 
5212         if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl, &msgp,
5213             MAD_METHOD_GET_RESPONSE) != IBT_SUCCESS) {
5214                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_classport_info: "
5215                     "ibcm_alloc_out_msg failed");
5216                 return;
5217         }
5218 
5219         /* copy the transaction id from input get mad */
5220         IBCM_OUT_HDRP(msgp)->TransactionID =
5221             ((ib_mad_hdr_t *)(input_madp))->TransactionID;
5222         IBCM_OUT_HDRP(msgp)->AttributeID = h2b16(MAD_ATTR_ID_CLASSPORTINFO);
5223 
5224         bcopy(&ibcm_clpinfo, IBCM_OUT_MSGP(msgp), sizeof (ibcm_clpinfo));
5225 
5226         (void) ibcm_post_mad(msgp, cm_mad_addr, NULL, NULL);
5227         (void) ibcm_free_out_msg(cm_mad_addr->ibmf_hdl, &msgp);
5228 
5229         IBTF_DPRINTF_L4(cmlog, "ibcm_process_get_classport_info: done");
5230 }
5231 
5232 /*
5233  * ibcm_decode_classport_info:
5234  *      Decode classportinfo
5235  *
5236  * INPUTS:
5237  *      hcap            - HCA entry pointer
5238  *      cm_mad_addr     - Address information for the MAD to be posted
5239  *      input_madp      - Input MAD pointer
5240  *
5241  * RETURN VALUE: NONE
5242  */
5243 static void
5244 ibcm_decode_classport_info(ibcm_hca_info_t *hcap, uint8_t *input_madp,
5245     ibcm_mad_addr_t *cm_mad_addr)
5246 {
5247         ibcm_classportinfo_msg_t *portinfop = (ibcm_classportinfo_msg_t *)
5248             (&input_madp[IBCM_MAD_HDR_SIZE]);
5249         IBTF_DPRINTF_L5(cmlog, "ibcm_decode_classport_info: (%p, %p, %p)",
5250             hcap, input_madp, cm_mad_addr);
5251 
5252         /* Print various fields of received classportinfo in debuf buf */
5253 
5254         IBTF_DPRINTF_L4(cmlog, "ibcm_decode_classport_info: "
5255             "Base version %d Class version %d", portinfop->BaseVersion,
5256             portinfop->ClassVersion);
5257         IBTF_DPRINTF_L4(cmlog, "ibcm_decode_classport_info: "
5258             "Cap Mask %d Resp Time %d", portinfop->CapabilityMask,
5259             portinfop->RespTimeValue_plus);
5260 }
5261 
5262 
5263 /*
5264  * ibcm_handler_conn_fail:
5265  *      Helper function used to call client handler for Conn fail event
5266  *
5267  * INPUTS:
5268  *      statep:                 The connection state pointer
5269  *      rej_type:               Message being rejected
5270  *      rej_reason:             Reason why CM is sending the REJ message
5271  *      client_data:            Private data returned by the client for REJ
5272  *      client_data_len:        Length of above client's private data.
5273  *
5274  * RETURN VALUE:        Client Handler's return status
5275  */
5276 static void
5277 ibcm_handler_conn_fail(ibcm_state_data_t *statep, uint8_t cf_code,
5278     uint8_t cf_msg, ibt_cm_reason_t cf_reason, uint8_t *client_data,
5279     ibt_priv_data_len_t client_data_len)
5280 {
5281         ibt_cm_event_t  event;
5282 
5283         ibcm_path_cache_purge();
5284 
5285         if (statep->channel)
5286                 ibtl_cm_chan_open_is_aborted(statep->channel);
5287 
5288         /* Invoke CM handler w/ event passed as arg */
5289         if (statep->cm_handler != NULL) {
5290                 bzero(&event, sizeof (ibt_cm_event_t));
5291 
5292                 event.cm_type = IBT_CM_EVENT_FAILURE;
5293                 event.cm_channel = statep->channel;
5294                 event.cm_session_id = NULL;
5295                 event.cm_priv_data = NULL;
5296                 event.cm_priv_data_len = 0;
5297 
5298                 event.cm_event.failed.cf_code = cf_code;
5299                 event.cm_event.failed.cf_msg =  cf_msg;
5300                 event.cm_event.failed.cf_reason =  cf_reason;
5301 
5302                 ibcm_insert_trace(statep, IBCM_TRACE_CALLED_CONN_FAIL_EVENT);
5303 
5304                 (void) statep->cm_handler(statep->state_cm_private, &event,
5305                     NULL, client_data, client_data_len);
5306 
5307                 ibcm_insert_trace(statep, IBCM_TRACE_RET_CONN_FAIL_EVENT);
5308         }
5309         if (ibcm_enable_trace != 0)
5310                 ibcm_dump_conn_trace(statep);
5311         mutex_enter(&statep->state_mutex);
5312         ibcm_open_done(statep);
5313         mutex_exit(&statep->state_mutex);
5314 }
5315 
5316 /*
5317  * QP State transition functions here
5318  *
5319  * The brief description of these functions :
5320  *      Validate QP related attributes in the messages
5321  *      Call client/server callback handlers
5322  *      Change QP state
5323  *      Set QP attributes (modify QP)
5324  *      Fill up the response MADs
5325  */
5326 
5327 /*
5328  * ibcm_set_primary_adds_vect:
5329  *      Helper function used to fill up ibt_adds_vect_t PRIMARY PATH
5330  *      (called from ibcm_cep_state_*() functions)
5331  *
5332  * INPUTS:
5333  * statep       : The connection state pointer
5334  * adds_vectp   : The ibt_adds_vect_t ptr that is being filled up
5335  * msgp         : CM REQ message that is the source of information
5336  *
5337  * RETURN VALUE:        NONE
5338  */
5339 static void
5340 ibcm_set_primary_adds_vect(ibcm_state_data_t *statep,
5341     ibt_adds_vect_t *adds_vectp, ibcm_req_msg_t *msgp)
5342 {
5343         uint32_t flow_label20_res6_rate6;
5344 
5345         flow_label20_res6_rate6 = b2h32(msgp->req_primary_flow_label_plus);
5346 
5347         /* first setup the srvl, srate, dlid and dgid */
5348         adds_vectp->av_srvl = msgp->req_primary_sl_plus >> 4;
5349         adds_vectp->av_src_path = statep->prim_src_path_bits;
5350 
5351         if (statep->mode == IBCM_PASSIVE_MODE) {
5352                 adds_vectp->av_dlid = b2h16(msgp->req_primary_l_port_lid);
5353                 adds_vectp->av_dgid.gid_prefix =
5354                     b2h64(msgp->req_primary_l_port_gid.gid_prefix);
5355                 adds_vectp->av_dgid.gid_guid =
5356                     b2h64(msgp->req_primary_l_port_gid.gid_guid);
5357                 adds_vectp->av_sgid.gid_prefix =
5358                     b2h64(msgp->req_primary_r_port_gid.gid_prefix);
5359                 adds_vectp->av_sgid.gid_guid =
5360                     b2h64(msgp->req_primary_r_port_gid.gid_guid);
5361                 adds_vectp->av_srate = flow_label20_res6_rate6 & 0x3f;
5362         } else {
5363                 adds_vectp->av_dlid = b2h16(msgp->req_primary_r_port_lid);
5364                 adds_vectp->av_dgid.gid_prefix =
5365                     b2h64(msgp->req_primary_r_port_gid.gid_prefix);
5366                 adds_vectp->av_dgid.gid_guid =
5367                     b2h64(msgp->req_primary_r_port_gid.gid_guid);
5368                 adds_vectp->av_sgid.gid_prefix =
5369                     b2h64(msgp->req_primary_l_port_gid.gid_prefix);
5370                 adds_vectp->av_sgid.gid_guid =
5371                     b2h64(msgp->req_primary_l_port_gid.gid_guid);
5372                 adds_vectp->av_srate = statep->local_srate;
5373         }
5374 
5375         /* next copy off the GRH info if it exists  */
5376         if ((msgp->req_primary_sl_plus & 0x8) == 0) {
5377                 adds_vectp->av_send_grh = B_TRUE;
5378                 adds_vectp->av_flow = flow_label20_res6_rate6 >> 12;
5379                 adds_vectp->av_tclass = msgp->req_primary_traffic_class;
5380                 adds_vectp->av_hop = msgp->req_primary_hop_limit;
5381         } else {
5382                 adds_vectp->av_send_grh = B_FALSE;
5383         }
5384 }
5385 
5386 
5387 /*
5388  * ibcm_set_alt_adds_vect:
5389  *      Helper function used to fill up ibt_adds_vect_t ALTERNATE PATH
5390  *      (called from ibcm_cep_state_*() functions)
5391  *
5392  * INPUTS:
5393  * statep       : The connection state pointer
5394  * adds_vectp   : The ibt_adds_vect_t ptr that is being filled up
5395  * msgp         : CM REQ message that is the source of information
5396  *
5397  * RETURN VALUE:        NONE
5398  */
5399 static void
5400 ibcm_set_alt_adds_vect(ibcm_state_data_t *statep,
5401     ibt_adds_vect_t *adds_vectp, ibcm_req_msg_t *msgp)
5402 {
5403         ib_gid_t dgid;
5404         ib_gid_t sgid;
5405         uint32_t flow_label20_res6_rate6;
5406 
5407         flow_label20_res6_rate6 = b2h32(msgp->req_alt_flow_label_plus);
5408 
5409         /* first setup the srvl, srate, dlid and dgid */
5410         adds_vectp->av_srvl = msgp->req_alt_sl_plus >> 4;
5411         adds_vectp->av_src_path = statep->alt_src_path_bits;
5412 
5413         if (statep->mode == IBCM_PASSIVE_MODE) {
5414                 adds_vectp->av_dlid = b2h16(msgp->req_alt_l_port_lid);
5415                 bcopy(&msgp->req_alt_l_port_gid[0], &dgid, sizeof (ib_gid_t));
5416                 bcopy(&msgp->req_alt_r_port_gid[0], &sgid, sizeof (ib_gid_t));
5417                 adds_vectp->av_srate = flow_label20_res6_rate6 & 0x3f;
5418         } else {
5419                 adds_vectp->av_dlid = b2h16(msgp->req_alt_r_port_lid);
5420                 bcopy(&msgp->req_alt_r_port_gid[0], &dgid, sizeof (ib_gid_t));
5421                 bcopy(&msgp->req_alt_l_port_gid[0], &sgid, sizeof (ib_gid_t));
5422                 adds_vectp->av_srate = statep->local_alt_srate;
5423         }
5424         adds_vectp->av_dgid.gid_prefix = b2h64(dgid.gid_prefix);
5425         adds_vectp->av_dgid.gid_guid = b2h64(dgid.gid_guid);
5426         adds_vectp->av_sgid.gid_prefix = b2h64(sgid.gid_prefix);
5427         adds_vectp->av_sgid.gid_guid = b2h64(sgid.gid_guid);
5428 
5429         /* next copy off the GRH info if it exists  */
5430         if ((msgp->req_alt_sl_plus & 0x8) == 0) {
5431                 adds_vectp->av_send_grh = B_TRUE;
5432                 adds_vectp->av_flow = flow_label20_res6_rate6 >> 12;
5433                 adds_vectp->av_tclass = msgp->req_alt_traffic_class;
5434                 adds_vectp->av_hop = msgp->req_alt_hop_limit;
5435         } else {
5436                 adds_vectp->av_send_grh = B_FALSE;   /* no GRH */
5437         }
5438 }
5439 
5440 
5441 /*
5442  * ibcm_set_primary_cep_path:
5443  *      Helper function used to fill up ibt_cep_path_t PRIMARY PATH
5444  *      (called from ibcm_cep_state_*() functions)
5445  *
5446  * INPUTS:
5447  * statep       : The connection state pointer
5448  * adds_vectp   : The ibt_cep_path_t ptr that is being filled up
5449  * msgp         : CM REQ message that is the source of information
5450  *
5451  * RETURN VALUE:        NONE
5452  */
5453 static ibt_status_t
5454 ibcm_set_primary_cep_path(ibcm_state_data_t *statep, ibt_cep_path_t *pathp,
5455     ibcm_req_msg_t *msgp)
5456 {
5457         ibt_status_t            status;
5458 
5459         /* validate the PKEY in REQ for prim port */
5460         status = ibt_pkey2index_byguid(statep->local_hca_guid,
5461             statep->prim_port, b2h16(msgp->req_part_key), &pathp->cep_pkey_ix);
5462 
5463         if (status != IBT_SUCCESS) {
5464                 IBTF_DPRINTF_L2(cmlog, "ibcm_set_primary_cep_path: "
5465                     "statep 0x%p pkey %x prim_port %d ", statep,
5466                     b2h16(msgp->req_part_key), statep->prim_port);
5467                 IBTF_DPRINTF_L2(cmlog, "ibcm_set_primary_cep_path: "
5468                     "statep 0x%p Invalid PKEY on prim_port, status %d ",
5469                     statep, status);
5470                 return (status);
5471         }
5472         statep->pkey = b2h16(msgp->req_part_key);
5473         ibcm_set_primary_adds_vect(statep, &pathp->cep_adds_vect, msgp);
5474         return (IBT_SUCCESS);
5475 }
5476 
5477 
5478 /*
5479  * ibcm_set_alt_cep_path:
5480  *      Helper function used to fill up ibt_cep_path_t ALTERNATE PATH
5481  *      (called from ibcm_cep_state_*() functions)
5482  *
5483  * INPUTS:
5484  * statep       : The connection state pointer
5485  * adds_vectp   : The ibt_cep_path_t ptr that is being filled up
5486  * msgp         : CM REQ message that is the source of information
5487  *
5488  * RETURN VALUE:        NONE
5489  */
5490 static ibt_status_t
5491 ibcm_set_alt_cep_path(ibcm_state_data_t *statep, ibt_cep_path_t *pathp,
5492     ibcm_req_msg_t *msgp)
5493 {
5494         ibt_status_t            status;
5495 
5496         if (b2h16(msgp->req_alt_l_port_lid) == 0) {
5497                 /* no alternate path specified */
5498                 return (IBT_SUCCESS);
5499         }
5500 
5501         /* validate the PKEY in REQ for alt port */
5502         status = ibt_pkey2index_byguid(statep->local_hca_guid,
5503             statep->alt_port, b2h16(msgp->req_part_key), &pathp->cep_pkey_ix);
5504 
5505         if (status != IBT_SUCCESS) {
5506                 IBTF_DPRINTF_L2(cmlog, "ibcm_set_alt_cep_path: "
5507                     "statep 0x%p pkey %x alt_port %d ", statep,
5508                     b2h16(msgp->req_part_key), statep->alt_port);
5509                 IBTF_DPRINTF_L2(cmlog, "ibcm_set_alt_cep_path: "
5510                     "statep 0x%p Invalid PKEY on alt_port, status %d ",
5511                     statep, status);
5512                 return (status);
5513         }
5514         pathp->cep_hca_port_num = statep->alt_port;
5515         ibcm_set_alt_adds_vect(statep, &pathp->cep_adds_vect, msgp);
5516         return (IBT_SUCCESS);
5517 
5518 }
5519 
5520 /*
5521  * ibcm_compare_prim_alt_paths:
5522  *      Helper function used to find if primary and alternate paths are
5523  *      identical
5524  *      (called from ibcm_cep_state_req)
5525  *
5526  * INPUTS:
5527  * req:                 Pointer to ibt_cm_req_rcv_t, filled before invoking
5528  *                      the function
5529  *
5530  * RETURN VALUE:        NONE
5531  */
5532 
5533 static boolean_t
5534 ibcm_compare_prim_alt_paths(ibt_adds_vect_t *prim, ibt_adds_vect_t *alt)
5535 {
5536 
5537         if ((alt->av_dlid == prim->av_dlid) &&
5538             (alt->av_dgid.gid_prefix == prim->av_dgid.gid_prefix) &&
5539             (alt->av_dgid.gid_guid == prim->av_dgid.gid_guid) &&
5540             (alt->av_sgid.gid_prefix == prim->av_sgid.gid_prefix) &&
5541             (alt->av_sgid.gid_guid == prim->av_sgid.gid_guid) &&
5542             (alt->av_src_path == prim->av_src_path)) {
5543 
5544                 return (B_TRUE);
5545         }
5546         return (B_FALSE);
5547 }
5548 
5549 
5550 /*
5551  * ibcm_invoke_qp_modify:
5552  *      Helper function used to call ibt_modify_qp()
5553  *      called from ibcm_cep_state_req()/ibcm_cep_state_rep()
5554  *      It sets up qp_info/eec_info
5555  *
5556  *      Sets state to RTR as well.
5557  *
5558  *
5559  * INPUTS:
5560  *      statep:         The connection state pointer
5561  *      req_msgp:       The CM REQ message
5562  *
5563  * RETURN VALUE:
5564  *      IBT_SUCCESS     -       call succeeded
5565  */
5566 static ibt_status_t
5567 ibcm_invoke_qp_modify(ibcm_state_data_t *statep, ibcm_req_msg_t *req_msgp,
5568     ibcm_rep_msg_t *rep_msgp)
5569 {
5570         ibt_status_t            status;
5571         ibt_qp_info_t           qp_info;
5572         ibt_cep_modify_flags_t  cep_flags;
5573         ibt_tran_srv_t          trans;
5574 
5575         cep_flags = IBT_CEP_SET_INIT_RTR | IBT_CEP_SET_PKEY_IX;
5576         trans = ((uint8_t *)&req_msgp->req_remote_eecn_plus)[3] >> 1 & 0x3;
5577 
5578         ASSERT(statep->channel != NULL);
5579 
5580         /*
5581          * If alternate path is present in REQ message then
5582          * OR in IBT_CEP_SET_ALT_PATH, if APM supported on hca
5583          */
5584         if (b2h16(req_msgp->req_alt_l_port_lid) != 0) {
5585 
5586                 if (statep->hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG)
5587                         cep_flags |= IBT_CEP_SET_ALT_PATH;
5588                         /* default value of rep_failover is ACCEPT */
5589                 else {
5590                         rep_msgp->rep_target_delay_plus |=
5591                             IBT_CM_FAILOVER_REJ_NOTSUPP << 1;
5592                         IBTF_DPRINTF_L3(cmlog, "ibcm_invoke_qp_modify"
5593                             " Alt Path specified in REQ, but not supported");
5594                 }
5595         }
5596 
5597         /* If transport type is RD OR in IBC_CEP_SET_QKEY */
5598         if (trans == IBT_RD_SRV) {
5599                 cep_flags |= IBT_CEP_SET_QKEY;
5600         }
5601 
5602         /* Start filling up ibt_qp_info_t.  */
5603         bzero(&qp_info, sizeof (qp_info));
5604         qp_info.qp_trans = trans;
5605         qp_info.qp_state = IBT_STATE_RTR;
5606         qp_info.qp_flags = IBT_CEP_NO_FLAGS;
5607 
5608         switch (trans) {
5609         case IBT_RC_SRV:
5610 
5611                 if (statep->mode == IBCM_ACTIVE_MODE) {
5612                         /* Setting PSN on RQ */
5613 
5614                         IBCM_QPINFO_RC(qp_info).rc_rq_psn =
5615                             b2h32(req_msgp->req_starting_psn_plus) >> 8;
5616 
5617                         IBCM_QPINFO_RC(qp_info).rc_dst_qpn =
5618                             b2h32(rep_msgp->rep_local_qpn_plus) >> 8;
5619 
5620                         /* RDMA resources taken from negotiated REP values */
5621                         IBCM_QPINFO_RC(qp_info).rc_rdma_ra_in =
5622                             rep_msgp->rep_initiator_depth;
5623 
5624                 } else { /* Passive side CM */
5625                         /* Setting PSN on SQ and RQ */
5626                         IBCM_QPINFO_RC(qp_info).rc_sq_psn =
5627                             IBCM_QPINFO_RC(qp_info).rc_rq_psn =
5628                             b2h32(rep_msgp->rep_starting_psn_plus) >> 8;
5629 
5630                         IBCM_QPINFO_RC(qp_info).rc_dst_qpn =
5631                             b2h32(req_msgp->req_local_qpn_plus) >> 8;
5632 
5633                         /* RDMA resources taken from negotiated REP values */
5634                         IBCM_QPINFO_RC(qp_info).rc_rdma_ra_in =
5635                             rep_msgp->rep_resp_resources;
5636                 }
5637 
5638                 /* XXX, Oh!, ibtl doesn't have interface for setting this */
5639                 IBCM_QPINFO_RC(qp_info).rc_min_rnr_nak =
5640                     ibcm_default_rnr_nak_time;
5641                 IBCM_QPINFO_RC(qp_info).rc_path_mtu =
5642                     req_msgp->req_mtu_plus >> 4;
5643                 IBCM_QPINFO_RC(qp_info).rc_retry_cnt =
5644                     ((uint8_t *)&req_msgp->req_starting_psn_plus)[3] & 0x7;
5645                 IBCM_QPINFO_RC(qp_info).rc_rnr_retry_cnt =
5646                     req_msgp->req_mtu_plus & 0x7;
5647 
5648                 if ((status = ibcm_set_primary_cep_path(statep,
5649                     &IBCM_QPINFO_RC(qp_info).rc_path, req_msgp)) !=
5650                     IBT_SUCCESS)
5651                         return (status);
5652 
5653                 if ((status = ibcm_set_alt_cep_path(statep,
5654                     &IBCM_QPINFO_RC(qp_info).rc_alt_path, req_msgp)) !=
5655                     IBT_SUCCESS)
5656                         return (status);
5657 
5658                 break;
5659         case IBT_RD_SRV:
5660                 if (statep->mode == IBCM_ACTIVE_MODE) { /* look at REP msg */
5661                         IBCM_QPINFO(qp_info).rd.rd_qkey =
5662                             b2h32(rep_msgp->rep_local_qkey);
5663                 } else {
5664                         IBCM_QPINFO(qp_info).rd.rd_qkey =
5665                             b2h32(req_msgp->req_local_qkey);
5666                 }
5667 
5668                 break;
5669 
5670         case IBT_UC_SRV:
5671                 if (statep->mode == IBCM_ACTIVE_MODE) { /* look at REP msg */
5672                         IBCM_QPINFO_UC(qp_info).uc_sq_psn =
5673                             b2h32(req_msgp->req_starting_psn_plus) >> 8;
5674                         IBCM_QPINFO_UC(qp_info).uc_dst_qpn =
5675                             b2h32(rep_msgp->rep_local_qpn_plus) >> 8;
5676                 } else {
5677                         IBCM_QPINFO_UC(qp_info).uc_rq_psn =
5678                             IBCM_QPINFO_UC(qp_info).uc_sq_psn =
5679                             b2h32(rep_msgp->rep_starting_psn_plus) >> 8;
5680                         IBCM_QPINFO_UC(qp_info).uc_dst_qpn =
5681                             b2h32(req_msgp->req_local_qpn_plus) >> 8;
5682                 }
5683                 IBCM_QPINFO_UC(qp_info).uc_path_mtu =
5684                     req_msgp->req_mtu_plus >> 4;
5685 
5686                 if ((status = ibcm_set_primary_cep_path(statep,
5687                     &IBCM_QPINFO_UC(qp_info).uc_path, req_msgp)) !=
5688                     IBT_SUCCESS)
5689                         return (status);
5690 
5691                 if ((status = ibcm_set_alt_cep_path(statep,
5692                     &IBCM_QPINFO_UC(qp_info).uc_alt_path, req_msgp)) !=
5693                     IBT_SUCCESS)
5694                         return (status);
5695 
5696                 break;
5697         default:
5698                 IBTF_DPRINTF_L2(cmlog, "ibcm_invoke_qp_modify: "
5699                     "unknown svc_type = %x", trans);
5700                 break;
5701         }
5702 
5703         /* Call modify_qp */
5704         status = ibt_modify_qp(statep->channel, cep_flags, &qp_info, NULL);
5705         IBTF_DPRINTF_L4(cmlog, "ibcm_invoke_qp_modify: statep 0x%p"
5706             " ibt_modify_qp() Init to RTR returned = %d", statep, status);
5707 
5708         if (status == IBT_SUCCESS)
5709                 ibcm_insert_trace(statep, IBCM_TRACE_INIT_RTR);
5710         else
5711                 ibcm_insert_trace(statep, IBCM_TRACE_INIT_RTR_FAIL);
5712 
5713 #ifdef  DEBUG
5714 
5715         print_modify_qp("Init to RTR", statep->channel, cep_flags, &qp_info);
5716 
5717         if (statep->channel != NULL) {
5718                 ibt_qp_query_attr_t     qp_attrs;
5719 
5720                 (void) ibt_query_qp(statep->channel, &qp_attrs);
5721                 IBTF_DPRINTF_L4(cmlog, "ibcm_invoke_qp_modify: "
5722                     "qp_info.qp_state = %x", qp_attrs.qp_info.qp_state);
5723         }
5724 #endif
5725 
5726         return (status);
5727 }
5728 
5729 
5730 /*
5731  * ibcm_verify_req_gids_and_svcid
5732  *      Validation of LIDs, GIDs and SVC ID
5733  *
5734  * INPUTS:
5735  *      statep          - state pointer
5736  *      cm_req_msgp     - REQ message pointer
5737  *
5738  * RETURN VALUE: IBCM_SUCCESS/IBCM_FAILURE
5739  *
5740  */
5741 ibcm_status_t
5742 ibcm_verify_req_gids_and_svcid(ibcm_state_data_t *statep,
5743     ibcm_req_msg_t *cm_req_msgp)
5744 {
5745         ib_gid_t                gid;
5746         ib_gid_t                agid;
5747         ib_lid_t                lid;
5748         ibt_status_t            status;
5749         ibtl_cm_hca_port_t      port;
5750         ibt_cm_reason_t         reject_reason = IBT_CM_SUCCESS;
5751         ibcm_svc_info_t         *svc_infop;
5752         ibcm_svc_bind_t         *svc_bindp;
5753         ibcm_svc_bind_t         *tmp_bindp;
5754         ib_pkey_t               pkey;
5755         uint8_t                 port_num;
5756         ib_guid_t               hca_guid;
5757         ibcm_ip_pvtdata_t       *ip_data;
5758 
5759         /* Verify LID and GID of primary port */
5760 
5761         gid.gid_prefix = b2h64(cm_req_msgp->req_primary_r_port_gid.gid_prefix);
5762         gid.gid_guid = b2h64(cm_req_msgp->req_primary_r_port_gid.gid_guid);
5763 
5764         IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: statep 0x%p"
5765             " PRIM _r_gid (%llx, %llx)", statep, gid.gid_prefix,
5766             gid.gid_guid);
5767 
5768         IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: statep 0x%p "
5769             "PRIM passive lid %x", statep,
5770             b2h16(cm_req_msgp->req_primary_r_port_lid));
5771 
5772         /* Verify GID validity, if specified */
5773         if ((status = ibtl_cm_get_hca_port(gid, 0, &port)) == IBT_SUCCESS) {
5774 
5775                 IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: statep 0x%p "
5776                     "prim_port_num %d", statep, port.hp_port);
5777 
5778                 IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: statep 0x%p "
5779                     "passive hca_guid 0x%llX", statep, port.hp_hca_guid);
5780 
5781                 port_num = port.hp_port;
5782                 hca_guid = port.hp_hca_guid;
5783         }
5784 
5785         if (status != IBT_SUCCESS) {
5786                 IBTF_DPRINTF_L2(cmlog, "ibcm_verify_req_gids: statep 0x%p "
5787                     "ibtl_cm_get_hca_port() primary port failed = %d", statep,
5788                     status);
5789                 reject_reason = IBT_CM_PRIM_GID;
5790                 /* we will search for an acceptable GID to this port */
5791                 port_num = statep->stored_reply_addr.port_num;
5792                 hca_guid = statep->hcap->hca_guid;
5793 
5794         } else if (port.hp_base_lid !=
5795             (b2h16(cm_req_msgp->req_primary_r_port_lid) &
5796             (~((1 << port.hp_lmc) - 1)))) {
5797                 IBTF_DPRINTF_L2(cmlog, "ibcm_verify_req_gids: statep 0x%p "
5798                     "primary port lid invalid (%x, %x, %x)", statep,
5799                     port.hp_base_lid,
5800                     b2h16(cm_req_msgp->req_primary_r_port_lid), port.hp_lmc);
5801                 reject_reason = IBT_CM_PRIM_LID;
5802         } else {
5803 
5804                 statep->local_hca_guid = port.hp_hca_guid;
5805                 statep->prim_port = port.hp_port;
5806                 statep->prim_src_path_bits =
5807                     b2h16(cm_req_msgp->req_primary_r_port_lid) -
5808                     port.hp_base_lid;
5809 
5810                 IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: "
5811                     "statep 0x%p prim_port_path_bits %d ",
5812                     statep, statep->prim_src_path_bits);
5813 
5814                 /* Verify LID and GID  of alternate port. Post REJ if invalid */
5815 
5816                 /* Need a bcopy, as alt port gid is unaligned in req message */
5817                 bcopy(&cm_req_msgp->req_alt_r_port_gid[0], &agid,
5818                     sizeof (ib_gid_t));
5819                 agid.gid_prefix = b2h64(agid.gid_prefix);
5820                 agid.gid_guid = b2h64(agid.gid_guid);
5821 
5822                 IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: statep 0x%p"
5823                     " Alt port_gid is (%llX:%llX)", statep, agid.gid_prefix,
5824                     agid.gid_guid);
5825 
5826                 if ((agid.gid_prefix != 0) || (agid.gid_guid != 0)) {
5827 
5828                         /* Verify GID validity, if specified */
5829                         if ((status = ibtl_cm_get_hca_port(agid,
5830                             statep->local_hca_guid, &port)) != IBT_SUCCESS) {
5831                                 IBTF_DPRINTF_L2(cmlog,
5832                                     "ibcm_verify_req_gids: ibtl_cm_get_hca_port"
5833                                     " statep 0x%p alternate port failed = %d",
5834                                     statep, status);
5835                                 reject_reason = IBT_CM_ALT_GID;
5836 
5837                         } else if (port.hp_base_lid !=
5838                             (b2h16(cm_req_msgp->req_alt_r_port_lid) &
5839                             (~((1 << port.hp_lmc) - 1)))) {
5840 
5841                                 IBTF_DPRINTF_L2(cmlog,
5842                                     "ibcm_verify_req_gids: statep 0x%p "
5843                                     "alternate port lid invalid (%x, %x, %x)",
5844                                     statep, port.hp_base_lid,
5845                                     cm_req_msgp->req_alt_r_port_lid,
5846                                     port.hp_lmc);
5847                                 reject_reason = IBT_CM_ALT_LID;
5848                         } else { /* Alt LID and GID are valid */
5849                                 statep->alt_port = port.hp_port;
5850                                 statep->alt_src_path_bits =
5851                                     b2h16(cm_req_msgp->req_alt_r_port_lid) -
5852                                     port.hp_base_lid;
5853 
5854                                 IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: "
5855                                     "statep 0x%p alt_port_num %d "
5856                                     "alt_rc_hca_guid 0x%llX", statep,
5857                                     port.hp_port, port.hp_hca_guid);
5858 
5859                                 IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: "
5860                                     "statep 0x%p alt_port_path_bits %d ",
5861                                     statep, statep->alt_src_path_bits);
5862                         }
5863                 }
5864         }
5865 
5866         mutex_enter(&ibcm_svc_info_lock);
5867         svc_infop = ibcm_find_svc_entry(statep->svcid);
5868 
5869         /*
5870          * Note: When we return SUCCESS, the reader lock won't get dropped
5871          * until after the cm_handler is called from ibcm_cep_state_req().
5872          */
5873 
5874         IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: "
5875             "ibcm_find_svc_entry found svc_infop %p", svc_infop);
5876 
5877         /*
5878          * Send REJ with reject reason "invalid service id" for the
5879          * the following cases :-
5880          * Service id is valid, but not available at gid/lid of REQ
5881          * Service id is invalid
5882          */
5883 
5884         if (svc_infop == NULL || svc_infop->svc_bind_list == NULL) {
5885                 mutex_exit(&ibcm_svc_info_lock);
5886 
5887                 IBTF_DPRINTF_L2(cmlog, "ibcm_verify_req_gids_and_svcid: "
5888                     "statep 0x%p svc_id %llX svc_infop NULL", statep,
5889                     statep->svcid);
5890 
5891                 /* Send a REJ with invalid SID reason */
5892                 ibcm_post_rej_mad(statep,
5893                     IBT_CM_INVALID_SID, IBT_CM_FAILURE_REQ, NULL, 0);
5894                 return (IBCM_FAILURE);
5895         }
5896 
5897         if (svc_infop->svc_rc_handler == NULL) {
5898                 mutex_exit(&ibcm_svc_info_lock);
5899 
5900                 /* Send a REJ with invalid SID reason */
5901                 ibcm_post_rej_mad(statep,
5902                     IBT_CM_INVALID_SRV_TYPE, IBT_CM_FAILURE_REQ, NULL, 0);
5903                 return (IBCM_FAILURE);
5904         }
5905 
5906         /*
5907          * Check if ServiceID is in RDMA IP CM SID range, if yes, we parse
5908          * the REQ's Private Data and verify for it's goodness.
5909          */
5910         if (((statep->svcid & IB_SID_IPADDR_PREFIX_MASK) == 0) &&
5911             (statep->svcid & IB_SID_IPADDR_PREFIX)) {
5912                 ibt_ari_ip_t    ari_ip;
5913                 boolean_t       rdma_rej_mad = B_FALSE;
5914 
5915                 if (cm_req_msgp->req_private_data == NULL) {
5916                         mutex_exit(&ibcm_svc_info_lock);
5917 
5918                         IBTF_DPRINTF_L2(cmlog, "ibcm_verify_req_gids_and_svcid:"
5919                             " RDMA CM IP REQ Priv Data is NULL");
5920 
5921                         /* Send a REJ with CONSUMER REJ */
5922                         ibcm_post_rej_mad(statep, IBT_CM_CONSUMER,
5923                             IBT_CM_FAILURE_REQ, NULL, 0);
5924                         return (IBCM_FAILURE);
5925                 }
5926                 ip_data = (ibcm_ip_pvtdata_t *)cm_req_msgp->req_private_data;
5927 
5928                 bzero(&ari_ip, sizeof (ibt_ari_ip_t));
5929 
5930                 /* RDMA IP CM Layer Rejects this */
5931                 if (ip_data->ip_MajV != IBT_CM_IP_MAJ_VER) {
5932                         IBTF_DPRINTF_L2(cmlog, "ibcm_verify_req_gids_and_svcid:"
5933                             "IP MajorVer mis-match %d", ip_data->ip_MajV);
5934                         ari_ip.ip_reason = IBT_ARI_IP_MAJOR_VERSION;
5935                         ari_ip.ip_suggested_version = IBT_CM_IP_MAJ_VER;
5936                         ari_ip.ip_suggested = B_TRUE;
5937                         rdma_rej_mad = B_TRUE;
5938                 } else if (ip_data->ip_MinV != IBT_CM_IP_MIN_VER) {
5939                         IBTF_DPRINTF_L2(cmlog, "ibcm_verify_req_gids_and_svcid:"
5940                             "IP MinorVer mis-match %d", ip_data->ip_MinV);
5941                         ari_ip.ip_reason = IBT_ARI_IP_MINOR_VERSION;
5942                         ari_ip.ip_suggested_version = IBT_CM_IP_MIN_VER;
5943                         ari_ip.ip_suggested = B_TRUE;
5944                         rdma_rej_mad = B_TRUE;
5945                 } else if ((ip_data->ip_ipv != IBT_CM_IP_IPV_V4) &&
5946                     (ip_data->ip_ipv != IBT_CM_IP_IPV_V6)) {
5947                         IBTF_DPRINTF_L2(cmlog, "ibcm_verify_req_gids_and_svcid:"
5948                             " Invalid IPV specified %d", ip_data->ip_ipv);
5949                         ari_ip.ip_reason = IBT_ARI_IP_IPV;
5950                         ari_ip.ip_suggested_version = IBT_CM_IP_IPV_V4;
5951                         ari_ip.ip_suggested = B_TRUE;
5952                         rdma_rej_mad = B_TRUE;
5953                 } else {
5954                         /*
5955                          * Validate whether ip_addr specified are non-NULL.
5956                          *
5957                          * NOTE:
5958                          * RDMA ULP which is servicing this SID, should validate
5959                          * the correctness of srcip/dstip and accordingly post
5960                          * REJ related to ibt_ari_ip_reason_t of
5961                          * IBT_ARI_IP_SRC_ADDR, IBT_ARI_IP_DST_ADDR and
5962                          * IBT_ARI_IP_UNKNOWN_ADDR.
5963                          */
5964                         if (ip_data->ip_ipv == IBT_CM_IP_IPV_V4) {
5965                                 if (ip_data->ip_srcv4 == 0) {
5966                                         IBTF_DPRINTF_L2(cmlog,
5967                                             "ibcm_verify_req_gids_and_svcid: "
5968                                             "Invalid NULL V4 SrcIp specified");
5969                                         rdma_rej_mad = B_TRUE;
5970                                         ari_ip.ip_reason = IBT_ARI_IP_SRC_ADDR;
5971                                         ari_ip.ip_suggested = B_TRUE;
5972                                         ari_ip.ip_suggested_version =
5973                                             IBT_CM_IP_IPV_V4;
5974                                 } else if (ip_data->ip_dstv4 == 0) {
5975                                         IBTF_DPRINTF_L2(cmlog,
5976                                             "ibcm_verify_req_gids_and_svcid: "
5977                                             "Invalid NULL V4 DstIp specified");
5978                                         rdma_rej_mad = B_TRUE;
5979                                         ari_ip.ip_reason = IBT_ARI_IP_DST_ADDR;
5980                                         ari_ip.ip_suggested = B_TRUE;
5981                                         ari_ip.ip_suggested_version =
5982                                             IBT_CM_IP_IPV_V4;
5983                                 }
5984                         } else if (ip_data->ip_ipv == IBT_CM_IP_IPV_V6) {
5985                                 if (IN6_IS_ADDR_UNSPECIFIED(
5986                                     &ip_data->ip_srcv6)) {
5987                                         IBTF_DPRINTF_L2(cmlog,
5988                                             "ibcm_verify_req_gids_and_svcid: "
5989                                             "Invalid NULL V6 SrcIp specified");
5990                                         rdma_rej_mad = B_TRUE;
5991                                         ari_ip.ip_reason = IBT_ARI_IP_SRC_ADDR;
5992                                         ari_ip.ip_suggested = B_TRUE;
5993                                         ari_ip.ip_suggested_version =
5994                                             IBT_CM_IP_IPV_V6;
5995                                 } else if (IN6_IS_ADDR_UNSPECIFIED(
5996                                     &ip_data->ip_dstv6)) {
5997                                         IBTF_DPRINTF_L2(cmlog,
5998                                             "ibcm_verify_req_gids_and_svcid: "
5999                                             "Invalid NULL V6 DstIp specified");
6000                                         rdma_rej_mad = B_TRUE;
6001                                         ari_ip.ip_reason = IBT_ARI_IP_DST_ADDR;
6002                                         ari_ip.ip_suggested = B_TRUE;
6003                                         ari_ip.ip_suggested_version =
6004                                             IBT_CM_IP_IPV_V6;
6005                                 }
6006                         }
6007                         /* TBD: IBT_ARI_IP_UNKNOWN_ADDR */
6008                 }
6009                 if (rdma_rej_mad == B_TRUE) {
6010                         ibt_ari_con_t   cons_rej;
6011 
6012                         mutex_exit(&ibcm_svc_info_lock);
6013 
6014                         cons_rej.rej_ari_len = 1 + sizeof (ibt_ari_ip_t);
6015                         cons_rej.rej_ari[0] = 0; /* Rejected by CM Layer */
6016                         bcopy(&ari_ip, &cons_rej.rej_ari[1],
6017                             sizeof (ibt_ari_ip_t));
6018                         /* Send a REJ with CONSUMER REJ */
6019                         ibcm_post_rej_mad(statep, IBT_CM_CONSUMER,
6020                             IBT_CM_FAILURE_REQ, &cons_rej,
6021                             sizeof (ibt_ari_con_t));
6022                         return (IBCM_FAILURE);
6023                 }
6024         }
6025 
6026         /* find the best "bind" entry that enables this port */
6027 
6028         pkey = b2h16(cm_req_msgp->req_part_key);
6029         svc_bindp = NULL;
6030         tmp_bindp = svc_infop->svc_bind_list;
6031         while (tmp_bindp) {
6032                 if (tmp_bindp->sbind_hcaguid == hca_guid &&
6033                     tmp_bindp->sbind_port == port_num) {
6034                         if (gid.gid_guid ==
6035                             tmp_bindp->sbind_gid.gid_guid &&
6036                             gid.gid_prefix ==
6037                             tmp_bindp->sbind_gid.gid_prefix) {
6038                                 /* gid match => really good match */
6039                                 svc_bindp = tmp_bindp;
6040                                 if (pkey == tmp_bindp->sbind_pkey)
6041                                         /* absolute best match */
6042                                         break;
6043                         } else if (svc_bindp == NULL) {
6044                                 /* port match => a good match */
6045                                 svc_bindp = tmp_bindp;
6046                         }
6047                 }
6048                 tmp_bindp = tmp_bindp->sbind_link;
6049         }
6050         if (svc_bindp == NULL) { /* port not enabled for this SID */
6051                 mutex_exit(&ibcm_svc_info_lock);
6052                 IBTF_DPRINTF_L2(cmlog,
6053                     "ibcm_verify_req_gids_and_svcid: statep 0x%p "
6054                     "no binding found", statep);
6055                 ibcm_post_rej_mad(statep,
6056                     IBT_CM_INVALID_SID, IBT_CM_FAILURE_REQ, NULL, 0);
6057                 return (IBCM_FAILURE);
6058         }
6059         /* copy the GID in case we need it in REJ below */
6060         gid.gid_prefix = b2h64(svc_bindp->sbind_gid.gid_prefix);
6061         gid.gid_guid = b2h64(svc_bindp->sbind_gid.gid_guid);
6062 
6063         statep->state_cm_private = svc_bindp->sbind_cm_private;
6064         statep->state_svc_infop = svc_infop;
6065         statep->cm_handler = svc_infop->svc_rc_handler;
6066         if (reject_reason == IBT_CM_SUCCESS)
6067                 IBCM_SVC_INCR(svc_infop);
6068         mutex_exit(&ibcm_svc_info_lock);
6069 
6070         /*
6071          * If the service id is valid, but gid in REQ is invalid,
6072          * then send a REJ with invalid gid
6073          * For Invalid primary gid, the ARI field is filled with
6074          * with gid from svcinfo
6075          * For invalid prim/alt gid reject, CM uses one of the gids
6076          * registered in ARI.
6077          * For invalid prim/alt lid reject, CM uses the base lid in ARI
6078          */
6079         if (reject_reason != IBT_CM_SUCCESS) {
6080 
6081                 switch (reject_reason) {
6082 
6083                 case IBT_CM_PRIM_GID :
6084                 case IBT_CM_ALT_GID :
6085                         ibcm_post_rej_mad(statep,
6086                             reject_reason, IBT_CM_FAILURE_REQ,
6087                             &gid, sizeof (ib_gid_t));
6088                         break;
6089 
6090                 case IBT_CM_PRIM_LID :
6091                 case IBT_CM_ALT_LID :
6092 
6093                         lid = h2b16(port.hp_base_lid);
6094                         ibcm_post_rej_mad(statep,
6095                             reject_reason, IBT_CM_FAILURE_REQ,
6096                             &lid, sizeof (ib_lid_t));
6097                         break;
6098                 }
6099 
6100                 return (IBCM_FAILURE);
6101         }
6102 
6103         /* Service, primary/alt gid and lid are all valid */
6104 
6105         return (IBCM_SUCCESS);
6106 }
6107 
6108 /*
6109  * ibcm_cep_state_req:
6110  *      QP state transition function called for an incoming REQ on passive side
6111  *      LIDs and GIDs should be maintained and validated by the client handler
6112  *
6113  * INPUTS:
6114  *      statep          - state pointer
6115  *      cm_req_msgp     - REQ message pointer
6116  *      reject_reason   - Rejection reason See Section 12.6.7.2 rev1.0a IB Spec
6117  *      arej_info_len   - Additional Rejection reason info length
6118  *
6119  * RETURN VALUE: IBCM_SEND_REP/IBCM_SEND_REJ
6120  */
6121 ibcm_status_t
6122 ibcm_cep_state_req(ibcm_state_data_t *statep, ibcm_req_msg_t *cm_req_msgp,
6123     ibt_cm_reason_t *reject_reason, uint8_t *arej_len)
6124 {
6125         void                    *priv_data = NULL;
6126         ibt_cm_event_t          event;
6127         ibt_cm_status_t         cb_status;
6128         ibcm_status_t           status;
6129         ibt_cm_return_args_t    ret_args;
6130         ibcm_clnt_reply_info_t  clnt_info;
6131 
6132         IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_req: statep 0x%p", statep);
6133         IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_req: SID 0x%lX",
6134             b2h64(cm_req_msgp->req_svc_id));
6135         /* client handler should be valid */
6136         ASSERT(statep->cm_handler != NULL);
6137 
6138         bzero(&event, sizeof (event));
6139 
6140         /* Fill in ibt_cm_event_t */
6141         event.cm_type = IBT_CM_EVENT_REQ_RCV;
6142         event.cm_session_id = statep;
6143         IBCM_EVT_REQ(event).req_service_id = b2h64(cm_req_msgp->req_svc_id);
6144         IBCM_EVT_REQ(event).req_transport =
6145             ((uint8_t *)&cm_req_msgp->req_remote_eecn_plus)[3] >> 1 & 0x3;
6146         IBCM_EVT_REQ(event).req_timeout = ibt_ib2usec(
6147             (((uint8_t *)&cm_req_msgp->req_remote_eecn_plus)[3] >> 3) & 0x1F);
6148         IBCM_EVT_REQ(event).req_retry_cnt =
6149             ((uint8_t *)&cm_req_msgp->req_starting_psn_plus)[3] & 0x7;
6150         IBCM_EVT_REQ(event).req_rnr_retry_cnt = cm_req_msgp->req_mtu_plus & 0x7;
6151         IBCM_EVT_REQ(event).req_pkey = b2h16(cm_req_msgp->req_part_key);
6152         IBCM_EVT_REQ(event).req_rdma_ra_in =
6153             ((uint8_t *)&cm_req_msgp->req_local_qpn_plus)[3];
6154         IBCM_EVT_REQ(event).req_rdma_ra_out =
6155             ((uint8_t *)&cm_req_msgp->req_local_eec_no_plus)[3];
6156 
6157         /* Check for HCA limits for RDMA Resources */
6158         if (IBCM_EVT_REQ(event).req_rdma_ra_in >
6159             statep->hcap->hca_max_rdma_in_qp) {
6160                 IBTF_DPRINTF_L2(cmlog, "ibcm_cep_state_req: statep 0x%p, REQ "
6161                     "req_rdma_ra_in %d is greater than HCA Limit %d, resetting"
6162                     "it to HCA limit", statep,
6163                     IBCM_EVT_REQ(event).req_rdma_ra_in,
6164                     statep->hcap->hca_max_rdma_in_qp);
6165                 IBCM_EVT_REQ(event).req_rdma_ra_in =
6166                     statep->hcap->hca_max_rdma_in_qp;
6167         }
6168 
6169         if (IBCM_EVT_REQ(event).req_rdma_ra_out >
6170             statep->hcap->hca_max_rdma_out_qp) {
6171                 IBTF_DPRINTF_L2(cmlog, "ibcm_cep_state_req: statep 0x%p, REQ "
6172                     "req_rdma_ra_out %d is greater than HCA Limit %d, resetting"
6173                     "it to HCA limit", statep,
6174                     IBCM_EVT_REQ(event).req_rdma_ra_out,
6175                     statep->hcap->hca_max_rdma_out_qp);
6176                 IBCM_EVT_REQ(event).req_rdma_ra_out =
6177                     statep->hcap->hca_max_rdma_out_qp;
6178         }
6179 
6180         /* Account for CM and other software delays */
6181         if (IBCM_EVT_REQ(event).req_timeout > ibcm_sw_delay) {
6182                 IBCM_EVT_REQ(event).req_timeout -= ibcm_sw_delay;
6183                 IBTF_DPRINTF_L5(cmlog, "ibcm_cep_state_req: statep 0x%p"
6184                     "Avail resp time %d (usec)", statep,
6185                     IBCM_EVT_REQ(event).req_timeout);
6186         } else {
6187                 IBTF_DPRINTF_L2(cmlog, "ibcm_cep_state_req: statep 0x%p "
6188                     "REQ rem_resp_time < local sw delay 0x%x", statep,
6189                     IBCM_EVT_REQ(event).req_timeout);
6190 
6191                 IBCM_EVT_REQ(event).req_timeout = 0;
6192         }
6193 
6194         IBCM_EVT_REQ(event).req_prim_hca_port = statep->prim_port;
6195         IBCM_EVT_REQ(event).req_alt_hca_port = statep->alt_port;
6196         IBCM_EVT_REQ(event).req_hca_guid = statep->local_hca_guid;
6197         IBCM_EVT_REQ(event).req_remote_qpn = statep->remote_qpn;
6198 
6199         if (((uint8_t *)&cm_req_msgp->req_remote_eecn_plus)[3] &
6200             IBT_CM_FLOW_CONTROL)
6201                 IBCM_EVT_REQ(event).req_flags |= IBT_CM_FLOW_CONTROL;
6202 
6203         if ((cm_req_msgp->req_max_cm_retries_plus >> 3) & 0x1)
6204                 IBCM_EVT_REQ(event).req_flags |= IBT_CM_SRQ_EXISTS;
6205 
6206         /* Initialize req.req_prim_addr */
6207         ibcm_set_primary_adds_vect(statep, &IBCM_EVT_REQ(event).req_prim_addr,
6208             cm_req_msgp);
6209 
6210         /* Initialize req.req_alternate_path if they exist */
6211         if (b2h16(cm_req_msgp->req_alt_l_port_lid) != 0) {
6212                 ibcm_set_alt_adds_vect(statep,
6213                     &IBCM_EVT_REQ(event).req_alt_addr, cm_req_msgp);
6214 
6215                 /* Verify, alt path is not same as primary */
6216                 if (ibcm_compare_prim_alt_paths(
6217                     &event.cm_event.req.req_prim_addr,
6218                     &event.cm_event.req.req_alt_addr) == B_TRUE) {
6219                         /* XXX New REJ code needed */
6220                         *reject_reason = IBT_CM_NO_RESC;
6221                         IBTF_DPRINTF_L2(cmlog, "ibcm_cep_state_req: statep 0x%p"
6222                             " Alt and prim paths are same", statep);
6223                         mutex_enter(&ibcm_svc_info_lock);
6224                         IBCM_SVC_DECR(statep->state_svc_infop);
6225                         mutex_exit(&ibcm_svc_info_lock);
6226                         return (IBCM_SEND_REJ);
6227                 }
6228         }
6229 
6230 #ifdef  NO_EEC_SUPPORT_YET
6231         IBCM_EVT_REQ(event).req_rdc_exists = cm_req_msgp->req_mtu_plus >> 3 & 1;
6232         IBCM_EVT_REQ(event).req_remote_eecn =
6233             b2h32(cm_req_msgp->req_remote_eecn_plus) >> 8;
6234         IBCM_EVT_REQ(event).req_local_eecn =
6235             b2h32(cm_req_msgp->req_local_eec_no_plus) >> 8;
6236         IBCM_EVT_REQ(event).req_remote_qkey =
6237             b2h32(cm_req_msgp->req_local_qkey);
6238 #endif
6239 
6240         /* cm_req_msgp->req_private_data to event.cm_event.cm_priv_data */
6241         event.cm_priv_data = cm_req_msgp->req_private_data;
6242 
6243         event.cm_priv_data_len = IBT_REQ_PRIV_DATA_SZ;
6244 
6245         /*
6246          * Allocate priv_data of size IBT_MAX_PRIV_DATA_SZ
6247          */
6248         priv_data = kmem_zalloc(IBT_MAX_PRIV_DATA_SZ, KM_SLEEP);
6249 
6250         bzero(&ret_args, sizeof (ret_args));
6251 
6252         /* Fill in the default values from REQ, that client can modify */
6253         ret_args.cm_ret.rep.cm_rdma_ra_in = IBCM_EVT_REQ(event).req_rdma_ra_out;
6254         ret_args.cm_ret.rep.cm_rdma_ra_out = IBCM_EVT_REQ(event).req_rdma_ra_in;
6255         ret_args.cm_ret.rep.cm_rnr_retry_cnt = cm_req_msgp->req_mtu_plus & 0x7;
6256 
6257         ibcm_insert_trace(statep, IBCM_TRACE_CALLED_REQ_RCVD_EVENT);
6258 
6259         /* Invoke the client handler */
6260         statep->req_msgp = cm_req_msgp;
6261         cb_status = statep->cm_handler(statep->state_cm_private, &event,
6262             &ret_args, priv_data, IBT_REP_PRIV_DATA_SZ);
6263         statep->req_msgp = NULL;
6264 
6265         ibcm_insert_trace(statep, IBCM_TRACE_RET_REQ_RCVD_EVENT);
6266 
6267         mutex_enter(&ibcm_svc_info_lock);
6268         IBCM_SVC_DECR(statep->state_svc_infop);
6269         mutex_exit(&ibcm_svc_info_lock);
6270 
6271         IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_req: Client handler returned %d"
6272             " statep 0x%p", cb_status, statep);
6273 
6274         if (cb_status == IBT_CM_DEFER) {
6275 
6276                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg))
6277 
6278                 if (statep->defer_cm_msg == NULL)
6279                         statep->defer_cm_msg =
6280                             kmem_zalloc(IBCM_MSG_SIZE, KM_SLEEP);
6281                 bcopy(cm_req_msgp, statep->defer_cm_msg, IBCM_MSG_SIZE);
6282 
6283                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg))
6284 
6285                 /*
6286                  * unblock any blocked cm proceed api calls. Do not access
6287                  * statep after cv_signal
6288                  */
6289                 mutex_enter(&statep->state_mutex);
6290                 statep->clnt_proceed = IBCM_UNBLOCK;
6291                 cv_broadcast(&statep->block_client_cv);
6292                 mutex_exit(&statep->state_mutex);
6293 
6294                 kmem_free(priv_data, IBT_MAX_PRIV_DATA_SZ);
6295                 return (IBCM_DEFER);
6296         }
6297 
6298         /* fail any blocked cm proceed api call - client bug */
6299         mutex_enter(&statep->state_mutex);
6300         statep->clnt_proceed = IBCM_FAIL;
6301         cv_broadcast(&statep->block_client_cv);
6302         mutex_exit(&statep->state_mutex);
6303 
6304         clnt_info.reply_event = (ibt_cm_proceed_reply_t *)&ret_args.cm_ret;
6305         clnt_info.priv_data = priv_data;
6306         clnt_info.priv_data_len = ret_args.cm_ret_len;
6307 
6308         status =
6309             ibcm_process_cep_req_cm_hdlr(statep, cb_status,
6310             &clnt_info, reject_reason, arej_len, cm_req_msgp);
6311         kmem_free(priv_data, IBT_MAX_PRIV_DATA_SZ);
6312         return (status);
6313 }
6314 
6315 /*
6316  * ibcm_process_cep_req_cm_hdlr:
6317  *      Processes the response from client handler for an incoming REQ.
6318  */
6319 ibcm_status_t
6320 ibcm_process_cep_req_cm_hdlr(ibcm_state_data_t *statep,
6321     ibt_cm_status_t cb_status, ibcm_clnt_reply_info_t *clnt_info,
6322     ibt_cm_reason_t *reject_reason, uint8_t *arej_len,
6323     ibcm_req_msg_t *cm_req_msg)
6324 {
6325         ibt_status_t            status;
6326         ibt_qp_query_attr_t     qp_attrs;
6327         ibcm_state_data_t       *old_statep;
6328         ibt_channel_hdl_t       channel;
6329         ib_guid_t               local_ca_guid;
6330         ibcm_rej_msg_t          *rej_msgp;
6331 #ifdef  NO_EEC_SUPPORT_YET
6332         ibt_eec_query_attr_t    eec_attrs;
6333 #endif
6334 
6335         if (cb_status == IBT_CM_DEFAULT)
6336                 cb_status = IBT_CM_REJECT;
6337 
6338         /* verify status */
6339         if (cb_status == IBT_CM_ACCEPT) {
6340                 *reject_reason = IBT_CM_SUCCESS;
6341         } else if (cb_status == IBT_CM_REJECT) {
6342                 *reject_reason = IBT_CM_CONSUMER;
6343         } else if (cb_status == IBT_CM_REDIRECT_PORT) {
6344                 *reject_reason = IBT_CM_PORT_REDIRECT;
6345         } else if (cb_status == IBT_CM_REDIRECT) {
6346                 *reject_reason = IBT_CM_REDIRECT_CM;
6347         } else if (cb_status == IBT_CM_NO_CHANNEL) {
6348                 *reject_reason = IBT_CM_NO_CHAN;
6349         } else if (cb_status == IBT_CM_NO_RESOURCE) {
6350                 *reject_reason = IBT_CM_NO_RESC;
6351         } else {
6352                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: statep %p"
6353                     " Client handler unexpected return %x", statep, cb_status);
6354                 *reject_reason = IBT_CM_CONSUMER;
6355         }
6356 
6357         /* client handler gave CM ok */
6358         if (cb_status == IBT_CM_ACCEPT) {
6359                 ibcm_rep_msg_t  *rep_msgp = (ibcm_rep_msg_t *)
6360                     IBCM_OUT_MSGP(statep->stored_msg);
6361 
6362 
6363                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
6364                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rep_msgp))
6365 
6366                 /*
6367                  * Check first if ret_args make sense. If not, bailout
6368                  * here rather than going along and panicing later.
6369                  */
6370                 channel = clnt_info->reply_event->rep.cm_channel;
6371                 if (IBCM_INVALID_CHANNEL(channel)) {
6372                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6373                             "statep 0x%p server's QP handle is NULL", statep);
6374                         *reject_reason = IBT_CM_NO_CHAN;
6375                 }
6376 
6377                 IBCM_GET_CHAN_PRIVATE(channel, old_statep);
6378 
6379                 if ((*reject_reason == IBT_CM_SUCCESS) &&
6380                     (old_statep != NULL)) {
6381                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6382                             "statep 0x%p Channel being re-used on passive side",
6383                             statep);
6384                         *reject_reason = IBT_CM_NO_CHAN;
6385                 }
6386                 if (old_statep != NULL)
6387                         IBCM_RELEASE_CHAN_PRIVATE(channel);
6388 
6389                 if (*reject_reason != IBT_CM_SUCCESS) {
6390                         ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6391                             IBT_CM_FAILURE_REQ, *reject_reason, NULL, 0);
6392                         return (IBCM_SEND_REJ);
6393                 }
6394 
6395                 statep->channel = channel;
6396                 status = ibt_query_qp(channel, &qp_attrs);
6397 
6398                 if (status != IBT_SUCCESS) {
6399                         IBTF_DPRINTF_L3(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6400                             "statep %p ibt_query_qp failed %d", statep, status);
6401                         *reject_reason = IBT_CM_NO_RESC;
6402                         ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6403                             IBT_CM_FAILURE_REQ, IBT_CM_CI_FAILURE, NULL, 0);
6404                         return (IBCM_SEND_REJ);
6405                 }
6406 
6407                 if (qp_attrs.qp_info.qp_trans != IBT_RC_SRV) {
6408                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6409                             "statep %p qp is not RC channel on server", statep);
6410                         *reject_reason = IBT_CM_INVALID_SRV_TYPE;
6411                         ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6412                             IBT_CM_FAILURE_REQ, IBT_CM_CHAN_INVALID_STATE,
6413                             NULL, 0);
6414                         return (IBCM_SEND_REJ);
6415                 }
6416 
6417                 if (qp_attrs.qp_info.qp_state != IBT_STATE_INIT &&
6418                     statep->is_this_ofuv_chan == B_FALSE) {
6419                         IBTF_DPRINTF_L3(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6420                             "qp state != INIT on server");
6421                         *reject_reason = IBT_CM_CHAN_INVALID_STATE;
6422                         ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6423                             IBT_CM_FAILURE_REQ, IBT_CM_CHAN_INVALID_STATE,
6424                             NULL, 0);
6425                         return (IBCM_SEND_REJ);
6426                 } else if (statep->is_this_ofuv_chan &&
6427                     qp_attrs.qp_info.qp_state != IBT_STATE_RTR &&
6428                     qp_attrs.qp_info.qp_state != IBT_STATE_INIT) {
6429                         IBTF_DPRINTF_L3(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6430                             "qp state != INIT or RTR on server");
6431                         *reject_reason = IBT_CM_CHAN_INVALID_STATE;
6432                         ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6433                             IBT_CM_FAILURE_REQ, IBT_CM_CHAN_INVALID_STATE,
6434                             NULL, 0);
6435                         return (IBCM_SEND_REJ);
6436                 }
6437 
6438                 if (statep->is_this_ofuv_chan &&
6439                     qp_attrs.qp_info.qp_state == IBT_STATE_RTR &&
6440                     qp_attrs.qp_info.qp_transport.rc.rc_path.cep_hca_port_num !=
6441                     statep->prim_port) {
6442                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6443                             "QP port invalid");
6444                         *reject_reason = IBT_CM_CHAN_INVALID_STATE;
6445                         ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6446                             IBT_CM_FAILURE_REQ, IBT_CM_CHAN_INVALID_STATE,
6447                             NULL, 0);
6448                         return (IBCM_SEND_REJ);
6449                 } else if (statep->is_this_ofuv_chan &&
6450                     qp_attrs.qp_info.qp_state == IBT_STATE_RTR) {
6451                         goto skip_init_trans;
6452                 }
6453 
6454                 /* Init to Init, if required */
6455                 if (qp_attrs.qp_info.qp_transport.rc.rc_path.cep_hca_port_num !=
6456                     statep->prim_port) {
6457 
6458                         ibt_qp_info_t           qp_info;
6459                         ibt_cep_modify_flags_t  cep_flags;
6460 
6461                         IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6462                             "chan 0x%p chan port %d", channel,
6463                             qp_attrs.qp_info.qp_transport.rc.rc_path.\
6464                             cep_hca_port_num);
6465 
6466                         IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6467                             "chan 0x%p d path port %d", channel,
6468                             statep->prim_port);
6469 
6470                         bzero(&qp_info, sizeof (qp_info));
6471                         qp_info.qp_trans = IBT_RC_SRV;
6472                         qp_info.qp_state = IBT_STATE_INIT;
6473                         qp_info.qp_transport.rc.rc_path.cep_hca_port_num =
6474                             statep->prim_port;
6475 
6476                         cep_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT;
6477 
6478                         status = ibt_modify_qp(statep->channel, cep_flags,
6479                             &qp_info, NULL);
6480 
6481                         if (status != IBT_SUCCESS) {
6482                                 IBTF_DPRINTF_L2(cmlog,
6483                                     "ibcm_process_cep_req_cm_hdlr: "
6484                                     "chan 0x%p ibt_modify_qp() = %d", channel,
6485                                     status);
6486                                 *reject_reason = IBT_CM_NO_RESC;
6487 
6488                                 ibcm_insert_trace(statep,
6489                                     IBCM_TRACE_INIT_INIT_FAIL);
6490 
6491                                 ibcm_handler_conn_fail(statep,
6492                                     IBT_CM_FAILURE_REJ_SENT, IBT_CM_FAILURE_REQ,
6493                                     IBT_CM_CI_FAILURE, NULL, 0);
6494                                 return (IBCM_SEND_REJ);
6495                         } else {
6496                                 ibcm_insert_trace(statep,
6497                                     IBCM_TRACE_INIT_INIT);
6498 
6499                                 IBTF_DPRINTF_L5(cmlog,
6500                                     "ibcm_process_cep_req_cm_hdlr: "
6501                                     "chan 0x%p ibt_modify_qp() = %d", channel,
6502                                     status);
6503                         }
6504                 }
6505 skip_init_trans:
6506                 /* Do sanity tests even if we are skipping RTR */
6507 
6508                 /* fill in the REP msg based on ret_args from client */
6509                 if (clnt_info->reply_event->rep.cm_rdma_ra_out >
6510                     ((uint8_t *)&cm_req_msg->req_local_qpn_plus)[3]) {
6511                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_cm_hdlr "
6512                             "statep 0x%p ERROR: InitiatorDepth(%d) is Greater "
6513                             "than ResponderResource(%d)", statep,
6514                             clnt_info->reply_event->rep.cm_rdma_ra_out,
6515                             ((uint8_t *)&cm_req_msg->req_local_qpn_plus)[3]);
6516                         *reject_reason = IBT_CM_NOT_SUPPORTED;
6517                         ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6518                             IBT_CM_FAILURE_REQ, IBT_CM_NOT_SUPPORTED, NULL, 0);
6519                         return (IBCM_SEND_REJ);
6520                 }
6521 
6522                 /* Check for HCA limits for RDMA Resources */
6523                 if (clnt_info->reply_event->rep.cm_rdma_ra_in >
6524                     statep->hcap->hca_max_rdma_in_qp) {
6525                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_cm_hdlr: "
6526                             "statep %p, ERROR: client specified rdma_ra_in %d "
6527                             "is greater than HCA Limit %d, rejecting MAD",
6528                             statep, clnt_info->reply_event->rep.cm_rdma_ra_in,
6529                             statep->hcap->hca_max_rdma_in_qp);
6530                         *reject_reason = IBT_CM_NOT_SUPPORTED;
6531                         ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6532                             IBT_CM_FAILURE_REQ, IBT_CM_NOT_SUPPORTED, NULL, 0);
6533                         return (IBCM_SEND_REJ);
6534                 }
6535 
6536                 if (clnt_info->reply_event->rep.cm_rdma_ra_out >
6537                     statep->hcap->hca_max_rdma_out_qp) {
6538                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_cm_hdlr: "
6539                             "statep %p, ERROR: client specified rdma_ra_out %d "
6540                             "is greater than HCA Limit %d, rejecting MAD",
6541                             statep, clnt_info->reply_event->rep.cm_rdma_ra_out,
6542                             statep->hcap->hca_max_rdma_out_qp);
6543                         *reject_reason = IBT_CM_NOT_SUPPORTED;
6544                         ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6545                             IBT_CM_FAILURE_REQ, IBT_CM_NOT_SUPPORTED, NULL, 0);
6546                         return (IBCM_SEND_REJ);
6547                 }
6548 
6549                 rep_msgp->rep_resp_resources =
6550                     clnt_info->reply_event->rep.cm_rdma_ra_in;
6551                 rep_msgp->rep_initiator_depth =
6552                     clnt_info->reply_event->rep.cm_rdma_ra_out;
6553 
6554                 /* IBT_CM_FLOW_CONTROL is always set by default. */
6555                 rep_msgp->rep_target_delay_plus |= IBT_CM_FLOW_CONTROL;
6556 
6557                 rep_msgp->rep_rnr_retry_cnt_plus =
6558                     (clnt_info->reply_event->rep.cm_rnr_retry_cnt & 0x7) << 5;
6559 
6560                 /*
6561                  * Check out whether SRQ is associated with this channel.
6562                  * If yes, then set the appropriate bit.
6563                  */
6564                 if (qp_attrs.qp_srq != NULL) {
6565                         rep_msgp->rep_rnr_retry_cnt_plus |= (1 << 4);
6566                 }
6567 
6568                 local_ca_guid = h2b64(statep->local_hca_guid);
6569                 bcopy(&local_ca_guid, rep_msgp->rep_local_ca_guid,
6570                     sizeof (ib_guid_t));
6571 
6572                 if (statep->is_this_ofuv_chan &&
6573                     qp_attrs.qp_info.qp_state == IBT_STATE_RTR)
6574                         goto skip_rtr_trans;
6575 
6576                 /* Transition QP from Init to RTR state */
6577                 if (ibcm_invoke_qp_modify(statep, cm_req_msg, rep_msgp) !=
6578                     IBT_SUCCESS) {
6579 
6580                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_cm_hdlr "
6581                             "statep 0x%p ibcm_invoke_qp_modify failed because "
6582                             "of invalid data", statep);
6583                         *reject_reason = IBT_CM_NO_RESC;
6584                         ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6585                             IBT_CM_FAILURE_REQ, IBT_CM_CI_FAILURE, NULL, 0);
6586                         return (IBCM_SEND_REJ);
6587                 }
6588 skip_rtr_trans:
6589 
6590                 /*
6591                  * Link statep and channel, once CM determines it is
6592                  * post REP definitely.
6593                  */
6594                 IBCM_SET_CHAN_PRIVATE(statep->channel, statep);
6595 
6596                 /*
6597                  * Fill up the REP fields from ret_args
6598                  * failover status,  from ret_args
6599                  *
6600                  * Fill up local QPN and EECN from ret_args->channel
6601                  */
6602 
6603                 /* fill in REP msg bytes Qkey, Starting PSN, 12-15, and 16-19 */
6604                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6605                     "qp_info.qp_state = %x", qp_attrs.qp_info.qp_state);
6606 
6607                 rep_msgp->rep_local_qpn_plus = h2b32(qp_attrs.qp_qpn << 8);
6608 
6609                 statep->local_qpn = qp_attrs.qp_qpn;
6610 
6611                 switch (qp_attrs.qp_info.qp_trans) {
6612                 case IBT_RD_SRV:
6613                         rep_msgp->rep_local_qkey = h2b32(
6614                             qp_attrs.qp_info.qp_transport.rd.rd_qkey);
6615                         break;
6616                 case IBT_RC_SRV:
6617                         rep_msgp->rep_starting_psn_plus =
6618                             h2b32(IBCM_QP_RC(qp_attrs).rc_rq_psn << 8);
6619                         break;
6620                 case IBT_UC_SRV:
6621                         rep_msgp->rep_starting_psn_plus =
6622                             h2b32(IBCM_QP_UC(qp_attrs).uc_sq_psn << 8);
6623                         break;
6624                 }
6625 
6626 #ifdef  NO_EEC_SUPPORT_YET
6627                 if (ret_args.cm_channel.ch_eec != NULL) {
6628                         status = ibt_query_eec(ret_args.cm_channel.ch_eec,
6629                             &eec_attrs);
6630                         if (status == IBT_SUCCESS) {
6631                                 rep_msgp->rep_local_eecn_plus =
6632                                     h2b32(((uint32_t)eec_attrs.eec_eecn << 8));
6633                         }
6634                 }
6635 #endif
6636 
6637                 /* figure out Target ACK delay */
6638                 rep_msgp->rep_target_delay_plus |= (status == IBT_SUCCESS) ?
6639                     statep->hcap->hca_ack_delay << 3 : 0;
6640 
6641                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_req_cm_hdlr:statep %p "
6642                     "REP priv len %x", statep, clnt_info->priv_data_len);
6643                 /* Copy PrivateData from priv_data */
6644                 if (clnt_info->priv_data_len != 0) {
6645                         bcopy(clnt_info->priv_data, rep_msgp->rep_private_data,
6646                             min(IBT_REP_PRIV_DATA_SZ,
6647                             clnt_info->priv_data_len));
6648                 }
6649 
6650                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
6651                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rep_msgp))
6652 
6653                 return (IBCM_SEND_REP);
6654         }
6655 
6656         /* REJ message */
6657         rej_msgp = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
6658 
6659         IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_req_cm_hdlr: statep %p REJ "
6660             "priv len %x", statep, clnt_info->priv_data_len);
6661 
6662         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msgp))
6663 
6664         /* if priv_data_len != 0 use priv_data to copy back to rej_priv_data */
6665         if (clnt_info->priv_data_len != 0) {
6666                 bcopy(clnt_info->priv_data, rej_msgp->rej_private_data,
6667                     min(IBT_REJ_PRIV_DATA_SZ, clnt_info->priv_data_len));
6668         }
6669 
6670         if (cb_status == IBT_CM_REDIRECT_PORT) {
6671                 ib_gid_t tgid;
6672 
6673                 tgid.gid_guid =
6674                     h2b64(clnt_info->reply_event->rej.ari_gid.gid_guid);
6675                 tgid.gid_prefix =
6676                     h2b64(clnt_info->reply_event->rej.ari_gid.gid_prefix);
6677 
6678                 *arej_len = sizeof (ib_gid_t);
6679                 bcopy(&tgid, &rej_msgp->rej_addl_rej_info, sizeof (ib_gid_t));
6680 
6681                 IBTF_DPRINTF_L3(cmlog, "ibcm_process_cep_req_cm_hdlr: ari_gid= "
6682                     "%llX:%llX", tgid.gid_prefix, tgid.gid_guid);
6683 
6684         } else if (cb_status == IBT_CM_REDIRECT) {
6685                 ibcm_classportinfo_msg_t        tclp;
6686 
6687                 ibcm_init_clp_to_mad(&tclp,
6688                     &clnt_info->reply_event->rej.ari_redirect);
6689                 bcopy(&tclp, rej_msgp->rej_addl_rej_info, sizeof (tclp));
6690 
6691                 *arej_len = sizeof (ibcm_classportinfo_msg_t);
6692 
6693         } else if (cb_status == IBT_CM_REJECT) {
6694 
6695                 /* Fill up the REJ fields, from ret_args */
6696                 *arej_len = min(
6697                     clnt_info->reply_event->rej.ari_consumer.rej_ari_len,
6698                     IBT_CM_ADDL_REJ_LEN);
6699                 bcopy(clnt_info->reply_event->rej.ari_consumer.rej_ari,
6700                     &rej_msgp->rej_addl_rej_info, *arej_len);
6701 
6702                 /*
6703                  * RDMA IP REQ was passed up to the ULP, the ULP decided to do
6704                  * a "normal" consumer REJ, by the returning IBT_CM_REJECT in
6705                  * the cm handler.
6706                  * CM has to do some extra stuff too, it has to
6707                  * a) return REJ code 28 (consumer) and b) put 0x1 in the first
6708                  * byte of the ARI data, to indicate that this is a RDMA aware
6709                  * ULP that is doing a consumer reject.  The ULP should have
6710                  * put its consumer specific data into ibt_arej_info_t(9s) at
6711                  * byte 1 of the rej_ari[] array.
6712                  */
6713                 if (((statep->svcid & IB_SID_IPADDR_PREFIX_MASK) == 0) &&
6714                     (statep->svcid & IB_SID_IPADDR_PREFIX)) {
6715                         rej_msgp->rej_addl_rej_info[0] = 1;
6716                 }
6717         }
6718 
6719         rej_msgp->rej_msg_type_plus = IBT_CM_FAILURE_REQ << 6;
6720 
6721         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msgp))
6722 
6723         return (IBCM_SEND_REJ);
6724 }
6725 
6726 /*
6727  * ibcm_cep_state_rep:
6728  *      QP state transition function called for an incoming REP on active side
6729  *
6730  * INPUTS:
6731  *      statep          - state pointer
6732  *      cm_rep_msg      - REP message pointer
6733  *      reject_reason   - Rejection reason See Section 12.6.7.2 rev1.0a IB Spec
6734  *
6735  * RETURN VALUE:
6736  */
6737 ibcm_status_t
6738 ibcm_cep_state_rep(ibcm_state_data_t *statep, ibcm_rep_msg_t *cm_rep_msgp,
6739     ibt_cm_reason_t *reject_reason, uint8_t *arej_len)
6740 {
6741         void                    *priv_data = NULL;
6742         ibcm_status_t           rval = IBCM_SEND_RTU;
6743         ibt_cm_event_t          event;
6744         ibt_cm_status_t         cb_status = IBT_CM_ACCEPT;
6745         ibt_cm_return_args_t    ret_args;
6746         ibcm_clnt_reply_info_t  clnt_info;
6747         uint8_t                 req_init_depth;
6748 
6749         IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_rep: statep 0x%p", statep);
6750 
6751         /* Check first if client handler is valid */
6752         if (statep->cm_handler != NULL) {
6753                 /* initialize fields in ibt_cm_event_t */
6754                 bzero(&event, sizeof (event));
6755                 event.cm_type = IBT_CM_EVENT_REP_RCV;
6756                 event.cm_channel = statep->channel;
6757                 event.cm_session_id = statep;
6758 
6759                 IBCM_EVT_REP(event).rep_rdma_ra_in =
6760                     cm_rep_msgp->rep_initiator_depth;
6761                 req_init_depth =
6762                     ((uint8_t *)&(((ibcm_req_msg_t *)IBCM_OUT_MSGP(
6763                     statep->stored_msg))->req_local_eec_no_plus))[3];
6764                 IBCM_EVT_REP(event).rep_rdma_ra_out =
6765                     min(cm_rep_msgp->rep_resp_resources, req_init_depth);
6766 
6767                 IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_rep: statep 0x%p, "
6768                     "InitDepth %d, RespResr %d", statep,
6769                     cm_rep_msgp->rep_initiator_depth,
6770                     IBCM_EVT_REP(event).rep_rdma_ra_out);
6771 
6772                 IBCM_EVT_REP(event).rep_service_time = ibt_ib2usec(
6773                     ((uint8_t *)&(((ibcm_req_msg_t *)IBCM_OUT_MSGP(
6774                     statep->stored_msg))->req_starting_psn_plus))[3] >> 3);
6775 
6776                 IBCM_EVT_REP(event).rep_service_time -=
6777                     2 * statep->pkt_life_time - ibcm_sw_delay;
6778 
6779                 IBCM_EVT_REP(event).rep_failover_status =
6780                     cm_rep_msgp->rep_target_delay_plus >> 1 & 3;
6781 
6782                 if (cm_rep_msgp->rep_target_delay_plus & 0x1)
6783                         IBCM_EVT_REP(event).rep_flags |= IBT_CM_FLOW_CONTROL;
6784 
6785                 if ((cm_rep_msgp->rep_rnr_retry_cnt_plus >> 4) & 0x1)
6786                         IBCM_EVT_REP(event).rep_flags |= IBT_CM_SRQ_EXISTS;
6787 
6788                 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rep: statep 0x%p "
6789                     "rep_service_time %d", statep,
6790                     IBCM_EVT_REP(event).rep_service_time);
6791 
6792                 event.cm_priv_data = &(cm_rep_msgp->rep_private_data[0]);
6793                 event.cm_priv_data_len = IBT_REP_PRIV_DATA_SZ;
6794 
6795                 /*
6796                  * Allocate priv_data of size IBT_MAX_PRIV_DATA_SZ
6797                  */
6798                 priv_data = kmem_zalloc(IBT_MAX_PRIV_DATA_SZ, KM_SLEEP);
6799                 bzero(&ret_args, sizeof (ret_args));
6800 
6801 
6802                 ibcm_insert_trace(statep, IBCM_TRACE_CALLED_REP_RCVD_EVENT);
6803 
6804                 /* invoke the CM handler */
6805                 cb_status = statep->cm_handler(statep->state_cm_private, &event,
6806                     &ret_args, priv_data, IBT_RTU_PRIV_DATA_SZ);
6807 
6808                 ibcm_insert_trace(statep, IBCM_TRACE_RET_REP_RCVD_EVENT);
6809 
6810                 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rep: statep 0x%p "
6811                     "Client handler returned %x", statep, cb_status);
6812 
6813                 if (cb_status == IBT_CM_DEFER) {
6814                         if (statep->defer_cm_msg == NULL)
6815                                 statep->defer_cm_msg =
6816                                     kmem_zalloc(IBCM_MSG_SIZE, KM_SLEEP);
6817                         bcopy(cm_rep_msgp, statep->defer_cm_msg, IBCM_MSG_SIZE);
6818 
6819                         /* unblock any blocked cm proceed api calls */
6820                         mutex_enter(&statep->state_mutex);
6821                         statep->clnt_proceed = IBCM_UNBLOCK;
6822                         cv_broadcast(&statep->block_client_cv);
6823                         mutex_exit(&statep->state_mutex);
6824 
6825                         kmem_free(priv_data, IBT_MAX_PRIV_DATA_SZ);
6826                         return (IBCM_DEFER);
6827                 }
6828         }
6829 
6830         /* fail any blocked cm proceed api calls - client bug */
6831         mutex_enter(&statep->state_mutex);
6832         statep->clnt_proceed = IBCM_FAIL;
6833         cv_broadcast(&statep->block_client_cv);
6834         mutex_exit(&statep->state_mutex);
6835 
6836         clnt_info.reply_event = (ibt_cm_proceed_reply_t *)&ret_args.cm_ret;
6837         clnt_info.priv_data = priv_data;
6838         clnt_info.priv_data_len = ret_args.cm_ret_len;
6839 
6840         rval =
6841             ibcm_process_cep_rep_cm_hdlr(statep, cb_status, &clnt_info,
6842             reject_reason, arej_len, cm_rep_msgp);
6843 
6844         if (priv_data != NULL)
6845                 kmem_free(priv_data, IBT_MAX_PRIV_DATA_SZ);
6846         return (rval);
6847 }
6848 
6849 
6850 /*
6851  * ibcm_process_cep_rep_cm_hdlr:
6852  *      Processes the response from client handler for an incoming REP.
6853  */
6854 ibcm_status_t
6855 ibcm_process_cep_rep_cm_hdlr(ibcm_state_data_t *statep,
6856     ibt_cm_status_t cb_status, ibcm_clnt_reply_info_t *clnt_info,
6857     ibt_cm_reason_t *reject_reason, uint8_t *arej_len,
6858     ibcm_rep_msg_t *cm_rep_msgp)
6859 {
6860         ibcm_status_t           rval = IBCM_SEND_RTU;
6861         ibcm_rej_msg_t          *rej_msgp;
6862 
6863         if (cb_status == IBT_CM_DEFAULT)
6864                 cb_status = IBT_CM_ACCEPT;
6865 
6866         if (cb_status == IBT_CM_REJECT) {
6867                 *reject_reason = IBT_CM_CONSUMER;
6868         } else if (cb_status == IBT_CM_REDIRECT_PORT) {
6869                 *reject_reason = IBT_CM_PORT_REDIRECT;
6870         } else if (cb_status == IBT_CM_REDIRECT) {
6871                 *reject_reason = IBT_CM_REDIRECT_CM;
6872         } else if (cb_status == IBT_CM_NO_RESOURCE) {
6873                 *reject_reason = IBT_CM_NO_RESC;
6874         } else if (cb_status != IBT_CM_ACCEPT) {
6875                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep "
6876                     "0x%p, Client handler returned unexpected value %d",
6877                     statep, cb_status);
6878                 *reject_reason = IBT_CM_CONSUMER;
6879         } else
6880                 *reject_reason = IBT_CM_SUCCESS;
6881 
6882 
6883         /* We come here if status is ACCEPT or CM handler is NULL */
6884         if (cb_status == IBT_CM_ACCEPT) {
6885                 ib_time_t       time;
6886 
6887                 time = ibt_usec2ib(statep->pkt_life_time * 2 +
6888                     ibt_ib2usec(cm_rep_msgp->rep_target_delay_plus >> 3));
6889 
6890                 IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p"
6891                     " active cep_timeout(usec) 0x%x ", statep, time);
6892 
6893                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p"
6894                     " passive hca_ack_delay(ib_time) = 0x%x, ", statep,
6895                     cm_rep_msgp->rep_target_delay_plus >> 3);
6896 
6897                 IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p"
6898                     " rnr_retry_cnt = 0x%x", statep,
6899                     cm_rep_msgp->rep_rnr_retry_cnt_plus >> 5);
6900 
6901                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
6902                 statep->starting_psn =
6903                     b2h32(cm_rep_msgp->rep_starting_psn_plus) >> 8;
6904 
6905                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
6906 
6907                 /* Call IBTL CM's qp modify function from Init to RTR */
6908                 if (ibcm_invoke_qp_modify(statep,
6909                     (ibcm_req_msg_t *)IBCM_OUT_MSGP(statep->stored_msg),
6910                     cm_rep_msgp) != IBT_SUCCESS) {
6911 
6912                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_rep_cm_hdlr: "
6913                             "statep %p, ibcm_invoke_qp_modify to RTR failed",
6914                             statep);
6915                         *reject_reason = IBT_CM_NO_RESC;
6916                 /*
6917                  * Call modify qp function from RTR to RTS
6918                  * RDMA initiator depth on active is same as negotiated
6919                  * passive REP's responder resources
6920                  */
6921                 } else if (ibcm_invoke_rtu_qp_modify(statep, time, cm_rep_msgp)
6922                     != IBT_SUCCESS) {
6923 
6924                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_rep_cm_hdlr: "
6925                             "statep %p ibcm_invoke_rtu_qp_modify to RTS failed",
6926                             statep);
6927                         (void) ibcm_cep_to_error_state(statep);
6928                         *reject_reason = IBT_CM_NO_RESC;
6929                 }
6930 
6931                 if (*reject_reason == IBT_CM_NO_RESC) {
6932 
6933                         /* Disassociate statep and QP */
6934                         IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
6935 
6936                         ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6937                             IBT_CM_FAILURE_REP, IBT_CM_CI_FAILURE, NULL, 0);
6938                         return (IBCM_SEND_REJ); /* send REJ */
6939                 }
6940 
6941                 if (clnt_info->priv_data_len != 0) {
6942                         ibcm_rtu_msg_t *rtu_msgp;
6943                         rtu_msgp = (ibcm_rtu_msg_t *)
6944                             IBCM_OUT_MSGP(statep->stored_msg);
6945                         bcopy(clnt_info->priv_data, rtu_msgp->rtu_private_data,
6946                             min(IBT_RTU_PRIV_DATA_SZ,
6947                             clnt_info->priv_data_len));
6948                 }
6949 
6950                 *reject_reason = IBT_CM_SUCCESS;
6951                 return (rval);
6952         }
6953 
6954         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msgp))
6955 
6956         /* Fill up the REJ fields, from ret_args */
6957         rej_msgp = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
6958         rej_msgp->rej_msg_type_plus = IBT_CM_FAILURE_REP << 6;
6959 
6960         /* if priv_len != 0 use priv_data to copy back to rej_priv_data */
6961         if (clnt_info->priv_data_len != 0)
6962                 bcopy(clnt_info->priv_data, rej_msgp->rej_private_data,
6963                     min(IBT_REJ_PRIV_DATA_SZ, clnt_info->priv_data_len));
6964 
6965         if (clnt_info->reply_event != NULL)
6966                 *arej_len =
6967                     min(clnt_info->reply_event->rej.ari_consumer.rej_ari_len,
6968                     IBT_CM_ADDL_REJ_LEN);
6969 
6970         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(clnt_info->reply_event->rej))
6971 
6972         if (*arej_len != 0)     /* asserts that clnt_info->reply_event != 0 */
6973                 bcopy(clnt_info->reply_event->rej.ari_consumer.rej_ari,
6974                     &rej_msgp->rej_addl_rej_info, *arej_len);
6975 
6976         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(clnt_info->reply_event->rej))
6977 
6978         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msgp))
6979 
6980         rval = IBCM_SEND_REJ;
6981 
6982         /* Disassociate statep and QP */
6983         IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
6984 
6985         /* callback client, to enable client to do resource cleanup */
6986         ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6987             IBT_CM_FAILURE_REP, *reject_reason, NULL, 0);
6988 
6989         return (rval);
6990 }
6991 
6992 /*
6993  * ibcm_invoke_rtu_qp_modify:
6994  *      Helper function to modify QP for RTU only called from
6995  *      ibcm_cep_state_rtu() and ibcm_cep_send_rtu()
6996  *
6997  * INPUTS:
6998  *      statep          - connection state pointer
6999  *
7000  * RETURN VALUE:
7001  */
7002 static ibt_status_t
7003 ibcm_invoke_rtu_qp_modify(ibcm_state_data_t *statep, ib_time_t timeout,
7004     ibcm_rep_msg_t *rep_msg)
7005 {
7006         ibt_status_t            status;
7007         ibt_qp_info_t           qp_info;
7008         ibt_cep_modify_flags_t  cep_flags = IBT_CEP_SET_RTR_RTS;
7009 
7010         /* Start filling up ibt_qp_info_t.  */
7011         bzero(&qp_info, sizeof (qp_info));
7012         qp_info.qp_trans = ibtl_cm_get_chan_type(statep->channel);
7013         qp_info.qp_current_state = IBT_STATE_RTR;
7014 
7015         switch (qp_info.qp_trans) {
7016         case IBT_RC_SRV:
7017                 IBCM_QPINFO_RC_PATH(qp_info).cep_timeout = timeout;
7018                 IBCM_QPINFO_RC(qp_info).rc_retry_cnt = statep->cep_retry_cnt;
7019                 IBCM_QPINFO_RC(qp_info).rc_rnr_retry_cnt =
7020                     statep->local_qp_rnr_cnt;
7021                 IBCM_QPINFO_RC(qp_info).rc_sq_psn = statep->starting_psn;
7022 
7023                 if (statep->mode == IBCM_ACTIVE_MODE) {
7024                         IBCM_QPINFO_RC(qp_info).rc_rdma_ra_out =
7025                             rep_msg->rep_resp_resources;
7026                 } else {
7027                         IBCM_QPINFO_RC(qp_info).rc_rdma_ra_out =
7028                             rep_msg->rep_initiator_depth;
7029                 }
7030                 if (statep->alt_port &&
7031                     (((rep_msg->rep_target_delay_plus >> 1) & 0x3) ==
7032                     IBT_CM_FAILOVER_ACCEPT)) {
7033                         /* failover was accepted */
7034                         cep_flags |= IBT_CEP_SET_MIG;
7035                         IBCM_QPINFO_RC(qp_info).rc_mig_state =
7036                             IBT_STATE_REARMED;
7037                 }
7038 
7039                 break;
7040         /* XXX RD? */
7041         case IBT_UC_SRV:
7042                 IBCM_QPINFO_UC_PATH(qp_info).cep_timeout = timeout;
7043                 break;
7044         default:
7045                 IBTF_DPRINTF_L2(cmlog, "ibcm_invoke_rtu_qp_modify: "
7046                     "unknow svc_type = %x", qp_info.qp_trans);
7047                 break;
7048         }
7049 
7050         /* Call modify_qp */
7051         status = ibt_modify_qp(statep->channel, cep_flags, &qp_info, NULL);
7052         IBTF_DPRINTF_L4(cmlog, "ibcm_invoke_rtu_qp_modify: statep 0x%p "
7053             "modify qp status = %d", statep, status);
7054 
7055         if (status == IBT_SUCCESS)
7056                 ibcm_insert_trace(statep, IBCM_TRACE_RTR_RTS);
7057         else
7058                 ibcm_insert_trace(statep, IBCM_TRACE_RTR_RTS_FAIL);
7059 
7060 #ifdef  DEBUG
7061         print_modify_qp("RTR to RTS", statep->channel, cep_flags, &qp_info);
7062 
7063         if (statep->channel != NULL) {
7064                 ibt_qp_query_attr_t     qp_attrs;
7065 
7066                 (void) ibt_query_qp(statep->channel, &qp_attrs);
7067                 IBTF_DPRINTF_L4(cmlog, "ibcm_invoke_rtu_qp_modify: "
7068                     "qp_info.qp_state = %x", qp_attrs.qp_info.qp_state);
7069         }
7070 #endif
7071         return (status);
7072 }
7073 
7074 
7075 /*
7076  * ibcm_cep_state_rtu:
7077  *      QP state transition function called for an incoming RTU
7078  *      on passive side.
7079  *
7080  * INPUTS:
7081  *      statep          - connection state pointer
7082  *      cm_rtu_msg      - RTU message pointer
7083  *
7084  */
7085 void
7086 ibcm_cep_state_rtu(ibcm_state_data_t *statep, ibcm_rtu_msg_t *cm_rtu_msgp)
7087 {
7088         ibt_status_t    status;
7089         ibt_cm_event_t  event;
7090         ibcm_rep_msg_t  *rep_msgp = (ibcm_rep_msg_t *)
7091             IBCM_OUT_MSGP(statep->stored_msg);
7092 
7093         IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rtu: statep 0x%p", statep);
7094 
7095         ASSERT(statep->channel != NULL);
7096 
7097         /* RDMA initiator depth taken from negotiated REP values */
7098         status = ibcm_invoke_rtu_qp_modify(statep,
7099             ibt_usec2ib(statep->remote_ack_delay), rep_msgp);
7100 
7101         if (status != IBT_SUCCESS) {
7102 
7103                 (void) ibcm_cep_to_error_state(statep);
7104                 /*
7105                  * Disassociate statep and QP, as there is a
7106                  * QP associated with this statep.
7107                  */
7108                 IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
7109 
7110                 ibcm_post_rej_mad(statep, IBT_CM_NO_RESC,
7111                     IBT_CM_FAILURE_UNKNOWN, NULL, 0);
7112                 /*
7113                  * Invoke CM handler, so client/server can do
7114                  * resource cleanup. No private data can be returned here
7115                  */
7116                 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
7117                     IBT_CM_FAILURE_UNKNOWN, IBT_CM_NO_RESC, NULL, 0);
7118 
7119                 /* unblock any pending DREQ threads */
7120                 mutex_enter(&statep->state_mutex);
7121                 statep->cep_in_rts = IBCM_FAIL;
7122                 cv_broadcast(&statep->block_mad_cv);
7123                 mutex_exit(&statep->state_mutex);
7124                 return;
7125         }
7126 
7127         mutex_enter(&statep->state_mutex);
7128         statep->state = IBCM_STATE_ESTABLISHED;
7129         ibtl_cm_chan_is_open(statep->channel);
7130         mutex_exit(&statep->state_mutex);
7131 
7132         /* invoke the CM handler */
7133         ASSERT(statep->cm_handler != NULL);
7134 
7135         bzero(&event, sizeof (event));
7136         event.cm_channel = statep->channel;
7137         event.cm_session_id = NULL;
7138 
7139         event.cm_type = IBT_CM_EVENT_CONN_EST;
7140         if (cm_rtu_msgp != NULL) {
7141                 event.cm_priv_data = &(cm_rtu_msgp->rtu_private_data[0]);
7142                 event.cm_priv_data_len = IBT_RTU_PRIV_DATA_SZ;
7143         }
7144 
7145         ibcm_insert_trace(statep, IBCM_TRACE_CALLED_CONN_EST_EVENT);
7146 
7147         (void) statep->cm_handler(statep->state_cm_private, &event, NULL,
7148             NULL, 0);
7149 
7150         ibcm_insert_trace(statep, IBCM_TRACE_RET_CONN_EST_EVENT);
7151         if (ibcm_enable_trace & 4)
7152                 ibcm_dump_conn_trace(statep);
7153         else
7154                 IBTF_DPRINTF_L2(cmlog, "ibcm_cep_state_rtu CONN_EST Channel %p",
7155                     statep->channel);
7156 
7157         /* unblock any pending DREQ threads */
7158         mutex_enter(&statep->state_mutex);
7159         statep->cep_in_rts = IBCM_UNBLOCK;
7160         cv_broadcast(&statep->block_mad_cv);
7161         mutex_exit(&statep->state_mutex);
7162 }
7163 
7164 
7165 /*
7166  * ibcm_cep_send_rtu:
7167  *      QP state transition function called for an outgoing RTU
7168  *      on active side.
7169  *
7170  * INPUTS:
7171  *      statep          - connection state pointer
7172  *
7173  * RETURN VALUE:
7174  */
7175 void
7176 ibcm_cep_send_rtu(ibcm_state_data_t *statep)
7177 {
7178         /* invoke the CM handler */
7179         if (statep->cm_handler) {
7180                 ibt_cm_event_t  event;
7181 
7182                 bzero(&event, sizeof (event));
7183                 event.cm_type  = IBT_CM_EVENT_CONN_EST;
7184                 event.cm_channel = statep->channel;
7185                 event.cm_session_id = NULL;
7186                 event.cm_priv_data = NULL;
7187                 event.cm_priv_data_len = 0;
7188 
7189                 ibcm_insert_trace(statep, IBCM_TRACE_CALLED_CONN_EST_EVENT);
7190 
7191                 (void) statep->cm_handler(statep->state_cm_private, &event,
7192                     NULL, NULL, 0);
7193 
7194                 ibcm_insert_trace(statep, IBCM_TRACE_RET_CONN_EST_EVENT);
7195 
7196         } else {
7197                 IBTF_DPRINTF_L2(cmlog, "ibcm_cep_send_rtu: cm_handler NULL");
7198         }
7199         if (ibcm_enable_trace & 4)
7200                 ibcm_dump_conn_trace(statep);
7201         else
7202                 IBTF_DPRINTF_L2(cmlog, "ibcm_cep_send_rtu CONN_EST Channel %p",
7203                     statep->channel);
7204 
7205         /* unblock any pending DREQ threads */
7206         mutex_enter(&statep->state_mutex);
7207         statep->cep_in_rts = IBCM_UNBLOCK;
7208         cv_broadcast(&statep->block_mad_cv);
7209         mutex_exit(&statep->state_mutex);
7210 }
7211 
7212 
7213 /*
7214  * ibcm_cep_to_error_state:
7215  *      CEP state transition function. Changes state to IBT_STATE_ERROR
7216  *
7217  * INPUTS:
7218  *      statep          - connection state pointer
7219  *
7220  * RETURN VALUE:
7221  *      IBT_SUCCESS     - if able to change state otherwise failure
7222  */
7223 ibt_status_t
7224 ibcm_cep_to_error_state(ibcm_state_data_t *statep)
7225 {
7226         ibt_status_t            status = IBT_SUCCESS;
7227 
7228         if (statep->channel != NULL) {
7229                 ibt_qp_info_t   qp_info;
7230 
7231                 bzero(&qp_info, sizeof (qp_info));
7232                 /* For now, set it to RC type */
7233                 qp_info.qp_trans = IBT_RC_SRV;
7234                 qp_info.qp_state = IBT_STATE_ERROR;
7235 
7236                 /* Call modify_qp to move to ERROR state */
7237                 status = ibt_modify_qp(statep->channel, IBT_CEP_SET_STATE,
7238                     &qp_info, NULL);
7239 
7240                 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_to_error_state: "
7241                     "statep %p ibt_modify_qp() = %d", statep, status);
7242 
7243                 if (status == IBT_SUCCESS)
7244                         ibcm_insert_trace(statep, IBCM_TRACE_ERROR);
7245                 else
7246                         ibcm_insert_trace(statep, IBCM_TRACE_ERROR_FAIL);
7247 
7248         }
7249 
7250 #ifdef  NO_EEC_SUPPORT_YET
7251         if (statep->channel.ch_eec != NULL) {
7252                 ibt_eec_info_t  eec_info;
7253 
7254                 bzero(&eec_info, sizeof (ibt_eec_info_t));
7255                 eec_info.eec_state = what;
7256 
7257                 /* Call modify_eec */
7258                 status = ibtl_cm_modify_eec(statep->channel.ch_eec, &eec_info,
7259                     IBT_CEP_SET_NOTHING);
7260                 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_to_error_state: "
7261                     "ibtl_cm_modify_eec() returned = %x", status);
7262         }
7263 #endif
7264 
7265         return (status);
7266 }
7267 
7268 
7269 /*
7270  * ibcm_cep_state_rej:
7271  *      QP state transition function called for an incoming REJ
7272  *      on active/passive side
7273  *
7274  * INPUTS:
7275  *      statep          - connection state pointer
7276  *      rej_msgp        - REJ message pointer
7277  *      rej_state       - State where REJ processing began
7278  *
7279  * RETURN VALUE:
7280  */
7281 void
7282 ibcm_cep_state_rej(ibcm_state_data_t *statep, ibcm_rej_msg_t *rej_msgp,
7283     ibcm_conn_state_t rej_state)
7284 {
7285         ibt_cm_event_t  event;
7286         ibt_status_t    status;
7287 
7288         IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rej: statep 0x%p", statep);
7289 
7290         ibcm_path_cache_purge();
7291 
7292         if ((rej_state == IBCM_STATE_REP_SENT) ||
7293             (rej_state == IBCM_STATE_MRA_REP_RCVD)) {
7294                 status = ibcm_cep_to_error_state(statep);
7295                 IBTF_DPRINTF_L5(cmlog, "ibcm_cep_state_rej: statep 0x%p "
7296                     "ibcm_cep_to_error_state returned %d", statep,
7297                     status);
7298         }
7299 
7300         if (statep->channel)
7301                 ibtl_cm_chan_open_is_aborted(statep->channel);
7302 
7303         /* Disassociate state structure and CM */
7304         IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
7305 
7306         /* invoke the CM handler */
7307         bzero(&event, sizeof (event));
7308         if (statep->cm_handler) {
7309                 event.cm_type = IBT_CM_EVENT_FAILURE;
7310                 event.cm_channel = statep->channel;
7311                 event.cm_session_id = NULL;
7312 
7313                 /*
7314                  * copy rej_msgp->rej_private_data to
7315                  * event.cm_event.cm_priv_data
7316                  */
7317                 event.cm_priv_data = &(rej_msgp->rej_private_data[0]);
7318                 event.cm_priv_data_len = IBT_REJ_PRIV_DATA_SZ;
7319 
7320                 event.cm_event.failed.cf_code = IBT_CM_FAILURE_REJ_RCV;
7321                 event.cm_event.failed.cf_msg = rej_msgp->rej_msg_type_plus >> 6;
7322                 event.cm_event.failed.cf_reason =
7323                     b2h16(rej_msgp->rej_rejection_reason);
7324 
7325                 IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_rej: rej_reason = %d",
7326                     event.cm_event.failed.cf_reason);
7327 
7328                 ibcm_copy_addl_rej(statep, rej_msgp, &event.cm_event.failed);
7329 
7330                 (void) statep->cm_handler(statep->state_cm_private, &event,
7331                     NULL, NULL, 0);
7332         }
7333 
7334         if (statep->open_return_data != NULL)
7335                 bcopy(&event.cm_event.failed.cf_additional,
7336                     &statep->open_return_data->rc_arej_info,
7337                     sizeof (ibt_arej_info_t));
7338         if (ibcm_enable_trace != 0)
7339                 ibcm_dump_conn_trace(statep);
7340         mutex_enter(&statep->state_mutex);
7341         ibcm_open_done(statep);
7342         mutex_exit(&statep->state_mutex);
7343 }
7344 
7345 /* Used to initialize client args with addl rej information from REJ MAD */
7346 static void
7347 ibcm_copy_addl_rej(ibcm_state_data_t *statep, ibcm_rej_msg_t *rej_msgp,
7348     ibt_cm_conn_failed_t *failed)
7349 {
7350         uint16_t        rej_reason = b2h16(rej_msgp->rej_rejection_reason);
7351         uint8_t         ari_len = rej_msgp->rej_reject_info_len_plus >> 1;
7352         ibcm_classportinfo_msg_t tclp;
7353         ibt_arej_info_t *cf_addl = &failed->cf_additional;
7354 
7355         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cf_addl))
7356         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(failed->cf_arej_info_valid))
7357 
7358         failed->cf_arej_info_valid = B_FALSE;
7359 
7360         IBTF_DPRINTF_L3(cmlog, "ibcm_copy_addl_rej: rej_reason = %d "
7361             "ari_len = %d", rej_reason, ari_len);
7362 
7363         if ((statep->mode == IBCM_PASSIVE_MODE) &&
7364             (rej_reason != IBT_CM_CONSUMER))
7365                 return;
7366 
7367         switch (rej_reason) {
7368         case IBT_CM_PRIM_GID:
7369         case IBT_CM_ALT_GID:
7370         case IBT_CM_PORT_REDIRECT:
7371                 if (ari_len < sizeof (ib_gid_t))
7372                         break;
7373                 failed->cf_arej_info_valid = B_TRUE;
7374                 bcopy(rej_msgp->rej_addl_rej_info, &cf_addl->ari_gid,
7375                     sizeof (ib_gid_t));
7376                 cf_addl->ari_gid.gid_guid = b2h64(cf_addl->ari_gid.gid_guid);
7377                 cf_addl->ari_gid.gid_prefix =
7378                     b2h64(cf_addl->ari_gid.gid_prefix);
7379 
7380                 IBTF_DPRINTF_L4(cmlog, "ibcm_copy_addl_rej: ari_gid= %llX:%llX",
7381                     cf_addl->ari_gid.gid_prefix, cf_addl->ari_gid.gid_guid);
7382 
7383                 break;
7384         case IBT_CM_PRIM_LID:
7385         case IBT_CM_ALT_LID:
7386                 if (ari_len < sizeof (ib_lid_t))
7387                         break;
7388                 failed->cf_arej_info_valid = B_TRUE;
7389                 bcopy(rej_msgp->rej_addl_rej_info, &cf_addl->ari_lid,
7390                     sizeof (ib_lid_t));
7391                 cf_addl->ari_lid = b2h16(cf_addl->ari_lid);
7392                 IBTF_DPRINTF_L4(cmlog, "ibcm_copy_addl_rej: ari_lid= 0x%lX",
7393                     cf_addl->ari_lid);
7394 
7395                 break;
7396         case IBT_CM_INVALID_PRIM_SL:
7397         case IBT_CM_INVALID_ALT_SL:
7398                 if (ari_len < 1)
7399                         break;
7400                 failed->cf_arej_info_valid = B_TRUE;
7401                 /* take the first 4 bits */
7402                 cf_addl->ari_sl = rej_msgp->rej_addl_rej_info[0] >> 4;
7403                 break;
7404         case IBT_CM_INVALID_PRIM_TC:
7405         case IBT_CM_INVALID_ALT_TC:
7406                 if (ari_len < 1)
7407                         break;
7408                 failed->cf_arej_info_valid = B_TRUE;
7409                 /* take the first byte */
7410                 cf_addl->ari_tclass = rej_msgp->rej_addl_rej_info[0];
7411                 break;
7412         case IBT_CM_INVALID_PRIM_HOP:
7413         case IBT_CM_INVALID_ALT_HOP:
7414                 if (ari_len < 1)
7415                         break;
7416                 failed->cf_arej_info_valid = B_TRUE;
7417                 /* take the first byte */
7418                 cf_addl->ari_hop = rej_msgp->rej_addl_rej_info[0];
7419                 break;
7420         case IBT_CM_INVALID_PRIM_RATE:
7421         case IBT_CM_INVALID_ALT_RATE:
7422                 if (ari_len < 1)
7423                         break;
7424                 failed->cf_arej_info_valid = B_TRUE;
7425                 /* take the first 6 bits */
7426                 cf_addl->ari_rate = rej_msgp->rej_addl_rej_info[0] >> 2;
7427                 break;
7428         case IBT_CM_REDIRECT_CM:
7429                 if (ari_len < sizeof (ibcm_classportinfo_msg_t))
7430                         break;
7431                 failed->cf_arej_info_valid = B_TRUE;
7432                 bcopy(rej_msgp->rej_addl_rej_info, &tclp, sizeof (tclp));
7433                 ibcm_init_clp_from_mad(&tclp, &cf_addl->ari_redirect);
7434                 break;
7435         case IBT_CM_INVALID_MTU:
7436                 if (ari_len < 1)
7437                         break;
7438                 failed->cf_arej_info_valid = B_TRUE;
7439                 /* take the first 4 bits */
7440                 cf_addl->ari_mtu = rej_msgp->rej_addl_rej_info[0] >> 4;
7441                 break;
7442         case IBT_CM_CONSUMER:
7443                 if (ari_len == 0)
7444                         break;
7445                 failed->cf_arej_info_valid = B_TRUE;
7446                 if (ari_len > IBT_CM_ADDL_REJ_LEN)
7447                         ari_len = IBT_CM_ADDL_REJ_LEN;
7448                 bcopy(&rej_msgp->rej_addl_rej_info,
7449                     cf_addl->ari_consumer.rej_ari, ari_len);
7450                 cf_addl->ari_consumer.rej_ari_len = ari_len;
7451                 break;
7452         case IBT_CM_INVALID_PRIM_FLOW:
7453         case IBT_CM_INVALID_ALT_FLOW:
7454                 if (ari_len < 3)     /* 3 bytes needed for 20 bits */
7455                         break;
7456                 failed->cf_arej_info_valid = B_TRUE;
7457                 /* take the first 20 bits */
7458                 cf_addl->ari_flow =
7459                     b2h32(*(uint32_t *)&rej_msgp->rej_addl_rej_info) >> 12;
7460                 break;
7461         default:
7462                 break;
7463         }
7464 
7465         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(failed->cf_arej_info_valid))
7466         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cf_addl))
7467 }
7468 
7469 
7470 /* Used to copy classportinfo to MAD from client initialized args */
7471 static void
7472 ibcm_init_clp_to_mad(ibcm_classportinfo_msg_t *clp, ibt_redirect_info_t *rinfo)
7473 {
7474 
7475         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*clp))
7476 
7477         bcopy(&ibcm_clpinfo, clp, sizeof (ibcm_clpinfo));
7478 
7479         clp->RedirectGID_hi = h2b64(rinfo->rdi_gid.gid_prefix);
7480         clp->RedirectGID_lo = h2b64(rinfo->rdi_gid.gid_guid);
7481         clp->RedirectTC_plus =
7482             h2b32((rinfo->rdi_tclass << 24) | (rinfo->rdi_sl << 20) |
7483             (rinfo->rdi_flow & 0xfffff));
7484         clp->RedirectLID = h2b16(rinfo->rdi_dlid);
7485         clp->RedirectQP_plus = h2b32(rinfo->rdi_qpn & 0xffffff);
7486         clp->RedirectQ_Key = h2b32(rinfo->rdi_qkey);
7487         clp->RedirectP_Key = h2b16(rinfo->rdi_pkey);
7488 
7489         IBTF_DPRINTF_L4(cmlog, "ibcm_init_clp_to_mad: RedirectGID= %llX:%llX,"
7490             " RedirectLID= 0x%lX", clp->RedirectGID_hi, clp->RedirectGID_lo,
7491             clp->RedirectLID);
7492 
7493         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*clp))
7494 }
7495 
7496 
7497 /* Used to initialize classportinfo to be returned to clients, from MAD */
7498 static void
7499 ibcm_init_clp_from_mad(ibcm_classportinfo_msg_t *clp,
7500     ibt_redirect_info_t *rinfo)
7501 {
7502         uint32_t temp32;
7503 
7504         rinfo->rdi_gid.gid_prefix = b2h64(clp->RedirectGID_hi);
7505         rinfo->rdi_gid.gid_guid = b2h64(clp->RedirectGID_lo);
7506         temp32 = b2h32(clp->RedirectTC_plus);
7507         rinfo->rdi_tclass = temp32 >> 24;
7508         rinfo->rdi_sl = (temp32 >> 20) & 0xf;
7509         rinfo->rdi_flow = temp32 & 0xffff;
7510         rinfo->rdi_dlid = b2h16(clp->RedirectLID);
7511         rinfo->rdi_qpn = b2h32(clp->RedirectQP_plus & 0xffffff);
7512         rinfo->rdi_qkey = b2h32(clp->RedirectQ_Key);
7513         rinfo->rdi_pkey = b2h16(clp->RedirectP_Key);
7514 
7515         IBTF_DPRINTF_L4(cmlog, "ibcm_init_clp_from_mad: RedirectGID= %llX:%llX,"
7516             " RedirectLID= 0x%lX", rinfo->rdi_gid.gid_prefix,
7517             rinfo->rdi_gid.gid_guid, rinfo->rdi_dlid);
7518 }
7519 
7520 
7521 /*
7522  * ibcm_cep_state_rej_est:
7523  *      QP state transition function called for an incoming REJ
7524  *      on active side in established state
7525  *
7526  * INPUTS:
7527  *      statep          - connection state pointer
7528  *
7529  * RETURN VALUE:
7530  */
7531 void
7532 ibcm_cep_state_rej_est(ibcm_state_data_t *statep)
7533 {
7534         ibt_cm_event_t  event;
7535         ibt_status_t    status;
7536 
7537         IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_rej_est:");
7538 
7539         status = ibcm_cep_to_error_state(statep);
7540         IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rej_est: statep 0x%p "
7541             "ibcm_cep_to_error_state returned %d", statep, status);
7542 
7543         /* Disassociate state structure and CM */
7544         IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
7545 
7546         ibtl_cm_chan_is_closing(statep->channel);
7547 
7548         /* invoke the CM handler */
7549         if (statep->cm_handler) {
7550                 bzero(&event, sizeof (event));
7551                 event.cm_type = IBT_CM_EVENT_CONN_CLOSED;
7552                 event.cm_channel = statep->channel;
7553                 event.cm_session_id = NULL;
7554 
7555                 event.cm_priv_data = NULL;
7556                 event.cm_priv_data_len = 0;
7557 
7558                 event.cm_event.closed = IBT_CM_CLOSED_REJ_RCVD;
7559 
7560                 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rej_est: "
7561                     "rej_reason = %d", event.cm_event.failed.cf_reason);
7562 
7563                 ibcm_insert_trace(statep, IBCM_TRACE_CALLED_CONN_CLOSE_EVENT);
7564 
7565                 (void) statep->cm_handler(statep->state_cm_private, &event,
7566                     NULL, NULL, 0);
7567 
7568                 ibcm_insert_trace(statep, IBCM_TRACE_RET_CONN_CLOSE_EVENT);
7569 
7570         }
7571 }
7572 
7573 
7574 /*
7575  * ibcm_sidr_req_ud_handler:
7576  *      Invoke Client's UD handler For SIDR_REQ msg
7577  *
7578  * INPUTS:
7579  *      ud_statep       - ud_state pointer
7580  *      sidr_reqp       - SIDR_REQ message pointer
7581  *
7582  * RETURN VALUE: IBCM_SEND_REP/IBCM_SEND_REJ
7583  */
7584 static ibcm_status_t
7585 ibcm_sidr_req_ud_handler(ibcm_ud_state_data_t *ud_statep,
7586     ibcm_sidr_req_msg_t *sidr_reqp, ibcm_mad_addr_t *cm_mad_addr,
7587     ibt_sidr_status_t *sidr_status)
7588 {
7589         void                    *priv_data = NULL;
7590         ibt_cm_ud_event_t       ud_event;
7591         ibcm_sidr_rep_msg_t     *sidr_repp;
7592         ibt_cm_ud_return_args_t ud_ret_args;
7593         ibt_cm_status_t         cb_status;
7594         ibt_qp_query_attr_t     qp_attr;
7595         ibt_status_t            retval;
7596         ibcm_ud_clnt_reply_info_t       ud_clnt_info;
7597 
7598         /* Check first if UD client handler is valid */
7599         ASSERT(ud_statep->ud_cm_handler != NULL);
7600 
7601         /* Fill in ibt_cm_ud_event_t */
7602         ud_event.cm_type = IBT_CM_UD_EVENT_SIDR_REQ;
7603         ud_event.cm_session_id = ud_statep;
7604         ud_event.cm_event.sidr_req.sreq_service_id = ud_statep->ud_svc_id;
7605         ud_event.cm_event.sidr_req.sreq_hca_guid = ud_statep->ud_hcap->hca_guid;
7606         ud_event.cm_event.sidr_req.sreq_pkey = b2h16(sidr_reqp->sidr_req_pkey);
7607         ud_event.cm_event.sidr_req.sreq_hca_port = cm_mad_addr->port_num;
7608 
7609         ud_event.cm_priv_data =
7610             &(sidr_reqp->sidr_req_private_data[0]);
7611         ud_event.cm_priv_data_len = IBT_SIDR_REQ_PRIV_DATA_SZ;
7612 
7613         sidr_repp =
7614             (ibcm_sidr_rep_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg);
7615 
7616         priv_data = &(sidr_repp->sidr_rep_private_data[0]);
7617 
7618         bzero(&ud_ret_args, sizeof (ud_ret_args));
7619 
7620         /* Invoke the client handler */
7621         cb_status = ud_statep->ud_cm_handler(ud_statep->ud_state_cm_private,
7622             &ud_event, &ud_ret_args, priv_data, IBT_SIDR_REP_PRIV_DATA_SZ);
7623 
7624         if (cb_status == IBT_CM_DEFER) {
7625 
7626                 /* unblock any blocked cm ud proceed api calls */
7627                 mutex_enter(&ud_statep->ud_state_mutex);
7628                 ud_statep->ud_clnt_proceed = IBCM_UNBLOCK;
7629                 cv_broadcast(&ud_statep->ud_block_client_cv);
7630                 mutex_exit(&ud_statep->ud_state_mutex);
7631 
7632                 return (IBCM_DEFER);
7633         }
7634 
7635         /* fail any blocked ud cm proceed api calls - client bug */
7636         mutex_enter(&ud_statep->ud_state_mutex);
7637         ud_statep->ud_clnt_proceed = IBCM_FAIL;
7638         cv_broadcast(&ud_statep->ud_block_client_cv);
7639         mutex_exit(&ud_statep->ud_state_mutex);
7640 
7641         /* do the query qp as soon as possible, after return from cm handler */
7642         if (cb_status == IBT_CM_ACCEPT) {
7643                 retval = ibt_query_qp(ud_ret_args.ud_channel, &qp_attr);
7644                 if (retval != IBT_SUCCESS) {
7645                         IBTF_DPRINTF_L2(cmlog, "ibcm_sidr_req_ud_handler: "
7646                             "Failed to retrieve QPN from the channel: %d",
7647                             retval);
7648                         *sidr_status = IBT_CM_SREP_NO_CHAN;
7649                         return (IBCM_SEND_SIDR_REP);
7650                 } else if (qp_attr.qp_info.qp_trans != IBT_UD_SRV) {
7651                         IBTF_DPRINTF_L2(cmlog, "ibcm_sidr_req_ud_handler: "
7652                             "Server/Passive returned non-UD %d transport type "
7653                             "QP", qp_attr.qp_info.qp_trans);
7654                         *sidr_status = IBT_CM_SREP_NO_CHAN;
7655                         return (IBCM_SEND_SIDR_REP);
7656                 }
7657 
7658                 ud_clnt_info.ud_qkey = qp_attr.qp_info.qp_transport.ud.ud_qkey;
7659                 ud_clnt_info.ud_qpn = qp_attr.qp_qpn;
7660         }
7661 
7662         ud_clnt_info.priv_data = priv_data;
7663         ud_clnt_info.priv_data_len = ud_ret_args.ud_ret_len;
7664 
7665         ud_clnt_info.redirect_infop = &ud_ret_args.ud_redirect;
7666 
7667         ibcm_process_sidr_req_cm_hdlr(ud_statep, cb_status, &ud_clnt_info,
7668             sidr_status, sidr_repp);
7669 
7670         return (IBCM_SEND_SIDR_REP);
7671 }
7672 
7673 /*ARGSUSED*/
7674 void
7675 ibcm_process_sidr_req_cm_hdlr(ibcm_ud_state_data_t *ud_statep,
7676     ibt_cm_status_t cb_status, ibcm_ud_clnt_reply_info_t *ud_clnt_info,
7677     ibt_sidr_status_t *sidr_status, ibcm_sidr_rep_msg_t *sidr_repp)
7678 {
7679         void    *sidr_rep_privp;
7680 
7681         IBTF_DPRINTF_L5(cmlog, "ibcm_process_sidr_req_cm_hdlr(%p, %x, "
7682             "%p, %p, %p)", ud_statep, cb_status, ud_clnt_info,
7683             sidr_status, sidr_repp);
7684 
7685         if (cb_status == IBT_CM_DEFAULT)
7686                 cb_status = IBT_CM_REJECT;
7687 
7688         if (cb_status == IBT_CM_ACCEPT)
7689                 *sidr_status = IBT_CM_SREP_CHAN_VALID;
7690         else if ((cb_status == IBT_CM_REJECT) ||
7691             (cb_status == IBT_CM_NO_RESOURCE))
7692                 *sidr_status = IBT_CM_SREP_REJ;
7693         else if (cb_status == IBT_CM_NO_CHANNEL)
7694                 *sidr_status = IBT_CM_SREP_NO_CHAN;
7695         else if (cb_status == IBT_CM_REDIRECT)
7696                 *sidr_status = IBT_CM_SREP_REDIRECT;
7697         else *sidr_status = IBT_CM_SREP_REJ;
7698 
7699         /*
7700          * For Accept and reject copy the private data, if ud_clnt_info
7701          * priv_data does not point to SIDR Response private data. This
7702          * copy is needed for ibt_cm_ud_proceed().
7703          */
7704         sidr_rep_privp = (void *)(&(sidr_repp->sidr_rep_private_data[0]));
7705         if ((cb_status == IBT_CM_ACCEPT || cb_status == IBT_CM_REJECT) &&
7706             (ud_clnt_info->priv_data != sidr_rep_privp) &&
7707             ud_clnt_info->priv_data_len) {
7708                 bcopy(ud_clnt_info->priv_data, sidr_rep_privp,
7709                     min(ud_clnt_info->priv_data_len,
7710                     IBT_SIDR_REP_PRIV_DATA_SZ));
7711         }
7712 
7713         if (*sidr_status != IBT_CM_SREP_CHAN_VALID) {
7714                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_req_cm_hdlr: "
7715                     "ud_handler return a failure: %d", cb_status);
7716                 if (*sidr_status == IBT_CM_SREP_REDIRECT) {
7717                 /*
7718                  * typecasting to ibcm_classportinfo_msg_t is ok, as addl info
7719                  * begins at offset 24 in sidr rep
7720                  */
7721                         ibcm_init_clp_to_mad(
7722                             (ibcm_classportinfo_msg_t *)
7723                             &sidr_repp->sidr_rep_class_port_info,
7724                             ud_clnt_info->redirect_infop);
7725                 }
7726                 return;
7727         }
7728 
7729 
7730         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_repp))
7731 
7732         sidr_repp->sidr_rep_qkey =
7733             h2b32(ud_clnt_info->ud_qkey);
7734         sidr_repp->sidr_rep_qpn_plus = h2b32(ud_clnt_info->ud_qpn << 8);
7735 
7736         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_repp))
7737 }
7738 
7739 /*
7740  * ibcm_sidr_rep_ud_handler:
7741  *      Invoke Client's UD handler For SIDR_REP msg
7742  *
7743  * INPUTS:
7744  *      ud_statep       - ud_state pointer
7745  *      sidr_rep_msgp   - SIDR_REQ message pointer
7746  *
7747  */
7748 static void
7749 ibcm_sidr_rep_ud_handler(ibcm_ud_state_data_t *ud_statep,
7750     ibcm_sidr_rep_msg_t *sidr_rep_msgp)
7751 {
7752         ibt_cm_ud_event_t       ud_event;
7753 
7754         IBTF_DPRINTF_L5(cmlog, "ibcm_sidr_rep_ud_handler: ud_statep 0x%p",
7755             ud_statep);
7756 
7757         /* Check first if UD client handler is valid */
7758         if (ud_statep->ud_cm_handler == NULL) {
7759                 IBTF_DPRINTF_L2(cmlog, "ibcm_sidr_rep_ud_handler: "
7760                     "cm_handler NULL");
7761                 return;
7762         }
7763 
7764         /* Fill in ibt_cm_ud_event_t */
7765         ud_event.cm_type = IBT_CM_UD_EVENT_SIDR_REP;
7766         ud_event.cm_session_id = NULL;
7767         ud_event.cm_event.sidr_rep.srep_status =
7768             sidr_rep_msgp->sidr_rep_rep_status;
7769         ud_event.cm_event.sidr_rep.srep_remote_qpn =
7770             b2h32(sidr_rep_msgp->sidr_rep_qpn_plus) >> 8;
7771         ud_event.cm_event.sidr_rep.srep_remote_qkey =
7772             h2b32(sidr_rep_msgp->sidr_rep_qkey);
7773 
7774         if (ud_event.cm_event.sidr_rep.srep_status == IBT_CM_SREP_REDIRECT) {
7775                 /*
7776                  * typecasting to ibcm_classportinfo_msg_t is ok, as addl info
7777                  * begins at offset 24 in sidr rep
7778                  */
7779                 ibcm_init_clp_from_mad(
7780                     (ibcm_classportinfo_msg_t *)
7781                     sidr_rep_msgp->sidr_rep_class_port_info,
7782                     &ud_event.cm_event.sidr_rep.srep_redirect);
7783 
7784                 if (ud_statep->ud_return_data != NULL)
7785                         bcopy(&ud_event.cm_event.sidr_rep.srep_redirect,
7786                             &ud_statep->ud_return_data->ud_redirect,
7787                             sizeof (ibt_redirect_info_t));
7788         }
7789 
7790         ud_event.cm_priv_data = &(sidr_rep_msgp->sidr_rep_private_data[0]);
7791         ud_event.cm_priv_data_len = IBT_SIDR_REP_PRIV_DATA_SZ;
7792 
7793         /* Invoke the client handler - inform only, so ignore retval */
7794         (void) ud_statep->ud_cm_handler(ud_statep->ud_state_cm_private,
7795             &ud_event, NULL, NULL, 0);
7796 
7797 
7798 }
7799 
7800 /*
7801  * ibcm_process_lap_msg:
7802  *      This call processes an incoming LAP message
7803  *
7804  * INPUTS:
7805  *      hcap            - HCA entry pointer
7806  *      input_madp      - incoming CM LAP MAD
7807  *      cm_mad_addr     - Address information for the MAD
7808  *
7809  * RETURN VALUE: NONE
7810  */
7811 /* ARGSUSED */
7812 void
7813 ibcm_process_lap_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
7814     ibcm_mad_addr_t *cm_mad_addr)
7815 {
7816         ibcm_status_t           state_lookup_status;
7817         ibcm_lap_msg_t          *lap_msg = (ibcm_lap_msg_t *)
7818             (&input_madp[IBCM_MAD_HDR_SIZE]);
7819         ibcm_apr_msg_t          *apr_msg;
7820         ibcm_state_data_t       *statep = NULL;
7821 
7822         IBTF_DPRINTF_L4(cmlog, "ibcm_process_lap_msg:");
7823 
7824         rw_enter(&hcap->hca_state_rwlock, RW_READER);
7825 
7826         state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_LAP,
7827             b2h32(lap_msg->lap_remote_comm_id), 0, 0, hcap, &statep);
7828 
7829         rw_exit(&hcap->hca_state_rwlock);
7830 
7831         IBTF_DPRINTF_L4(cmlog, "ibcm_process_lap_msg: lookup status %x"
7832             " com id %x", state_lookup_status,
7833             b2h32(lap_msg->lap_remote_comm_id));
7834 
7835         if (state_lookup_status != IBCM_LOOKUP_EXISTS) {
7836                 /* Post a REJ message ? - but spec doesn't state so */
7837                 return;
7838         }
7839 
7840         /* There is an existing state structure entry with active comid */
7841 
7842         ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_LAP);
7843 
7844         mutex_enter(&statep->state_mutex);
7845 
7846         if ((statep->state == IBCM_STATE_ESTABLISHED) &&
7847             (statep->ap_state == IBCM_AP_STATE_IDLE) &&
7848             (statep->mode == IBCM_PASSIVE_MODE)) {
7849                 if ((statep->lapr_msg) &&
7850                     (IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID ==
7851                     ((ib_mad_hdr_t *)(input_madp))->TransactionID))
7852                         ibcm_post_stored_apr_mad(statep, input_madp);
7853                 else {
7854                         ibcm_status_t   clnt_response;
7855 
7856                         statep->ap_state = IBCM_AP_STATE_LAP_RCVD;
7857                         statep->clnt_proceed = IBCM_BLOCK;
7858                         mutex_exit(&statep->state_mutex);
7859 
7860                         if (statep->lapr_msg == NULL) {
7861                                 if (ibcm_alloc_out_msg(
7862                                     statep->stored_reply_addr.ibmf_hdl,
7863                                     &statep->lapr_msg, MAD_METHOD_SEND) !=
7864                                     IBT_SUCCESS) {
7865 
7866                                         mutex_enter(&statep->state_mutex);
7867                                         statep->clnt_proceed = IBCM_FAIL;
7868                                         cv_broadcast(&statep->block_client_cv);
7869                                         IBCM_REF_CNT_DECR(statep);
7870                                         mutex_exit(&statep->state_mutex);
7871                                         return;
7872                                 }
7873                         }
7874                         apr_msg = (ibcm_apr_msg_t *)
7875                             IBCM_OUT_MSGP(statep->lapr_msg);
7876                         IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID =
7877                             ((ib_mad_hdr_t *)(input_madp))->TransactionID;
7878                         clnt_response =
7879                             ibcm_cep_state_lap(statep, lap_msg, apr_msg);
7880                         IBTF_DPRINTF_L4(cmlog, "ibcm_process_lap_msg:"
7881                             " statep 0x%p  apr status %d", statep,
7882                             apr_msg->apr_ap_status);
7883 
7884                         if (clnt_response == IBCM_DEFER) {
7885                                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_lap_msg: "
7886                                     "client returned DEFER response");
7887                                 return;
7888                         }
7889 
7890                         /* fail any blocked cm proceed api calls - client bug */
7891                         mutex_enter(&statep->state_mutex);
7892                         statep->clnt_proceed = IBCM_FAIL;
7893                         cv_broadcast(&statep->block_client_cv);
7894                         mutex_exit(&statep->state_mutex);
7895 
7896                         ibcm_post_apr_mad(statep);
7897                         return;
7898                 }
7899         }       /* drop the LAP MAD in any other state */
7900 
7901         IBCM_REF_CNT_DECR(statep); /* decrement the ref count */
7902         mutex_exit(&statep->state_mutex);
7903 }
7904 
7905 /*
7906  * ibcm_post_stored_apr_mad:
7907  *      Builds and posts an APR MAD from the stored APR MAD
7908  *
7909  * INPUTS:
7910  *      statep          - pointer to ibcm_state_data_t
7911  *      input_madp      - pointer to incoming lap mad
7912  *
7913  * RETURN VALUE:
7914  *      NONE
7915  *
7916  * This function is called holding the state mutex, and returns
7917  * holding the state mutex
7918  */
7919 static void
7920 ibcm_post_stored_apr_mad(ibcm_state_data_t *statep, uint8_t *input_madp)
7921 {
7922         ibmf_msg_t      *ibmf_apr_msg;
7923         uint8_t         apr_msg[IBCM_MSG_SIZE];
7924 
7925         /* Need to make a copy, else an incoming new LAP may modify lapr_msg */
7926         bcopy(IBCM_OUT_MSGP(statep->lapr_msg), apr_msg, IBCM_MSG_SIZE);
7927 
7928         mutex_exit(&statep->state_mutex);
7929 
7930         if (ibcm_alloc_out_msg(statep->stored_reply_addr.ibmf_hdl,
7931             &ibmf_apr_msg, MAD_METHOD_SEND) != IBT_SUCCESS) {
7932                 IBTF_DPRINTF_L2(cmlog, "ibcm_post_stored_apr_mad: "
7933                     "ibcm_alloc_out_msg failed");
7934                 mutex_enter(&statep->state_mutex);
7935                 return;
7936         }
7937 
7938         bcopy(apr_msg, IBCM_OUT_MSGP(ibmf_apr_msg), IBCM_MSG_SIZE);
7939 
7940         IBCM_OUT_HDRP(ibmf_apr_msg)->AttributeID =
7941             h2b16(IBCM_INCOMING_APR + IBCM_ATTR_BASE_ID);
7942 
7943         IBCM_OUT_HDRP(ibmf_apr_msg)->TransactionID =
7944             ((ib_mad_hdr_t *)(input_madp))->TransactionID;
7945 
7946         ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_APR);
7947 
7948         ibcm_post_rc_mad(statep, ibmf_apr_msg, ibcm_post_stored_apr_complete,
7949             ibmf_apr_msg);
7950 
7951         /* ibcm_free_out_msg done in ibcm_post_stored_apr_complete */
7952 
7953         mutex_enter(&statep->state_mutex);
7954 }
7955 
7956 /*
7957  * ibcm_cep_state_lap:
7958  *      This call processes an incoming LAP message for cep state
7959  *      transition and invoking cm handler
7960  *
7961  * INPUTS:
7962  *      statep          - pointer to ibcm_state_data_t
7963  *      lap_msg         - lap msg received
7964  *      apr_msg         - apr msg to be sent
7965  *
7966  * RETURN VALUE: NONE
7967  */
7968 ibcm_status_t
7969 ibcm_cep_state_lap(ibcm_state_data_t *statep, ibcm_lap_msg_t *lap_msg,
7970     ibcm_apr_msg_t *apr_msg)
7971 {
7972         ibt_cm_event_t          event;
7973         ibt_cm_return_args_t    ret_args;
7974         ibt_cm_status_t         cb_status;
7975         ibcm_clnt_reply_info_t  clnt_info;
7976 
7977 
7978         IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_lap: statep 0x%p", statep);
7979 
7980         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*apr_msg))
7981 
7982         /* If APM is not supported, return error */
7983         if (!(statep->hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG)) {
7984                 apr_msg->apr_ap_status = IBT_CM_AP_NOT_SUPPORTED;
7985                 return (IBCM_SEND_APR);
7986         }
7987 
7988         if (statep->local_qpn !=
7989             b2h32(lap_msg->lap_remote_qpn_eecn_plus) >> 8) {
7990                 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
7991                 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_lap: local_qpn %x does "
7992                     "not match remote's remote_qpn %x", statep->local_qpn,
7993                     b2h32(lap_msg->lap_remote_qpn_eecn_plus) >> 8);
7994                 return (IBCM_SEND_APR);
7995         }
7996 
7997         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*apr_msg))
7998 
7999         /* Fill up the event */
8000         bzero(&event, sizeof (event));
8001         event.cm_type = IBT_CM_EVENT_LAP_RCV;
8002         event.cm_channel = statep->channel;
8003         event.cm_session_id = statep;
8004         event.cm_priv_data = lap_msg->lap_private_data;
8005         event.cm_priv_data_len =  IBT_LAP_PRIV_DATA_SZ;
8006         event.cm_event.lap.lap_timeout = ibt_ib2usec(
8007             ((uint8_t *)&lap_msg->lap_remote_qpn_eecn_plus)[3] >> 3);
8008 
8009         ibcm_fill_adds_from_lap(&event.cm_event.lap.lap_alternate_path,
8010             lap_msg, IBCM_PASSIVE_MODE);
8011 
8012         cb_status = statep->cm_handler(statep->state_cm_private, &event,
8013             &ret_args, apr_msg->apr_private_data, IBT_APR_PRIV_DATA_SZ);
8014 
8015         IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_lap: cb_status = %d", cb_status);
8016         if (cb_status == IBT_CM_DEFER) {
8017 
8018                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg))
8019 
8020                 if (statep->defer_cm_msg == NULL)
8021                         statep->defer_cm_msg =
8022                             kmem_zalloc(IBCM_MSG_SIZE, KM_SLEEP);
8023                 bcopy(lap_msg, statep->defer_cm_msg, IBCM_MSG_SIZE);
8024 
8025                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg))
8026 
8027                 /* unblock any blocked cm proceed api calls */
8028                 mutex_enter(&statep->state_mutex);
8029                 statep->clnt_proceed = IBCM_UNBLOCK;
8030                 cv_broadcast(&statep->block_client_cv);
8031                 mutex_exit(&statep->state_mutex);
8032 
8033                 return (IBCM_DEFER);
8034         }
8035 
8036         clnt_info.reply_event = (ibt_cm_proceed_reply_t *)&ret_args.cm_ret;
8037         clnt_info.priv_data = NULL;
8038         clnt_info.priv_data_len = 0;
8039 
8040         ibcm_process_cep_lap_cm_hdlr(statep, cb_status, &clnt_info, lap_msg,
8041             apr_msg);
8042         return (IBCM_SEND_APR);
8043 }
8044 
8045 /*
8046  * ibcm_fill_adds_from_lap:
8047  *      Fills the address vector (part of event structure passed to
8048  * client) from the LAP message
8049  *
8050  * INPUTS:
8051  *      adds            - Address vector to be filled-in
8052  *      lap_msg         - LAP message used to fill the address vector
8053  *
8054  * RETURN VALUE: NONE
8055  */
8056 static void
8057 ibcm_fill_adds_from_lap(ibt_adds_vect_t *adds, ibcm_lap_msg_t *lap_msg,
8058     ibcm_mode_t mode)
8059 {
8060         adds->av_srvl = lap_msg->lap_alt_sl_plus >> 4;
8061         if (mode == IBCM_PASSIVE_MODE) {
8062                 adds->av_dgid.gid_prefix =
8063                     b2h64(lap_msg->lap_alt_l_port_gid.gid_prefix);
8064                 adds->av_dgid.gid_guid =
8065                     b2h64(lap_msg->lap_alt_l_port_gid.gid_guid);
8066                 adds->av_sgid.gid_prefix =
8067                     b2h64(lap_msg->lap_alt_r_port_gid.gid_prefix);
8068                 adds->av_sgid.gid_guid =
8069                     b2h64(lap_msg->lap_alt_r_port_gid.gid_guid);
8070                 adds->av_dlid = b2h16(lap_msg->lap_alt_l_port_lid);
8071         } else {
8072                 adds->av_sgid.gid_prefix =
8073                     b2h64(lap_msg->lap_alt_l_port_gid.gid_prefix);
8074                 adds->av_sgid.gid_guid =
8075                     b2h64(lap_msg->lap_alt_l_port_gid.gid_guid);
8076                 adds->av_dgid.gid_prefix =
8077                     b2h64(lap_msg->lap_alt_r_port_gid.gid_prefix);
8078                 adds->av_dgid.gid_guid =
8079                     b2h64(lap_msg->lap_alt_r_port_gid.gid_guid);
8080                 adds->av_dlid = b2h16(lap_msg->lap_alt_r_port_lid);
8081         }
8082 
8083         IBTF_DPRINTF_L4(cmlog, "ibcm_fill_adds_from_lap: SGID=(%llX:%llX)",
8084             adds->av_sgid.gid_prefix, adds->av_sgid.gid_guid);
8085 
8086         IBTF_DPRINTF_L4(cmlog, "ibcm_fill_adds_from_lap: DGID=(%llX:%llX)",
8087             adds->av_dgid.gid_prefix, adds->av_dgid.gid_guid);
8088 
8089         adds->av_srate = lap_msg->lap_alt_srate_plus & 0x3f;
8090 
8091         /* next copy off the GRH info if it exists  */
8092         if ((lap_msg->lap_alt_sl_plus & 0x8) == 0) {
8093                 uint32_t flow_tclass = b2h32(lap_msg->lap_alt_flow_label_plus);
8094 
8095                 adds->av_send_grh = B_TRUE;
8096                 adds->av_flow = flow_tclass >> 12;
8097                 adds->av_tclass = flow_tclass & 0xff;
8098                 adds->av_hop = lap_msg->lap_alt_hop_limit;
8099         } else {
8100                 adds->av_send_grh = B_FALSE;
8101         }
8102 }
8103 
8104 /*
8105  * ibcm_process_cep_lap_cm_hdlr:
8106  * Processes the cm handler response for an incoming LAP.
8107  */
8108 
8109 void
8110 ibcm_process_cep_lap_cm_hdlr(ibcm_state_data_t *statep,
8111     ibt_cm_status_t cb_status, ibcm_clnt_reply_info_t *clnt_info,
8112     ibcm_lap_msg_t *lap_msg, ibcm_apr_msg_t *apr_msg)
8113 {
8114         ibtl_cm_hca_port_t      port;
8115         ibt_qp_query_attr_t     qp_attrs;
8116         ibt_cep_modify_flags_t  cep_flags;
8117         ibt_status_t            status;
8118         ibt_adds_vect_t         *adds;
8119 
8120         if (cb_status == IBT_CM_DEFAULT)
8121                 cb_status = IBT_CM_REJECT;
8122 
8123         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*apr_msg))
8124 
8125         /* verify status */
8126         apr_msg->apr_addl_info_len = 0;
8127         if (cb_status == IBT_CM_ACCEPT) {
8128                 apr_msg->apr_ap_status = IBT_CM_AP_LOADED;
8129         } else if (cb_status == IBT_CM_REJECT) {
8130                 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8131         } else if (cb_status == IBT_CM_REDIRECT) {
8132                 apr_msg->apr_ap_status = IBT_CM_AP_REDIRECT;
8133                 /* copy redirect info to APR */
8134                 apr_msg->apr_addl_info_len = sizeof (ibcm_classportinfo_msg_t);
8135                 ibcm_init_clp_to_mad(
8136                     (ibcm_classportinfo_msg_t *)apr_msg->apr_addl_info,
8137                     &clnt_info->reply_event->apr);
8138         } else if (cb_status == IBT_CM_NO_RESOURCE) {
8139                 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8140         } else {
8141                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep %p"
8142                     " Client handler unexpected return %x", statep, cb_status);
8143                 cb_status = IBT_CM_REJECT;
8144                 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8145         }
8146 
8147         IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep 0x%p "
8148             " client handler returned %d, apr status %d", statep, cb_status,
8149             apr_msg->apr_ap_status);
8150 
8151         /* copy private data to outgoing apr, specified via priv_data */
8152         if ((clnt_info->priv_data != NULL) && (clnt_info->priv_data_len > 0))
8153                 bcopy(clnt_info->priv_data, apr_msg->apr_private_data,
8154                     min(clnt_info->priv_data_len, IBT_APR_PRIV_DATA_SZ));
8155 
8156         if (cb_status != IBT_CM_ACCEPT)
8157                 return;
8158 
8159         if (ibt_query_qp(statep->channel, &qp_attrs) != IBT_SUCCESS ||
8160             (qp_attrs.qp_info.qp_state != IBT_STATE_RTS &&
8161             qp_attrs.qp_info.qp_state != IBT_STATE_SQD)) {
8162                 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8163                 return;
8164         }
8165 
8166         /* Fill up input args for ibt_modify_qp */
8167         cep_flags = IBT_CEP_SET_ALT_PATH | IBT_CEP_SET_STATE;
8168 
8169         /* do RTS=>RTS or SQD=>SQD.  The next line is needed for RTS=>RTS. */
8170         qp_attrs.qp_info.qp_current_state = qp_attrs.qp_info.qp_state;
8171 
8172         adds = &IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect;
8173         ibcm_fill_adds_from_lap(adds, lap_msg, IBCM_PASSIVE_MODE);
8174 
8175         if ((status = ibtl_cm_get_hca_port(adds->av_sgid,
8176             statep->local_hca_guid, &port)) != IBT_SUCCESS) {
8177 
8178                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr:"
8179                     " ibtl_cm_get_hca_port failed status %d", status);
8180                 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8181                 return;
8182         }
8183 
8184         IBCM_QP_RC(qp_attrs).rc_alt_path.cep_hca_port_num = port.hp_port;
8185 
8186         IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep 0x%p "
8187             "gid = (%llx, %llx), port_num = %d", statep,
8188             IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect.av_dgid.
8189             gid_prefix,
8190             IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect.av_dgid.gid_guid,
8191             port.hp_port);
8192 
8193         /* The pkey is same as the primary path */
8194         status = ibt_pkey2index_byguid(statep->local_hca_guid,
8195             port.hp_port, statep->pkey,
8196             &IBCM_QP_RC(qp_attrs).rc_alt_path.cep_pkey_ix);
8197 
8198         if (status != IBT_SUCCESS) {
8199                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep %p"
8200                     " ibt_pkey2index_byguid failed %d", statep, status);
8201                 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8202                 return;
8203         }
8204 
8205         IBCM_QP_RC(qp_attrs).rc_alt_path.cep_timeout =
8206             lap_msg->lap_alt_local_acktime_plus >> 3;
8207 
8208         qp_attrs.qp_info.qp_trans = IBT_RC_SRV;
8209         if (IBCM_QP_RC(qp_attrs).rc_mig_state == IBT_STATE_MIGRATED) {
8210                 IBTF_DPRINTF_L3(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep %p"
8211                     ": rearming APM", statep);
8212                 cep_flags |= IBT_CEP_SET_MIG;
8213                 IBCM_QP_RC(qp_attrs).rc_mig_state = IBT_STATE_REARMED;
8214         }
8215         status = ibt_modify_qp(statep->channel, cep_flags, &qp_attrs.qp_info,
8216             NULL);
8217 
8218         if (status != IBT_SUCCESS) {
8219                 ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT_FAIL);
8220         } else
8221                 ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT);
8222 
8223 #ifdef  DEBUG
8224         (void) ibt_query_qp(statep->channel, &qp_attrs);
8225         print_modify_qp("PASSIVE LAP QUERY", statep->channel,
8226             cep_flags, &qp_attrs.qp_info);
8227 #endif
8228 
8229         if (status != IBT_SUCCESS) {
8230                 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8231                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr:"
8232                     " ibt_modify_qp() returned = %d", status);
8233                 return;
8234         }
8235         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*apr_msg))
8236 }
8237 
8238 
8239 /*
8240  * ibcm_post_apr_mad:
8241  *      Posts a APR MAD and starts timer
8242  *
8243  * INPUTS:
8244  *      statep          - state pointer
8245  *
8246  * RETURN VALUE: NONE
8247  */
8248 void
8249 ibcm_post_apr_mad(ibcm_state_data_t *statep)
8250 {
8251         ibcm_apr_msg_t  *apr_msgp;
8252 
8253         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*apr_msgp))
8254 
8255         apr_msgp = (ibcm_apr_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg);
8256 
8257         apr_msgp->apr_local_comm_id = h2b32(statep->local_comid);
8258         apr_msgp->apr_remote_comm_id = h2b32(statep->remote_comid);
8259         IBCM_OUT_HDRP(statep->lapr_msg)->AttributeID =
8260             h2b16(IBCM_INCOMING_APR + IBCM_ATTR_BASE_ID);
8261 
8262         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*apr_msgp))
8263 
8264         ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_APR);
8265 
8266         ibcm_post_rc_mad(statep, statep->lapr_msg, ibcm_post_apr_complete,
8267             statep);
8268 }
8269 
8270 /*
8271  * ibcm_process_apr_msg:
8272  *      This call processes an incoming APR message
8273  *
8274  * INPUTS:
8275  *      hcap            - HCA entry pointer
8276  *      input_madp      - incoming CM SIDR REP MAD
8277  *      cm_mad_addr     - Address information for the MAD to be posted
8278  *
8279  * RETURN VALUE: NONE
8280  */
8281 /*ARGSUSED*/
8282 void
8283 ibcm_process_apr_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
8284     ibcm_mad_addr_t *cm_mad_addr)
8285 {
8286         ibcm_status_t           state_lookup_status;
8287         ibcm_apr_msg_t          *apr_msg = (ibcm_apr_msg_t *)
8288             (&input_madp[IBCM_MAD_HDR_SIZE]);
8289         ibcm_state_data_t       *statep = NULL;
8290 
8291         IBTF_DPRINTF_L4(cmlog, "ibcm_process_apr_msg:");
8292 
8293         rw_enter(&hcap->hca_state_rwlock, RW_READER);
8294         state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_APR,
8295             b2h32(apr_msg->apr_remote_comm_id), 0, 0, hcap, &statep);
8296         rw_exit(&hcap->hca_state_rwlock);
8297 
8298         if (state_lookup_status != IBCM_LOOKUP_EXISTS) {
8299                 return;
8300         }
8301 
8302         /* if transaction id is not as expected, drop the APR mad */
8303         if (IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID !=
8304             ((ib_mad_hdr_t *)(input_madp))->TransactionID) {
8305                 mutex_enter(&statep->state_mutex);
8306                 IBCM_REF_CNT_DECR(statep);
8307                 mutex_exit(&statep->state_mutex);
8308                 IBTF_DPRINTF_L3(cmlog, "ibcm_process_apr_msg: statep 0x%p"
8309                     ": rcv'd APR MAD with comid 0x%x",
8310                     statep, b2h32(apr_msg->apr_remote_comm_id));
8311                 IBTF_DPRINTF_L3(cmlog, "ibcm_process_apr_msg: "
8312                     "tid expected 0x%llX tid found 0x%llX",
8313                     b2h64(IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID),
8314                     b2h64(((ib_mad_hdr_t *)(input_madp))->TransactionID));
8315                 return;
8316         }
8317 
8318         IBTF_DPRINTF_L4(cmlog, "ibcm_process_apr_msg: statep 0x%p "
8319             "lookup status %x", statep, state_lookup_status);
8320 
8321         mutex_enter(&statep->state_mutex);
8322 
8323         if (!((statep->state == IBCM_STATE_ESTABLISHED) &&
8324             ((statep->ap_state == IBCM_AP_STATE_LAP_SENT) ||
8325             (statep->ap_state == IBCM_AP_STATE_MRA_LAP_RCVD)))) {
8326                 IBCM_REF_CNT_DECR(statep); /* decrement the ref count */
8327                 mutex_exit(&statep->state_mutex);
8328                 return;
8329         }
8330 
8331         statep->ap_state = IBCM_AP_STATE_APR_RCVD;
8332 
8333         /* cancel the LAP timer */
8334         if (statep->timerid != 0) {
8335                 timeout_id_t timer_val;
8336                 timer_val = statep->timerid;
8337                 statep->timerid = 0;
8338                 mutex_exit(&statep->state_mutex);
8339                 (void) untimeout(timer_val);
8340         } else {
8341                 mutex_exit(&statep->state_mutex);
8342         }
8343 
8344         ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_APR);
8345 
8346         ibcm_cep_state_apr(statep,
8347             (ibcm_lap_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg), apr_msg);
8348 
8349         mutex_enter(&statep->state_mutex);
8350         statep->ap_state = IBCM_AP_STATE_IDLE;
8351 
8352         /* unblock any DREQ threads and close channels */
8353         cv_broadcast(&statep->block_mad_cv);
8354 
8355         statep->ap_done = B_TRUE;
8356 
8357         /* wake up blocking ibt_set_alt_path */
8358         cv_broadcast(&statep->block_client_cv);
8359 
8360         IBCM_REF_CNT_DECR(statep); /* decrement the ref count */
8361         mutex_exit(&statep->state_mutex);
8362 }
8363 
8364 static void
8365 ibcm_set_apr_arej(int ap_status, ibcm_apr_msg_t *apr_msgp,
8366     ibt_arej_info_t *ari, boolean_t *ari_valid)
8367 {
8368         uint8_t ari_len = apr_msgp->apr_addl_info_len;
8369         ibcm_classportinfo_msg_t tclp;
8370 
8371         *ari_valid = B_FALSE;
8372 
8373         IBTF_DPRINTF_L3(cmlog, "ibcm_set_apr_arej: apr_status = %d "
8374             "ari_len = %d", ap_status, ari_len);
8375 
8376         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ari))
8377 
8378         switch (ap_status) {
8379         case IBT_CM_AP_REDIRECT:
8380                 if (ari_len < sizeof (ibcm_classportinfo_msg_t))
8381                         break;
8382                 *ari_valid = B_TRUE;
8383                 bcopy(apr_msgp->apr_addl_info, &tclp, sizeof (tclp));
8384                 ibcm_init_clp_from_mad(&tclp, &ari->ari_redirect);
8385                 break;
8386         case IBT_CM_AP_RLID_REJECTED:
8387                 if (ari_len < sizeof (ib_lid_t))
8388                         break;
8389                 *ari_valid = B_TRUE;
8390                 bcopy(apr_msgp->apr_addl_info, &ari->ari_lid,
8391                     sizeof (ib_lid_t));
8392                 ari->ari_lid = b2h16(ari->ari_lid);
8393                 break;
8394         case IBT_CM_AP_RGID_REJECTED:
8395                 if (ari_len < sizeof (ib_gid_t))
8396                         break;
8397                 *ari_valid = B_TRUE;
8398                 bcopy(apr_msgp->apr_addl_info, &ari->ari_gid,
8399                     sizeof (ib_gid_t));
8400                 ari->ari_gid.gid_guid = b2h64(ari->ari_gid.gid_guid);
8401                 ari->ari_gid.gid_prefix = b2h64(ari->ari_gid.gid_prefix);
8402 
8403                 IBTF_DPRINTF_L4(cmlog, "ibcm_set_apr_arej: ari_gid= %llX:%llX",
8404                     ari->ari_gid.gid_prefix, ari->ari_gid.gid_guid);
8405                 break;
8406         case IBT_CM_AP_FLOW_REJECTED:
8407                 if (ari_len < 3)     /* 3 bytes needed for 20 bits */
8408                         break;
8409                 *ari_valid = B_TRUE;
8410                 /* take the first 20 bits */
8411                 ari->ari_flow =
8412                     b2h32(*(uint32_t *)&apr_msgp->apr_addl_info) >> 12;
8413                 break;
8414         case IBT_CM_AP_TCLASS_REJECTED:
8415                 if (ari_len < 1)
8416                         break;
8417                 *ari_valid = B_TRUE;
8418                 /* take the first byte */
8419                 ari->ari_tclass = apr_msgp->apr_addl_info[0];
8420                 break;
8421         case IBT_CM_AP_HOP_REJECTED:
8422                 if (ari_len < 1)
8423                         break;
8424                 *ari_valid = B_TRUE;
8425                 /* take the first byte */
8426                 ari->ari_hop = apr_msgp->apr_addl_info[0];
8427                 break;
8428         case IBT_CM_AP_RATE_REJECTED:
8429                 if (ari_len < 1)
8430                         break;
8431                 *ari_valid = B_TRUE;
8432                 /* take the first 6 bits */
8433                 ari->ari_rate = apr_msgp->apr_addl_info[0] >> 2;
8434                 break;
8435         case IBT_CM_AP_SL_REJECTED:
8436                 if (ari_len < 1)
8437                         break;
8438                 *ari_valid = B_TRUE;
8439                 /* take the first 4 bits */
8440                 ari->ari_sl = apr_msgp->apr_addl_info[0] >> 4;
8441                 break;
8442         default:
8443                 break;
8444         }
8445         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ari))
8446 }
8447 
8448 /*
8449  * ibcm_cep_state_apr:
8450  *      This call processes an incoming APR message
8451  *
8452  * INPUTS:
8453  *      statep          - pointer to ibcm_state_data_t
8454  *      lap_msg         - lap msg sent earlier
8455  *      apr_msg         - apr msg received
8456  *
8457  * RETURN VALUE: NONE
8458  */
8459 void
8460 ibcm_cep_state_apr(ibcm_state_data_t *statep, ibcm_lap_msg_t *lap_msg,
8461     ibcm_apr_msg_t *apr_msg)
8462 {
8463         ibt_cm_event_t          event;
8464         ibcm_status_t           status = IBCM_SUCCESS;
8465         uint8_t                 ap_status = apr_msg->apr_ap_status;
8466 
8467         IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_apr: statep 0x%p, ap_status %d",
8468             statep, ap_status);
8469 
8470         if (ap_status == IBT_CM_AP_LOADED)
8471                 status = ibcm_set_qp_from_apr(statep, lap_msg);
8472 
8473         if (statep->ap_return_data != NULL) {        /* blocking call */
8474 
8475                 /* copy the private data */
8476                 if ((statep->ap_return_data->ap_priv_data != NULL) &&
8477                     (statep->ap_return_data->ap_priv_data_len > 0))
8478                         bcopy(apr_msg->apr_private_data,
8479                             statep->ap_return_data->ap_priv_data,
8480                             statep->ap_return_data->ap_priv_data_len);
8481 
8482                 /* initialize the ap status */
8483                 if (status == IBCM_FAILURE) {
8484                         statep->ap_return_data->ap_status = IBT_CM_AP_REJECT;
8485                         statep->ap_return_data->ap_arej_info_valid = B_FALSE;
8486                 } else {
8487                         statep->ap_return_data->ap_status = ap_status;
8488                         ibcm_set_apr_arej(ap_status, apr_msg,
8489                             &statep->ap_return_data->ap_arej_info,
8490                             &statep->ap_return_data->ap_arej_info_valid);
8491                 }
8492 
8493                 /* do a cv signal for a blocking ibt_set_alt_path */
8494                 mutex_enter(&statep->state_mutex);
8495                 statep->ap_done = B_TRUE;
8496                 cv_broadcast(&statep->block_client_cv);
8497                 mutex_exit(&statep->state_mutex);
8498 
8499         } else {        /* Non blocking call */
8500                 /* Fill up the event */
8501 
8502                 bzero(&event, sizeof (event));
8503                 event.cm_type = IBT_CM_EVENT_APR_RCV;
8504                 event.cm_channel = statep->channel;
8505                 event.cm_session_id = NULL;
8506                 event.cm_priv_data = apr_msg->apr_private_data;
8507                 event.cm_priv_data_len =  IBT_APR_PRIV_DATA_SZ;
8508                 if (status == IBCM_FAILURE) {
8509                         event.cm_event.apr.apr_status = IBT_CM_AP_REJECT;
8510                         event.cm_event.apr.apr_arej_info_valid = B_FALSE;
8511                 } else {
8512                         event.cm_event.apr.apr_status = ap_status;
8513                         ibcm_set_apr_arej(ap_status, apr_msg,
8514                             &event.cm_event.apr.apr_arej_info,
8515                             &event.cm_event.apr.apr_arej_info_valid);
8516                 }
8517 
8518                 /* initialize the ap status */
8519                 statep->cm_handler(statep->state_cm_private, &event,
8520                     NULL, apr_msg->apr_private_data, IBT_APR_PRIV_DATA_SZ);
8521         }
8522         mutex_enter(&statep->state_mutex);
8523         ibcm_open_done(statep);
8524         mutex_exit(&statep->state_mutex);
8525 }
8526 
8527 /*
8528  * ibcm_set_qp_from_apr:
8529  *      This call sets QP's alt path info based on APR message contents
8530  *
8531  * INPUTS:
8532  *      statep          - pointer to ibcm_state_data_t
8533  *      lap_msg         - lap msg sent earlier
8534  *
8535  * RETURN VALUE: ibcm_status_t
8536  */
8537 static ibcm_status_t
8538 ibcm_set_qp_from_apr(ibcm_state_data_t *statep, ibcm_lap_msg_t *lap_msg)
8539 {
8540         ibtl_cm_hca_port_t      port;
8541         ibt_adds_vect_t         *adds;
8542 
8543         ibt_qp_query_attr_t     qp_attrs;
8544         ibt_cep_modify_flags_t  cep_flags;
8545         ibt_status_t            status;
8546 
8547         IBTF_DPRINTF_L3(cmlog, "ibcm_set_qp_from_apr: statep 0x%p", statep);
8548 
8549         status = ibt_query_qp(statep->channel, &qp_attrs);
8550         if (status != IBT_SUCCESS ||
8551             (qp_attrs.qp_info.qp_state != IBT_STATE_RTS &&
8552             qp_attrs.qp_info.qp_state != IBT_STATE_SQD)) {
8553                 IBTF_DPRINTF_L2(cmlog, "ibcm_set_qp_from_apr: ibt_query_qp "
8554                     "failed, status = %d, qp_state = %d", statep, status,
8555                     qp_attrs.qp_info.qp_state);
8556                 return (IBCM_FAILURE);
8557         }
8558 
8559         /* Fill up input args for ibt_modify_qp */
8560         cep_flags = IBT_CEP_SET_ALT_PATH | IBT_CEP_SET_STATE;
8561 
8562         /* do RTS=>RTS or SQD=>SQD.  The next line is needed for RTS=>RTS. */
8563         qp_attrs.qp_info.qp_current_state = qp_attrs.qp_info.qp_state;
8564 
8565         /* Fill up input args for ibt_modify_qp */
8566         adds = &IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect;
8567 
8568         ibcm_fill_adds_from_lap(adds, lap_msg, IBCM_ACTIVE_MODE);
8569 
8570         if ((status = ibtl_cm_get_hca_port(adds->av_sgid,
8571             statep->local_hca_guid, &port)) != IBT_SUCCESS) {
8572                 IBTF_DPRINTF_L2(cmlog, "ibcm_set_qp_from_apr: "
8573                     "ibtl_cm_get_hca_port failed status = %d", status);
8574                 IBTF_DPRINTF_L5(cmlog, "ibcm_set_qp_from_apr:"
8575                     " ibtl_cm_get_hca_port sgid guid %llX",
8576                     adds->av_sgid.gid_guid);
8577                 IBTF_DPRINTF_L5(cmlog, "ibcm_set_qp_from_apr:"
8578                     " ibtl_cm_get_hca_port sgid prefix %llX ",
8579                     adds->av_sgid.gid_prefix);
8580                 return (IBCM_FAILURE);
8581         }
8582 
8583         IBCM_QP_RC(qp_attrs).rc_alt_path.cep_hca_port_num =
8584             port.hp_port;
8585 
8586         IBTF_DPRINTF_L4(cmlog, "ibcm_set_qp_from_apr: "
8587             "gid = %llx:%llx, port_num = %d",
8588             IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect.av_sgid.
8589             gid_prefix,
8590             IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect.av_sgid.gid_guid,
8591             port.hp_port);
8592 
8593         /* The pkey is same as the primary path */
8594         status = ibt_pkey2index_byguid(statep->local_hca_guid,
8595             port.hp_port, statep->pkey,
8596             &IBCM_QP_RC(qp_attrs).rc_alt_path.cep_pkey_ix);
8597 
8598         if (status != IBT_SUCCESS) {
8599                 IBTF_DPRINTF_L2(cmlog, "ibcm_set_qp_from_apr: "
8600                     "ibt_pkey2index_byguid failed %d", status);
8601                 return (IBCM_FAILURE);
8602         }
8603         qp_attrs.qp_info.qp_trans = IBT_RC_SRV;
8604         IBCM_QP_RC(qp_attrs).rc_alt_path.cep_timeout =
8605             ibt_usec2ib(statep->remote_ack_delay +
8606             2 * statep->rc_alt_pkt_lt);
8607         if (IBCM_QP_RC(qp_attrs).rc_mig_state == IBT_STATE_MIGRATED) {
8608                 /* Need to rearm */
8609                 IBTF_DPRINTF_L3(cmlog, "ibcm_set_qp_from_apr: statep 0x%p: "
8610                     "rearming APM", statep);
8611                 cep_flags |= IBT_CEP_SET_MIG;
8612                 IBCM_QP_RC(qp_attrs).rc_mig_state = IBT_STATE_REARMED;
8613         }
8614 
8615         status = ibt_modify_qp(statep->channel, cep_flags, &qp_attrs.qp_info,
8616             NULL);
8617 
8618         if (status != IBT_SUCCESS)
8619                 ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT_FAIL);
8620         else
8621                 ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT);
8622 
8623 #ifdef  DEBUG
8624         (void) ibt_query_qp(statep->channel, &qp_attrs);
8625         print_modify_qp("ACTIVE LAP QUERY", statep->channel,
8626             cep_flags, &qp_attrs.qp_info);
8627 #endif
8628 
8629         if (status != IBT_SUCCESS) {
8630                 IBTF_DPRINTF_L2(cmlog, "ibcm_set_qp_from_apr:"
8631                     " ibt_modify_qp() failed, status = %d", status);
8632                 return (IBCM_FAILURE);
8633         }
8634 
8635         return (IBCM_SUCCESS);
8636 }
8637 
8638 /*
8639  * ibcm_sync_lapr_idle:
8640  *
8641  *      This call either cancels a LAP/APR operation or waits
8642  *      until the operation is complete
8643  *
8644  * INPUTS:
8645  *      statep  Pointer to ibcm_state_data_t
8646  *
8647  * RETURN VALUE: NONE
8648  *
8649  * This function is called holding state mutex
8650  * This function returns, releasing the state mutex
8651  */
8652 void
8653 ibcm_sync_lapr_idle(ibcm_state_data_t *statep)
8654 {
8655         timeout_id_t    timer_val = statep->timerid;
8656         ibt_cm_event_t  event;
8657 
8658         IBTF_DPRINTF_L3(cmlog, "ibcm_sync_lapr_idle:"
8659             "statep %p state %d ap_state %d", statep, statep->state,
8660             statep->ap_state);
8661 
8662         ASSERT(MUTEX_HELD(&statep->state_mutex));
8663         _NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(&statep->state_mutex))
8664 
8665         /* Busy AP states on active/passive sides */
8666         if ((statep->ap_state == IBCM_AP_STATE_LAP_RCVD) ||
8667             (statep->ap_state == IBCM_AP_STATE_APR_RCVD) ||
8668             (statep->ap_state == IBCM_AP_STATE_MRA_LAP_SENT) ||
8669             (statep->ap_state == IBCM_AP_STATE_TIMED_OUT)) {
8670 
8671                 /* wait till ap_state becomes IBCM_AP_STATE_IDLE */
8672                 while (statep->ap_state != IBCM_AP_STATE_IDLE)
8673                         cv_wait(&statep->block_mad_cv, &statep->state_mutex);
8674 
8675                 mutex_exit(&statep->state_mutex);
8676 
8677         } else if ((statep->ap_state == IBCM_AP_STATE_LAP_SENT) ||
8678             (statep->ap_state == IBCM_AP_STATE_MRA_LAP_RCVD)) {
8679 
8680                 /* fail the client's ibt_set_alt_path */
8681 
8682                 /* blocking ibt_set_alt_path */
8683                 if (statep->ap_return_data != NULL) {
8684                         statep->ap_return_data->ap_status =
8685                             IBT_CM_AP_ABORT;
8686                         statep->ap_state = IBCM_AP_STATE_IDLE;
8687                         cv_broadcast(&statep->block_client_cv);
8688                         IBTF_DPRINTF_L3(cmlog, "ibcm_sync_lapr_idle:"
8689                             "blocked wait");
8690                 }
8691 
8692                 statep->timerid = 0;
8693                 /* Cancel the timeout */
8694                 mutex_exit(&statep->state_mutex);
8695                 if (timer_val != 0)
8696                         (void) untimeout(timer_val);
8697 
8698                 /* Non blocking ibt_set_alt_path */
8699                 if (statep->ap_return_data == NULL) {
8700 
8701                         /* Fill up the event */
8702 
8703                         bzero(&event, sizeof (event));
8704                         event.cm_type = IBT_CM_EVENT_APR_RCV;
8705                         event.cm_channel = statep->channel;
8706                         event.cm_session_id = NULL;
8707                         event.cm_priv_data = NULL;
8708                         event.cm_priv_data_len =  0;
8709                         event.cm_event.apr.apr_status = IBT_CM_AP_ABORT;
8710 
8711                         /* Call the cm handler */
8712                         statep->cm_handler(statep->state_cm_private, &event,
8713                             NULL, NULL, 0);
8714                         IBTF_DPRINTF_L3(cmlog, "ibcm_sync_lapr_idle:"
8715                             "non-blocked wait");
8716                 }
8717         } else mutex_exit(&statep->state_mutex);
8718 
8719         ASSERT(!MUTEX_HELD(&statep->state_mutex));
8720 }
8721 
8722 #ifdef DEBUG
8723 
8724 /*
8725  * Debug function used to print all the modify qp attributes.
8726  * Useful to manually verify the modify qp parameters are as
8727  * expected
8728  */
8729 static void
8730 print_modify_qp(char *prefix, ibt_qp_hdl_t ibt_qp,
8731     ibt_cep_modify_flags_t flags, ibt_qp_info_t *qp_attr)
8732 {
8733         IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP %s %p", prefix, ibt_qp);
8734         IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP flags 0x%x", flags);
8735 
8736         IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP "
8737             "rc_rdma_ra_in %d rc_rdma_ra_out %d",
8738             qp_attr->qp_transport.rc.rc_rdma_ra_in,
8739             qp_attr->qp_transport.rc.rc_rdma_ra_out);
8740 
8741         IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: "
8742             "port %d path bits %d dlid %X",
8743             qp_attr->qp_transport.rc.rc_path.cep_hca_port_num,
8744             qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_src_path,
8745             qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_dlid);
8746         IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: "
8747             "pkey index %d cep_timeout %d",
8748             qp_attr->qp_transport.rc.rc_path.cep_pkey_ix,
8749             qp_attr->qp_transport.rc.rc_path.cep_timeout);
8750         IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: "
8751             "srvl %d flow label %d tclass %d",
8752             qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_srvl,
8753             qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_flow,
8754             qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_tclass);
8755         IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: "
8756             "hop %d srate %d sgid_ix %d send_grh %d",
8757             qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_hop,
8758             qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_srate,
8759             qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_sgid_ix,
8760             qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_send_grh);
8761         IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: "
8762             "dgid prefix %llX dgid guid %llX",
8763             qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_dgid.gid_prefix,
8764             qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_dgid.gid_guid);
8765         IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: "
8766             "sgid prefix %llX sgid guid %llX",
8767             qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_sgid.gid_prefix,
8768             qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_sgid.gid_guid);
8769 
8770         IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: "
8771             "port %d path bits %d dlid %X",
8772             qp_attr->qp_transport.rc.rc_alt_path.cep_hca_port_num,
8773             qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_src_path,
8774             qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_dlid);
8775         IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: "
8776             "pkey index %d cep_timeout %d",
8777             qp_attr->qp_transport.rc.rc_alt_path.cep_pkey_ix,
8778             qp_attr->qp_transport.rc.rc_alt_path.cep_timeout);
8779         IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: "
8780             "srvl %d flow label %d tclass %d",
8781             qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_srvl,
8782             qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_flow,
8783             qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_tclass);
8784         IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: "
8785             "hop %d srate %d sgid_ix %d send_grh %d",
8786             qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_hop,
8787             qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_srate,
8788             qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_sgid_ix,
8789             qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_send_grh);
8790         IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: "
8791             "dgid prefix %llX dgid guid %llX",
8792             qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_dgid.
8793             gid_prefix,
8794             qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_dgid.
8795             gid_guid);
8796         IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: "
8797             "sgid prefix %llX sgid guid %llX",
8798             qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_sgid.
8799             gid_prefix,
8800             qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_sgid.
8801             gid_guid);
8802 }
8803 #endif