Print this page
8368 remove warlock leftovers from usr/src/uts


 467 int ibcm_recv_tasks = 0;
 468 int ibcm_max_recv_tasks = 24;
 469 int ibcm_recv_timeouts = 0;
 470 
 471 /*
 472  * Tunable MAX MRA Service Timeout value in MicroSECONDS.
 473  *      0 - Tunable parameter not used.
 474  *
 475  *      Ex:   60000000 - Max MRA Service Delay is 60 Seconds.
 476  */
 477 clock_t ibcm_mra_service_timeout_max = 0;
 478 
 479 #ifdef  DEBUG
 480 
 481 static void                     print_modify_qp(char *prefix,
 482                                     ibt_qp_hdl_t ibt_qp,
 483                                     ibt_cep_modify_flags_t flags,
 484                                     ibt_qp_info_t *qp_attr);
 485 #endif
 486 
 487 /*      Warlock annotations */
 488 
 489 _NOTE(READ_ONLY_DATA(ibt_arej_info_u))
 490 
 491 /*
 492  * ibcm_process_incoming_mad:
 493  *      The CM callback that is invoked by IBMF, when a valid CM MAD arrives
 494  *      on any of the registered ibmf handles by CM.
 495  *
 496  *      It is assumed that the incoming MAD (except for incoming REQ) belongs
 497  *      to a connection on the HCA, on which the MAD is received.
 498  *      The IBMF callback arg specifies ibcm_hca_info_t
 499  *
 500  * NOTE: IBMF always invokes ibcm_recv_cb() in a taskq. CM does some memory
 501  * allocations and invoke ibcm_sm_funcs_tbl[i]() in the same taskq.
 502  *
 503  * INPUTS:
 504  *      ibmf_handle     - IBMF Handle
 505  *      args            - from IBMF. Is a ptr to ibcm_hca_info_t
 506  *      status          - Callback status. Is mostly IBMF_SUCCESS
 507  *      madbuf          - IBMF allocated MAD buffer (CM should free it)
 508  *      madaddr         - IBMF MAD's address
 509  *      grhvalid        - If GRH is valid or not
 510  *


 549 #endif
 550 
 551         portp = cm_qp_entry->qp_port;
 552         hcap = portp->port_hcap;
 553 
 554         IBTF_DPRINTF_L4(cmlog, "ibcm_process_incoming_mad: CM MAD on "
 555             "port %d", portp->port_num);
 556 
 557         /* Increment hca ref cnt, if HCA is in attached state, else fail */
 558         if (ibcm_inc_hca_acc_cnt(hcap) != IBCM_SUCCESS) {
 559                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
 560                     "hca not in attach state");
 561                 /* IBMF allocates Input MAD, and ibcm free's it */
 562                 if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) !=
 563                     IBMF_SUCCESS)
 564                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
 565                             "ibmf_free_msg failed %d", ibmf_status);
 566                 return;
 567         }
 568 
 569         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cm_mad_addr))
 570 
 571         /* allocate memory for internal MAD address buffer */
 572         cm_mad_addr = &loc_mad_addr;
 573         bzero(cm_mad_addr, sizeof (ibcm_mad_addr_t));
 574 
 575         cm_mad_addr->port_num = portp->port_num;
 576 
 577         /* initialize cm_mad_addr field(s) */
 578         in_mad_hdr = msgp->im_msgbufs_recv.im_bufs_mad_hdr;
 579 
 580         if (in_mad_hdr->MgmtClass != MAD_MGMT_CLASS_COMM_MGT) {
 581                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
 582                     "bad mgmt class %x", in_mad_hdr->MgmtClass);
 583                 if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) !=
 584                     IBMF_SUCCESS)
 585                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
 586                             "ibmf_free_msg failed %d", ibmf_status);
 587                 ibcm_dec_hca_acc_cnt(hcap);
 588                 return;
 589         }
 590 


 629 
 630                 if (attr_id == (IBCM_INCOMING_REQ + IBCM_ATTR_BASE_ID))
 631                         ibcm_post_rej_ver_mismatch(
 632                             (uint8_t *)IBCM_IN_HDRP(msgp), cm_mad_addr);
 633 
 634                 if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) !=
 635                     IBMF_SUCCESS)
 636                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
 637                             "ibmf_free_msg failed %d", ibmf_status);
 638                 ibcm_dec_hca_acc_cnt(hcap);
 639                 return;
 640         }
 641 
 642         IBTF_DPRINTF_L4(cmlog, "ibcm_process_incoming_mad: "
 643             "Transaction Id 0x%llX", b2h64(in_mad_hdr->TransactionID));
 644 
 645 #ifdef  DEBUG
 646         ibcm_decode_tranid(b2h64(in_mad_hdr->TransactionID), NULL);
 647 #endif
 648 
 649         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cm_mad_addr))
 650 
 651         /*
 652          * The following are valid combination of Method type
 653          * and attribute id in the received MAD :-
 654          *      o ClassPortInfo with Get method
 655          *      o CM messages with Send method
 656          */
 657         if ((attr_id == MAD_ATTR_ID_CLASSPORTINFO) &&
 658             ((method == MAD_METHOD_GET) ||
 659             (method == MAD_METHOD_GET_RESPONSE))) {
 660                 if (method == MAD_METHOD_GET)
 661                         ibcm_process_get_classport_info(hcap,
 662                             (uint8_t *)IBCM_IN_HDRP(msgp), cm_mad_addr);
 663                 else if (method == MAD_METHOD_GET_RESPONSE)
 664                         ibcm_decode_classport_info(hcap,
 665                             (uint8_t *)IBCM_IN_HDRP(msgp), cm_mad_addr);
 666         } else if ((attr_id >= IBCM_ATTR_BASE_ID) &&
 667             (attr_id < (IBCM_ATTR_BASE_ID + IBCM_MAX_EVENTS)) &&
 668             (method == MAD_METHOD_SEND)) {
 669 
 670                 attr_id -= IBCM_ATTR_BASE_ID;   /* figure out CM message id */


 693                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
 694                     "ibmf_free_msg failed %d", ibmf_status);
 695 }
 696 
 697 /*
 698  * Structure to carry the arguments from ibcm_recv_cb() to
 699  * ibcm_recv_incoming_mad() via taskq_dispatch
 700  */
 701 typedef struct ibcm_taskq_args_s {
 702         ibmf_handle_t   tq_ibmf_handle;
 703         ibmf_msg_t      *tq_ibmf_msgp;
 704         void            *tq_args;
 705 } ibcm_taskq_args_t;
 706 
 707 #define IBCM_RECV_MAX   128
 708 ibcm_taskq_args_t ibcm_recv_array[IBCM_RECV_MAX + 1];
 709 int ibcm_get, ibcm_put;
 710 int ibcm_recv_total;
 711 int ibcm_recv_queued;
 712 
 713 _NOTE(READ_ONLY_DATA(ibcm_taskq_args_t))
 714 
 715 static int
 716 ibcm_recv_dequeue(ibmf_handle_t *ibmf_handlep, ibmf_msg_t **msgpp, void **argsp)
 717 {
 718         ibcm_taskq_args_t *tq;
 719 
 720         if (ibcm_put == ibcm_get)
 721                 return (0);
 722 
 723         if (++ibcm_get >= IBCM_RECV_MAX)
 724                 ibcm_get = 0;
 725         tq = ibcm_recv_array + ibcm_get;
 726         *ibmf_handlep = tq->tq_ibmf_handle;
 727         *msgpp = tq->tq_ibmf_msgp;
 728         *argsp = tq->tq_args;
 729         return (1);
 730 }
 731 
 732 static int
 733 ibcm_recv_enqueue(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp, void *args)
 734 {
 735         int next;
 736         ibcm_taskq_args_t *tq;
 737 
 738         ASSERT(MUTEX_HELD(&ibcm_recv_mutex));
 739         next = ibcm_put + 1;
 740         if (next >= IBCM_RECV_MAX)
 741                 next = 0;
 742         if (next != ibcm_get) {
 743                 ibcm_recv_queued++;
 744                 ibcm_put = next;
 745                 tq = ibcm_recv_array + next;
 746                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tq))
 747                 tq->tq_ibmf_handle = ibmf_handle;
 748                 tq->tq_ibmf_msgp = msgp;
 749                 tq->tq_args = args;
 750                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*tq))
 751                 return (1);
 752         } else {
 753                 return (0);
 754         }
 755 }
 756 
 757 void
 758 ibcm_drop_msg(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp)
 759 {
 760         int ibmf_status;
 761 
 762         IBTF_DPRINTF_L2(cmlog, "ibcm_drop_msg: discarding MAD");
 763 
 764         if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) != IBMF_SUCCESS)
 765                 IBTF_DPRINTF_L2(cmlog, "ibcm_drop_msg: "
 766                     "ibmf_free_msg failed %d", ibmf_status);
 767 }
 768 
 769 /*
 770  * Processing done in taskq thread.


 850 
 851         mutex_enter(&ibcm_recv_mutex);
 852         ibcm_recv_total++;
 853         if (ibcm_recv_tasks >= ibcm_max_recv_tasks) { /* just queue this one */
 854                 rv = ibcm_recv_enqueue(ibmf_handle, msgp, args);
 855                 mutex_exit(&ibcm_recv_mutex);
 856                 return (rv);
 857         } else {
 858                 ibcm_recv_tasks++; /* dispatch this one to a taskq thread */
 859                 mutex_exit(&ibcm_recv_mutex);
 860                 tq = kmem_alloc(sizeof (*tq), KM_NOSLEEP);
 861                 if (tq == NULL) {
 862                         mutex_enter(&ibcm_recv_mutex);
 863                         if (--ibcm_recv_tasks > 0)
 864                                 rv = ibcm_recv_enqueue(ibmf_handle, msgp, args);
 865                         else    /* don't enqueue if no threads are running */
 866                                 rv = 0;
 867                         mutex_exit(&ibcm_recv_mutex);
 868                         return (rv);
 869                 }
 870                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tq))
 871                 tq->tq_ibmf_handle = ibmf_handle;
 872                 tq->tq_ibmf_msgp = msgp;
 873                 tq->tq_args = args;
 874                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*tq))
 875                 if (taskq_dispatch(ibcm_taskq, ibcm_recv_task, tq,
 876                     TQ_NOQUEUE | TQ_NOSLEEP) == 0) {    /* dispatch failed */
 877                         mutex_enter(&ibcm_recv_mutex);
 878                         if (--ibcm_recv_tasks == 0) {
 879                                 /* try the dispatch again, after a tick */
 880                                 (void) timeout(ibcm_recv_timeout_cb, tq, 1);
 881                                 ibcm_recv_timeouts++;
 882                                 rv = 1; /* indicate success */
 883                         } else {
 884                                 rv = ibcm_recv_enqueue(ibmf_handle, msgp, args);
 885                                 kmem_free(tq, sizeof (*tq));
 886                         }
 887                         mutex_exit(&ibcm_recv_mutex);
 888                         return (rv);
 889                 } else {
 890                         return (1);
 891                 }
 892         }
 893 }
 894 


 963             hcap, input_madp, cm_mad_addr);
 964 
 965         /*
 966          * Lookup for an existing state structure or create a new state struct
 967          * If there is no entry, the lookup function also allocates a new
 968          * state structure and inserts in the table, initializes remote qpn
 969          * and hca guid from REQ
 970          */
 971         remote_hca_guid = b2h64(req_msgp->req_local_ca_guid);
 972         remote_qpn = b2h32(req_msgp->req_local_qpn_plus) >> 8;
 973         remote_comid = b2h32(req_msgp->req_local_comm_id);
 974 
 975         IBCM_DUMP_RAW_MSG((uchar_t *)input_madp);
 976 
 977         IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: remote_comid = %x"
 978             " remote_qpn = %x", remote_comid, remote_qpn);
 979 
 980         IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: remote_hcaguid = %llX",
 981             remote_hca_guid);
 982 
 983         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
 984 
 985 new_req:
 986         /* allocate the local_comid before proceeding */
 987         if (ibcm_alloc_comid(hcap, &local_comid) != IBCM_SUCCESS) {
 988                 ibcm_build_n_post_rej_mad(input_madp,
 989                     b2h32(req_msgp->req_local_comm_id), cm_mad_addr,
 990                     IBT_CM_FAILURE_REQ, IBT_CM_NO_RESC);
 991                 return;
 992         }
 993 
 994         /* allocate ibcm_state_data_t before grabbing the WRITER lock */
 995         statep = kmem_zalloc(sizeof (*statep), KM_SLEEP);
 996 
 997         rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
 998 
 999         /* NOTE that only a writer lock is held here */
