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