1000 
1001         state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_REQ,
1002             local_comid, remote_qpn, remote_hca_guid, hcap, &statep);
1003 
1004         if (state_lookup_status == IBCM_LOOKUP_NEW) {
1005                 /* seeing the REQ request for the first time */
1006 
1007                 mutex_enter(&statep->state_mutex);
1008                 /* Release the state table lock */
1009                 rw_exit(&hcap->hca_state_rwlock);
1010 
1011                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: New statep 0x%p"
1012                     " created", statep);
1013 
1014                 psn24_timeout5_retry3 = b2h32(req_msgp->req_starting_psn_plus);
1015 
1016                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
1017 
1018                 /* if ibmf msg allocation fails, delete the statep */
1019                 if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl,
1020                     &statep->stored_msg, MAD_METHOD_SEND) != IBT_SUCCESS) {
1021 
1022                         IBCM_REF_CNT_DECR(statep);
1023                         statep->state = IBCM_STATE_DELETE;
1024                         mutex_exit(&statep->state_mutex);
1025                         /* HCA res cnt decremented via ibcm_delete_state_data */
1026                         ibcm_inc_hca_res_cnt(hcap);
1027                         ibcm_delete_state_data(statep);
1028                         return;
1029                 }
1030 
1031                 /* Allocate dreq_msg buf to be used during teardown. */
1032                 if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl,
1033                     &statep->dreq_msg, MAD_METHOD_SEND) != IBT_SUCCESS) {
1034 
1035                         IBCM_REF_CNT_DECR(statep);
1036                         statep->state = IBCM_STATE_DELETE;
1037                         mutex_exit(&statep->state_mutex);


1236                         /* REJ posted from ibcm_verify_req_gids_and_svcid */
1237                         return;
1238                 }
1239 
1240                 /* Call the QP state transition processing function */
1241                 response = ibcm_cep_state_req(statep, req_msgp,
1242                     &reject_reason, &arej_info_len);
1243 
1244                 /* If defer, return holding the statep ref cnt */
1245                 if (response == IBCM_DEFER) {
1246                         IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: "
1247                             "statep %0xp client returned DEFER response",
1248                             statep);
1249                         return;
1250                 }
1251 
1252                 /* statep ref cnt decremented in the func below */
1253                 ibcm_handle_cep_req_response(statep, response,
1254                     reject_reason, arej_info_len);
1255 
1256                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
1257 
1258                 return;
1259 
1260         } else {
1261                 rw_exit(&hcap->hca_state_rwlock);
1262                 ibcm_free_comid(hcap, local_comid);
1263         }
1264 
1265         if (state_lookup_status == IBCM_LOOKUP_EXISTS) {
1266                 hrtime_t        cur_time;
1267 
1268                 mutex_enter(&statep->state_mutex);
1269 
1270                 /*
1271                  * There is an existing state structure entry
1272                  * with the same active comid
1273                  * Resending REP MAD is necessary only for REP/REJ/MRA Sent
1274                  * states
1275                  * Any other state implies the active has already received
1276                  * the REP/REJ response, and this REQ is an old MAD popping
1277                  * out of the fabric, hence no resend is required


1378                         ibcm_build_n_post_rej_mad(input_madp,
1379                             b2h32(req_msgp->req_local_comm_id),
1380                             cm_mad_addr, IBT_CM_FAILURE_REQ, IBT_CM_CONN_STALE);
1381 
1382                         mutex_enter(&statep->state_mutex);
1383                 }
1384                 IBCM_REF_CNT_DECR(statep); /* decrement the ref count */
1385                 mutex_exit(&statep->state_mutex);
1386         }
1387 }
1388 
1389 /*
1390  * ibcm_handle_cep_req_response:
1391  *      Processes the response from ibcm_cep_state_req. Called holding a
1392  *      statep ref cnt. The statep ref cnt is decremented before returning.
1393  */
1394 void
1395 ibcm_handle_cep_req_response(ibcm_state_data_t *statep, ibcm_status_t response,
1396     ibt_cm_reason_t reject_reason, uint8_t arej_info_len)
1397 {
1398         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
1399 
1400         if (response == IBCM_SEND_REP)
1401                 ibcm_post_rep_mad(statep);
1402         else {
1403                 ASSERT(response == IBCM_SEND_REJ);
1404                 IBTF_DPRINTF_L4(cmlog, "ibcm_handle_cep_req_response: statep %p"
1405                     " posting REJ reject_reason = %d", statep, reject_reason);
1406 
1407                 ibcm_post_rej_mad(statep,
1408                     reject_reason, IBT_CM_FAILURE_REQ,
1409                     NULL, arej_info_len);
1410         }
1411 
1412         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
1413 
1414         mutex_enter(&statep->state_mutex);
1415         IBCM_REF_CNT_DECR(statep);
1416         mutex_exit(&statep->state_mutex);
1417 }
1418 
1419 
1420 /*
1421  * ibcm_process_rep_msg:
1422  *      ACTIVE SIDE CM
1423  *      Called from ibcm_process_incoming_mad on reception of a REP message
1424  *
1425  * INPUTS:
1426  *      hcap            - HCA entry pointer
1427  *      input_madp      - CM MAD that is input to this function
1428  *      cm_mad_addr     - Address information for the MAD
1429  *
1430  * RETURN VALUE:        NONE
1431  */
1432 void
1433 ibcm_process_rep_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,


1511                 ibcm_resend_mra_mad(statep);
1512         else if ((statep->state == IBCM_STATE_REQ_SENT) ||
1513             (statep->state == IBCM_STATE_REP_WAIT)) {
1514 
1515                 /* change state */
1516                 statep->state = IBCM_STATE_REP_RCVD;
1517                 statep->clnt_proceed = IBCM_BLOCK;
1518                 statep->local_qp_rnr_cnt =
1519                     rep_msgp->rep_rnr_retry_cnt_plus >> 5;
1520 
1521                 /* cancel the REQ timer */
1522                 if (statep->timerid != 0) {
1523                         timer_val = statep->timerid;
1524                         statep->timerid = 0;
1525                         mutex_exit(&statep->state_mutex);
1526                         (void) untimeout(timer_val);
1527                 } else {
1528                         mutex_exit(&statep->state_mutex);
1529                 }
1530 
1531                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
1532 
1533                 /* Initialize the remote destination QPN for further MADs */
1534                 statep->stored_reply_addr.rcvd_addr.ia_remote_qno =
1535                     cm_mad_addr->rcvd_addr.ia_remote_qno;
1536                 statep->remote_qpn = b2h32(rep_msgp->rep_local_qpn_plus) >> 8;
1537                 statep->remote_comid = b2h32(rep_msgp->rep_local_comm_id);
1538                 bcopy(rep_msgp->rep_local_ca_guid, &remote_ca_guid,
1539                     sizeof (ib_guid_t));
1540                 statep->remote_hca_guid = b2h64(remote_ca_guid);
1541 
1542                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: statep 0x%p "
1543                     "passive cid = %x passive qpn = %x", statep,
1544                     statep->remote_comid, statep->remote_qpn);
1545 
1546                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: statep 0x%p "
1547                     "passive hcaguid = %llX", statep, statep->remote_hca_guid);
1548 
1549                 stale_qpn = statep;
1550                 stale_comid = statep;
1551 
1552                 /* Handle stale connection detection on active side */


1740                 /* Initialize the remote ack delay */
1741                 statep->remote_ack_delay =
1742                     ibt_ib2usec(rep_msgp->rep_target_delay_plus >> 3);
1743 
1744                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: statep 0x%p"
1745                     " passive hca_ack_delay= %x ", statep,
1746                     statep->remote_ack_delay);
1747 
1748                 response = ibcm_cep_state_rep(statep, rep_msgp,
1749                     &reject_reason, &arej_info_len);
1750 
1751                 if (response == IBCM_DEFER) {
1752                         IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: "
1753                             "statep 0x%p client returned DEFER response",
1754                             statep);
1755                         return;
1756                 }
1757                 ibcm_handle_cep_rep_response(statep, response,
1758                     reject_reason, arej_info_len, rep_msgp);
1759 
1760                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
1761 
1762                 return;
1763 
1764         } else if (statep->state == IBCM_STATE_DELETE) {
1765 
1766                 mutex_exit(&statep->state_mutex);
1767                 ibcm_build_n_post_rej_mad(input_madp,
1768                     b2h32(rep_msgp->rep_local_comm_id), cm_mad_addr,
1769                     IBT_CM_FAILURE_REP, IBT_CM_INVALID_CID);
1770                 mutex_enter(&statep->state_mutex);
1771         } else {
1772 
1773 #ifdef DEBUG
1774                 if (ibcm_test_mode > 0)
1775                         if (statep->state == IBCM_STATE_REP_RCVD)
1776                                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_rep_msg: "
1777                                     "REP re-send from passive for statep 0x%p"
1778                                     " in state %d", statep, statep->state);
1779                         else
1780                                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_rep_msg: "
1781                                     "Unexpected REP for statep 0x%p in "


2622 
2623 /*
2624  * ibcm_post_dreq_mad:
2625  *      Posts a DREQ MAD
2626  * Post DREQ now for TIMEWAIT state and DREQ_RCVD
2627  *
2628  * INPUTS:
2629  *      statep          - state pointer
2630  *
2631  * RETURN VALUE:
2632  *      NONE
2633  */
2634 void
2635 ibcm_post_dreq_mad(void *vstatep)
2636 {
2637         ibcm_state_data_t       *statep = vstatep;
2638         ibcm_dreq_msg_t         *dreq_msgp;
2639 
2640         ASSERT(statep->dreq_msg != NULL);
2641 
2642         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dreq_msgp))
2643 
2644         /* Fill in the DREQ message */
2645         dreq_msgp = (ibcm_dreq_msg_t *)IBCM_OUT_MSGP(statep->dreq_msg);
2646         dreq_msgp->dreq_local_comm_id = h2b32(statep->local_comid);
2647         dreq_msgp->dreq_remote_comm_id = h2b32(statep->remote_comid);
2648         dreq_msgp->dreq_remote_qpn_eecn_plus = h2b32(statep->remote_qpn << 8);
2649 
2650         IBCM_OUT_HDRP(statep->dreq_msg)->AttributeID =
2651             h2b16(IBCM_INCOMING_DREQ + IBCM_ATTR_BASE_ID);
2652 
2653         /* wait until client knows CONN EST event */
2654         mutex_enter(&statep->state_mutex);
2655         while (statep->cep_in_rts == IBCM_BLOCK)
2656                 cv_wait(&statep->block_mad_cv, &statep->state_mutex);
2657         mutex_exit(&statep->state_mutex);
2658 
2659         /* Transition QP/EEC state to ERROR state */
2660         (void) ibcm_cep_to_error_state(statep);
2661 
2662         IBCM_OUT_HDRP(statep->dreq_msg)->TransactionID =
2663             h2b64(ibcm_generate_tranid(IBCM_INCOMING_DREQ, statep->local_comid,
2664             0));
2665 
2666         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*dreq_msgp))
2667 
2668         /* post the first DREQ via timeout callback */
2669         mutex_enter(&statep->state_mutex);
2670 
2671         statep->state = IBCM_STATE_DREQ_SENT;
2672         cv_broadcast(&statep->block_mad_cv);
2673 
2674         statep->timer_stored_state = statep->state;
2675         /* client cannot specify more than 16 retries */
2676         statep->timer_value = statep->remote_ack_delay;
2677         if (statep->mode == IBCM_ACTIVE_MODE) {
2678                 statep->timer_value += (2 * statep->pkt_life_time);
2679         }
2680         statep->remaining_retry_cnt = statep->max_cm_retries + 1;
2681         statep->timerid = IBCM_TIMEOUT(statep, 0);
2682         mutex_exit(&statep->state_mutex);
2683 }
2684 
2685 /*
2686  * ibcm_post_drep_mad:
2687  *      Posts a DREP MAD
2688  * Post DREP now for TIMEWAIT state and DREQ_RCVD
2689  *
2690  * INPUTS:
2691  *      statep          - state pointer
2692  *
2693  * RETURN VALUE:
2694  *      NONE
2695  */
2696 static void
2697 ibcm_post_drep_mad(ibcm_state_data_t *statep)
2698 {
2699         ibcm_drep_msg_t *drep_msgp;
2700 
2701         drep_msgp = (ibcm_drep_msg_t *)IBCM_OUT_MSGP(statep->drep_msg);
2702 
2703         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*drep_msgp))
2704 
2705         IBTF_DPRINTF_L4(cmlog, "ibcm_post_drep_mad:");
2706 
2707         /* Fill up DREP fields */
2708         drep_msgp->drep_local_comm_id = h2b32(statep->local_comid);
2709         drep_msgp->drep_remote_comm_id = h2b32(statep->remote_comid);
2710         IBCM_OUT_HDRP(statep->drep_msg)->AttributeID =
2711             h2b16(IBCM_INCOMING_DREP + IBCM_ATTR_BASE_ID);
2712 
2713         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*drep_msgp))
2714 
2715         ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_DREP);
2716 
2717         /* Post the DREP MAD now.  */
2718         ibcm_post_rc_mad(statep, statep->drep_msg, ibcm_post_drep_complete,
2719             statep);
2720 }
2721 
2722 /*
2723  * ibcm_process_drep_msg:
2724  *      Processes incoming DREP message on active/passive side
2725  *
2726  * INPUTS:
2727  *      hcap            - HCA entry pointer
2728  *      input_madp      - CM MAD that is input to this function
2729  *      cm_mad_addr     - Address information for the MAD
2730  *
2731  * RETURN VALUE: NONE
2732  */
2733 /* ARGSUSED */
2734 void


3009  * RETURN VALUE:
3010  *      NONE
3011  * Notes
3012  *  There is no need to hold the statep->mutex and call ibcm_post_rej_mad
3013  *  REJ can be posted either in IBCM_STATE_REQ_RCVD or IBCM_STATE_REP_RCVD
3014  *  In these states, there is no timer active, and an incoming REJ shall
3015  *  not modify the state or cancel timers
3016  *  An incoming REJ doesn't affect statep in state = IBCM_STATE_REJ_SENT/BUSY
3017  */
3018 void
3019 ibcm_post_rej_mad(ibcm_state_data_t *statep, ibt_cm_reason_t reject_reason,
3020     int which_msg, void *addl_rej_info, ibt_priv_data_len_t arej_info_len)
3021 {
3022         ibcm_rej_msg_t  *rej_msg =
3023             (ibcm_rej_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
3024 
3025         /* Message printed if connection gets REJed */
3026         IBTF_DPRINTF_L3(cmlog, "ibcm_post_rej_mad: "
3027             "statep = %p, reject_reason = %d", statep, reject_reason);
3028 
3029         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msg))
3030 
3031         /* Initialize rej_msg fields */
3032         rej_msg->rej_local_comm_id = h2b32(statep->local_comid);
3033         rej_msg->rej_remote_comm_id = h2b32(statep->remote_comid);
3034         rej_msg->rej_msg_type_plus = (which_msg & 0x3) << 6;
3035         rej_msg->rej_reject_info_len_plus = arej_info_len << 1;
3036         rej_msg->rej_rejection_reason = h2b16((uint16_t)reject_reason);
3037 
3038         if ((arej_info_len != 0) && (addl_rej_info != NULL))
3039                 bcopy(addl_rej_info, rej_msg->rej_addl_rej_info, arej_info_len);
3040 
3041         IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
3042             h2b16(IBCM_INCOMING_REJ + IBCM_ATTR_BASE_ID);
3043 
3044         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msg))
3045 
3046         mutex_enter(&statep->state_mutex);
3047 
3048         /* signal any waiting close channels with blocking or no callbacks  */
3049         statep->close_done = B_TRUE;
3050         statep->close_nocb_state = IBCM_FAIL;
3051 
3052         cv_signal(&statep->block_client_cv);
3053 
3054         statep->timer_stored_state = statep->state = IBCM_STATE_REJ_SENT;
3055         statep->send_mad_flags |= IBCM_REJ_POST_BUSY;
3056 
3057         IBCM_REF_CNT_INCR(statep); /* for non-blocking post */
3058         mutex_exit(&statep->state_mutex);
3059 
3060         ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_REJ);
3061         if (ibcm_enable_trace & 2)
3062                 ibcm_dump_conn_trace(statep);
3063         else
3064                 IBTF_DPRINTF_L2(cmlog, "ibcm_post_rej_mad statep %p "
3065                     "OUTGOING_REJ", statep);


3084  *      NONE
3085  */
3086 static void
3087 ibcm_build_n_post_rej_mad(uint8_t *input_madp, ib_com_id_t remote_comid,
3088     ibcm_mad_addr_t *cm_mad_addr, int which_msg, uint16_t reject_reason)
3089 {
3090         ibcm_rej_msg_t  *rej_msg;
3091         ibmf_msg_t      *cm_rej_msg;
3092         ibcm_mad_addr_t rej_reply_addr;
3093 
3094         IBTF_DPRINTF_L3(cmlog, "ibcm_build_n_post_rej_mad: "
3095             "remote_comid: %x reject_reason %d", remote_comid, reject_reason);
3096 
3097         if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg,
3098             MAD_METHOD_SEND) != IBT_SUCCESS) {
3099                 IBTF_DPRINTF_L2(cmlog, "ibcm_build_n_post_rej_mad: "
3100                     "ibcm_alloc_out_msg failed");
3101                 return;
3102         }
3103 
3104         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msg))
3105 
3106         IBCM_OUT_HDRP(cm_rej_msg)->TransactionID =
3107             ((ib_mad_hdr_t *)(input_madp))->TransactionID;
3108 
3109         /* Initialize rej_msg fields */
3110         rej_msg = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(cm_rej_msg);
3111         rej_msg->rej_local_comm_id = 0;
3112         rej_msg->rej_remote_comm_id = h2b32(remote_comid);
3113         rej_msg->rej_msg_type_plus = (which_msg & 0x3) << 6;
3114         rej_msg->rej_reject_info_len_plus = 0;
3115         rej_msg->rej_rejection_reason = h2b16(reject_reason);
3116 
3117         IBCM_OUT_HDRP(cm_rej_msg)->AttributeID =
3118             h2b16(IBCM_INCOMING_REJ + IBCM_ATTR_BASE_ID);
3119 
3120         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msg))
3121 
3122         ibcm_build_reply_mad_addr(cm_mad_addr, &rej_reply_addr);
3123 
3124         if (rej_reply_addr.cm_qp_entry != NULL) {
3125                 (void) ibcm_post_mad(cm_rej_msg, &rej_reply_addr, NULL, NULL);
3126                 ibcm_release_qp(rej_reply_addr.cm_qp_entry);
3127         }
3128 
3129         (void) ibcm_free_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg);
3130 }
3131 
3132 /* posts a REJ for an incoming REQ with unsupported class version */
3133 
3134 static void
3135 ibcm_post_rej_ver_mismatch(uint8_t *input_madp, ibcm_mad_addr_t *cm_mad_addr)
3136 {
3137         ibcm_req_msg_t  *req_msgp =
3138             (ibcm_req_msg_t *)&input_madp[IBCM_MAD_HDR_SIZE];
3139         ibcm_rej_msg_t  *rej_msg;
3140         ibmf_msg_t      *cm_rej_msg;
3141         ibcm_mad_addr_t rej_reply_addr;
3142 
3143         IBTF_DPRINTF_L3(cmlog, "ibcm_post_rej_ver_mismatch: remote comid %x",
3144             b2h32(req_msgp->req_local_comm_id));
3145 
3146         if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg,
3147             MAD_METHOD_SEND) != IBT_SUCCESS) {
3148                 IBTF_DPRINTF_L2(cmlog, "ibcm_post_rej_ver_mismatch: "
3149                     "ibcm_alloc_out_msg failed");
3150                 return;
3151         }
3152 
3153         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msg))
3154 
3155         IBCM_OUT_HDRP(cm_rej_msg)->TransactionID =
3156             ((ib_mad_hdr_t *)(input_madp))->TransactionID;
3157 
3158         /* Initialize rej_msg fields */
3159         rej_msg = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(cm_rej_msg);
3160         rej_msg->rej_local_comm_id = 0;
3161         rej_msg->rej_remote_comm_id = req_msgp->req_local_comm_id;
3162         rej_msg->rej_msg_type_plus = IBT_CM_FAILURE_REQ << 6;
3163         rej_msg->rej_rejection_reason = h2b16(IBT_CM_CLASS_NO_SUPPORT);
3164         rej_msg->rej_reject_info_len_plus = 1 << 1;
3165         rej_msg->rej_addl_rej_info[0] = IBCM_MAD_CLASS_VERSION;
3166 
3167         IBCM_OUT_HDRP(cm_rej_msg)->AttributeID =
3168             h2b16(IBCM_INCOMING_REJ + IBCM_ATTR_BASE_ID);
3169         IBCM_OUT_HDRP(cm_rej_msg)->Status = h2b16(MAD_STATUS_BAD_VERSION);
3170 
3171         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msg))
3172 
3173         ibcm_build_reply_mad_addr(cm_mad_addr, &rej_reply_addr);
3174         if (rej_reply_addr.cm_qp_entry != NULL) {
3175                 (void) ibcm_post_mad(cm_rej_msg, &rej_reply_addr, NULL, NULL);
3176                 ibcm_release_qp(rej_reply_addr.cm_qp_entry);
3177         }
3178         (void) ibcm_free_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg);
3179 }
3180 
3181 
3182 /*
3183  * ibcm_post_rep_mad:
3184  *      Posts a REP MAD and starts timer
3185  *
3186  * INPUTS:
3187  *      statep          - state pointer
3188  *
3189  * RETURN VALUE:
3190  *      NONE
3191  */
3192 void
3193 ibcm_post_rep_mad(ibcm_state_data_t *statep)
3194 {
3195         ibcm_rep_msg_t  *rep_msgp =
3196             (ibcm_rep_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
3197         ibmf_msg_t      *mra_msg = NULL;
3198         boolean_t       ret = B_FALSE;
3199 
3200         IBTF_DPRINTF_L4(cmlog, "ibcm_post_rep_mad: statep 0x%p", statep);
3201 
3202         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rep_msgp))
3203 
3204         /*
3205          * All other REP fields, other that the 2 below, are filled in
3206          * the ibcm_cep_state_req() function.
3207          */
3208         rep_msgp->rep_local_comm_id = h2b32(statep->local_comid);
3209         rep_msgp->rep_remote_comm_id = h2b32(statep->remote_comid);
3210         IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
3211             h2b16(IBCM_INCOMING_REP + IBCM_ATTR_BASE_ID);
3212 
3213         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rep_msgp))
3214 
3215         /*
3216          * Changing state and attempt to delete the mra msg must be done
3217          * together holding the state_mutex
3218          */
3219         mutex_enter(&statep->state_mutex);
3220 
3221         /* Now, attempt to delete the mra_msg, if there is one allocated */
3222         if (statep->mra_msg != NULL) {
3223                 if (!(statep->send_mad_flags & IBCM_MRA_POST_BUSY)) {
3224                         mra_msg = statep->mra_msg;
3225                         statep->mra_msg = NULL;
3226                 } else statep->delete_mra_msg = B_TRUE;
3227         }
3228 
3229         if (statep->abort_flag == IBCM_ABORT_CLIENT) {
3230                 statep->state = IBCM_STATE_ABORTED;
3231                 mutex_exit(&statep->state_mutex);
3232                 ibcm_process_abort(statep);
3233 
3234                 /* Now post a REJ MAD, rej reason consumer abort */


3269 /*
3270  * ibcm_post_rtu_mad:
3271  *      From active side post RTU MAD
3272  *
3273  * INPUTS:
3274  *      statep          - state pointer
3275  *
3276  * RETURN VALUE: NONE
3277  *
3278  * NOTE: No timer set after posting RTU
3279  */
3280 ibcm_status_t
3281 ibcm_post_rtu_mad(ibcm_state_data_t *statep)
3282 {
3283         ibcm_rtu_msg_t  *rtu_msg;
3284         ibmf_msg_t      *mra_msg = NULL;
3285         boolean_t       ret = B_FALSE;
3286 
3287         IBTF_DPRINTF_L4(cmlog, "ibcm_post_rtu_mad: statep 0x%p", statep);
3288 
3289         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rtu_msg))
3290 
3291         rtu_msg = (ibcm_rtu_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
3292 
3293         rtu_msg->rtu_local_comm_id = h2b32(statep->local_comid);
3294         rtu_msg->rtu_remote_comm_id = h2b32(statep->remote_comid);
3295         IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
3296             h2b16(IBCM_INCOMING_RTU + IBCM_ATTR_BASE_ID);
3297 
3298         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rtu_msg))
3299 
3300         mutex_enter(&statep->state_mutex);
3301 
3302         /* Now, attempt to delete the mra_msg, if there is one allocated */
3303         if (statep->mra_msg != NULL) {
3304                 if (!(statep->send_mad_flags & IBCM_MRA_POST_BUSY)) {
3305                         mra_msg = statep->mra_msg;
3306                         statep->mra_msg = NULL;
3307                 } else statep->delete_mra_msg = B_TRUE;
3308         }
3309 
3310         if (statep->abort_flag == IBCM_ABORT_CLIENT) {
3311                 statep->state = IBCM_STATE_ABORTED;
3312                 mutex_exit(&statep->state_mutex);
3313 
3314                 ibcm_process_abort(statep);
3315 
3316                 /* Now post a REJ MAD */
3317                 ibcm_post_rej_mad(statep, IBT_CM_CONSUMER, IBT_CM_FAILURE_REP,
3318                     NULL, 0);
3319                 ret = B_TRUE;


3466                 mutex_exit(&statep->state_mutex);
3467 
3468                 /* Deallocate the CM state structure */
3469                 ibcm_delete_state_data(statep);
3470                 return;
3471 
3472         } else if (statep->state == IBCM_STATE_TIMEWAIT) {
3473                 statep->state = IBCM_STATE_DELETE;
3474 
3475                 /* TIME_WAIT timer expired, so cleanup */
3476                 mutex_exit(&statep->state_mutex);
3477 
3478                 if (statep->channel)
3479                         ibtl_cm_chan_is_closed(statep->channel);
3480 
3481                 if (statep->recycle_arg) {
3482                         struct ibcm_taskq_recycle_arg_s *recycle_arg;
3483 
3484                         recycle_arg = statep->recycle_arg;
3485 
3486                         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(
3487                             statep->recycle_arg))
3488                         statep->recycle_arg = NULL;
3489                         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
3490 
3491                         /* if possible, do not slow down calling recycle func */
3492                         if (taskq_dispatch(ibcm_taskq, ibcm_process_rc_recycle,
3493                             recycle_arg, TQ_NOQUEUE | TQ_NOSLEEP) == 0) {
3494 
3495                                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(
3496                                     statep->recycle_arg))
3497                                 statep->recycle_arg = recycle_arg;
3498                                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(
3499                                     statep->recycle_arg))
3500                                 ibcm_add_tlist(statep);
3501                                 return;
3502                         }
3503                 }
3504 
3505                 ibcm_delete_state_data(statep);
3506                 return;
3507         } else if (statep->remaining_retry_cnt > 0) {
3508                 ibcm_conn_state_t       stored_state;
3509                 ibcm_ap_state_t         stored_ap_state;
3510 
3511                 statep->remaining_retry_cnt--;
3512                 IBTF_DPRINTF_L3(cmlog, "ibcm_timeout_cb: statep 0x%p "
3513                     "attr-id= 0x%x, retries remaining = 0x%x", statep,
3514                     b2h16(IBCM_OUT_HDRP(statep->stored_msg)->AttributeID),
3515                     statep->remaining_retry_cnt);
3516 
3517                 /*
3518                  * REP could be resent, either because of timeout or an
3519                  * incoming REQ. Any other MAD below can be resent, because


4244                         ud_statep = ibcm_ud_timeout_list_hdr;
4245                         ibcm_ud_timeout_list_hdr = ud_statep->ud_timeout_next;
4246 
4247                         if (ibcm_ud_timeout_list_hdr == NULL)
4248                                 ibcm_ud_timeout_list_tail = NULL;
4249 
4250                         ud_statep->ud_timeout_next = NULL;
4251 
4252                         mutex_exit(&ibcm_timeout_list_lock);
4253                         IBTF_DPRINTF_L3(cmlog, "ibcm_process_tlist: "
4254                             "ud scheduling state = %p", ud_statep);
4255                         ibcm_ud_timeout_client_cb(ud_statep);
4256                         mutex_enter(&ibcm_timeout_list_lock);
4257                 } else {
4258                         CALLB_CPR_SAFE_BEGIN(&cprinfo);
4259                         cv_wait(&ibcm_timeout_list_cv, &ibcm_timeout_list_lock);
4260                         CALLB_CPR_SAFE_END(&cprinfo, &ibcm_timeout_list_lock);
4261                 }
4262         }
4263 
4264 #ifndef __lock_lint
4265         CALLB_CPR_EXIT(&cprinfo);   /* mutex_exit */
4266 #endif
4267 }
4268 
4269 
4270 /*
4271  * ibcm_timeout_client_cb:
4272  *      Called from timeout thread processing
4273  *      Primary purpose is to call client handler
4274  *
4275  * INPUTS:
4276  *      arg     - ibcm_state_data_t is passed
4277  *
4278  * RETURN VALUES: NONE
4279  */
4280 void
4281 ibcm_timeout_client_cb(ibcm_state_data_t *statep)
4282 {
4283         mutex_enter(&statep->state_mutex);
4284 
4285         if ((statep->state == IBCM_STATE_DELETE) &&
4286             (statep->recycle_arg != NULL)) {
4287                 struct ibcm_taskq_recycle_arg_s *recycle_arg;
4288 
4289                 recycle_arg = statep->recycle_arg;
4290                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
4291                 statep->recycle_arg = NULL;
4292                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
4293                 mutex_exit(&statep->state_mutex);
4294                 (void) ibcm_process_rc_recycle(recycle_arg);
4295                 ibcm_delete_state_data(statep);
4296                 return;
4297         }
4298 
4299         if ((statep->state == IBCM_STATE_DELETE) &&
4300             (statep->delete_state_data == B_TRUE)) {
4301                 mutex_exit(&statep->state_mutex);
4302                 ibcm_dealloc_state_data(statep);
4303                 return;
4304         }
4305 
4306         /* Else, it must be in TIMEOUT state, do the necessary processing */
4307         if (statep->state == IBCM_STATE_TIMED_OUT) {
4308                 void            *data;
4309                 uint8_t         cf_msg;
4310                 ib_guid_t       local_hca_guid;
4311 
4312                 mutex_exit(&statep->state_mutex);


4492 
4493         hca_guid = hcap->hca_guid;
4494         port_num = cm_mad_addr->port_num;
4495 
4496         /* Figure out LID, GID, RequestId for svc_id lookup */
4497         lid = cm_mad_addr->rcvd_addr.ia_remote_lid;
4498         req_id = b2h32(sidr_reqp->sidr_req_request_id);
4499         pkey = b2h16(sidr_reqp->sidr_req_pkey);
4500         if (cm_mad_addr->grh_exists == B_TRUE)
4501                 gid = cm_mad_addr->grh_hdr.ig_sender_gid;
4502         else
4503                 gid.gid_prefix = gid.gid_guid = 0;
4504 
4505         /*
4506          * Lookup for an existing state structure
4507          * - if lookup fails it creates a new ud_state struct
4508          * No need to hold a lock across the call to ibcm_find_sidr_entry() as
4509          * the list lock is held in that function to find the matching entry.
4510          */
4511 
4512         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(srch_sidr))
4513 
4514         srch_sidr.srch_lid = lid;
4515         srch_sidr.srch_gid = gid;
4516         srch_sidr.srch_grh_exists = cm_mad_addr->grh_exists;
4517         srch_sidr.srch_req_id = req_id;
4518         srch_sidr.srch_mode = IBCM_PASSIVE_MODE;
4519 
4520         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(srch_sidr))
4521 
4522         rw_enter(&hcap->hca_sidr_list_lock, RW_WRITER);
4523         state_lookup_status = ibcm_find_sidr_entry(&srch_sidr, hcap, &ud_statep,
4524             IBCM_FLAG_LOOKUP_AND_ADD);
4525         rw_exit(&hcap->hca_sidr_list_lock);
4526 
4527         IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_req_msg: ud_statep 0x%p "
4528             "lookup status %x", ud_statep, state_lookup_status);
4529 
4530         if (state_lookup_status == IBCM_LOOKUP_NEW) {
4531 
4532                 /* Increment hca's resource count */
4533                 ibcm_inc_hca_res_cnt(hcap);
4534 
4535                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ud_statep))
4536 
4537                 /*
4538                  * Allocate CM MAD for a response
4539                  * This MAD is deallocated on state structure delete
4540                  * and re-used for all outgoing MADs for this connection.
4541                  * If MAD allocation fails, delete the ud statep
4542                  */
4543                 if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl,
4544                     &ud_statep->ud_stored_msg, MAD_METHOD_SEND) !=
4545                     IBT_SUCCESS) {
4546                         mutex_enter(&ud_statep->ud_state_mutex);
4547                         IBCM_UD_REF_CNT_DECR(ud_statep);
4548                         mutex_exit(&ud_statep->ud_state_mutex);
4549                         ibcm_delete_ud_state_data(ud_statep);
4550                         return;
4551                 }
4552 
4553                 /* Lookup for service */
4554                 ud_statep->ud_svc_id = b2h64(sidr_reqp->sidr_req_service_id);
4555                 ud_statep->ud_state  = IBCM_STATE_SIDR_REQ_RCVD;
4556                 ud_statep->ud_clnt_proceed = IBCM_BLOCK;


4633 
4634                         /* Call Client's UD handler */
4635                         cm_status = ibcm_sidr_req_ud_handler(ud_statep,
4636                             sidr_reqp, cm_mad_addr, &sidr_status);
4637 
4638                         mutex_enter(&ibcm_svc_info_lock);
4639                         IBCM_SVC_DECR(svc_infop);
4640                 }
4641 
4642                 mutex_exit(&ibcm_svc_info_lock);
4643 
4644                 if (cm_status == IBCM_DEFER) {
4645                         IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_req_msg: "
4646                             "ud_statep 0x%p client returned DEFER response",
4647                             ud_statep);
4648                         return;
4649                 }
4650 
4651                 ibcm_post_sidr_rep_mad(ud_statep, sidr_status);
4652 
4653                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ud_statep))
4654 
4655                 mutex_enter(&ud_statep->ud_state_mutex);
4656                 IBCM_UD_REF_CNT_DECR(ud_statep);
4657                 mutex_exit(&ud_statep->ud_state_mutex);
4658         } else {
4659                 ASSERT(state_lookup_status == IBCM_LOOKUP_EXISTS);
4660 
4661                 mutex_enter(&ud_statep->ud_state_mutex);
4662 
4663                 if (ud_statep->ud_state == IBCM_STATE_SIDR_REP_SENT)
4664                         ibcm_resend_srep_mad(ud_statep);
4665 
4666                 IBCM_UD_REF_CNT_DECR(ud_statep);
4667                 mutex_exit(&ud_statep->ud_state_mutex);
4668         }
4669 }
4670 
4671 
4672 /*
4673  * ibcm_process_sidr_rep_msg:
4674  *      This call processes an incoming SIDR REP


4697         IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_rep_msg:");
4698 
4699         lid = cm_mad_addr->rcvd_addr.ia_local_lid;
4700         if (cm_mad_addr->grh_exists == B_TRUE)
4701                 gid = cm_mad_addr->grh_hdr.ig_recver_gid;
4702         else
4703                 gid.gid_prefix = gid.gid_guid = 0;
4704 
4705         IBTF_DPRINTF_L3(cmlog, "ibcm_process_sidr_rep_msg: QPN rcvd = %x",
4706             h2b32(sidr_repp->sidr_rep_qpn_plus) >> 8);
4707 
4708         /*
4709          * Lookup for an existing state structure.
4710          * No need to hold a lock as ibcm_find_sidr_entry() holds the
4711          * list lock to find the matching entry.
4712          */
4713         IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_rep: lid=%x, (%llX, %llX), "
4714             "grh = %x, id = %x", lid, gid.gid_prefix, gid.gid_guid,
4715             cm_mad_addr->grh_exists, sidr_repp->sidr_rep_request_id);
4716 
4717         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(srch_sidr))
4718 
4719         srch_sidr.srch_lid = lid;
4720         srch_sidr.srch_gid = gid;
4721         srch_sidr.srch_grh_exists = cm_mad_addr->grh_exists;
4722         srch_sidr.srch_req_id = b2h32(sidr_repp->sidr_rep_request_id);
4723         srch_sidr.srch_mode = IBCM_ACTIVE_MODE;
4724 
4725         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(srch_sidr))
4726 
4727         rw_enter(&hcap->hca_sidr_list_lock, RW_READER);
4728         status = ibcm_find_sidr_entry(&srch_sidr, hcap, &ud_statep,
4729             IBCM_FLAG_LOOKUP);
4730         rw_exit(&hcap->hca_sidr_list_lock);
4731 
4732         IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_rep_msg: ud_statep 0x%p "
4733             "find sidr entry status = %x", ud_statep, status);
4734 
4735         if (status != IBCM_LOOKUP_EXISTS) {
4736                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_rep_msg: "
4737                     "No matching ud_statep for SIDR REP");
4738                 return;
4739         }
4740 
4741         if (IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->TransactionID !=
4742             ((ib_mad_hdr_t *)(input_madp))->TransactionID) {
4743                 mutex_enter(&ud_statep->ud_state_mutex);
4744                 IBCM_UD_REF_CNT_DECR(ud_statep);
4745                 mutex_exit(&ud_statep->ud_state_mutex);
4746                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_rep_msg: "


4844  * ibcm_post_sidr_rep_mad:
4845  *      This call posts a SIDR REP MAD
4846  *
4847  * INPUTS:
4848  *      ud_statep       - pointer to ibcm_ud_state_data_t
4849  *      status          - Status information
4850  *
4851  * RETURN VALUE: NONE
4852  */
4853 void
4854 ibcm_post_sidr_rep_mad(ibcm_ud_state_data_t *ud_statep,
4855     ibt_sidr_status_t status)
4856 {
4857         ib_svc_id_t             tmp_svc_id;
4858         ibcm_sidr_rep_msg_t     *sidr_repp =
4859             (ibcm_sidr_rep_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg);
4860         clock_t                 timer_value;
4861 
4862         IBTF_DPRINTF_L5(cmlog, "ibcm_post_sidr_rep_mad:");
4863 
4864         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_repp))
4865 
4866         IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->AttributeID =
4867             h2b16(IBCM_INCOMING_SIDR_REP + IBCM_ATTR_BASE_ID);
4868 
4869         /*
4870          * Initialize SIDR REP message. (Other fields were
4871          * already filled up in ibcm_sidr_req_ud_handler()
4872          */
4873         sidr_repp->sidr_rep_request_id = h2b32(ud_statep->ud_req_id);
4874         tmp_svc_id = h2b64(ud_statep->ud_svc_id);
4875         bcopy(&tmp_svc_id, sidr_repp->sidr_rep_service_id, sizeof (tmp_svc_id));
4876 
4877         sidr_repp->sidr_rep_rep_status = (uint8_t)status;
4878 
4879         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sidr_repp))
4880 
4881         /* post the SIDR REP MAD */
4882         ibcm_post_ud_mad(ud_statep, ud_statep->ud_stored_msg, NULL, NULL);
4883 
4884         timer_value = ibt_ib2usec(ibcm_max_sidr_rep_store_time);
4885         /*
4886          * Hold the statep lock, as a SIDR REQ may come in after setting state
4887          * but before timeout. This can result in a dangling timeout ie.,
4888          * the incoming SIDR REQ would be unable to cancel this timeout
4889          */
4890         mutex_enter(&ud_statep->ud_state_mutex);
4891 
4892         ud_statep->ud_remaining_retry_cnt = 1;
4893         ud_statep->ud_timer_value = timer_value;
4894 
4895         ud_statep->ud_timer_stored_state = ud_statep->ud_state =
4896             IBCM_STATE_SIDR_REP_SENT;
4897         ud_statep->ud_timerid = IBCM_UD_TIMEOUT(ud_statep,
4898             ud_statep->ud_timer_value);
4899 
4900         mutex_exit(&ud_statep->ud_state_mutex);


5041 /*
5042  * ibcm_build_reply_mad_addr:
5043  *      Forms the reply MAD address based on "incoming mad addr" that is
5044  *      supplied as an arg.
5045  *
5046  *      Swaps the source and destination gids in ib_grh_t
5047  *
5048  * INPUTS:
5049  * inp_mad_addr:        Address information in the incoming MAD
5050  * out_mad_addr:        Derived address for the reply MAD
5051  *                      The reply MAD address is derived based
5052  *                      address information of incoming CM MAD
5053  * RETURN VALUE: NONE
5054  */
5055 void
5056 ibcm_build_reply_mad_addr(ibcm_mad_addr_t *inp_mad_addr,
5057     ibcm_mad_addr_t *out_mad_addr)
5058 {
5059         IBTF_DPRINTF_L5(cmlog, "ibcm_build_reply_mad_addr:");
5060 
5061         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*out_mad_addr))
5062 
5063         bcopy(inp_mad_addr, out_mad_addr, sizeof (ibcm_mad_addr_t));
5064 
5065         /* Swap the GIDs in the GRH */
5066         if (inp_mad_addr->grh_exists == B_TRUE) {
5067                 ib_gid_t sgid = inp_mad_addr->grh_hdr.ig_sender_gid;
5068 
5069                 /* swap the SGID and DGID */
5070                 out_mad_addr->grh_hdr.ig_sender_gid =
5071                     inp_mad_addr->grh_hdr.ig_recver_gid;
5072                 out_mad_addr->grh_hdr.ig_recver_gid = sgid;
5073         }
5074 
5075         /*
5076          * CM posts response MAD on a new/existing internal QP on the same port
5077          * and pkey
5078          */
5079         out_mad_addr->cm_qp_entry =
5080             ibcm_find_qp(inp_mad_addr->cm_qp_entry->qp_port->port_hcap,
5081             inp_mad_addr->port_num, inp_mad_addr->rcvd_addr.ia_p_key);
5082 
5083         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*out_mad_addr))
5084 }
5085 
5086 
5087 /*
5088  * ibcm_post_rc_mad
5089  *      Posts a CM MAD associated with a RC statep
5090  *
5091  * INPUTS:
5092  * statep       : RC statep associated with the post
5093  * msgp         : CM MAD to be posted
5094  * post_cb      : non-NULL callback address implies non-blocking post
5095  * args         : Args to ibmf send callback
5096  *
5097  * RETURN VALUE: based on ibmf_send_mad
5098  */
5099 void
5100 ibcm_post_rc_mad(ibcm_state_data_t *statep, ibmf_msg_t *msgp,
5101     ibmf_msg_cb_t post_cb, void *args)
5102 {
5103         ibt_status_t    status;


6256 
6257         ibcm_insert_trace(statep, IBCM_TRACE_CALLED_REQ_RCVD_EVENT);
6258 
6259         /* Invoke the client handler */
6260         statep->req_msgp = cm_req_msgp;
6261         cb_status = statep->cm_handler(statep->state_cm_private, &event,
6262             &ret_args, priv_data, IBT_REP_PRIV_DATA_SZ);
6263         statep->req_msgp = NULL;
6264 
6265         ibcm_insert_trace(statep, IBCM_TRACE_RET_REQ_RCVD_EVENT);
6266 
6267         mutex_enter(&ibcm_svc_info_lock);
6268         IBCM_SVC_DECR(statep->state_svc_infop);
6269         mutex_exit(&ibcm_svc_info_lock);
6270 
6271         IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_req: Client handler returned %d"
6272             " statep 0x%p", cb_status, statep);
6273 
6274         if (cb_status == IBT_CM_DEFER) {
6275 
6276                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg))
6277 
6278                 if (statep->defer_cm_msg == NULL)
6279                         statep->defer_cm_msg =
6280                             kmem_zalloc(IBCM_MSG_SIZE, KM_SLEEP);
6281                 bcopy(cm_req_msgp, statep->defer_cm_msg, IBCM_MSG_SIZE);
6282 
6283                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg))
6284 
6285                 /*
6286                  * unblock any blocked cm proceed api calls. Do not access
6287                  * statep after cv_signal
6288                  */
6289                 mutex_enter(&statep->state_mutex);
6290                 statep->clnt_proceed = IBCM_UNBLOCK;
6291                 cv_broadcast(&statep->block_client_cv);
6292                 mutex_exit(&statep->state_mutex);
6293 
6294                 kmem_free(priv_data, IBT_MAX_PRIV_DATA_SZ);
6295                 return (IBCM_DEFER);
6296         }
6297 
6298         /* fail any blocked cm proceed api call - client bug */
6299         mutex_enter(&statep->state_mutex);
6300         statep->clnt_proceed = IBCM_FAIL;
6301         cv_broadcast(&statep->block_client_cv);
6302         mutex_exit(&statep->state_mutex);
6303 
6304         clnt_info.reply_event = (ibt_cm_proceed_reply_t *)&ret_args.cm_ret;


6342                 *reject_reason = IBT_CM_CONSUMER;
6343         } else if (cb_status == IBT_CM_REDIRECT_PORT) {
6344                 *reject_reason = IBT_CM_PORT_REDIRECT;
6345         } else if (cb_status == IBT_CM_REDIRECT) {
6346                 *reject_reason = IBT_CM_REDIRECT_CM;
6347         } else if (cb_status == IBT_CM_NO_CHANNEL) {
6348                 *reject_reason = IBT_CM_NO_CHAN;
6349         } else if (cb_status == IBT_CM_NO_RESOURCE) {
6350                 *reject_reason = IBT_CM_NO_RESC;
6351         } else {
6352                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: statep %p"
6353                     " Client handler unexpected return %x", statep, cb_status);
6354                 *reject_reason = IBT_CM_CONSUMER;
6355         }
6356 
6357         /* client handler gave CM ok */
6358         if (cb_status == IBT_CM_ACCEPT) {
6359                 ibcm_rep_msg_t  *rep_msgp = (ibcm_rep_msg_t *)
6360                     IBCM_OUT_MSGP(statep->stored_msg);
6361 
6362 
6363                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
6364                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rep_msgp))
6365 
6366                 /*
6367                  * Check first if ret_args make sense. If not, bailout
6368                  * here rather than going along and panicing later.
6369                  */
6370                 channel = clnt_info->reply_event->rep.cm_channel;
6371                 if (IBCM_INVALID_CHANNEL(channel)) {
6372                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6373                             "statep 0x%p server's QP handle is NULL", statep);
6374                         *reject_reason = IBT_CM_NO_CHAN;
6375                 }
6376 
6377                 IBCM_GET_CHAN_PRIVATE(channel, old_statep);
6378 
6379                 if ((*reject_reason == IBT_CM_SUCCESS) &&
6380                     (old_statep != NULL)) {
6381                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6382                             "statep 0x%p Channel being re-used on passive side",
6383                             statep);
6384                         *reject_reason = IBT_CM_NO_CHAN;
6385                 }


6630                         if (status == IBT_SUCCESS) {
6631                                 rep_msgp->rep_local_eecn_plus =
6632                                     h2b32(((uint32_t)eec_attrs.eec_eecn << 8));
6633                         }
6634                 }
6635 #endif
6636 
6637                 /* figure out Target ACK delay */
6638                 rep_msgp->rep_target_delay_plus |= (status == IBT_SUCCESS) ?
6639                     statep->hcap->hca_ack_delay << 3 : 0;
6640 
6641                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_req_cm_hdlr:statep %p "
6642                     "REP priv len %x", statep, clnt_info->priv_data_len);
6643                 /* Copy PrivateData from priv_data */
6644                 if (clnt_info->priv_data_len != 0) {
6645                         bcopy(clnt_info->priv_data, rep_msgp->rep_private_data,
6646                             min(IBT_REP_PRIV_DATA_SZ,
6647                             clnt_info->priv_data_len));
6648                 }
6649 
6650                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
6651                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rep_msgp))
6652 
6653                 return (IBCM_SEND_REP);
6654         }
6655 
6656         /* REJ message */
6657         rej_msgp = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
6658 
6659         IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_req_cm_hdlr: statep %p REJ "
6660             "priv len %x", statep, clnt_info->priv_data_len);
6661 
6662         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msgp))
6663 
6664         /* if priv_data_len != 0 use priv_data to copy back to rej_priv_data */
6665         if (clnt_info->priv_data_len != 0) {
6666                 bcopy(clnt_info->priv_data, rej_msgp->rej_private_data,
6667                     min(IBT_REJ_PRIV_DATA_SZ, clnt_info->priv_data_len));
6668         }
6669 
6670         if (cb_status == IBT_CM_REDIRECT_PORT) {
6671                 ib_gid_t tgid;
6672 
6673                 tgid.gid_guid =
6674                     h2b64(clnt_info->reply_event->rej.ari_gid.gid_guid);
6675                 tgid.gid_prefix =
6676                     h2b64(clnt_info->reply_event->rej.ari_gid.gid_prefix);
6677 
6678                 *arej_len = sizeof (ib_gid_t);
6679                 bcopy(&tgid, &rej_msgp->rej_addl_rej_info, sizeof (ib_gid_t));
6680 
6681                 IBTF_DPRINTF_L3(cmlog, "ibcm_process_cep_req_cm_hdlr: ari_gid= "
6682                     "%llX:%llX", tgid.gid_prefix, tgid.gid_guid);
6683 


6701 
6702                 /*
6703                  * RDMA IP REQ was passed up to the ULP, the ULP decided to do
6704                  * a "normal" consumer REJ, by the returning IBT_CM_REJECT in
6705                  * the cm handler.
6706                  * CM has to do some extra stuff too, it has to
6707                  * a) return REJ code 28 (consumer) and b) put 0x1 in the first
6708                  * byte of the ARI data, to indicate that this is a RDMA aware
6709                  * ULP that is doing a consumer reject.  The ULP should have
6710                  * put its consumer specific data into ibt_arej_info_t(9s) at
6711                  * byte 1 of the rej_ari[] array.
6712                  */
6713                 if (((statep->svcid & IB_SID_IPADDR_PREFIX_MASK) == 0) &&
6714                     (statep->svcid & IB_SID_IPADDR_PREFIX)) {
6715                         rej_msgp->rej_addl_rej_info[0] = 1;
6716                 }
6717         }
6718 
6719         rej_msgp->rej_msg_type_plus = IBT_CM_FAILURE_REQ << 6;
6720 
6721         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msgp))
6722 
6723         return (IBCM_SEND_REJ);
6724 }
6725 
6726 /*
6727  * ibcm_cep_state_rep:
6728  *      QP state transition function called for an incoming REP on active side
6729  *
6730  * INPUTS:
6731  *      statep          - state pointer
6732  *      cm_rep_msg      - REP message pointer
6733  *      reject_reason   - Rejection reason See Section 12.6.7.2 rev1.0a IB Spec
6734  *
6735  * RETURN VALUE:
6736  */
6737 ibcm_status_t
6738 ibcm_cep_state_rep(ibcm_state_data_t *statep, ibcm_rep_msg_t *cm_rep_msgp,
6739     ibt_cm_reason_t *reject_reason, uint8_t *arej_len)
6740 {
6741         void                    *priv_data = NULL;
6742         ibcm_status_t           rval = IBCM_SEND_RTU;


6881 
6882 
6883         /* We come here if status is ACCEPT or CM handler is NULL */
6884         if (cb_status == IBT_CM_ACCEPT) {
6885                 ib_time_t       time;
6886 
6887                 time = ibt_usec2ib(statep->pkt_life_time * 2 +
6888                     ibt_ib2usec(cm_rep_msgp->rep_target_delay_plus >> 3));
6889 
6890                 IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p"
6891                     " active cep_timeout(usec) 0x%x ", statep, time);
6892 
6893                 IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p"
6894                     " passive hca_ack_delay(ib_time) = 0x%x, ", statep,
6895                     cm_rep_msgp->rep_target_delay_plus >> 3);
6896 
6897                 IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p"
6898                     " rnr_retry_cnt = 0x%x", statep,
6899                     cm_rep_msgp->rep_rnr_retry_cnt_plus >> 5);
6900 
6901                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
6902                 statep->starting_psn =
6903                     b2h32(cm_rep_msgp->rep_starting_psn_plus) >> 8;
6904 
6905                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
6906 
6907                 /* Call IBTL CM's qp modify function from Init to RTR */
6908                 if (ibcm_invoke_qp_modify(statep,
6909                     (ibcm_req_msg_t *)IBCM_OUT_MSGP(statep->stored_msg),
6910                     cm_rep_msgp) != IBT_SUCCESS) {
6911 
6912                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_rep_cm_hdlr: "
6913                             "statep %p, ibcm_invoke_qp_modify to RTR failed",
6914                             statep);
6915                         *reject_reason = IBT_CM_NO_RESC;
6916                 /*
6917                  * Call modify qp function from RTR to RTS
6918                  * RDMA initiator depth on active is same as negotiated
6919                  * passive REP's responder resources
6920                  */
6921                 } else if (ibcm_invoke_rtu_qp_modify(statep, time, cm_rep_msgp)
6922                     != IBT_SUCCESS) {
6923 
6924                         IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_rep_cm_hdlr: "
6925                             "statep %p ibcm_invoke_rtu_qp_modify to RTS failed",
6926                             statep);


6934                         IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
6935 
6936                         ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6937                             IBT_CM_FAILURE_REP, IBT_CM_CI_FAILURE, NULL, 0);
6938                         return (IBCM_SEND_REJ); /* send REJ */
6939                 }
6940 
6941                 if (clnt_info->priv_data_len != 0) {
6942                         ibcm_rtu_msg_t *rtu_msgp;
6943                         rtu_msgp = (ibcm_rtu_msg_t *)
6944                             IBCM_OUT_MSGP(statep->stored_msg);
6945                         bcopy(clnt_info->priv_data, rtu_msgp->rtu_private_data,
6946                             min(IBT_RTU_PRIV_DATA_SZ,
6947                             clnt_info->priv_data_len));
6948                 }
6949 
6950                 *reject_reason = IBT_CM_SUCCESS;
6951                 return (rval);
6952         }
6953 
6954         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msgp))
6955 
6956         /* Fill up the REJ fields, from ret_args */
6957         rej_msgp = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
6958         rej_msgp->rej_msg_type_plus = IBT_CM_FAILURE_REP << 6;
6959 
6960         /* if priv_len != 0 use priv_data to copy back to rej_priv_data */
6961         if (clnt_info->priv_data_len != 0)
6962                 bcopy(clnt_info->priv_data, rej_msgp->rej_private_data,
6963                     min(IBT_REJ_PRIV_DATA_SZ, clnt_info->priv_data_len));
6964 
6965         if (clnt_info->reply_event != NULL)
6966                 *arej_len =
6967                     min(clnt_info->reply_event->rej.ari_consumer.rej_ari_len,
6968                     IBT_CM_ADDL_REJ_LEN);
6969 
6970         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(clnt_info->reply_event->rej))
6971 
6972         if (*arej_len != 0)     /* asserts that clnt_info->reply_event != 0 */
6973                 bcopy(clnt_info->reply_event->rej.ari_consumer.rej_ari,
6974                     &rej_msgp->rej_addl_rej_info, *arej_len);
6975 
6976         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(clnt_info->reply_event->rej))
6977 
6978         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msgp))
6979 
6980         rval = IBCM_SEND_REJ;
6981 
6982         /* Disassociate statep and QP */
6983         IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
6984 
6985         /* callback client, to enable client to do resource cleanup */
6986         ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6987             IBT_CM_FAILURE_REP, *reject_reason, NULL, 0);
6988 
6989         return (rval);
6990 }
6991 
6992 /*
6993  * ibcm_invoke_rtu_qp_modify:
6994  *      Helper function to modify QP for RTU only called from
6995  *      ibcm_cep_state_rtu() and ibcm_cep_send_rtu()
6996  *
6997  * INPUTS:
6998  *      statep          - connection state pointer
6999  *


7335                 bcopy(&event.cm_event.failed.cf_additional,
7336                     &statep->open_return_data->rc_arej_info,
7337                     sizeof (ibt_arej_info_t));
7338         if (ibcm_enable_trace != 0)
7339                 ibcm_dump_conn_trace(statep);
7340         mutex_enter(&statep->state_mutex);
7341         ibcm_open_done(statep);
7342         mutex_exit(&statep->state_mutex);
7343 }
7344 
7345 /* Used to initialize client args with addl rej information from REJ MAD */
7346 static void
7347 ibcm_copy_addl_rej(ibcm_state_data_t *statep, ibcm_rej_msg_t *rej_msgp,
7348     ibt_cm_conn_failed_t *failed)
7349 {
7350         uint16_t        rej_reason = b2h16(rej_msgp->rej_rejection_reason);
7351         uint8_t         ari_len = rej_msgp->rej_reject_info_len_plus >> 1;
7352         ibcm_classportinfo_msg_t tclp;
7353         ibt_arej_info_t *cf_addl = &failed->cf_additional;
7354 
7355         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cf_addl))
7356         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(failed->cf_arej_info_valid))
7357 
7358         failed->cf_arej_info_valid = B_FALSE;
7359 
7360         IBTF_DPRINTF_L3(cmlog, "ibcm_copy_addl_rej: rej_reason = %d "
7361             "ari_len = %d", rej_reason, ari_len);
7362 
7363         if ((statep->mode == IBCM_PASSIVE_MODE) &&
7364             (rej_reason != IBT_CM_CONSUMER))
7365                 return;
7366 
7367         switch (rej_reason) {
7368         case IBT_CM_PRIM_GID:
7369         case IBT_CM_ALT_GID:
7370         case IBT_CM_PORT_REDIRECT:
7371                 if (ari_len < sizeof (ib_gid_t))
7372                         break;
7373                 failed->cf_arej_info_valid = B_TRUE;
7374                 bcopy(rej_msgp->rej_addl_rej_info, &cf_addl->ari_gid,
7375                     sizeof (ib_gid_t));
7376                 cf_addl->ari_gid.gid_guid = b2h64(cf_addl->ari_gid.gid_guid);
7377                 cf_addl->ari_gid.gid_prefix =


7444                         break;
7445                 failed->cf_arej_info_valid = B_TRUE;
7446                 if (ari_len > IBT_CM_ADDL_REJ_LEN)
7447                         ari_len = IBT_CM_ADDL_REJ_LEN;
7448                 bcopy(&rej_msgp->rej_addl_rej_info,
7449                     cf_addl->ari_consumer.rej_ari, ari_len);
7450                 cf_addl->ari_consumer.rej_ari_len = ari_len;
7451                 break;
7452         case IBT_CM_INVALID_PRIM_FLOW:
7453         case IBT_CM_INVALID_ALT_FLOW:
7454                 if (ari_len < 3)     /* 3 bytes needed for 20 bits */
7455                         break;
7456                 failed->cf_arej_info_valid = B_TRUE;
7457                 /* take the first 20 bits */
7458                 cf_addl->ari_flow =
7459                     b2h32(*(uint32_t *)&rej_msgp->rej_addl_rej_info) >> 12;
7460                 break;
7461         default:
7462                 break;
7463         }
7464 
7465         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(failed->cf_arej_info_valid))
7466         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cf_addl))
7467 }
7468 
7469 
7470 /* Used to copy classportinfo to MAD from client initialized args */
7471 static void
7472 ibcm_init_clp_to_mad(ibcm_classportinfo_msg_t *clp, ibt_redirect_info_t *rinfo)
7473 {
7474 
7475         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*clp))
7476 
7477         bcopy(&ibcm_clpinfo, clp, sizeof (ibcm_clpinfo));
7478 
7479         clp->RedirectGID_hi = h2b64(rinfo->rdi_gid.gid_prefix);
7480         clp->RedirectGID_lo = h2b64(rinfo->rdi_gid.gid_guid);
7481         clp->RedirectTC_plus =
7482             h2b32((rinfo->rdi_tclass << 24) | (rinfo->rdi_sl << 20) |
7483             (rinfo->rdi_flow & 0xfffff));
7484         clp->RedirectLID = h2b16(rinfo->rdi_dlid);
7485         clp->RedirectQP_plus = h2b32(rinfo->rdi_qpn & 0xffffff);
7486         clp->RedirectQ_Key = h2b32(rinfo->rdi_qkey);
7487         clp->RedirectP_Key = h2b16(rinfo->rdi_pkey);
7488 
7489         IBTF_DPRINTF_L4(cmlog, "ibcm_init_clp_to_mad: RedirectGID= %llX:%llX,"
7490             " RedirectLID= 0x%lX", clp->RedirectGID_hi, clp->RedirectGID_lo,
7491             clp->RedirectLID);
7492 
7493         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*clp))
7494 }
7495 
7496 
7497 /* Used to initialize classportinfo to be returned to clients, from MAD */
7498 static void
7499 ibcm_init_clp_from_mad(ibcm_classportinfo_msg_t *clp,
7500     ibt_redirect_info_t *rinfo)
7501 {
7502         uint32_t temp32;
7503 
7504         rinfo->rdi_gid.gid_prefix = b2h64(clp->RedirectGID_hi);
7505         rinfo->rdi_gid.gid_guid = b2h64(clp->RedirectGID_lo);
7506         temp32 = b2h32(clp->RedirectTC_plus);
7507         rinfo->rdi_tclass = temp32 >> 24;
7508         rinfo->rdi_sl = (temp32 >> 20) & 0xf;
7509         rinfo->rdi_flow = temp32 & 0xffff;
7510         rinfo->rdi_dlid = b2h16(clp->RedirectLID);
7511         rinfo->rdi_qpn = b2h32(clp->RedirectQP_plus & 0xffffff);
7512         rinfo->rdi_qkey = b2h32(clp->RedirectQ_Key);
7513         rinfo->rdi_pkey = b2h16(clp->RedirectP_Key);


7709                     min(ud_clnt_info->priv_data_len,
7710                     IBT_SIDR_REP_PRIV_DATA_SZ));
7711         }
7712 
7713         if (*sidr_status != IBT_CM_SREP_CHAN_VALID) {
7714                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_req_cm_hdlr: "
7715                     "ud_handler return a failure: %d", cb_status);
7716                 if (*sidr_status == IBT_CM_SREP_REDIRECT) {
7717                 /*
7718                  * typecasting to ibcm_classportinfo_msg_t is ok, as addl info
7719                  * begins at offset 24 in sidr rep
7720                  */
7721                         ibcm_init_clp_to_mad(
7722                             (ibcm_classportinfo_msg_t *)
7723                             &sidr_repp->sidr_rep_class_port_info,
7724                             ud_clnt_info->redirect_infop);
7725                 }
7726                 return;
7727         }
7728 
7729 
7730         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_repp))
7731 
7732         sidr_repp->sidr_rep_qkey =
7733             h2b32(ud_clnt_info->ud_qkey);
7734         sidr_repp->sidr_rep_qpn_plus = h2b32(ud_clnt_info->ud_qpn << 8);
7735 
7736         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_repp))
7737 }
7738 
7739 /*
7740  * ibcm_sidr_rep_ud_handler:
7741  *      Invoke Client's UD handler For SIDR_REP msg
7742  *
7743  * INPUTS:
7744  *      ud_statep       - ud_state pointer
7745  *      sidr_rep_msgp   - SIDR_REQ message pointer
7746  *
7747  */
7748 static void
7749 ibcm_sidr_rep_ud_handler(ibcm_ud_state_data_t *ud_statep,
7750     ibcm_sidr_rep_msg_t *sidr_rep_msgp)
7751 {
7752         ibt_cm_ud_event_t       ud_event;
7753 
7754         IBTF_DPRINTF_L5(cmlog, "ibcm_sidr_rep_ud_handler: ud_statep 0x%p",
7755             ud_statep);
7756 


7960  *
7961  * INPUTS:
7962  *      statep          - pointer to ibcm_state_data_t
7963  *      lap_msg         - lap msg received
7964  *      apr_msg         - apr msg to be sent
7965  *
7966  * RETURN VALUE: NONE
7967  */
7968 ibcm_status_t
7969 ibcm_cep_state_lap(ibcm_state_data_t *statep, ibcm_lap_msg_t *lap_msg,
7970     ibcm_apr_msg_t *apr_msg)
7971 {
7972         ibt_cm_event_t          event;
7973         ibt_cm_return_args_t    ret_args;
7974         ibt_cm_status_t         cb_status;
7975         ibcm_clnt_reply_info_t  clnt_info;
7976 
7977 
7978         IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_lap: statep 0x%p", statep);
7979 
7980         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*apr_msg))
7981 
7982         /* If APM is not supported, return error */
7983         if (!(statep->hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG)) {
7984                 apr_msg->apr_ap_status = IBT_CM_AP_NOT_SUPPORTED;
7985                 return (IBCM_SEND_APR);
7986         }
7987 
7988         if (statep->local_qpn !=
7989             b2h32(lap_msg->lap_remote_qpn_eecn_plus) >> 8) {
7990                 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
7991                 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_lap: local_qpn %x does "
7992                     "not match remote's remote_qpn %x", statep->local_qpn,
7993                     b2h32(lap_msg->lap_remote_qpn_eecn_plus) >> 8);
7994                 return (IBCM_SEND_APR);
7995         }
7996 
7997         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*apr_msg))
7998 
7999         /* Fill up the event */
8000         bzero(&event, sizeof (event));
8001         event.cm_type = IBT_CM_EVENT_LAP_RCV;
8002         event.cm_channel = statep->channel;
8003         event.cm_session_id = statep;
8004         event.cm_priv_data = lap_msg->lap_private_data;
8005         event.cm_priv_data_len =  IBT_LAP_PRIV_DATA_SZ;
8006         event.cm_event.lap.lap_timeout = ibt_ib2usec(
8007             ((uint8_t *)&lap_msg->lap_remote_qpn_eecn_plus)[3] >> 3);
8008 
8009         ibcm_fill_adds_from_lap(&event.cm_event.lap.lap_alternate_path,
8010             lap_msg, IBCM_PASSIVE_MODE);
8011 
8012         cb_status = statep->cm_handler(statep->state_cm_private, &event,
8013             &ret_args, apr_msg->apr_private_data, IBT_APR_PRIV_DATA_SZ);
8014 
8015         IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_lap: cb_status = %d", cb_status);
8016         if (cb_status == IBT_CM_DEFER) {
8017 
8018                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg))
8019 
8020                 if (statep->defer_cm_msg == NULL)
8021                         statep->defer_cm_msg =
8022                             kmem_zalloc(IBCM_MSG_SIZE, KM_SLEEP);
8023                 bcopy(lap_msg, statep->defer_cm_msg, IBCM_MSG_SIZE);
8024 
8025                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg))
8026 
8027                 /* unblock any blocked cm proceed api calls */
8028                 mutex_enter(&statep->state_mutex);
8029                 statep->clnt_proceed = IBCM_UNBLOCK;
8030                 cv_broadcast(&statep->block_client_cv);
8031                 mutex_exit(&statep->state_mutex);
8032 
8033                 return (IBCM_DEFER);
8034         }
8035 
8036         clnt_info.reply_event = (ibt_cm_proceed_reply_t *)&ret_args.cm_ret;
8037         clnt_info.priv_data = NULL;
8038         clnt_info.priv_data_len = 0;
8039 
8040         ibcm_process_cep_lap_cm_hdlr(statep, cb_status, &clnt_info, lap_msg,
8041             apr_msg);
8042         return (IBCM_SEND_APR);
8043 }
8044 
8045 /*
8046  * ibcm_fill_adds_from_lap:


8103 
8104 /*
8105  * ibcm_process_cep_lap_cm_hdlr:
8106  * Processes the cm handler response for an incoming LAP.
8107  */
8108 
8109 void
8110 ibcm_process_cep_lap_cm_hdlr(ibcm_state_data_t *statep,
8111     ibt_cm_status_t cb_status, ibcm_clnt_reply_info_t *clnt_info,
8112     ibcm_lap_msg_t *lap_msg, ibcm_apr_msg_t *apr_msg)
8113 {
8114         ibtl_cm_hca_port_t      port;
8115         ibt_qp_query_attr_t     qp_attrs;
8116         ibt_cep_modify_flags_t  cep_flags;
8117         ibt_status_t            status;
8118         ibt_adds_vect_t         *adds;
8119 
8120         if (cb_status == IBT_CM_DEFAULT)
8121                 cb_status = IBT_CM_REJECT;
8122 
8123         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*apr_msg))
8124 
8125         /* verify status */
8126         apr_msg->apr_addl_info_len = 0;
8127         if (cb_status == IBT_CM_ACCEPT) {
8128                 apr_msg->apr_ap_status = IBT_CM_AP_LOADED;
8129         } else if (cb_status == IBT_CM_REJECT) {
8130                 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8131         } else if (cb_status == IBT_CM_REDIRECT) {
8132                 apr_msg->apr_ap_status = IBT_CM_AP_REDIRECT;
8133                 /* copy redirect info to APR */
8134                 apr_msg->apr_addl_info_len = sizeof (ibcm_classportinfo_msg_t);
8135                 ibcm_init_clp_to_mad(
8136                     (ibcm_classportinfo_msg_t *)apr_msg->apr_addl_info,
8137                     &clnt_info->reply_event->apr);
8138         } else if (cb_status == IBT_CM_NO_RESOURCE) {
8139                 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8140         } else {
8141                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep %p"
8142                     " Client handler unexpected return %x", statep, cb_status);
8143                 cb_status = IBT_CM_REJECT;
8144                 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;


8215         status = ibt_modify_qp(statep->channel, cep_flags, &qp_attrs.qp_info,
8216             NULL);
8217 
8218         if (status != IBT_SUCCESS) {
8219                 ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT_FAIL);
8220         } else
8221                 ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT);
8222 
8223 #ifdef  DEBUG
8224         (void) ibt_query_qp(statep->channel, &qp_attrs);
8225         print_modify_qp("PASSIVE LAP QUERY", statep->channel,
8226             cep_flags, &qp_attrs.qp_info);
8227 #endif
8228 
8229         if (status != IBT_SUCCESS) {
8230                 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8231                 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr:"
8232                     " ibt_modify_qp() returned = %d", status);
8233                 return;
8234         }
8235         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*apr_msg))
8236 }
8237 
8238 
8239 /*
8240  * ibcm_post_apr_mad:
8241  *      Posts a APR MAD and starts timer
8242  *
8243  * INPUTS:
8244  *      statep          - state pointer
8245  *
8246  * RETURN VALUE: NONE
8247  */
8248 void
8249 ibcm_post_apr_mad(ibcm_state_data_t *statep)
8250 {
8251         ibcm_apr_msg_t  *apr_msgp;
8252 
8253         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*apr_msgp))
8254 
8255         apr_msgp = (ibcm_apr_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg);
8256 
8257         apr_msgp->apr_local_comm_id = h2b32(statep->local_comid);
8258         apr_msgp->apr_remote_comm_id = h2b32(statep->remote_comid);
8259         IBCM_OUT_HDRP(statep->lapr_msg)->AttributeID =
8260             h2b16(IBCM_INCOMING_APR + IBCM_ATTR_BASE_ID);
8261 
8262         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*apr_msgp))
8263 
8264         ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_APR);
8265 
8266         ibcm_post_rc_mad(statep, statep->lapr_msg, ibcm_post_apr_complete,
8267             statep);
8268 }
8269 
8270 /*
8271  * ibcm_process_apr_msg:
8272  *      This call processes an incoming APR message
8273  *
8274  * INPUTS:
8275  *      hcap            - HCA entry pointer
8276  *      input_madp      - incoming CM SIDR REP MAD
8277  *      cm_mad_addr     - Address information for the MAD to be posted
8278  *
8279  * RETURN VALUE: NONE
8280  */
8281 /*ARGSUSED*/
8282 void
8283 ibcm_process_apr_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,


8356 
8357         /* wake up blocking ibt_set_alt_path */
8358         cv_broadcast(&statep->block_client_cv);
8359 
8360         IBCM_REF_CNT_DECR(statep); /* decrement the ref count */
8361         mutex_exit(&statep->state_mutex);
8362 }
8363 
8364 static void
8365 ibcm_set_apr_arej(int ap_status, ibcm_apr_msg_t *apr_msgp,
8366     ibt_arej_info_t *ari, boolean_t *ari_valid)
8367 {
8368         uint8_t ari_len = apr_msgp->apr_addl_info_len;
8369         ibcm_classportinfo_msg_t tclp;
8370 
8371         *ari_valid = B_FALSE;
8372 
8373         IBTF_DPRINTF_L3(cmlog, "ibcm_set_apr_arej: apr_status = %d "
8374             "ari_len = %d", ap_status, ari_len);
8375 
8376         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ari))
8377 
8378         switch (ap_status) {
8379         case IBT_CM_AP_REDIRECT:
8380                 if (ari_len < sizeof (ibcm_classportinfo_msg_t))
8381                         break;
8382                 *ari_valid = B_TRUE;
8383                 bcopy(apr_msgp->apr_addl_info, &tclp, sizeof (tclp));
8384                 ibcm_init_clp_from_mad(&tclp, &ari->ari_redirect);
8385                 break;
8386         case IBT_CM_AP_RLID_REJECTED:
8387                 if (ari_len < sizeof (ib_lid_t))
8388                         break;
8389                 *ari_valid = B_TRUE;
8390                 bcopy(apr_msgp->apr_addl_info, &ari->ari_lid,
8391                     sizeof (ib_lid_t));
8392                 ari->ari_lid = b2h16(ari->ari_lid);
8393                 break;
8394         case IBT_CM_AP_RGID_REJECTED:
8395                 if (ari_len < sizeof (ib_gid_t))
8396                         break;
8397                 *ari_valid = B_TRUE;


8425                 /* take the first byte */
8426                 ari->ari_hop = apr_msgp->apr_addl_info[0];
8427                 break;
8428         case IBT_CM_AP_RATE_REJECTED:
8429                 if (ari_len < 1)
8430                         break;
8431                 *ari_valid = B_TRUE;
8432                 /* take the first 6 bits */
8433                 ari->ari_rate = apr_msgp->apr_addl_info[0] >> 2;
8434                 break;
8435         case IBT_CM_AP_SL_REJECTED:
8436                 if (ari_len < 1)
8437                         break;
8438                 *ari_valid = B_TRUE;
8439                 /* take the first 4 bits */
8440                 ari->ari_sl = apr_msgp->apr_addl_info[0] >> 4;
8441                 break;
8442         default:
8443                 break;
8444         }
8445         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ari))
8446 }
8447 
8448 /*
8449  * ibcm_cep_state_apr:
8450  *      This call processes an incoming APR message
8451  *
8452  * INPUTS:
8453  *      statep          - pointer to ibcm_state_data_t
8454  *      lap_msg         - lap msg sent earlier
8455  *      apr_msg         - apr msg received
8456  *
8457  * RETURN VALUE: NONE
8458  */
8459 void
8460 ibcm_cep_state_apr(ibcm_state_data_t *statep, ibcm_lap_msg_t *lap_msg,
8461     ibcm_apr_msg_t *apr_msg)
8462 {
8463         ibt_cm_event_t          event;
8464         ibcm_status_t           status = IBCM_SUCCESS;
8465         uint8_t                 ap_status = apr_msg->apr_ap_status;


8643  *
8644  * INPUTS:
8645  *      statep  Pointer to ibcm_state_data_t
8646  *
8647  * RETURN VALUE: NONE
8648  *
8649  * This function is called holding state mutex
8650  * This function returns, releasing the state mutex
8651  */
8652 void
8653 ibcm_sync_lapr_idle(ibcm_state_data_t *statep)
8654 {
8655         timeout_id_t    timer_val = statep->timerid;
8656         ibt_cm_event_t  event;
8657 
8658         IBTF_DPRINTF_L3(cmlog, "ibcm_sync_lapr_idle:"
8659             "statep %p state %d ap_state %d", statep, statep->state,
8660             statep->ap_state);
8661 
8662         ASSERT(MUTEX_HELD(&statep->state_mutex));
8663         _NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(&statep->state_mutex))
8664 
8665         /* Busy AP states on active/passive sides */
8666         if ((statep->ap_state == IBCM_AP_STATE_LAP_RCVD) ||
8667             (statep->ap_state == IBCM_AP_STATE_APR_RCVD) ||
8668             (statep->ap_state == IBCM_AP_STATE_MRA_LAP_SENT) ||
8669             (statep->ap_state == IBCM_AP_STATE_TIMED_OUT)) {
8670 
8671                 /* wait till ap_state becomes IBCM_AP_STATE_IDLE */
8672                 while (statep->ap_state != IBCM_AP_STATE_IDLE)
8673                         cv_wait(&statep->block_mad_cv, &statep->state_mutex);
8674 
8675                 mutex_exit(&statep->state_mutex);
8676 
8677         } else if ((statep->ap_state == IBCM_AP_STATE_LAP_SENT) ||
8678             (statep->ap_state == IBCM_AP_STATE_MRA_LAP_RCVD)) {
8679 
8680                 /* fail the client's ibt_set_alt_path */
8681 
8682                 /* blocking ibt_set_alt_path */
8683                 if (statep->ap_return_data != NULL) {




 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  *


 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 


 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 */


 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.


 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 


 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);


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


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,


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 */


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 "


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


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);


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 */


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;


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


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);


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;


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


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: "


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);


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;


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;


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                 }


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 


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;


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);


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  *


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 =


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);


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 


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:


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;


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,


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;


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;


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) {