23 */
24
25 #include <sys/ib/mgt/ibcm/ibcm_impl.h>
26 #include <sys/ib/ibtl/ibti.h>
27 #include <sys/ib/mgt/ibcm/ibcm_arp.h>
28
29 /*
30 * ibcm_ti.c
31 * These routines implement the Communication Manager's interfaces to IBTL.
32 */
33
34 /* CM rc recycle task args structure definition */
35 typedef struct ibcm_taskq_recycle_arg_s {
36 ibt_channel_hdl_t rc_chan;
37 ibt_cep_flags_t control;
38 uint8_t hca_port_num;
39 ibt_recycle_handler_t func;
40 void *arg;
41 } ibcm_taskq_recycle_arg_t;
42
43 _NOTE(READ_ONLY_DATA(ibcm_taskq_recycle_arg_s))
44
45 static ibt_status_t ibcm_init_reply_addr(ibcm_hca_info_t *hcap,
46 ibcm_mad_addr_t *reply_addr, ibt_chan_open_args_t *chan_args,
47 ibt_chan_open_flags_t flags, ib_time_t *cm_pkt_lt, ib_lid_t prim_slid);
48 static void ibcm_process_abort_via_taskq(void *args);
49 static ibt_status_t ibcm_process_rc_recycle_ret(void *recycle_arg);
50 static ibt_status_t ibcm_process_join_mcg(void *taskq_arg);
51 static void ibcm_process_async_join_mcg(void *tq_arg);
52
53 ibt_status_t ibcm_get_node_rec(ibmf_saa_handle_t, sa_node_record_t *,
54 uint64_t c_mask, void *, size_t *);
55
56 static ibt_status_t ibcm_close_rc_channel(ibt_channel_hdl_t channel,
57 ibcm_state_data_t *statep, ibt_execution_mode_t mode);
58
59 /* Address Record management definitions */
60 #define IBCM_DAPL_ATS_NAME "DAPL Address Translation Service"
61 #define IBCM_DAPL_ATS_SID 0x10000CE100415453ULL
62 #define IBCM_DAPL_ATS_NBYTES 16
63 ibcm_svc_info_t *ibcm_ar_svcinfop;
64 ibcm_ar_t *ibcm_ar_list;
65
66 /*
67 * Tunable parameter to turnoff the overriding of pi_path_mtu value.
68 * 1 By default override the path record's pi_path_mtu value to
69 * IB_MTU_1K for all RC channels. This is done only for the
70 * channels established on Tavor HCA and the path's pi_path_mtu
71 * is greater than IB_MTU_1K.
72 * 0 Do not override, use pi_path_mtu by default.
73 */
74 int ibcm_override_path_mtu = 1;
75
76 #ifdef DEBUG
77 static void ibcm_print_reply_addr(ibt_channel_hdl_t channel,
78 ibcm_mad_addr_t *cm_reply_addr);
79 #endif
80
81 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_port_info_s::{port_ibmf_hdl}))
82
83 /* access is controlled between ibcm_sm.c and ibcm_ti.c by CVs */
84 _NOTE(SCHEME_PROTECTS_DATA("Serialized access by CV", {ibt_rc_returns_t
85 ibt_ud_returns_t ibt_ap_returns_t ibt_ar_t}))
86
87 /*
88 * Typically, clients initialize these args in one api call, and use in
89 * another api
90 */
91 _NOTE(SCHEME_PROTECTS_DATA("Expected usage of ibtl api by client",
92 {ibt_path_info_s ibt_cep_path_s ibt_adds_vect_s ibt_mcg_info_s ib_gid_s
93 ibt_ud_dest_attr_s ibt_ud_dest_s ibt_srv_data_s ibt_redirect_info_s}))
94
95 /*
96 * ibt_open_rc_channel()
97 * ibt_open_rc_channel opens a communication channel on the specified
98 * channel to the specified service. For connection service type qp's
99 * the CM initiates the CEP to establish the connection and transitions
100 * the QP/EEC to the "Ready to send" State modifying the QP/EEC's
101 * attributes as necessary.
102 * The implementation of this function assumes that alt path is different
103 * from primary path. It is assumed that the Path functions ensure that.
104 *
105 * RETURN VALUES:
106 * IBT_SUCCESS on success (or respective failure on error)
107 */
108 ibt_status_t
109 ibt_open_rc_channel(ibt_channel_hdl_t channel, ibt_chan_open_flags_t flags,
110 ibt_execution_mode_t mode, ibt_chan_open_args_t *chan_args,
111 ibt_rc_returns_t *ret_args)
112 {
113 /* all fields that are related to REQ MAD formation */
114
115 ib_pkey_t prim_pkey;
559 IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: "
560 "chan 0x%p ibt_modify_qp() = %d", channel, status);
561 }
562
563 /* allocate ibcm_state_data_t before grabbing the WRITER lock */
564 statep = kmem_zalloc(sizeof (ibcm_state_data_t), KM_SLEEP);
565 rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
566 lkup_status = ibcm_lookup_msg(IBCM_OUTGOING_REQ, local_comid, 0, 0,
567 hcap, &statep);
568 rw_exit(&hcap->hca_state_rwlock);
569
570 /* CM should be seeing this for the first time */
571 ASSERT(lkup_status == IBCM_LOOKUP_NEW);
572
573 /* Increment the hca's resource count */
574 ibcm_inc_hca_res_cnt(hcap);
575
576 /* Once a resource created on hca, no need to hold the acc cnt */
577 ibcm_dec_hca_acc_cnt(hcap);
578
579 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
580
581 statep->timerid = 0;
582 statep->local_hca_guid = hca_guid;
583 statep->local_qpn = local_qpn;
584 statep->stored_reply_addr.cm_qp_entry = cm_qp_entry;
585 statep->prim_port = IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num;
586 statep->alt_port = IBCM_ALT_CEP_PATH(chan_args).cep_hca_port_num;
587
588
589 /* Save "statep" as channel's CM private data. */
590 statep->channel = channel;
591 IBCM_SET_CHAN_PRIVATE(statep->channel, statep);
592
593 statep->stored_msg = ibmf_msg;
594 statep->dreq_msg = ibmf_msg_dreq;
595
596 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*req_msgp))
597
598 /* Start filling in the REQ MAD */
599 req_msgp = (ibcm_req_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
600 req_msgp->req_local_comm_id = h2b32(local_comid);
601 req_msgp->req_svc_id = h2b64(chan_args->oc_path->pi_sid);
602 req_msgp->req_local_ca_guid = h2b64(hca_guid);
603 req_msgp->req_local_qkey = h2b32(local_qkey); /* for EEC/RD */
604
605 /* Bytes 32-35 are req_local_qpn and req_off_resp_resources */
606 req_msgp->req_local_qpn_plus = h2b32(local_qpn << 8 | rdma_in);
607
608 /* Bytes 36-39 are req_local_eec_no and req_off_initiator_depth */
609 req_msgp->req_local_eec_no_plus = h2b32(local_eecn << 8 | rdma_out);
610
611 if (flags & IBT_OCHAN_REMOTE_CM_TM)
612 remote_cm_resp_time = chan_args->oc_remote_cm_time;
613 else
614 remote_cm_resp_time = ibcm_remote_response_time;
615
616 /*
617 * Bytes 40-43 - remote_eecn, remote_cm_resp_time, tran_type,
793 IBCM_ALT_ADDS_VECT(chan_args).av_srvl << 4 |
794 ((alternate_grh == B_TRUE) ? 0 : 8);
795 req_msgp->req_alt_localtime_plus = ibt_usec2ib((2 *
796 ibt_ib2usec(chan_args->oc_path->pi_alt_pkt_lt)) +
797 ibt_ib2usec(hcap->hca_ack_delay)) << 3;
798
799 IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
800 "alt_dlid %x ", channel,
801 IBCM_ALT_ADDS_VECT(chan_args).av_dlid);
802
803 IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
804 "alt GID %llX:%llX", channel,
805 IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_prefix,
806 IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_guid);
807 }
808
809 len = min(chan_args->oc_priv_data_len, IBT_REQ_PRIV_DATA_SZ);
810 if ((len > 0) && chan_args->oc_priv_data)
811 bcopy(chan_args->oc_priv_data, req_msgp->req_private_data, len);
812
813 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*req_msgp))
814
815 /* return_data is filled up in the state machine code */
816 if (ret_args != NULL) {
817 statep->open_return_data = ret_args;
818 }
819
820 /* initialize some statep fields here */
821 statep->mode = IBCM_ACTIVE_MODE;
822 statep->hcap = hcap;
823
824 statep->cm_handler = chan_args->oc_cm_handler;
825 statep->state_cm_private = chan_args->oc_cm_clnt_private;
826
827 statep->pkt_life_time =
828 ibt_ib2usec(chan_args->oc_path->pi_prim_pkt_lt);
829
830 statep->timer_value = ibt_ib2usec(ibt_usec2ib(
831 2 * ibt_ib2usec(cm_pkt_lt) + remote_cm_resp_time));
832
833 /* Initialize statep->stored_reply_addr */
834 statep->stored_reply_addr.ibmf_hdl = ibmf_hdl;
854 statep->open_done = B_FALSE;
855 statep->state = statep->timer_stored_state = IBCM_STATE_REQ_SENT;
856 IBCM_REF_CNT_INCR(statep); /* Decremented before return */
857 IBCM_REF_CNT_INCR(statep); /* Decremented after REQ is posted */
858 statep->send_mad_flags |= IBCM_REQ_POST_BUSY;
859
860 /*
861 * Skip moving channel to error state during close, for OFUV clients.
862 * OFUV clients transition the channel to error state by itself.
863 */
864 if (flags & IBT_OCHAN_OFUV)
865 statep->is_this_ofuv_chan = B_TRUE;
866
867 IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
868 h2b16(IBCM_INCOMING_REQ + IBCM_ATTR_BASE_ID);
869
870 IBCM_OUT_HDRP(statep->stored_msg)->TransactionID =
871 h2b64(ibcm_generate_tranid(IBCM_INCOMING_REQ, statep->local_comid,
872 0));
873
874 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
875
876 ibtl_cm_chan_is_opening(channel);
877
878 ibcm_open_enqueue(statep);
879
880 mutex_enter(&statep->state_mutex);
881
882 if (mode == IBT_BLOCKING) {
883
884 /* wait for REQ/REP/RTU */
885 while (statep->open_done != B_TRUE) {
886 cv_wait(&statep->block_client_cv, &statep->state_mutex);
887 }
888
889 /*
890 * In the case that open_channel() fails because of a
891 * REJ or timeout, change retval to IBT_CM_FAILURE
892 */
893 if (statep->open_return_data->rc_status != IBT_CM_SUCCESS) {
894 status = IBT_CM_FAILURE;
895 ibtl_cm_chan_open_is_aborted(channel);
923 * If Redirect GID is not specified or specified to be on the same
924 * subnet, then
925 * Build CM path from chan_args->oc_cm_redirect_info
926 * Set CM pkt lt to subnet timeout
927 * Else (ie., GID specified, but on a different subnet)
928 * Do a path lookup to build CM Path and set CM pkt lt
929 *
930 */
931 static ibt_status_t
932 ibcm_init_reply_addr(ibcm_hca_info_t *hcap, ibcm_mad_addr_t *reply_addr,
933 ibt_chan_open_args_t *chan_args, ibt_chan_open_flags_t flags,
934 ib_time_t *cm_pkt_lt, ib_lid_t prim_slid)
935 {
936 ibt_adds_vect_t *cm_adds;
937 ibt_path_info_t path;
938 boolean_t cm_grh;
939 ibt_status_t status;
940
941 IBTF_DPRINTF_L5(cmlog, "ibcm_init_reply_addr:");
942
943 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*reply_addr))
944
945 /*
946 * sending side CM lid/gid/port num are not based on any redirect
947 * params. These values are set to primary RC path lid/gid/port num.
948 * In the future, these values can be set based on framework policy
949 * decisions ensuring reachability.
950 */
951 reply_addr->grh_hdr.ig_sender_gid =
952 IBCM_PRIM_ADDS_VECT(chan_args).av_sgid;
953 reply_addr->rcvd_addr.ia_local_lid = prim_slid;
954 reply_addr->port_num = IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num;
955
956 if (flags & IBT_OCHAN_PORT_REDIRECTED) {
957 IBTF_DPRINTF_L4(cmlog, "ibcm_init_rely_addr: "
958 "IBT_OCHAN_PORT_REDIRECTED specified");
959
960 status = ibt_index2pkey_byguid(hcap->hca_guid,
961 chan_args->oc_cm_cep_path->cep_hca_port_num,
962 chan_args->oc_cm_cep_path->cep_pkey_ix,
963 &reply_addr->rcvd_addr.ia_p_key);
964
1089 cm_adds = &(IBCM_PRIM_ADDS_VECT(chan_args));
1090 }
1091
1092
1093 cm_grh = cm_adds->av_send_grh;
1094 reply_addr->grh_exists = cm_grh;
1095
1096 reply_addr->rcvd_addr.ia_remote_lid =
1097 cm_adds->av_dlid;
1098 reply_addr->grh_hdr.ig_recver_gid =
1099 cm_adds->av_dgid;
1100 reply_addr->grh_hdr.ig_flow_label =
1101 cm_adds->av_flow & IB_GRH_FLOW_LABEL_MASK;
1102 reply_addr->grh_hdr.ig_tclass =
1103 (cm_grh == B_TRUE) ? cm_adds->av_tclass : 0;
1104 reply_addr->grh_hdr.ig_hop_limit =
1105 (cm_grh == B_TRUE) ? cm_adds->av_hop : 1;
1106 reply_addr->rcvd_addr.ia_service_level =
1107 cm_adds->av_srvl;
1108
1109 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*reply_addr))
1110
1111 return (IBT_SUCCESS);
1112 }
1113
1114
1115 /*
1116 * ibt_prime_close_rc_channel()
1117 * It allocates resources required for close channel operation, so
1118 * ibt_close_rc_channel can be called from interrupt routine.
1119 *
1120 * INPUTS:
1121 * channel The address of an ibt_channel_t struct that
1122 * specifies the channel to open.
1123 *
1124 * RETURN VALUES:
1125 * IBT_SUCCESS on success(or respective failure on error)
1126 *
1127 * Clients are typically expected to call this function in established state
1128 */
1129 ibt_status_t
1130 ibt_prime_close_rc_channel(ibt_channel_hdl_t channel)
1317 ibcm_close_enqueue(statep);
1318 mutex_exit(&statep->state_mutex);
1319
1320 return (IBT_SUCCESS);
1321 }
1322
1323 void
1324 ibcm_close_start(ibcm_state_data_t *statep)
1325 {
1326 mutex_enter(&statep->state_mutex);
1327 (void) ibcm_close_rc_channel(statep->channel, statep, IBT_NONBLOCKING);
1328 }
1329
1330 static
1331 ibt_status_t
1332 ibcm_close_rc_channel(ibt_channel_hdl_t channel, ibcm_state_data_t *statep,
1333 ibt_execution_mode_t mode)
1334 {
1335 ibcm_hca_info_t *hcap;
1336
1337 _NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(&statep->state_mutex));
1338 ASSERT(MUTEX_HELD(&statep->state_mutex));
1339
1340 IBTF_DPRINTF_L3(cmlog, "ibcm_close_rc_channel: chan 0x%p statep %p",
1341 channel, statep);
1342
1343 hcap = statep->hcap;
1344
1345 /* HCA must have been in active state. If not, it's a client bug */
1346 if (!IBCM_ACCESS_HCA_OK(hcap)) {
1347 IBTF_DPRINTF_L2(cmlog, "ibcm_close_rc_channel: chan 0x%p "
1348 "hcap 0x%p not active", channel, hcap);
1349 IBCM_REF_CNT_DECR(statep);
1350 mutex_exit(&statep->state_mutex);
1351 return (IBT_CHAN_HDL_INVALID);
1352 }
1353
1354 if (statep->state == IBCM_STATE_TRANSIENT_ESTABLISHED) {
1355 while (statep->cep_in_rts == IBCM_BLOCK)
1356 cv_wait(&statep->block_mad_cv, &statep->state_mutex);
1357 }
1636 IBTF_DPRINTF_L3(cmlog, "ibt_recycle_rc (%p, 0x%X, %d, %p, %p)", rc_chan,
1637 control, hca_port_num, func, arg);
1638
1639 if (IBCM_INVALID_CHANNEL(rc_chan)) {
1640 IBTF_DPRINTF_L2(cmlog, "ibt_recycle_rc: invalid channel");
1641 return (IBT_CHAN_HDL_INVALID);
1642 }
1643
1644 /* check qp state */
1645 retval = ibt_query_qp(rc_chan, &qp_attr);
1646
1647 if (retval != IBT_SUCCESS)
1648 return (retval);
1649
1650 if (qp_attr.qp_info.qp_trans != IBT_RC_SRV)
1651 return (IBT_CHAN_SRV_TYPE_INVALID);
1652
1653 if (qp_attr.qp_info.qp_state != IBT_STATE_ERROR)
1654 return (IBT_CHAN_STATE_INVALID);
1655
1656 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ibcm_tq_recycle_arg))
1657
1658 ibcm_tq_recycle_arg = kmem_alloc(sizeof (ibcm_taskq_recycle_arg_t),
1659 KM_SLEEP);
1660
1661 ibcm_tq_recycle_arg->rc_chan = rc_chan;
1662 ibcm_tq_recycle_arg->control = control;
1663 ibcm_tq_recycle_arg->hca_port_num = hca_port_num;
1664 ibcm_tq_recycle_arg->func = func;
1665 ibcm_tq_recycle_arg->arg = arg;
1666
1667 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ibcm_tq_recycle_arg))
1668
1669 IBCM_GET_CHAN_PRIVATE(rc_chan, statep);
1670
1671 /*
1672 * If non-blocking ie., func specified and channel has not yet completed
1673 * the timewait, then schedule the work for later
1674 */
1675 if ((func != NULL) && (statep != NULL)) {
1676 IBCM_RELEASE_CHAN_PRIVATE(rc_chan);
1677 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
1678 statep->recycle_arg = ibcm_tq_recycle_arg;
1679 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
1680 return (IBT_SUCCESS);
1681 }
1682
1683 /*
1684 * if blocking ie., func specified, and channel has not yet completed
1685 * the timewait, then block until the channel completes the timewait
1686 */
1687 if (statep != NULL)
1688 IBCM_RELEASE_CHAN_PRIVATE(rc_chan);
1689 IBCM_WAIT_CHAN_PRIVATE(rc_chan);
1690
1691 if (func) { /* NON BLOCKING case. Taskq for QP state change */
1692 (void) taskq_dispatch(ibcm_taskq, ibcm_process_rc_recycle,
1693 ibcm_tq_recycle_arg, TQ_SLEEP);
1694 return (IBT_SUCCESS);
1695 } else /* BLOCKING case */
1696 return (ibcm_process_rc_recycle_ret(ibcm_tq_recycle_arg));
1697 }
1698
1699 void
1785 ibcm_process_abort_via_taskq(void *args)
1786 {
1787 ibcm_state_data_t *statep = (ibcm_state_data_t *)args;
1788
1789 ibcm_process_abort(statep);
1790 mutex_enter(&statep->state_mutex);
1791 IBCM_REF_CNT_DECR(statep);
1792 mutex_exit(&statep->state_mutex);
1793 }
1794
1795 /*
1796 * Local UD CM Handler's private data, used during ibt_request_ud_dest() in
1797 * Non-Blocking mode operations.
1798 */
1799 typedef struct ibcm_local_handler_s {
1800 ibt_cm_ud_handler_t actual_cm_handler;
1801 void *actual_cm_private;
1802 ibt_ud_dest_t *dest_hdl;
1803 } ibcm_local_handler_t;
1804
1805 _NOTE(READ_ONLY_DATA(ibcm_local_handler_s))
1806
1807 /*
1808 * Local UD CM Handler, used when ibt_alloc_ud_dest() is issued in
1809 * NON-Blocking mode.
1810 *
1811 * Out here, we update the UD Destination handle with
1812 * the obtained DQPN and QKey (from SIDR REP) and invokes actual client
1813 * handler that was specified by the client.
1814 */
1815 static ibt_cm_status_t
1816 ibcm_local_cm_handler(void *priv, ibt_cm_ud_event_t *event,
1817 ibt_cm_ud_return_args_t *ret_args, void *priv_data, ibt_priv_data_len_t len)
1818 {
1819 ibcm_local_handler_t *handler_priv = (ibcm_local_handler_t *)priv;
1820
1821 IBTF_DPRINTF_L4(cmlog, "ibcm_local_cm_handler: event %d",
1822 event->cm_type);
1823
1824 ASSERT(handler_priv != NULL);
1825
1826 switch (event->cm_type) {
1956 /* Return failure if the HCA device or Port is not operational */
1957
1958 if ((retval = ibt_get_port_state_byguid(port.hp_hca_guid, port.hp_port,
1959 NULL, NULL)) != IBT_SUCCESS) {
1960 /* Device Port is not in good state, don't use it. */
1961 IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: Invalid "
1962 "port specified or port not active");
1963 ibcm_dec_hca_acc_cnt(hcap);
1964 return (retval);
1965 }
1966
1967 retval = ibt_index2pkey_byguid(port.hp_hca_guid, port.hp_port,
1968 attr->ud_pkey_ix, &ud_pkey);
1969 if (retval != IBT_SUCCESS) {
1970 IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
1971 "Failed to convert index2pkey: %d", retval);
1972 ibcm_dec_hca_acc_cnt(hcap);
1973 return (retval);
1974 }
1975
1976 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(sidr_entry))
1977
1978 /* Allocate a new request id */
1979 if (ibcm_alloc_reqid(hcap, &sidr_entry.srch_req_id) == IBCM_FAILURE) {
1980 IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
1981 "no req id available");
1982 ibcm_dec_hca_acc_cnt(hcap);
1983 return (IBT_INSUFF_KERNEL_RESOURCE);
1984 }
1985
1986 if ((hcap->hca_port_info[port.hp_port - 1].port_ibmf_hdl == NULL) &&
1987 ((retval = ibcm_hca_reinit_port(hcap, port.hp_port - 1))
1988 != IBT_SUCCESS)) {
1989 IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
1990 "ibmf reg or callback setup failed during re-initialize");
1991 return (retval);
1992 }
1993
1994 ibmf_hdl = hcap->hca_port_info[port.hp_port - 1].port_ibmf_hdl;
1995
1996 /* find the ibmf QP to post the SIDR REQ */
1997 if ((cm_qp_entry = ibcm_find_qp(hcap, port.hp_port, ud_pkey)) ==
1999 IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: IBMF QP allocation"
2000 " failed");
2001 ibcm_dec_hca_acc_cnt(hcap);
2002 return (IBT_INSUFF_RESOURCE);
2003 }
2004
2005 if ((retval = ibcm_alloc_out_msg(ibmf_hdl, &ibmf_msg, MAD_METHOD_SEND))
2006 != IBT_SUCCESS) {
2007 IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: IBMF MSG allocation"
2008 " failed");
2009 ibcm_release_qp(cm_qp_entry);
2010 ibcm_dec_hca_acc_cnt(hcap);
2011 return (retval);
2012 }
2013
2014 sidr_entry.srch_lid = port.hp_base_lid;
2015 sidr_entry.srch_gid = attr->ud_addr->av_sgid;
2016 sidr_entry.srch_grh_exists = attr->ud_addr->av_send_grh;
2017 sidr_entry.srch_mode = IBCM_ACTIVE_MODE;
2018
2019 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(sidr_entry))
2020
2021 /* do various allocations needed here */
2022 rw_enter(&hcap->hca_sidr_list_lock, RW_WRITER);
2023
2024 (void) ibcm_find_sidr_entry(&sidr_entry, hcap, &ud_statep,
2025 IBCM_FLAG_ADD);
2026 rw_exit(&hcap->hca_sidr_list_lock);
2027
2028 /* Increment hca's resource count */
2029 ibcm_inc_hca_res_cnt(hcap);
2030
2031 /* After a resource created on hca, no need to hold the acc cnt */
2032 ibcm_dec_hca_acc_cnt(hcap);
2033
2034 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ud_statep))
2035
2036 /* Initialize some ud_statep fields */
2037 ud_statep->ud_stored_msg = ibmf_msg;
2038 ud_statep->ud_svc_id = attr->ud_sid;
2039 ud_statep->ud_pkt_life_time =
2040 ibt_ib2usec(attr->ud_pkt_lt);
2041 ud_statep->ud_stored_reply_addr.cm_qp_entry = cm_qp_entry;
2042
2043 /* set remaining retry cnt */
2044 ud_statep->ud_remaining_retry_cnt = ud_statep->ud_max_cm_retries;
2045
2046 /*
2047 * Get UD handler and corresponding args which is pass it back
2048 * as first argument for the handler.
2049 */
2050 ud_statep->ud_state_cm_private = attr->ud_cm_private;
2051
2052 if (mode == IBT_BLOCKING)
2053 ud_statep->ud_return_data = ret_args;
2054 else
2055 ud_statep->ud_cm_handler = attr->ud_cm_handler;
2068 ud_statep->ud_stored_reply_addr.grh_hdr.ig_flow_label =
2069 attr->ud_addr->av_flow & IB_GRH_FLOW_LABEL_MASK;
2070
2071 /* needs to be derived based on the base LID and path bits */
2072 ud_statep->ud_stored_reply_addr.rcvd_addr.ia_local_lid =
2073 port.hp_base_lid;
2074 ud_statep->ud_stored_reply_addr.rcvd_addr.ia_remote_lid =
2075 attr->ud_addr->av_dlid;
2076 ud_statep->ud_stored_reply_addr.rcvd_addr.ia_p_key = ud_pkey;
2077 ud_statep->ud_stored_reply_addr.rcvd_addr.ia_q_key = IB_GSI_QKEY;
2078 ud_statep->ud_stored_reply_addr.rcvd_addr.ia_service_level =
2079 attr->ud_addr->av_srvl;
2080
2081 /*
2082 * This may be enchanced later, to use a remote qno based on past
2083 * redirect rej mad responses. This would be the place to specify
2084 * appropriate remote qno
2085 */
2086 ud_statep->ud_stored_reply_addr.rcvd_addr.ia_remote_qno = 1;
2087
2088 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_req_msgp))
2089
2090 /* Initialize the SIDR REQ message fields */
2091 sidr_req_msgp =
2092 (ibcm_sidr_req_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg);
2093
2094 sidr_req_msgp->sidr_req_request_id = h2b32(ud_statep->ud_req_id);
2095 sidr_req_msgp->sidr_req_service_id = h2b64(attr->ud_sid);
2096 sidr_req_msgp->sidr_req_pkey = h2b16(ud_pkey);
2097 IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->AttributeID =
2098 h2b16(IBCM_INCOMING_SIDR_REQ + IBCM_ATTR_BASE_ID);
2099
2100 if ((attr->ud_priv_data != NULL) && (attr->ud_priv_data_len > 0)) {
2101 bcopy(attr->ud_priv_data, sidr_req_msgp->sidr_req_private_data,
2102 min(attr->ud_priv_data_len, IBT_SIDR_REQ_PRIV_DATA_SZ));
2103 }
2104
2105 /* Send out the SIDR REQ message */
2106 ud_statep->ud_state = IBCM_STATE_SIDR_REQ_SENT;
2107 ud_statep->ud_timer_stored_state = IBCM_STATE_SIDR_REQ_SENT;
2108 IBCM_UD_REF_CNT_INCR(ud_statep); /* for non-blocking SIDR REQ post */
2109 ud_statep->ud_timer_value = ibt_ib2usec(ibcm_max_sidr_rep_proctime) +
2110 (ud_statep->ud_pkt_life_time * 2);
2111
2112 IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->TransactionID =
2113 h2b64(ibcm_generate_tranid(IBCM_INCOMING_SIDR_REQ,
2114 ud_statep->ud_req_id, 0));
2115
2116 IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: timer_value in HZ = %x",
2117 ud_statep->ud_timer_value);
2118
2119 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ud_statep))
2120 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sidr_req_msgp))
2121
2122 ibcm_post_ud_mad(ud_statep, ud_statep->ud_stored_msg,
2123 ibcm_post_sidr_req_complete, ud_statep);
2124
2125 mutex_enter(&ud_statep->ud_state_mutex);
2126
2127 /* Wait for SIDR_REP */
2128 if (mode == IBT_BLOCKING) {
2129 IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: blocking");
2130
2131 while (ud_statep->ud_blocking_done != B_TRUE) {
2132 cv_wait(&ud_statep->ud_block_client_cv,
2133 &ud_statep->ud_state_mutex);
2134 }
2135
2136 IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: finished blocking");
2137
2138 if (ret_args->ud_status == IBT_CM_SREP_QPN_VALID) {
2139 IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: DQPN = %x, "
2140 "status = %x, QKey = %x", ret_args->ud_dqpn,
2141 ret_args->ud_status, ret_args->ud_qkey);
2196 attr->ud_addr);
2197 if (retval != IBT_SUCCESS) {
2198 IBTF_DPRINTF_L2(cmlog, "ibt_request_ud_dest: "
2199 "Address Handle Modification failed: %d", retval);
2200 return (retval);
2201 }
2202
2203 if (mode == IBT_NONBLOCKING) {
2204 /*
2205 * In NON-BLOCKING mode, and we need to update the destination
2206 * handle with the DQPN and QKey that are obtained from
2207 * SIDR REP, hook-up our own handler, so that we can catch
2208 * the event, and we ourselves call the actual client's
2209 * ud_cm_handler, in our handler.
2210 */
2211
2212 /* Allocate memory for local handler's private data. */
2213 local_handler_priv =
2214 kmem_alloc(sizeof (*local_handler_priv), KM_SLEEP);
2215
2216 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*local_handler_priv))
2217
2218 local_handler_priv->actual_cm_handler = attr->ud_cm_handler;
2219 local_handler_priv->actual_cm_private = attr->ud_cm_private;
2220 local_handler_priv->dest_hdl = ud_destp;
2221
2222 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*local_handler_priv))
2223
2224 attr->ud_cm_handler = ibcm_local_cm_handler;
2225 attr->ud_cm_private = local_handler_priv;
2226 }
2227
2228 /* In order to get DQPN and Destination QKey, perform SIDR */
2229 retval = ibcm_ud_get_dqpn(attr, mode, ud_ret_args);
2230 if (retval != IBT_SUCCESS) {
2231 IBTF_DPRINTF_L2(cmlog, "ibt_request_ud_dest: "
2232 "Failed to get DQPN: %d", retval);
2233
2234 /* Free memory allocated for local handler's private data. */
2235 if (local_handler_priv != NULL)
2236 kmem_free(local_handler_priv,
2237 sizeof (*local_handler_priv));
2238 return (retval);
2239 }
2240
2241 /*
2242 * Fill in the dqpn and dqkey as obtained from ud_ret_args,
2243 * values will be valid only on BLOCKING mode.
2328 statep = (ibcm_state_data_t *)cm_session_id;
2329
2330 if (statep == NULL) {
2331 IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: statep NULL");
2332 return (IBT_INVALID_PARAM);
2333 }
2334
2335 IBTF_DPRINTF_L4(cmlog, "ibt_cm_delay: statep %p", statep);
2336
2337 /* Allocate an ibmf msg for mra, if not allocated yet */
2338 if (statep->mra_msg == NULL) {
2339 if ((status = ibcm_alloc_out_msg(
2340 statep->stored_reply_addr.ibmf_hdl, &statep->mra_msg,
2341 MAD_METHOD_SEND)) != IBT_SUCCESS) {
2342 IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: chan 0x%p"
2343 "IBMF MSG allocation failed", statep->channel);
2344 return (status);
2345 }
2346 }
2347
2348 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mra_msgp))
2349
2350 mra_msgp = (ibcm_mra_msg_t *)IBCM_OUT_MSGP(statep->mra_msg);
2351 mra_msgp->mra_local_comm_id = h2b32(statep->local_comid);
2352 mra_msgp->mra_remote_comm_id = h2b32(statep->remote_comid);
2353
2354 /* fill in rest of MRA's fields - Message MRAed and Service Timeout */
2355 if (flags == IBT_CM_DELAY_REQ) {
2356 msg_typ = IBT_CM_MRA_TYPE_REQ;
2357 } else if (flags == IBT_CM_DELAY_REP) {
2358 msg_typ = IBT_CM_MRA_TYPE_REP;
2359 } else if (flags == IBT_CM_DELAY_LAP) {
2360 msg_typ = IBT_CM_MRA_TYPE_LAP;
2361 }
2362
2363 mra_msgp->mra_message_type_plus = msg_typ << 6;
2364 mra_msgp->mra_service_timeout_plus = ibt_usec2ib(service_time) << 3;
2365
2366 len = min(len, IBT_MRA_PRIV_DATA_SZ);
2367 if (priv_data && (len > 0))
2368 bcopy(priv_data, mra_msgp->mra_private_data, len);
2369
2370 IBCM_OUT_HDRP(statep->mra_msg)->AttributeID =
2371 h2b16(IBCM_INCOMING_MRA + IBCM_ATTR_BASE_ID);
2372
2373 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mra_msgp))
2374
2375 mutex_enter(&statep->state_mutex);
2376
2377 if ((statep->mode == IBCM_ACTIVE_MODE) &&
2378 (statep->state == IBCM_STATE_REP_RCVD)) {
2379 statep->state = IBCM_STATE_MRA_REP_SENT;
2380 } else if (statep->mode == IBCM_PASSIVE_MODE) {
2381 if (statep->state == IBCM_STATE_REQ_RCVD) {
2382 statep->state = IBCM_STATE_MRA_SENT;
2383 } else if (statep->ap_state == IBCM_AP_STATE_LAP_RCVD) {
2384 statep->ap_state = IBCM_AP_STATE_MRA_LAP_RCVD;
2385 } else {
2386 IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: invalid state "
2387 "/ap_state/mode %x, %x, %x", statep->state,
2388 statep->ap_state, statep->mode);
2389 mutex_exit(&statep->state_mutex);
2390 return (IBT_CHAN_STATE_INVALID);
2391 }
2392 } else {
2393 IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: invalid state "
2394 "/ap_state/mode %x, %x, %x", statep->state,
2448 * in the range.
2449 *
2450 * ibt_register_service() returns:
2451 * IBT_SUCCESS - added a service successfully.
2452 * IBT_INVALID_PARAM - invalid input parameter.
2453 * IBT_CM_FAILURE - failed to add the service.
2454 * IBT_CM_SERVICE_EXISTS - service already exists.
2455 * IBT_INSUFF_KERNEL_RESOURCE - ran out of local service ids (should
2456 * never happen).
2457 */
2458 ibt_status_t
2459 ibt_register_service(ibt_clnt_hdl_t ibt_hdl, ibt_srv_desc_t *srv,
2460 ib_svc_id_t sid, int num_sids, ibt_srv_hdl_t *srv_hdl, ib_svc_id_t *ret_sid)
2461 {
2462 ibcm_svc_info_t *svcinfop;
2463
2464 IBTF_DPRINTF_L2(cmlog, "ibt_register_service(%p (%s), %p, 0x%llX, %d)",
2465 ibt_hdl, ibtl_cm_get_clnt_name(ibt_hdl), srv, (longlong_t)sid,
2466 num_sids);
2467
2468 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*svcinfop))
2469
2470 *srv_hdl = NULL;
2471
2472 if (num_sids <= 0) {
2473 IBTF_DPRINTF_L2(cmlog, "ibt_register_service: "
2474 "Invalid number of service-ids specified (%d)", num_sids);
2475 return (IBT_INVALID_PARAM);
2476 }
2477
2478 if (sid == 0) {
2479 if (ret_sid == NULL)
2480 return (IBT_INVALID_PARAM);
2481 sid = ibcm_alloc_local_sids(num_sids);
2482 if (sid == 0)
2483 return (IBT_INSUFF_KERNEL_RESOURCE);
2484
2485 /* Make sure that the ServiceId specified is not of LOCAL AGN type. */
2486 } else if ((sid & IB_SID_AGN_MASK) == IB_SID_AGN_LOCAL) {
2487 IBTF_DPRINTF_L2(cmlog, "ibt_register_service: "
2488 "Invalid non-LOCAL SID specified: 0x%llX",
2489 (longlong_t)sid);
2499 }
2500
2501 /*
2502 * 'sid' and 'num_sids' are filled in ibcm_create_svc_entry()
2503 */
2504 svcinfop->svc_flags = srv->sd_flags;
2505 svcinfop->svc_rc_handler = srv->sd_handler;
2506 svcinfop->svc_ud_handler = srv->sd_ud_handler;
2507
2508 if (ret_sid != NULL)
2509 *ret_sid = sid;
2510
2511 *srv_hdl = svcinfop;
2512
2513 ibtl_cm_change_service_cnt(ibt_hdl, num_sids);
2514
2515 /* If this message isn't seen, then ibt_register_service failed. */
2516 IBTF_DPRINTF_L2(cmlog, "ibt_register_service: done (%p, %llX)",
2517 svcinfop, sid);
2518
2519 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*svcinfop))
2520
2521 return (IBT_SUCCESS);
2522 }
2523
2524
2525 static ibt_status_t
2526 ibcm_write_service_record(ibmf_saa_handle_t saa_handle,
2527 sa_service_record_t *srv_recp, ibmf_saa_access_type_t saa_type)
2528 {
2529 int rval;
2530 int retry;
2531
2532 ibcm_sa_access_enter();
2533 for (retry = 0; retry < ibcm_max_sa_retries; retry++) {
2534 rval = ibmf_saa_update_service_record(
2535 saa_handle, srv_recp, saa_type, 0);
2536 if (rval != IBMF_TRANS_TIMEOUT) {
2537 break;
2538 }
2539 IBTF_DPRINTF_L2(cmlog, "ibcm_write_service_record: "
2540 "ibmf_saa_update_service_record timed out"
2612 mutex_exit(&ibcm_svc_info_lock);
2613 IBTF_DPRINTF_L3(cmlog, "ibcm_rem_stale_srec: "
2614 "This is not Stale, it's an active record");
2615 continue;
2616 }
2617 mutex_exit(&ibcm_svc_info_lock);
2618
2619 IBTF_DPRINTF_L2(cmlog, "ibcm_rem_stale_srec: "
2620 "Removing Stale Rec: %s, %llX",
2621 srv_resp->ServiceName, srv_resp->ServiceID);
2622
2623 IBCM_DUMP_SERVICE_REC(srv_resp);
2624
2625 /*
2626 * Remove the Service Record Entry from SA.
2627 *
2628 * Get ServiceID info from Response Buf, other
2629 * attributes are already filled-in.
2630 */
2631
2632 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(srec->ServiceID))
2633
2634 srec->ServiceID = srv_resp->ServiceID;
2635
2636 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(srec->ServiceID))
2637
2638 (void) ibcm_write_service_record(saa_handle, srec,
2639 IBMF_SAA_DELETE);
2640 }
2641
2642 /* Deallocate the memory for results_p. */
2643 kmem_free(results_p, length);
2644 }
2645 }
2646
2647
2648
2649 /*
2650 * ibt_bind_service()
2651 * Register a service with the IBCM
2652 *
2653 * INPUTS:
2654 * srv_hdl The service id handle returned to the client
2655 * on an ibt_service_register() call.
2656 *
2657 * gid The GID to which to bind the service.
2680 */
2681 ibt_status_t
2682 ibt_bind_service(ibt_srv_hdl_t srv_hdl, ib_gid_t gid, ibt_srv_bind_t *srv_bind,
2683 void *cm_private, ibt_sbind_hdl_t *sb_hdl_p)
2684 {
2685 ibt_status_t status;
2686 ibtl_cm_hca_port_t port;
2687 ibcm_svc_bind_t *sbindp, *sbp;
2688 ibcm_hca_info_t *hcap;
2689 ib_svc_id_t sid, start_sid, end_sid;
2690 ibmf_saa_handle_t saa_handle;
2691 sa_service_record_t srv_rec;
2692 uint16_t pkey_ix;
2693
2694 if (sb_hdl_p != NULL)
2695 *sb_hdl_p = NULL; /* return value for error cases */
2696
2697 IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: srv_hdl %p, gid (%llX:%llX)",
2698 srv_hdl, (longlong_t)gid.gid_prefix, (longlong_t)gid.gid_guid);
2699
2700 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sbindp))
2701
2702 /* Call ibtl_cm_get_hca_port to get the port number and the HCA GUID. */
2703 if ((status = ibtl_cm_get_hca_port(gid, 0, &port)) != IBT_SUCCESS) {
2704 IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
2705 "ibtl_cm_get_hca_port failed: %d", status);
2706 return (status);
2707 }
2708 IBTF_DPRINTF_L4(cmlog, "ibt_bind_service: Port:%d HCA GUID:%llX",
2709 port.hp_port, port.hp_hca_guid);
2710
2711 hcap = ibcm_find_hca_entry(port.hp_hca_guid);
2712 if (hcap == NULL) {
2713 IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: NO HCA found");
2714 return (IBT_HCA_BUSY_DETACHING);
2715 }
2716 IBTF_DPRINTF_L4(cmlog, "ibt_bind_service: hcap = %p", hcap);
2717
2718 if (srv_bind != NULL) {
2719 saa_handle = ibcm_get_saa_handle(hcap, port.hp_port);
2720 if (saa_handle == NULL) {
2721 IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
2875 }
2876 mutex_exit(&ibcm_svc_info_lock);
2877 ibcm_dec_hca_acc_cnt(hcap);
2878
2879 kmem_free(sbindp, sizeof (*sbindp));
2880 }
2881 return (status);
2882 }
2883 }
2884 }
2885 ibcm_inc_hca_svc_cnt(hcap);
2886 ibcm_dec_hca_acc_cnt(hcap);
2887
2888 /* If this message isn't seen then ibt_bind_service failed */
2889 IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: DONE (%p, %llX:%llX)",
2890 srv_hdl, gid.gid_prefix, gid.gid_guid);
2891
2892 if (sb_hdl_p != NULL)
2893 *sb_hdl_p = sbindp;
2894
2895 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sbindp))
2896
2897 return (IBT_SUCCESS);
2898 }
2899
2900 ibt_status_t
2901 ibt_unbind_service(ibt_srv_hdl_t srv_hdl, ibt_sbind_hdl_t sbindp)
2902 {
2903 ib_svc_id_t sid, end_sid;
2904 ibt_status_t rval;
2905 ibcm_hca_info_t *hcap;
2906 ibcm_svc_bind_t *sbp, **sbpp;
2907
2908 IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service(%p, %p)",
2909 srv_hdl, sbindp);
2910
2911 hcap = ibcm_find_hca_entry(sbindp->sbind_hcaguid);
2912
2913 /* If there is a service on hca, respective hcap cannot go away */
2914 ASSERT(hcap != NULL);
2915
2916 mutex_enter(&ibcm_svc_info_lock);
3049 {
3050 ibcm_svc_info_t *svcp;
3051 ibcm_svc_lookup_t svc;
3052
3053 IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service(%p (%s), %p)",
3054 ibt_hdl, ibtl_cm_get_clnt_name(ibt_hdl), srv_hdl);
3055
3056 mutex_enter(&ibcm_svc_info_lock);
3057
3058 if (srv_hdl->svc_bind_list != NULL) {
3059 IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service:"
3060 " srv_hdl %p still has bindings", srv_hdl);
3061 mutex_exit(&ibcm_svc_info_lock);
3062 return (IBT_CM_SERVICE_BUSY);
3063 }
3064 svc.sid = srv_hdl->svc_id;
3065 svc.num_sids = 1;
3066 IBTF_DPRINTF_L3(cmlog, "ibt_deregister_service: SID 0x%llX, numsids %d",
3067 srv_hdl->svc_id, srv_hdl->svc_num_sids);
3068
3069 #ifdef __lock_lint
3070 ibcm_svc_compare(NULL, NULL);
3071 #endif
3072 svcp = avl_find(&ibcm_svc_avl_tree, &svc, NULL);
3073 if (svcp != srv_hdl) {
3074 mutex_exit(&ibcm_svc_info_lock);
3075 IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service(): "
3076 "srv_hdl %p not found", srv_hdl);
3077 return (IBT_INVALID_PARAM);
3078 }
3079 avl_remove(&ibcm_svc_avl_tree, svcp);
3080
3081 /* wait for active REQ/SREQ handling to be done */
3082 svcp->svc_to_delete = 1;
3083 while (svcp->svc_ref_cnt != 0)
3084 cv_wait(&ibcm_svc_info_cv, &ibcm_svc_info_lock);
3085
3086 mutex_exit(&ibcm_svc_info_lock);
3087
3088 if ((srv_hdl->svc_id & IB_SID_AGN_MASK) == IB_SID_AGN_LOCAL)
3089 ibcm_free_local_sids(srv_hdl->svc_id, srv_hdl->svc_num_sids);
3090
3091 ibtl_cm_change_service_cnt(ibt_hdl, -srv_hdl->svc_num_sids);
3994 /* wait until client's CM handler returns DEFER status back to CM */
3995
3996 while (statep->clnt_proceed == IBCM_BLOCK) {
3997 IBTF_DPRINTF_L5(cmlog, "ibt_cm_proceed : chan 0x%p blocked for "
3998 "return of client's cm handler", statep->channel);
3999 cv_wait(&statep->block_client_cv, &statep->state_mutex);
4000 }
4001
4002 if (statep->clnt_proceed == IBCM_FAIL) {
4003 mutex_exit(&statep->state_mutex);
4004 IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p Failed as "
4005 "client returned non-DEFER status from cm handler",
4006 statep->channel);
4007 return (IBT_CHAN_STATE_INVALID);
4008 }
4009
4010 ASSERT(statep->clnt_proceed == IBCM_UNBLOCK);
4011 statep->clnt_proceed = IBCM_FAIL;
4012 mutex_exit(&statep->state_mutex);
4013
4014 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*proceed_targs))
4015
4016 /* the state machine processing is done in a separate thread */
4017
4018 /* proceed_targs is freed in ibcm_proceed_via_taskq */
4019 proceed_targs = kmem_alloc(sizeof (ibcm_proceed_targs_t),
4020 KM_SLEEP);
4021
4022 proceed_targs->event = event;
4023 proceed_targs->status = status;
4024 proceed_targs->priv_data_len = priv_data_len;
4025
4026 bcopy(priv_data, proceed_targs->priv_data, priv_data_len);
4027
4028 proceed_targs->tst.rc.statep = statep;
4029 bcopy(cm_event_data, &proceed_targs->tst.rc.rc_cm_event_data,
4030 sizeof (ibt_cm_proceed_reply_t));
4031
4032 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*proceed_targs))
4033
4034 (void) taskq_dispatch(ibcm_taskq, ibcm_proceed_via_taskq,
4035 proceed_targs, TQ_SLEEP);
4036
4037 return (IBT_SUCCESS);
4038 }
4039
4040 /*
4041 * Function:
4042 * ibcm_proceed_via_taskq
4043 *
4044 * Called from taskq, dispatched by ibt_cm_proceed
4045 * Completes the cm state processing for ibt_cm_proceed
4046 */
4047 void
4048 ibcm_proceed_via_taskq(void *targs)
4049 {
4050 ibcm_proceed_targs_t *proceed_targs = (ibcm_proceed_targs_t *)targs;
4051 ibcm_state_data_t *statep = proceed_targs->tst.rc.statep;
4052 ibt_cm_reason_t reject_reason;
4053 uint8_t arej_len;
4159 /* wait until client's CM handler returns DEFER status back to CM */
4160
4161 while (ud_statep->ud_clnt_proceed == IBCM_BLOCK) {
4162 IBTF_DPRINTF_L5(cmlog, "ibt_cm_ud_proceed : Blocked for return"
4163 " of client's ud cm handler");
4164 cv_wait(&ud_statep->ud_block_client_cv,
4165 &ud_statep->ud_state_mutex);
4166 }
4167
4168 if (ud_statep->ud_clnt_proceed == IBCM_FAIL) {
4169 mutex_exit(&ud_statep->ud_state_mutex);
4170 IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed : Failed as client "
4171 "returned non-DEFER status from cm handler");
4172 return (IBT_INVALID_PARAM);
4173 }
4174
4175 ASSERT(ud_statep->ud_clnt_proceed == IBCM_UNBLOCK);
4176 ud_statep->ud_clnt_proceed = IBCM_FAIL;
4177 mutex_exit(&ud_statep->ud_state_mutex);
4178
4179 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*proceed_targs))
4180
4181 /* the state machine processing is done in a separate thread */
4182
4183 /* proceed_targs is freed in ibcm_proceed_via_taskq */
4184 proceed_targs = kmem_zalloc(sizeof (ibcm_proceed_targs_t),
4185 KM_SLEEP);
4186
4187 proceed_targs->status = status;
4188 proceed_targs->priv_data_len = priv_data_len;
4189
4190 bcopy(priv_data, proceed_targs->priv_data, priv_data_len);
4191
4192 if (status == IBT_CM_ACCEPT) {
4193 proceed_targs->tst.ud.ud_qkey =
4194 qp_attr.qp_info.qp_transport.ud.ud_qkey;
4195 proceed_targs->tst.ud.ud_qpn = qp_attr.qp_qpn;
4196 }
4197
4198 proceed_targs->tst.ud.ud_statep = ud_statep;
4199
4200 /* copy redirect info based on status */
4201 if (status == IBT_CM_REDIRECT)
4202 bcopy(redirect_infop, &proceed_targs->tst.ud.ud_redirect_info,
4203 sizeof (ibt_redirect_info_t));
4204
4205 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*proceed_targs))
4206
4207 (void) taskq_dispatch(ibcm_taskq, ibcm_ud_proceed_via_taskq,
4208 proceed_targs, TQ_SLEEP);
4209
4210 return (IBT_SUCCESS);
4211 }
4212
4213 /*
4214 * Function:
4215 * ibcm_ud_proceed_via_taskq
4216 *
4217 * Called from taskq, dispatched by ibt_cm_ud_proceed
4218 * Completes the cm state processing for ibt_cm_ud_proceed
4219 */
4220 void
4221 ibcm_ud_proceed_via_taskq(void *targs)
4222 {
4223 ibcm_proceed_targs_t *proceed_targs = (ibcm_proceed_targs_t *)targs;
4224 ibcm_ud_state_data_t *ud_statep = proceed_targs->tst.ud.ud_statep;
4225 ibcm_ud_clnt_reply_info_t ud_clnt_info;
4226 ibt_sidr_status_t sidr_status;
4427 ibcm_lapr_exit();
4428 return (IBT_CHAN_STATE_INVALID);
4429 } else {
4430 /* Set to LAP Sent state */
4431 statep->ap_state = IBCM_AP_STATE_LAP_SENT;
4432 statep->ap_done = B_FALSE;
4433 statep->remaining_retry_cnt = statep->max_cm_retries;
4434 statep->timer_stored_state = statep->state;
4435 statep->timer_stored_ap_state = statep->ap_state;
4436 IBCM_REF_CNT_INCR(statep); /* for ibcm_post_lap_complete */
4437 }
4438
4439 mutex_exit(&statep->state_mutex);
4440
4441 /* No more failure returns below */
4442
4443 /* Allocate MAD for LAP */
4444 IBTF_DPRINTF_L5(cmlog, "ibt_set_alt_path:"
4445 " statep's mad addr = 0x%p", IBCM_OUT_HDRP(statep->lapr_msg));
4446
4447 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lap_msgp))
4448
4449 lap_msgp = (ibcm_lap_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg);
4450
4451 lap_msgp->lap_alt_l_port_lid = h2b16(alternate_slid);
4452 lap_msgp->lap_alt_r_port_lid =
4453 h2b16(alt_path->ap_alt_cep_path.cep_adds_vect.av_dlid);
4454
4455 /* Fill in remote port gid */
4456 lap_msgp->lap_alt_r_port_gid.gid_prefix =
4457 h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_dgid.gid_prefix);
4458 lap_msgp->lap_alt_r_port_gid.gid_guid =
4459 h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_dgid.gid_guid);
4460
4461 /* Fill in local port gid */
4462 lap_msgp->lap_alt_l_port_gid.gid_prefix =
4463 h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_sgid.gid_prefix);
4464 lap_msgp->lap_alt_l_port_gid.gid_guid =
4465 h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_sgid.gid_guid);
4466
4467 alt_grh = alt_path->ap_alt_cep_path.cep_adds_vect.av_send_grh;
4468
4480 alt_path->ap_alt_cep_path.cep_adds_vect.av_srvl << 4 |
4481 ((alt_grh == B_FALSE) ? 0x8 : 0);
4482
4483 lap_msgp->lap_alt_local_acktime_plus = ibt_usec2ib(
4484 (2 * statep->rc_alt_pkt_lt) +
4485 ibt_ib2usec(hcap->hca_ack_delay)) << 3;
4486
4487 lap_msgp->lap_local_comm_id = h2b32(statep->local_comid);
4488 lap_msgp->lap_remote_comm_id = h2b32(statep->remote_comid);
4489
4490 lap_msgp->lap_remote_qpn_eecn_plus =
4491 h2b32((statep->remote_qpn << 8) |
4492 ibt_usec2ib(ibcm_remote_response_time) << 3);
4493
4494 len = min(priv_data_len, IBT_LAP_PRIV_DATA_SZ);
4495 if ((len > 0) && priv_data) {
4496 bcopy(priv_data, lap_msgp->lap_private_data, len);
4497 }
4498
4499 /* only rc_alt_pkt_lt and ap_return_data fields are initialized */
4500 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
4501
4502 statep->rc_alt_pkt_lt = ibt_ib2usec(alt_path->ap_alt_pkt_lt);
4503
4504 /* return_data is filled up in the state machine code */
4505 statep->ap_return_data = ret_args;
4506
4507 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
4508
4509 IBCM_OUT_HDRP(statep->lapr_msg)->AttributeID =
4510 h2b16(IBCM_INCOMING_LAP + IBCM_ATTR_BASE_ID);
4511
4512 IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID =
4513 h2b64(ibcm_generate_tranid(IBCM_INCOMING_LAP, statep->local_comid,
4514 0));
4515 IBTF_DPRINTF_L3(cmlog, "ibt_set_alt_path: statep %p, tid %llx",
4516 statep, IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID);
4517
4518 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*lap_msgp))
4519
4520 /* Send LAP */
4521 ibcm_post_rc_mad(statep, statep->lapr_msg, ibcm_post_lap_complete,
4522 statep);
4523
4524 mutex_enter(&statep->state_mutex);
4525
4526 if (mode == IBT_BLOCKING) {
4527 IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: blocking");
4528
4529 /* wait for APR */
4530 while (statep->ap_done != B_TRUE) {
4531 cv_wait(&statep->block_client_cv,
4532 &statep->state_mutex);
4533 }
4534
4535 IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: done blocking");
4536
4537 /*
4538 * In the case that ibt_set_alt_path fails,
4539 * change retval to IBT_CM_FAILURE
4650 cm_reply_addr->grh_hdr.ig_flow_label,
4651 cm_reply_addr->grh_hdr.ig_tclass,
4652 cm_reply_addr->grh_hdr.ig_hop_limit);
4653 }
4654
4655 #endif
4656
4657 /* For MCG List search */
4658 typedef struct ibcm_mcg_list_s {
4659 struct ibcm_mcg_list_s *ml_next;
4660 ib_gid_t ml_sgid;
4661 ib_gid_t ml_mgid;
4662 ib_pkey_t ml_pkey;
4663 ib_qkey_t ml_qkey;
4664 uint_t ml_refcnt;
4665 uint8_t ml_jstate;
4666 } ibcm_mcg_list_t;
4667
4668 ibcm_mcg_list_t *ibcm_mcglist = NULL;
4669
4670 _NOTE(MUTEX_PROTECTS_DATA(ibcm_mcglist_lock, ibcm_mcg_list_s))
4671 _NOTE(MUTEX_PROTECTS_DATA(ibcm_mcglist_lock, ibcm_mcglist))
4672
4673 typedef struct ibcm_join_mcg_tqarg_s {
4674 ib_gid_t rgid;
4675 ibt_mcg_attr_t mcg_attr;
4676 ibt_mcg_info_t *mcg_infop;
4677 ibt_mcg_handler_t func;
4678 void *arg;
4679 } ibcm_join_mcg_tqarg_t;
4680
4681 _NOTE(READ_ONLY_DATA(ibcm_join_mcg_tqarg_s))
4682
4683 void
4684 ibcm_add_incr_mcg_entry(sa_mcmember_record_t *mcg_req,
4685 sa_mcmember_record_t *mcg_resp)
4686 {
4687 ibcm_mcg_list_t *new = NULL;
4688 ibcm_mcg_list_t *head = NULL;
4689
4690 IBTF_DPRINTF_L3(cmlog, "ibcm_add_incr_mcg_entry: MGID %llX:%llX"
4691 "\n SGID %llX:%llX, JState %X)", mcg_req->MGID.gid_prefix,
4692 mcg_req->MGID.gid_guid, mcg_req->PortGID.gid_prefix,
4693 mcg_req->PortGID.gid_guid, mcg_req->JoinState);
4694
4695 mutex_enter(&ibcm_mcglist_lock);
4696 head = ibcm_mcglist;
4697
4698 while (head != NULL) {
4699 if ((head->ml_mgid.gid_guid == mcg_resp->MGID.gid_guid) &&
4700 (head->ml_mgid.gid_prefix == mcg_resp->MGID.gid_prefix) &&
4701 (head->ml_sgid.gid_guid == mcg_resp->PortGID.gid_guid)) {
4702 /* Increment the count */
4859 IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Request GID is required");
4860 return (IBT_INVALID_PARAM);
4861 }
4862
4863 if ((mcg_attr->mc_pkey == IB_PKEY_INVALID_LIMITED) ||
4864 (mcg_attr->mc_pkey == IB_PKEY_INVALID_FULL)) {
4865 IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Invalid P_Key specified");
4866 return (IBT_INVALID_PARAM);
4867 }
4868
4869 if (mcg_attr->mc_join_state == 0) {
4870 IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: JoinState not specified");
4871 return (IBT_INVALID_PARAM);
4872 }
4873
4874 if (mcg_info_p == NULL) {
4875 IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: mcg_info_p is NULL");
4876 return (IBT_INVALID_PARAM);
4877 }
4878
4879 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mcg_tq))
4880
4881 mcg_tq = kmem_alloc(sizeof (ibcm_join_mcg_tqarg_t), flag);
4882 if (mcg_tq == NULL) {
4883 IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: "
4884 "Unable to allocate memory for local usage.");
4885 return (IBT_INSUFF_KERNEL_RESOURCE);
4886 }
4887
4888 mcg_tq->rgid = rgid;
4889 bcopy(mcg_attr, &mcg_tq->mcg_attr, sizeof (ibt_mcg_attr_t));
4890 mcg_tq->mcg_infop = mcg_info_p;
4891 mcg_tq->func = func;
4892 mcg_tq->arg = arg;
4893
4894 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mcg_tq))
4895
4896 if (func != NULL) { /* Non-Blocking */
4897 IBTF_DPRINTF_L3(cmlog, "ibt_join_mcg: Non-Blocking Call");
4898 if (taskq_dispatch(ibcm_taskq, ibcm_process_async_join_mcg,
4899 mcg_tq, TQ_NOSLEEP) == 0) {
4900 IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Failed to "
4901 "Dispatch the TaskQ");
4902 kmem_free(mcg_tq, sizeof (ibcm_join_mcg_tqarg_t));
4903 return (IBT_INSUFF_KERNEL_RESOURCE);
4904 } else
4905 return (IBT_SUCCESS);
4906 } else { /* Blocking */
4907 return (ibcm_process_join_mcg(mcg_tq));
4908 }
4909 }
4910
4911 static void
4912 ibcm_process_async_join_mcg(void *tq_arg)
4913 {
4914 (void) ibcm_process_join_mcg(tq_arg);
4915 }
5812 SA_NODEINFO_COMPMASK_NODELID, &res_p, &len);
5813 if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
5814 IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
5815 "failed (%d) to get Node records", retval);
5816 continue;
5817 } else if (retval != IBT_SUCCESS) {
5818 IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
5819 "failed (%d) to get Node records", retval);
5820 ibcm_dec_hca_acc_cnt(hcap);
5821 goto gid_to_ni_exit;
5822 }
5823
5824 num_rec = len/sizeof (sa_node_record_t);
5825 nr_resp = (sa_node_record_t *)(uchar_t *)res_p;
5826
5827 /* Validate the returned number of records. */
5828 if ((nr_resp != NULL) && (num_rec > 0)) {
5829
5830 IBCM_DUMP_NODE_REC(nr_resp);
5831
5832 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(
5833 *node_info_p))
5834
5835 node_info_p->n_sys_img_guid =
5836 nr_resp->NodeInfo.SystemImageGUID;
5837 node_info_p->n_node_guid =
5838 nr_resp->NodeInfo.NodeGUID;
5839 node_info_p->n_port_guid =
5840 nr_resp->NodeInfo.PortGUID;
5841 node_info_p->n_dev_id =
5842 nr_resp->NodeInfo.DeviceID;
5843 node_info_p->n_revision =
5844 nr_resp->NodeInfo.Revision;
5845 node_info_p->n_vendor_id =
5846 nr_resp->NodeInfo.VendorID;
5847 node_info_p->n_num_ports =
5848 nr_resp->NodeInfo.NumPorts;
5849 node_info_p->n_port_num =
5850 nr_resp->NodeInfo.LocalPortNum;
5851 node_info_p->n_node_type =
5852 nr_resp->NodeInfo.NodeType;
5853 (void) strncpy(node_info_p->n_description,
5854 (char *)&nr_resp->NodeDescription, 64);
5855
5856 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(
5857 *node_info_p))
5858
5859 /*
5860 * Deallocate the memory allocated by SA for
5861 * 'nr_resp'.
5862 */
5863 ibcm_dec_hca_acc_cnt(hcap);
5864 kmem_free(nr_resp, len);
5865 retval = IBT_SUCCESS;
5866
5867 goto gid_to_ni_exit;
5868 } else {
5869 retval = IBT_NODE_RECORDS_NOT_FOUND;
5870 IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
5871 "Node Records NOT found - PortGUID %016llX",
5872 gid.gid_guid);
5873 }
5874 }
5875 ibcm_dec_hca_acc_cnt(hcap);
5876
5877 if (local_node == B_TRUE)
5878 break;
6010 SA_NODEINFO_COMPMASK_NODELID, &res_p, &len);
6011 if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
6012 IBTF_DPRINTF_L2(cmlog, "ibt_lid_to_node_info: "
6013 "failed (%d) to get Node records", retval);
6014 continue;
6015 } else if (retval != IBT_SUCCESS) {
6016 IBTF_DPRINTF_L2(cmlog, "ibt_lid_to_node_info: "
6017 "failed (%d) to get Node records", retval);
6018 ibcm_dec_hca_acc_cnt(hcap);
6019 goto lid_to_ni_exit;
6020 }
6021
6022 num_rec = len/sizeof (sa_node_record_t);
6023 nr_resp = (sa_node_record_t *)(uchar_t *)res_p;
6024
6025 /* Validate the returned number of records. */
6026 if ((nr_resp != NULL) && (num_rec > 0)) {
6027
6028 IBCM_DUMP_NODE_REC(nr_resp);
6029
6030 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(
6031 *node_info_p))
6032
6033 node_info_p->n_sys_img_guid =
6034 nr_resp->NodeInfo.SystemImageGUID;
6035 node_info_p->n_node_guid =
6036 nr_resp->NodeInfo.NodeGUID;
6037 node_info_p->n_port_guid =
6038 nr_resp->NodeInfo.PortGUID;
6039 node_info_p->n_dev_id =
6040 nr_resp->NodeInfo.DeviceID;
6041 node_info_p->n_revision =
6042 nr_resp->NodeInfo.Revision;
6043 node_info_p->n_vendor_id =
6044 nr_resp->NodeInfo.VendorID;
6045 node_info_p->n_num_ports =
6046 nr_resp->NodeInfo.NumPorts;
6047 node_info_p->n_port_num =
6048 nr_resp->NodeInfo.LocalPortNum;
6049 node_info_p->n_node_type =
6050 nr_resp->NodeInfo.NodeType;
6051 (void) strncpy(node_info_p->n_description,
6052 (char *)&nr_resp->NodeDescription, 64);
6053
6054 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(
6055 *node_info_p))
6056
6057 /*
6058 * Deallocate the memory allocated by SA for
6059 * 'nr_resp'.
6060 */
6061 ibcm_dec_hca_acc_cnt(hcap);
6062 kmem_free(nr_resp, len);
6063 retval = IBT_SUCCESS;
6064
6065 goto lid_to_ni_exit;
6066 } else {
6067 retval = IBT_NODE_RECORDS_NOT_FOUND;
6068 IBTF_DPRINTF_L3(cmlog, "ibt_lid_to_node_info: "
6069 "Node Records NOT found - LID 0x%lX",
6070 lid);
6071 }
6072 }
6073 ibcm_dec_hca_acc_cnt(hcap);
6074 }
6075
6076 lid_to_ni_exit:
6555 *src_info_p = s_ip;
6556 *entries_p = count;
6557
6558 j = 0;
6559 for (i = 0, ipp = ibds.ibcm_arp_ip; i < ibds.ibcm_arp_ibd_cnt;
6560 i++, ipp++) {
6561 if (ipp->ip_inet_family == AF_UNSPEC)
6562 continue;
6563 if ((ipp->ip_port_gid.gid_prefix ==
6564 sattr->sip_gid.gid_prefix) &&
6565 (ipp->ip_port_gid.gid_guid ==
6566 sattr->sip_gid.gid_guid)) {
6567 if ((sattr->sip_pkey) &&
6568 (ipp->ip_pkey != sattr->sip_pkey))
6569 continue;
6570
6571 if ((sattr->sip_zoneid != ALL_ZONES) &&
6572 (sattr->sip_zoneid != ipp->ip_zoneid))
6573 continue;
6574
6575 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s_ip))
6576 s_ip[j].ip_addr.family = ipp->ip_inet_family;
6577 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*s_ip))
6578 if (s_ip[j].ip_addr.family == AF_INET) {
6579 bcopy(&ipp->ip_cm_sin.sin_addr,
6580 &s_ip[j].ip_addr.un.ip4addr,
6581 sizeof (in_addr_t));
6582 } else if (s_ip[j].ip_addr.family == AF_INET6) {
6583 bcopy(&ipp->ip_cm_sin6.sin6_addr,
6584 &s_ip[j].ip_addr.un.ip6addr,
6585 sizeof (in6_addr_t));
6586 /* TBD: scope_id */
6587 }
6588 IBCM_PRINT_IP("ibt_get_src_ip",
6589 &s_ip[j].ip_addr);
6590 j++;
6591 }
6592 }
6593 } else {
6594 retval = IBT_SRC_IP_NOT_FOUND;
6595 }
6596
6597 get_src_ip_end:
6667 }
6668
6669 ibcm_free_ip_sid(ip_sid);
6670
6671 return (IBT_SUCCESS);
6672 }
6673
6674
6675 uint8_t
6676 ibt_get_ip_protocol_num(ib_svc_id_t sid)
6677 {
6678 return ((sid & IB_SID_IPADDR_IPNUM_MASK) >> 16);
6679 }
6680
6681 in_port_t
6682 ibt_get_ip_dst_port(ib_svc_id_t sid)
6683 {
6684 return (sid & IB_SID_IPADDR_PORTNUM_MASK);
6685 }
6686
6687 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibt_ip_cm_info_t))
6688 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibcm_ip_pvtdata_t))
6689
6690 ibt_status_t
6691 ibt_format_ip_private_data(ibt_ip_cm_info_t *ip_cm_info,
6692 ibt_priv_data_len_t priv_data_len, void *priv_data_p)
6693 {
6694 ibcm_ip_pvtdata_t ip_data;
6695
6696 IBTF_DPRINTF_L4(cmlog, "ibt_format_ip_private_data(%p, %d, %p)",
6697 ip_cm_info, priv_data_len, priv_data_p);
6698
6699 if ((ip_cm_info == NULL) || (priv_data_p == NULL) ||
6700 (priv_data_len < IBT_IP_HDR_PRIV_DATA_SZ)) {
6701 IBTF_DPRINTF_L2(cmlog, "ibt_format_ip_private_data: ERROR "
6702 "Invalid Inputs.");
6703 return (IBT_INVALID_PARAM);
6704 }
6705
6706 bzero(&ip_data, sizeof (ibcm_ip_pvtdata_t));
6707 ip_data.ip_srcport = ip_cm_info->src_port; /* Source Port */
6708
6709 IBCM_PRINT_IP("format_ip_pvt: src", &ip_cm_info->src_addr);
6759 AF_INET;
6760 ip_cm_infop->src_addr.un.ip4addr = ip_data.ip_srcv4;
6761 ip_cm_infop->dst_addr.un.ip4addr = ip_data.ip_dstv4;
6762 } else if (ip_data.ip_ipv == IBT_CM_IP_IPV_V6) {
6763 /* Copy IPv6 Addr */
6764 ip_cm_infop->src_addr.family = ip_cm_infop->dst_addr.family =
6765 AF_INET6;
6766 bcopy(&ip_data.ip_srcv6, &ip_cm_infop->src_addr.un.ip6addr,
6767 sizeof (in6_addr_t));
6768 bcopy(&ip_data.ip_dstv6, &ip_cm_infop->dst_addr.un.ip6addr,
6769 sizeof (in6_addr_t));
6770 } else {
6771 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_data: ERROR: IP Addr needs"
6772 " to be either AF_INET or AF_INET6 family.");
6773 return (IBT_INVALID_PARAM);
6774 }
6775 IBCM_PRINT_IP("ibt_get_ip_data: src", &ip_cm_infop->src_addr);
6776 IBCM_PRINT_IP("ibt_get_ip_data: dst", &ip_cm_infop->dst_addr);
6777
6778 return (IBT_SUCCESS);
6779 }
6780
6781
6782 /* Routines for warlock */
6783
6784 /* ARGSUSED */
6785 static void
6786 ibcm_dummy_mcg_handler(void *arg, ibt_status_t retval, ibt_mcg_info_t *minfo)
6787 {
6788 ibcm_join_mcg_tqarg_t dummy_mcg;
6789
6790 dummy_mcg.func = ibcm_dummy_mcg_handler;
6791
6792 IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_mcg_handler: "
6793 "dummy_mcg.func %p", dummy_mcg.func);
6794 }
6795
6796
6797 /* ARGSUSED */
6798 static void
6799 ibcm_dummy_recycle_rc_handler(ibt_status_t retval, void *arg)
6800 {
6801 ibcm_taskq_recycle_arg_t dummy_rc_recycle;
6802
6803 dummy_rc_recycle.func = ibcm_dummy_recycle_rc_handler;
6804
6805 IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_recycle_rc_handler: "
6806 "dummy_rc_recycle.func %p", dummy_rc_recycle.func);
6807 }
6808
6809
6810 /* ARGSUSED */
6811 static ibt_cm_status_t
6812 ibcm_dummy_ud_handler(void *priv, ibt_cm_ud_event_t *event,
6813 ibt_cm_ud_return_args_t *ret_args,
6814 void *priv_data, ibt_priv_data_len_t len)
6815 {
6816 /*
6817 * Let warlock see that ibcm_local_handler_s::actual_cm_handler
6818 * points to this routine.
6819 */
6820 ibcm_local_handler_t p;
6821 ibcm_ud_state_data_t dummy_ud;
6822
6823 p.actual_cm_handler = ibcm_dummy_ud_handler;
6824 dummy_ud.ud_cm_handler = ibcm_dummy_ud_handler;
6825
6826 IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_ud_handler: p.actual_cm_handler %p"
6827 "dummy_ud.ud_cm_handler %p", p.actual_cm_handler,
6828 dummy_ud.ud_cm_handler);
6829 /*
6830 * Call all routines that the client's callback routine could call.
6831 */
6832
6833 return (IBT_CM_ACCEPT);
6834 }
6835
6836 /* ARGSUSED */
6837 static ibt_cm_status_t
6838 ibcm_dummy_rc_handler(void *priv, ibt_cm_event_t *event,
6839 ibt_cm_return_args_t *ret_args, void *priv_data, ibt_priv_data_len_t len)
6840 {
6841 ibcm_state_data_t dummy_rc;
6842
6843 dummy_rc.cm_handler = ibcm_dummy_rc_handler;
6844
6845 IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_rc_handler: "
6846 "dummy_ud.ud_cm_handler %p", dummy_rc.cm_handler);
6847 /*
6848 * Call all routines that the client's callback routine could call.
6849 */
6850
6851 return (IBT_CM_ACCEPT);
6852 }
|
23 */
24
25 #include <sys/ib/mgt/ibcm/ibcm_impl.h>
26 #include <sys/ib/ibtl/ibti.h>
27 #include <sys/ib/mgt/ibcm/ibcm_arp.h>
28
29 /*
30 * ibcm_ti.c
31 * These routines implement the Communication Manager's interfaces to IBTL.
32 */
33
34 /* CM rc recycle task args structure definition */
35 typedef struct ibcm_taskq_recycle_arg_s {
36 ibt_channel_hdl_t rc_chan;
37 ibt_cep_flags_t control;
38 uint8_t hca_port_num;
39 ibt_recycle_handler_t func;
40 void *arg;
41 } ibcm_taskq_recycle_arg_t;
42
43 static ibt_status_t ibcm_init_reply_addr(ibcm_hca_info_t *hcap,
44 ibcm_mad_addr_t *reply_addr, ibt_chan_open_args_t *chan_args,
45 ibt_chan_open_flags_t flags, ib_time_t *cm_pkt_lt, ib_lid_t prim_slid);
46 static void ibcm_process_abort_via_taskq(void *args);
47 static ibt_status_t ibcm_process_rc_recycle_ret(void *recycle_arg);
48 static ibt_status_t ibcm_process_join_mcg(void *taskq_arg);
49 static void ibcm_process_async_join_mcg(void *tq_arg);
50
51 ibt_status_t ibcm_get_node_rec(ibmf_saa_handle_t, sa_node_record_t *,
52 uint64_t c_mask, void *, size_t *);
53
54 static ibt_status_t ibcm_close_rc_channel(ibt_channel_hdl_t channel,
55 ibcm_state_data_t *statep, ibt_execution_mode_t mode);
56
57 /* Address Record management definitions */
58 #define IBCM_DAPL_ATS_NAME "DAPL Address Translation Service"
59 #define IBCM_DAPL_ATS_SID 0x10000CE100415453ULL
60 #define IBCM_DAPL_ATS_NBYTES 16
61 ibcm_svc_info_t *ibcm_ar_svcinfop;
62 ibcm_ar_t *ibcm_ar_list;
63
64 /*
65 * Tunable parameter to turnoff the overriding of pi_path_mtu value.
66 * 1 By default override the path record's pi_path_mtu value to
67 * IB_MTU_1K for all RC channels. This is done only for the
68 * channels established on Tavor HCA and the path's pi_path_mtu
69 * is greater than IB_MTU_1K.
70 * 0 Do not override, use pi_path_mtu by default.
71 */
72 int ibcm_override_path_mtu = 1;
73
74 #ifdef DEBUG
75 static void ibcm_print_reply_addr(ibt_channel_hdl_t channel,
76 ibcm_mad_addr_t *cm_reply_addr);
77 #endif
78
79 /*
80 * ibt_open_rc_channel()
81 * ibt_open_rc_channel opens a communication channel on the specified
82 * channel to the specified service. For connection service type qp's
83 * the CM initiates the CEP to establish the connection and transitions
84 * the QP/EEC to the "Ready to send" State modifying the QP/EEC's
85 * attributes as necessary.
86 * The implementation of this function assumes that alt path is different
87 * from primary path. It is assumed that the Path functions ensure that.
88 *
89 * RETURN VALUES:
90 * IBT_SUCCESS on success (or respective failure on error)
91 */
92 ibt_status_t
93 ibt_open_rc_channel(ibt_channel_hdl_t channel, ibt_chan_open_flags_t flags,
94 ibt_execution_mode_t mode, ibt_chan_open_args_t *chan_args,
95 ibt_rc_returns_t *ret_args)
96 {
97 /* all fields that are related to REQ MAD formation */
98
99 ib_pkey_t prim_pkey;
543 IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: "
544 "chan 0x%p ibt_modify_qp() = %d", channel, status);
545 }
546
547 /* allocate ibcm_state_data_t before grabbing the WRITER lock */
548 statep = kmem_zalloc(sizeof (ibcm_state_data_t), KM_SLEEP);
549 rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
550 lkup_status = ibcm_lookup_msg(IBCM_OUTGOING_REQ, local_comid, 0, 0,
551 hcap, &statep);
552 rw_exit(&hcap->hca_state_rwlock);
553
554 /* CM should be seeing this for the first time */
555 ASSERT(lkup_status == IBCM_LOOKUP_NEW);
556
557 /* Increment the hca's resource count */
558 ibcm_inc_hca_res_cnt(hcap);
559
560 /* Once a resource created on hca, no need to hold the acc cnt */
561 ibcm_dec_hca_acc_cnt(hcap);
562
563 statep->timerid = 0;
564 statep->local_hca_guid = hca_guid;
565 statep->local_qpn = local_qpn;
566 statep->stored_reply_addr.cm_qp_entry = cm_qp_entry;
567 statep->prim_port = IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num;
568 statep->alt_port = IBCM_ALT_CEP_PATH(chan_args).cep_hca_port_num;
569
570
571 /* Save "statep" as channel's CM private data. */
572 statep->channel = channel;
573 IBCM_SET_CHAN_PRIVATE(statep->channel, statep);
574
575 statep->stored_msg = ibmf_msg;
576 statep->dreq_msg = ibmf_msg_dreq;
577
578 /* Start filling in the REQ MAD */
579 req_msgp = (ibcm_req_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
580 req_msgp->req_local_comm_id = h2b32(local_comid);
581 req_msgp->req_svc_id = h2b64(chan_args->oc_path->pi_sid);
582 req_msgp->req_local_ca_guid = h2b64(hca_guid);
583 req_msgp->req_local_qkey = h2b32(local_qkey); /* for EEC/RD */
584
585 /* Bytes 32-35 are req_local_qpn and req_off_resp_resources */
586 req_msgp->req_local_qpn_plus = h2b32(local_qpn << 8 | rdma_in);
587
588 /* Bytes 36-39 are req_local_eec_no and req_off_initiator_depth */
589 req_msgp->req_local_eec_no_plus = h2b32(local_eecn << 8 | rdma_out);
590
591 if (flags & IBT_OCHAN_REMOTE_CM_TM)
592 remote_cm_resp_time = chan_args->oc_remote_cm_time;
593 else
594 remote_cm_resp_time = ibcm_remote_response_time;
595
596 /*
597 * Bytes 40-43 - remote_eecn, remote_cm_resp_time, tran_type,
773 IBCM_ALT_ADDS_VECT(chan_args).av_srvl << 4 |
774 ((alternate_grh == B_TRUE) ? 0 : 8);
775 req_msgp->req_alt_localtime_plus = ibt_usec2ib((2 *
776 ibt_ib2usec(chan_args->oc_path->pi_alt_pkt_lt)) +
777 ibt_ib2usec(hcap->hca_ack_delay)) << 3;
778
779 IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
780 "alt_dlid %x ", channel,
781 IBCM_ALT_ADDS_VECT(chan_args).av_dlid);
782
783 IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
784 "alt GID %llX:%llX", channel,
785 IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_prefix,
786 IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_guid);
787 }
788
789 len = min(chan_args->oc_priv_data_len, IBT_REQ_PRIV_DATA_SZ);
790 if ((len > 0) && chan_args->oc_priv_data)
791 bcopy(chan_args->oc_priv_data, req_msgp->req_private_data, len);
792
793 /* return_data is filled up in the state machine code */
794 if (ret_args != NULL) {
795 statep->open_return_data = ret_args;
796 }
797
798 /* initialize some statep fields here */
799 statep->mode = IBCM_ACTIVE_MODE;
800 statep->hcap = hcap;
801
802 statep->cm_handler = chan_args->oc_cm_handler;
803 statep->state_cm_private = chan_args->oc_cm_clnt_private;
804
805 statep->pkt_life_time =
806 ibt_ib2usec(chan_args->oc_path->pi_prim_pkt_lt);
807
808 statep->timer_value = ibt_ib2usec(ibt_usec2ib(
809 2 * ibt_ib2usec(cm_pkt_lt) + remote_cm_resp_time));
810
811 /* Initialize statep->stored_reply_addr */
812 statep->stored_reply_addr.ibmf_hdl = ibmf_hdl;
832 statep->open_done = B_FALSE;
833 statep->state = statep->timer_stored_state = IBCM_STATE_REQ_SENT;
834 IBCM_REF_CNT_INCR(statep); /* Decremented before return */
835 IBCM_REF_CNT_INCR(statep); /* Decremented after REQ is posted */
836 statep->send_mad_flags |= IBCM_REQ_POST_BUSY;
837
838 /*
839 * Skip moving channel to error state during close, for OFUV clients.
840 * OFUV clients transition the channel to error state by itself.
841 */
842 if (flags & IBT_OCHAN_OFUV)
843 statep->is_this_ofuv_chan = B_TRUE;
844
845 IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
846 h2b16(IBCM_INCOMING_REQ + IBCM_ATTR_BASE_ID);
847
848 IBCM_OUT_HDRP(statep->stored_msg)->TransactionID =
849 h2b64(ibcm_generate_tranid(IBCM_INCOMING_REQ, statep->local_comid,
850 0));
851
852 ibtl_cm_chan_is_opening(channel);
853
854 ibcm_open_enqueue(statep);
855
856 mutex_enter(&statep->state_mutex);
857
858 if (mode == IBT_BLOCKING) {
859
860 /* wait for REQ/REP/RTU */
861 while (statep->open_done != B_TRUE) {
862 cv_wait(&statep->block_client_cv, &statep->state_mutex);
863 }
864
865 /*
866 * In the case that open_channel() fails because of a
867 * REJ or timeout, change retval to IBT_CM_FAILURE
868 */
869 if (statep->open_return_data->rc_status != IBT_CM_SUCCESS) {
870 status = IBT_CM_FAILURE;
871 ibtl_cm_chan_open_is_aborted(channel);
899 * If Redirect GID is not specified or specified to be on the same
900 * subnet, then
901 * Build CM path from chan_args->oc_cm_redirect_info
902 * Set CM pkt lt to subnet timeout
903 * Else (ie., GID specified, but on a different subnet)
904 * Do a path lookup to build CM Path and set CM pkt lt
905 *
906 */
907 static ibt_status_t
908 ibcm_init_reply_addr(ibcm_hca_info_t *hcap, ibcm_mad_addr_t *reply_addr,
909 ibt_chan_open_args_t *chan_args, ibt_chan_open_flags_t flags,
910 ib_time_t *cm_pkt_lt, ib_lid_t prim_slid)
911 {
912 ibt_adds_vect_t *cm_adds;
913 ibt_path_info_t path;
914 boolean_t cm_grh;
915 ibt_status_t status;
916
917 IBTF_DPRINTF_L5(cmlog, "ibcm_init_reply_addr:");
918
919 /*
920 * sending side CM lid/gid/port num are not based on any redirect
921 * params. These values are set to primary RC path lid/gid/port num.
922 * In the future, these values can be set based on framework policy
923 * decisions ensuring reachability.
924 */
925 reply_addr->grh_hdr.ig_sender_gid =
926 IBCM_PRIM_ADDS_VECT(chan_args).av_sgid;
927 reply_addr->rcvd_addr.ia_local_lid = prim_slid;
928 reply_addr->port_num = IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num;
929
930 if (flags & IBT_OCHAN_PORT_REDIRECTED) {
931 IBTF_DPRINTF_L4(cmlog, "ibcm_init_rely_addr: "
932 "IBT_OCHAN_PORT_REDIRECTED specified");
933
934 status = ibt_index2pkey_byguid(hcap->hca_guid,
935 chan_args->oc_cm_cep_path->cep_hca_port_num,
936 chan_args->oc_cm_cep_path->cep_pkey_ix,
937 &reply_addr->rcvd_addr.ia_p_key);
938
1063 cm_adds = &(IBCM_PRIM_ADDS_VECT(chan_args));
1064 }
1065
1066
1067 cm_grh = cm_adds->av_send_grh;
1068 reply_addr->grh_exists = cm_grh;
1069
1070 reply_addr->rcvd_addr.ia_remote_lid =
1071 cm_adds->av_dlid;
1072 reply_addr->grh_hdr.ig_recver_gid =
1073 cm_adds->av_dgid;
1074 reply_addr->grh_hdr.ig_flow_label =
1075 cm_adds->av_flow & IB_GRH_FLOW_LABEL_MASK;
1076 reply_addr->grh_hdr.ig_tclass =
1077 (cm_grh == B_TRUE) ? cm_adds->av_tclass : 0;
1078 reply_addr->grh_hdr.ig_hop_limit =
1079 (cm_grh == B_TRUE) ? cm_adds->av_hop : 1;
1080 reply_addr->rcvd_addr.ia_service_level =
1081 cm_adds->av_srvl;
1082
1083 return (IBT_SUCCESS);
1084 }
1085
1086
1087 /*
1088 * ibt_prime_close_rc_channel()
1089 * It allocates resources required for close channel operation, so
1090 * ibt_close_rc_channel can be called from interrupt routine.
1091 *
1092 * INPUTS:
1093 * channel The address of an ibt_channel_t struct that
1094 * specifies the channel to open.
1095 *
1096 * RETURN VALUES:
1097 * IBT_SUCCESS on success(or respective failure on error)
1098 *
1099 * Clients are typically expected to call this function in established state
1100 */
1101 ibt_status_t
1102 ibt_prime_close_rc_channel(ibt_channel_hdl_t channel)
1289 ibcm_close_enqueue(statep);
1290 mutex_exit(&statep->state_mutex);
1291
1292 return (IBT_SUCCESS);
1293 }
1294
1295 void
1296 ibcm_close_start(ibcm_state_data_t *statep)
1297 {
1298 mutex_enter(&statep->state_mutex);
1299 (void) ibcm_close_rc_channel(statep->channel, statep, IBT_NONBLOCKING);
1300 }
1301
1302 static
1303 ibt_status_t
1304 ibcm_close_rc_channel(ibt_channel_hdl_t channel, ibcm_state_data_t *statep,
1305 ibt_execution_mode_t mode)
1306 {
1307 ibcm_hca_info_t *hcap;
1308
1309 ASSERT(MUTEX_HELD(&statep->state_mutex));
1310
1311 IBTF_DPRINTF_L3(cmlog, "ibcm_close_rc_channel: chan 0x%p statep %p",
1312 channel, statep);
1313
1314 hcap = statep->hcap;
1315
1316 /* HCA must have been in active state. If not, it's a client bug */
1317 if (!IBCM_ACCESS_HCA_OK(hcap)) {
1318 IBTF_DPRINTF_L2(cmlog, "ibcm_close_rc_channel: chan 0x%p "
1319 "hcap 0x%p not active", channel, hcap);
1320 IBCM_REF_CNT_DECR(statep);
1321 mutex_exit(&statep->state_mutex);
1322 return (IBT_CHAN_HDL_INVALID);
1323 }
1324
1325 if (statep->state == IBCM_STATE_TRANSIENT_ESTABLISHED) {
1326 while (statep->cep_in_rts == IBCM_BLOCK)
1327 cv_wait(&statep->block_mad_cv, &statep->state_mutex);
1328 }
1607 IBTF_DPRINTF_L3(cmlog, "ibt_recycle_rc (%p, 0x%X, %d, %p, %p)", rc_chan,
1608 control, hca_port_num, func, arg);
1609
1610 if (IBCM_INVALID_CHANNEL(rc_chan)) {
1611 IBTF_DPRINTF_L2(cmlog, "ibt_recycle_rc: invalid channel");
1612 return (IBT_CHAN_HDL_INVALID);
1613 }
1614
1615 /* check qp state */
1616 retval = ibt_query_qp(rc_chan, &qp_attr);
1617
1618 if (retval != IBT_SUCCESS)
1619 return (retval);
1620
1621 if (qp_attr.qp_info.qp_trans != IBT_RC_SRV)
1622 return (IBT_CHAN_SRV_TYPE_INVALID);
1623
1624 if (qp_attr.qp_info.qp_state != IBT_STATE_ERROR)
1625 return (IBT_CHAN_STATE_INVALID);
1626
1627 ibcm_tq_recycle_arg = kmem_alloc(sizeof (ibcm_taskq_recycle_arg_t),
1628 KM_SLEEP);
1629
1630 ibcm_tq_recycle_arg->rc_chan = rc_chan;
1631 ibcm_tq_recycle_arg->control = control;
1632 ibcm_tq_recycle_arg->hca_port_num = hca_port_num;
1633 ibcm_tq_recycle_arg->func = func;
1634 ibcm_tq_recycle_arg->arg = arg;
1635
1636 IBCM_GET_CHAN_PRIVATE(rc_chan, statep);
1637
1638 /*
1639 * If non-blocking ie., func specified and channel has not yet completed
1640 * the timewait, then schedule the work for later
1641 */
1642 if ((func != NULL) && (statep != NULL)) {
1643 IBCM_RELEASE_CHAN_PRIVATE(rc_chan);
1644 statep->recycle_arg = ibcm_tq_recycle_arg;
1645 return (IBT_SUCCESS);
1646 }
1647
1648 /*
1649 * if blocking ie., func specified, and channel has not yet completed
1650 * the timewait, then block until the channel completes the timewait
1651 */
1652 if (statep != NULL)
1653 IBCM_RELEASE_CHAN_PRIVATE(rc_chan);
1654 IBCM_WAIT_CHAN_PRIVATE(rc_chan);
1655
1656 if (func) { /* NON BLOCKING case. Taskq for QP state change */
1657 (void) taskq_dispatch(ibcm_taskq, ibcm_process_rc_recycle,
1658 ibcm_tq_recycle_arg, TQ_SLEEP);
1659 return (IBT_SUCCESS);
1660 } else /* BLOCKING case */
1661 return (ibcm_process_rc_recycle_ret(ibcm_tq_recycle_arg));
1662 }
1663
1664 void
1750 ibcm_process_abort_via_taskq(void *args)
1751 {
1752 ibcm_state_data_t *statep = (ibcm_state_data_t *)args;
1753
1754 ibcm_process_abort(statep);
1755 mutex_enter(&statep->state_mutex);
1756 IBCM_REF_CNT_DECR(statep);
1757 mutex_exit(&statep->state_mutex);
1758 }
1759
1760 /*
1761 * Local UD CM Handler's private data, used during ibt_request_ud_dest() in
1762 * Non-Blocking mode operations.
1763 */
1764 typedef struct ibcm_local_handler_s {
1765 ibt_cm_ud_handler_t actual_cm_handler;
1766 void *actual_cm_private;
1767 ibt_ud_dest_t *dest_hdl;
1768 } ibcm_local_handler_t;
1769
1770 /*
1771 * Local UD CM Handler, used when ibt_alloc_ud_dest() is issued in
1772 * NON-Blocking mode.
1773 *
1774 * Out here, we update the UD Destination handle with
1775 * the obtained DQPN and QKey (from SIDR REP) and invokes actual client
1776 * handler that was specified by the client.
1777 */
1778 static ibt_cm_status_t
1779 ibcm_local_cm_handler(void *priv, ibt_cm_ud_event_t *event,
1780 ibt_cm_ud_return_args_t *ret_args, void *priv_data, ibt_priv_data_len_t len)
1781 {
1782 ibcm_local_handler_t *handler_priv = (ibcm_local_handler_t *)priv;
1783
1784 IBTF_DPRINTF_L4(cmlog, "ibcm_local_cm_handler: event %d",
1785 event->cm_type);
1786
1787 ASSERT(handler_priv != NULL);
1788
1789 switch (event->cm_type) {
1919 /* Return failure if the HCA device or Port is not operational */
1920
1921 if ((retval = ibt_get_port_state_byguid(port.hp_hca_guid, port.hp_port,
1922 NULL, NULL)) != IBT_SUCCESS) {
1923 /* Device Port is not in good state, don't use it. */
1924 IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: Invalid "
1925 "port specified or port not active");
1926 ibcm_dec_hca_acc_cnt(hcap);
1927 return (retval);
1928 }
1929
1930 retval = ibt_index2pkey_byguid(port.hp_hca_guid, port.hp_port,
1931 attr->ud_pkey_ix, &ud_pkey);
1932 if (retval != IBT_SUCCESS) {
1933 IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
1934 "Failed to convert index2pkey: %d", retval);
1935 ibcm_dec_hca_acc_cnt(hcap);
1936 return (retval);
1937 }
1938
1939 /* Allocate a new request id */
1940 if (ibcm_alloc_reqid(hcap, &sidr_entry.srch_req_id) == IBCM_FAILURE) {
1941 IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
1942 "no req id available");
1943 ibcm_dec_hca_acc_cnt(hcap);
1944 return (IBT_INSUFF_KERNEL_RESOURCE);
1945 }
1946
1947 if ((hcap->hca_port_info[port.hp_port - 1].port_ibmf_hdl == NULL) &&
1948 ((retval = ibcm_hca_reinit_port(hcap, port.hp_port - 1))
1949 != IBT_SUCCESS)) {
1950 IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
1951 "ibmf reg or callback setup failed during re-initialize");
1952 return (retval);
1953 }
1954
1955 ibmf_hdl = hcap->hca_port_info[port.hp_port - 1].port_ibmf_hdl;
1956
1957 /* find the ibmf QP to post the SIDR REQ */
1958 if ((cm_qp_entry = ibcm_find_qp(hcap, port.hp_port, ud_pkey)) ==
1960 IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: IBMF QP allocation"
1961 " failed");
1962 ibcm_dec_hca_acc_cnt(hcap);
1963 return (IBT_INSUFF_RESOURCE);
1964 }
1965
1966 if ((retval = ibcm_alloc_out_msg(ibmf_hdl, &ibmf_msg, MAD_METHOD_SEND))
1967 != IBT_SUCCESS) {
1968 IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: IBMF MSG allocation"
1969 " failed");
1970 ibcm_release_qp(cm_qp_entry);
1971 ibcm_dec_hca_acc_cnt(hcap);
1972 return (retval);
1973 }
1974
1975 sidr_entry.srch_lid = port.hp_base_lid;
1976 sidr_entry.srch_gid = attr->ud_addr->av_sgid;
1977 sidr_entry.srch_grh_exists = attr->ud_addr->av_send_grh;
1978 sidr_entry.srch_mode = IBCM_ACTIVE_MODE;
1979
1980 /* do various allocations needed here */
1981 rw_enter(&hcap->hca_sidr_list_lock, RW_WRITER);
1982
1983 (void) ibcm_find_sidr_entry(&sidr_entry, hcap, &ud_statep,
1984 IBCM_FLAG_ADD);
1985 rw_exit(&hcap->hca_sidr_list_lock);
1986
1987 /* Increment hca's resource count */
1988 ibcm_inc_hca_res_cnt(hcap);
1989
1990 /* After a resource created on hca, no need to hold the acc cnt */
1991 ibcm_dec_hca_acc_cnt(hcap);
1992
1993 /* Initialize some ud_statep fields */
1994 ud_statep->ud_stored_msg = ibmf_msg;
1995 ud_statep->ud_svc_id = attr->ud_sid;
1996 ud_statep->ud_pkt_life_time =
1997 ibt_ib2usec(attr->ud_pkt_lt);
1998 ud_statep->ud_stored_reply_addr.cm_qp_entry = cm_qp_entry;
1999
2000 /* set remaining retry cnt */
2001 ud_statep->ud_remaining_retry_cnt = ud_statep->ud_max_cm_retries;
2002
2003 /*
2004 * Get UD handler and corresponding args which is pass it back
2005 * as first argument for the handler.
2006 */
2007 ud_statep->ud_state_cm_private = attr->ud_cm_private;
2008
2009 if (mode == IBT_BLOCKING)
2010 ud_statep->ud_return_data = ret_args;
2011 else
2012 ud_statep->ud_cm_handler = attr->ud_cm_handler;
2025 ud_statep->ud_stored_reply_addr.grh_hdr.ig_flow_label =
2026 attr->ud_addr->av_flow & IB_GRH_FLOW_LABEL_MASK;
2027
2028 /* needs to be derived based on the base LID and path bits */
2029 ud_statep->ud_stored_reply_addr.rcvd_addr.ia_local_lid =
2030 port.hp_base_lid;
2031 ud_statep->ud_stored_reply_addr.rcvd_addr.ia_remote_lid =
2032 attr->ud_addr->av_dlid;
2033 ud_statep->ud_stored_reply_addr.rcvd_addr.ia_p_key = ud_pkey;
2034 ud_statep->ud_stored_reply_addr.rcvd_addr.ia_q_key = IB_GSI_QKEY;
2035 ud_statep->ud_stored_reply_addr.rcvd_addr.ia_service_level =
2036 attr->ud_addr->av_srvl;
2037
2038 /*
2039 * This may be enchanced later, to use a remote qno based on past
2040 * redirect rej mad responses. This would be the place to specify
2041 * appropriate remote qno
2042 */
2043 ud_statep->ud_stored_reply_addr.rcvd_addr.ia_remote_qno = 1;
2044
2045 /* Initialize the SIDR REQ message fields */
2046 sidr_req_msgp =
2047 (ibcm_sidr_req_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg);
2048
2049 sidr_req_msgp->sidr_req_request_id = h2b32(ud_statep->ud_req_id);
2050 sidr_req_msgp->sidr_req_service_id = h2b64(attr->ud_sid);
2051 sidr_req_msgp->sidr_req_pkey = h2b16(ud_pkey);
2052 IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->AttributeID =
2053 h2b16(IBCM_INCOMING_SIDR_REQ + IBCM_ATTR_BASE_ID);
2054
2055 if ((attr->ud_priv_data != NULL) && (attr->ud_priv_data_len > 0)) {
2056 bcopy(attr->ud_priv_data, sidr_req_msgp->sidr_req_private_data,
2057 min(attr->ud_priv_data_len, IBT_SIDR_REQ_PRIV_DATA_SZ));
2058 }
2059
2060 /* Send out the SIDR REQ message */
2061 ud_statep->ud_state = IBCM_STATE_SIDR_REQ_SENT;
2062 ud_statep->ud_timer_stored_state = IBCM_STATE_SIDR_REQ_SENT;
2063 IBCM_UD_REF_CNT_INCR(ud_statep); /* for non-blocking SIDR REQ post */
2064 ud_statep->ud_timer_value = ibt_ib2usec(ibcm_max_sidr_rep_proctime) +
2065 (ud_statep->ud_pkt_life_time * 2);
2066
2067 IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->TransactionID =
2068 h2b64(ibcm_generate_tranid(IBCM_INCOMING_SIDR_REQ,
2069 ud_statep->ud_req_id, 0));
2070
2071 IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: timer_value in HZ = %x",
2072 ud_statep->ud_timer_value);
2073
2074 ibcm_post_ud_mad(ud_statep, ud_statep->ud_stored_msg,
2075 ibcm_post_sidr_req_complete, ud_statep);
2076
2077 mutex_enter(&ud_statep->ud_state_mutex);
2078
2079 /* Wait for SIDR_REP */
2080 if (mode == IBT_BLOCKING) {
2081 IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: blocking");
2082
2083 while (ud_statep->ud_blocking_done != B_TRUE) {
2084 cv_wait(&ud_statep->ud_block_client_cv,
2085 &ud_statep->ud_state_mutex);
2086 }
2087
2088 IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: finished blocking");
2089
2090 if (ret_args->ud_status == IBT_CM_SREP_QPN_VALID) {
2091 IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: DQPN = %x, "
2092 "status = %x, QKey = %x", ret_args->ud_dqpn,
2093 ret_args->ud_status, ret_args->ud_qkey);
2148 attr->ud_addr);
2149 if (retval != IBT_SUCCESS) {
2150 IBTF_DPRINTF_L2(cmlog, "ibt_request_ud_dest: "
2151 "Address Handle Modification failed: %d", retval);
2152 return (retval);
2153 }
2154
2155 if (mode == IBT_NONBLOCKING) {
2156 /*
2157 * In NON-BLOCKING mode, and we need to update the destination
2158 * handle with the DQPN and QKey that are obtained from
2159 * SIDR REP, hook-up our own handler, so that we can catch
2160 * the event, and we ourselves call the actual client's
2161 * ud_cm_handler, in our handler.
2162 */
2163
2164 /* Allocate memory for local handler's private data. */
2165 local_handler_priv =
2166 kmem_alloc(sizeof (*local_handler_priv), KM_SLEEP);
2167
2168 local_handler_priv->actual_cm_handler = attr->ud_cm_handler;
2169 local_handler_priv->actual_cm_private = attr->ud_cm_private;
2170 local_handler_priv->dest_hdl = ud_destp;
2171
2172 attr->ud_cm_handler = ibcm_local_cm_handler;
2173 attr->ud_cm_private = local_handler_priv;
2174 }
2175
2176 /* In order to get DQPN and Destination QKey, perform SIDR */
2177 retval = ibcm_ud_get_dqpn(attr, mode, ud_ret_args);
2178 if (retval != IBT_SUCCESS) {
2179 IBTF_DPRINTF_L2(cmlog, "ibt_request_ud_dest: "
2180 "Failed to get DQPN: %d", retval);
2181
2182 /* Free memory allocated for local handler's private data. */
2183 if (local_handler_priv != NULL)
2184 kmem_free(local_handler_priv,
2185 sizeof (*local_handler_priv));
2186 return (retval);
2187 }
2188
2189 /*
2190 * Fill in the dqpn and dqkey as obtained from ud_ret_args,
2191 * values will be valid only on BLOCKING mode.
2276 statep = (ibcm_state_data_t *)cm_session_id;
2277
2278 if (statep == NULL) {
2279 IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: statep NULL");
2280 return (IBT_INVALID_PARAM);
2281 }
2282
2283 IBTF_DPRINTF_L4(cmlog, "ibt_cm_delay: statep %p", statep);
2284
2285 /* Allocate an ibmf msg for mra, if not allocated yet */
2286 if (statep->mra_msg == NULL) {
2287 if ((status = ibcm_alloc_out_msg(
2288 statep->stored_reply_addr.ibmf_hdl, &statep->mra_msg,
2289 MAD_METHOD_SEND)) != IBT_SUCCESS) {
2290 IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: chan 0x%p"
2291 "IBMF MSG allocation failed", statep->channel);
2292 return (status);
2293 }
2294 }
2295
2296 mra_msgp = (ibcm_mra_msg_t *)IBCM_OUT_MSGP(statep->mra_msg);
2297 mra_msgp->mra_local_comm_id = h2b32(statep->local_comid);
2298 mra_msgp->mra_remote_comm_id = h2b32(statep->remote_comid);
2299
2300 /* fill in rest of MRA's fields - Message MRAed and Service Timeout */
2301 if (flags == IBT_CM_DELAY_REQ) {
2302 msg_typ = IBT_CM_MRA_TYPE_REQ;
2303 } else if (flags == IBT_CM_DELAY_REP) {
2304 msg_typ = IBT_CM_MRA_TYPE_REP;
2305 } else if (flags == IBT_CM_DELAY_LAP) {
2306 msg_typ = IBT_CM_MRA_TYPE_LAP;
2307 }
2308
2309 mra_msgp->mra_message_type_plus = msg_typ << 6;
2310 mra_msgp->mra_service_timeout_plus = ibt_usec2ib(service_time) << 3;
2311
2312 len = min(len, IBT_MRA_PRIV_DATA_SZ);
2313 if (priv_data && (len > 0))
2314 bcopy(priv_data, mra_msgp->mra_private_data, len);
2315
2316 IBCM_OUT_HDRP(statep->mra_msg)->AttributeID =
2317 h2b16(IBCM_INCOMING_MRA + IBCM_ATTR_BASE_ID);
2318
2319 mutex_enter(&statep->state_mutex);
2320
2321 if ((statep->mode == IBCM_ACTIVE_MODE) &&
2322 (statep->state == IBCM_STATE_REP_RCVD)) {
2323 statep->state = IBCM_STATE_MRA_REP_SENT;
2324 } else if (statep->mode == IBCM_PASSIVE_MODE) {
2325 if (statep->state == IBCM_STATE_REQ_RCVD) {
2326 statep->state = IBCM_STATE_MRA_SENT;
2327 } else if (statep->ap_state == IBCM_AP_STATE_LAP_RCVD) {
2328 statep->ap_state = IBCM_AP_STATE_MRA_LAP_RCVD;
2329 } else {
2330 IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: invalid state "
2331 "/ap_state/mode %x, %x, %x", statep->state,
2332 statep->ap_state, statep->mode);
2333 mutex_exit(&statep->state_mutex);
2334 return (IBT_CHAN_STATE_INVALID);
2335 }
2336 } else {
2337 IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: invalid state "
2338 "/ap_state/mode %x, %x, %x", statep->state,
2392 * in the range.
2393 *
2394 * ibt_register_service() returns:
2395 * IBT_SUCCESS - added a service successfully.
2396 * IBT_INVALID_PARAM - invalid input parameter.
2397 * IBT_CM_FAILURE - failed to add the service.
2398 * IBT_CM_SERVICE_EXISTS - service already exists.
2399 * IBT_INSUFF_KERNEL_RESOURCE - ran out of local service ids (should
2400 * never happen).
2401 */
2402 ibt_status_t
2403 ibt_register_service(ibt_clnt_hdl_t ibt_hdl, ibt_srv_desc_t *srv,
2404 ib_svc_id_t sid, int num_sids, ibt_srv_hdl_t *srv_hdl, ib_svc_id_t *ret_sid)
2405 {
2406 ibcm_svc_info_t *svcinfop;
2407
2408 IBTF_DPRINTF_L2(cmlog, "ibt_register_service(%p (%s), %p, 0x%llX, %d)",
2409 ibt_hdl, ibtl_cm_get_clnt_name(ibt_hdl), srv, (longlong_t)sid,
2410 num_sids);
2411
2412 *srv_hdl = NULL;
2413
2414 if (num_sids <= 0) {
2415 IBTF_DPRINTF_L2(cmlog, "ibt_register_service: "
2416 "Invalid number of service-ids specified (%d)", num_sids);
2417 return (IBT_INVALID_PARAM);
2418 }
2419
2420 if (sid == 0) {
2421 if (ret_sid == NULL)
2422 return (IBT_INVALID_PARAM);
2423 sid = ibcm_alloc_local_sids(num_sids);
2424 if (sid == 0)
2425 return (IBT_INSUFF_KERNEL_RESOURCE);
2426
2427 /* Make sure that the ServiceId specified is not of LOCAL AGN type. */
2428 } else if ((sid & IB_SID_AGN_MASK) == IB_SID_AGN_LOCAL) {
2429 IBTF_DPRINTF_L2(cmlog, "ibt_register_service: "
2430 "Invalid non-LOCAL SID specified: 0x%llX",
2431 (longlong_t)sid);
2441 }
2442
2443 /*
2444 * 'sid' and 'num_sids' are filled in ibcm_create_svc_entry()
2445 */
2446 svcinfop->svc_flags = srv->sd_flags;
2447 svcinfop->svc_rc_handler = srv->sd_handler;
2448 svcinfop->svc_ud_handler = srv->sd_ud_handler;
2449
2450 if (ret_sid != NULL)
2451 *ret_sid = sid;
2452
2453 *srv_hdl = svcinfop;
2454
2455 ibtl_cm_change_service_cnt(ibt_hdl, num_sids);
2456
2457 /* If this message isn't seen, then ibt_register_service failed. */
2458 IBTF_DPRINTF_L2(cmlog, "ibt_register_service: done (%p, %llX)",
2459 svcinfop, sid);
2460
2461 return (IBT_SUCCESS);
2462 }
2463
2464
2465 static ibt_status_t
2466 ibcm_write_service_record(ibmf_saa_handle_t saa_handle,
2467 sa_service_record_t *srv_recp, ibmf_saa_access_type_t saa_type)
2468 {
2469 int rval;
2470 int retry;
2471
2472 ibcm_sa_access_enter();
2473 for (retry = 0; retry < ibcm_max_sa_retries; retry++) {
2474 rval = ibmf_saa_update_service_record(
2475 saa_handle, srv_recp, saa_type, 0);
2476 if (rval != IBMF_TRANS_TIMEOUT) {
2477 break;
2478 }
2479 IBTF_DPRINTF_L2(cmlog, "ibcm_write_service_record: "
2480 "ibmf_saa_update_service_record timed out"
2552 mutex_exit(&ibcm_svc_info_lock);
2553 IBTF_DPRINTF_L3(cmlog, "ibcm_rem_stale_srec: "
2554 "This is not Stale, it's an active record");
2555 continue;
2556 }
2557 mutex_exit(&ibcm_svc_info_lock);
2558
2559 IBTF_DPRINTF_L2(cmlog, "ibcm_rem_stale_srec: "
2560 "Removing Stale Rec: %s, %llX",
2561 srv_resp->ServiceName, srv_resp->ServiceID);
2562
2563 IBCM_DUMP_SERVICE_REC(srv_resp);
2564
2565 /*
2566 * Remove the Service Record Entry from SA.
2567 *
2568 * Get ServiceID info from Response Buf, other
2569 * attributes are already filled-in.
2570 */
2571
2572 srec->ServiceID = srv_resp->ServiceID;
2573
2574 (void) ibcm_write_service_record(saa_handle, srec,
2575 IBMF_SAA_DELETE);
2576 }
2577
2578 /* Deallocate the memory for results_p. */
2579 kmem_free(results_p, length);
2580 }
2581 }
2582
2583
2584
2585 /*
2586 * ibt_bind_service()
2587 * Register a service with the IBCM
2588 *
2589 * INPUTS:
2590 * srv_hdl The service id handle returned to the client
2591 * on an ibt_service_register() call.
2592 *
2593 * gid The GID to which to bind the service.
2616 */
2617 ibt_status_t
2618 ibt_bind_service(ibt_srv_hdl_t srv_hdl, ib_gid_t gid, ibt_srv_bind_t *srv_bind,
2619 void *cm_private, ibt_sbind_hdl_t *sb_hdl_p)
2620 {
2621 ibt_status_t status;
2622 ibtl_cm_hca_port_t port;
2623 ibcm_svc_bind_t *sbindp, *sbp;
2624 ibcm_hca_info_t *hcap;
2625 ib_svc_id_t sid, start_sid, end_sid;
2626 ibmf_saa_handle_t saa_handle;
2627 sa_service_record_t srv_rec;
2628 uint16_t pkey_ix;
2629
2630 if (sb_hdl_p != NULL)
2631 *sb_hdl_p = NULL; /* return value for error cases */
2632
2633 IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: srv_hdl %p, gid (%llX:%llX)",
2634 srv_hdl, (longlong_t)gid.gid_prefix, (longlong_t)gid.gid_guid);
2635
2636 /* Call ibtl_cm_get_hca_port to get the port number and the HCA GUID. */
2637 if ((status = ibtl_cm_get_hca_port(gid, 0, &port)) != IBT_SUCCESS) {
2638 IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
2639 "ibtl_cm_get_hca_port failed: %d", status);
2640 return (status);
2641 }
2642 IBTF_DPRINTF_L4(cmlog, "ibt_bind_service: Port:%d HCA GUID:%llX",
2643 port.hp_port, port.hp_hca_guid);
2644
2645 hcap = ibcm_find_hca_entry(port.hp_hca_guid);
2646 if (hcap == NULL) {
2647 IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: NO HCA found");
2648 return (IBT_HCA_BUSY_DETACHING);
2649 }
2650 IBTF_DPRINTF_L4(cmlog, "ibt_bind_service: hcap = %p", hcap);
2651
2652 if (srv_bind != NULL) {
2653 saa_handle = ibcm_get_saa_handle(hcap, port.hp_port);
2654 if (saa_handle == NULL) {
2655 IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
2809 }
2810 mutex_exit(&ibcm_svc_info_lock);
2811 ibcm_dec_hca_acc_cnt(hcap);
2812
2813 kmem_free(sbindp, sizeof (*sbindp));
2814 }
2815 return (status);
2816 }
2817 }
2818 }
2819 ibcm_inc_hca_svc_cnt(hcap);
2820 ibcm_dec_hca_acc_cnt(hcap);
2821
2822 /* If this message isn't seen then ibt_bind_service failed */
2823 IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: DONE (%p, %llX:%llX)",
2824 srv_hdl, gid.gid_prefix, gid.gid_guid);
2825
2826 if (sb_hdl_p != NULL)
2827 *sb_hdl_p = sbindp;
2828
2829 return (IBT_SUCCESS);
2830 }
2831
2832 ibt_status_t
2833 ibt_unbind_service(ibt_srv_hdl_t srv_hdl, ibt_sbind_hdl_t sbindp)
2834 {
2835 ib_svc_id_t sid, end_sid;
2836 ibt_status_t rval;
2837 ibcm_hca_info_t *hcap;
2838 ibcm_svc_bind_t *sbp, **sbpp;
2839
2840 IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service(%p, %p)",
2841 srv_hdl, sbindp);
2842
2843 hcap = ibcm_find_hca_entry(sbindp->sbind_hcaguid);
2844
2845 /* If there is a service on hca, respective hcap cannot go away */
2846 ASSERT(hcap != NULL);
2847
2848 mutex_enter(&ibcm_svc_info_lock);
2981 {
2982 ibcm_svc_info_t *svcp;
2983 ibcm_svc_lookup_t svc;
2984
2985 IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service(%p (%s), %p)",
2986 ibt_hdl, ibtl_cm_get_clnt_name(ibt_hdl), srv_hdl);
2987
2988 mutex_enter(&ibcm_svc_info_lock);
2989
2990 if (srv_hdl->svc_bind_list != NULL) {
2991 IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service:"
2992 " srv_hdl %p still has bindings", srv_hdl);
2993 mutex_exit(&ibcm_svc_info_lock);
2994 return (IBT_CM_SERVICE_BUSY);
2995 }
2996 svc.sid = srv_hdl->svc_id;
2997 svc.num_sids = 1;
2998 IBTF_DPRINTF_L3(cmlog, "ibt_deregister_service: SID 0x%llX, numsids %d",
2999 srv_hdl->svc_id, srv_hdl->svc_num_sids);
3000
3001 svcp = avl_find(&ibcm_svc_avl_tree, &svc, NULL);
3002 if (svcp != srv_hdl) {
3003 mutex_exit(&ibcm_svc_info_lock);
3004 IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service(): "
3005 "srv_hdl %p not found", srv_hdl);
3006 return (IBT_INVALID_PARAM);
3007 }
3008 avl_remove(&ibcm_svc_avl_tree, svcp);
3009
3010 /* wait for active REQ/SREQ handling to be done */
3011 svcp->svc_to_delete = 1;
3012 while (svcp->svc_ref_cnt != 0)
3013 cv_wait(&ibcm_svc_info_cv, &ibcm_svc_info_lock);
3014
3015 mutex_exit(&ibcm_svc_info_lock);
3016
3017 if ((srv_hdl->svc_id & IB_SID_AGN_MASK) == IB_SID_AGN_LOCAL)
3018 ibcm_free_local_sids(srv_hdl->svc_id, srv_hdl->svc_num_sids);
3019
3020 ibtl_cm_change_service_cnt(ibt_hdl, -srv_hdl->svc_num_sids);
3923 /* wait until client's CM handler returns DEFER status back to CM */
3924
3925 while (statep->clnt_proceed == IBCM_BLOCK) {
3926 IBTF_DPRINTF_L5(cmlog, "ibt_cm_proceed : chan 0x%p blocked for "
3927 "return of client's cm handler", statep->channel);
3928 cv_wait(&statep->block_client_cv, &statep->state_mutex);
3929 }
3930
3931 if (statep->clnt_proceed == IBCM_FAIL) {
3932 mutex_exit(&statep->state_mutex);
3933 IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p Failed as "
3934 "client returned non-DEFER status from cm handler",
3935 statep->channel);
3936 return (IBT_CHAN_STATE_INVALID);
3937 }
3938
3939 ASSERT(statep->clnt_proceed == IBCM_UNBLOCK);
3940 statep->clnt_proceed = IBCM_FAIL;
3941 mutex_exit(&statep->state_mutex);
3942
3943 /* the state machine processing is done in a separate thread */
3944
3945 /* proceed_targs is freed in ibcm_proceed_via_taskq */
3946 proceed_targs = kmem_alloc(sizeof (ibcm_proceed_targs_t),
3947 KM_SLEEP);
3948
3949 proceed_targs->event = event;
3950 proceed_targs->status = status;
3951 proceed_targs->priv_data_len = priv_data_len;
3952
3953 bcopy(priv_data, proceed_targs->priv_data, priv_data_len);
3954
3955 proceed_targs->tst.rc.statep = statep;
3956 bcopy(cm_event_data, &proceed_targs->tst.rc.rc_cm_event_data,
3957 sizeof (ibt_cm_proceed_reply_t));
3958
3959 (void) taskq_dispatch(ibcm_taskq, ibcm_proceed_via_taskq,
3960 proceed_targs, TQ_SLEEP);
3961
3962 return (IBT_SUCCESS);
3963 }
3964
3965 /*
3966 * Function:
3967 * ibcm_proceed_via_taskq
3968 *
3969 * Called from taskq, dispatched by ibt_cm_proceed
3970 * Completes the cm state processing for ibt_cm_proceed
3971 */
3972 void
3973 ibcm_proceed_via_taskq(void *targs)
3974 {
3975 ibcm_proceed_targs_t *proceed_targs = (ibcm_proceed_targs_t *)targs;
3976 ibcm_state_data_t *statep = proceed_targs->tst.rc.statep;
3977 ibt_cm_reason_t reject_reason;
3978 uint8_t arej_len;
4084 /* wait until client's CM handler returns DEFER status back to CM */
4085
4086 while (ud_statep->ud_clnt_proceed == IBCM_BLOCK) {
4087 IBTF_DPRINTF_L5(cmlog, "ibt_cm_ud_proceed : Blocked for return"
4088 " of client's ud cm handler");
4089 cv_wait(&ud_statep->ud_block_client_cv,
4090 &ud_statep->ud_state_mutex);
4091 }
4092
4093 if (ud_statep->ud_clnt_proceed == IBCM_FAIL) {
4094 mutex_exit(&ud_statep->ud_state_mutex);
4095 IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed : Failed as client "
4096 "returned non-DEFER status from cm handler");
4097 return (IBT_INVALID_PARAM);
4098 }
4099
4100 ASSERT(ud_statep->ud_clnt_proceed == IBCM_UNBLOCK);
4101 ud_statep->ud_clnt_proceed = IBCM_FAIL;
4102 mutex_exit(&ud_statep->ud_state_mutex);
4103
4104 /* the state machine processing is done in a separate thread */
4105
4106 /* proceed_targs is freed in ibcm_proceed_via_taskq */
4107 proceed_targs = kmem_zalloc(sizeof (ibcm_proceed_targs_t),
4108 KM_SLEEP);
4109
4110 proceed_targs->status = status;
4111 proceed_targs->priv_data_len = priv_data_len;
4112
4113 bcopy(priv_data, proceed_targs->priv_data, priv_data_len);
4114
4115 if (status == IBT_CM_ACCEPT) {
4116 proceed_targs->tst.ud.ud_qkey =
4117 qp_attr.qp_info.qp_transport.ud.ud_qkey;
4118 proceed_targs->tst.ud.ud_qpn = qp_attr.qp_qpn;
4119 }
4120
4121 proceed_targs->tst.ud.ud_statep = ud_statep;
4122
4123 /* copy redirect info based on status */
4124 if (status == IBT_CM_REDIRECT)
4125 bcopy(redirect_infop, &proceed_targs->tst.ud.ud_redirect_info,
4126 sizeof (ibt_redirect_info_t));
4127
4128 (void) taskq_dispatch(ibcm_taskq, ibcm_ud_proceed_via_taskq,
4129 proceed_targs, TQ_SLEEP);
4130
4131 return (IBT_SUCCESS);
4132 }
4133
4134 /*
4135 * Function:
4136 * ibcm_ud_proceed_via_taskq
4137 *
4138 * Called from taskq, dispatched by ibt_cm_ud_proceed
4139 * Completes the cm state processing for ibt_cm_ud_proceed
4140 */
4141 void
4142 ibcm_ud_proceed_via_taskq(void *targs)
4143 {
4144 ibcm_proceed_targs_t *proceed_targs = (ibcm_proceed_targs_t *)targs;
4145 ibcm_ud_state_data_t *ud_statep = proceed_targs->tst.ud.ud_statep;
4146 ibcm_ud_clnt_reply_info_t ud_clnt_info;
4147 ibt_sidr_status_t sidr_status;
4348 ibcm_lapr_exit();
4349 return (IBT_CHAN_STATE_INVALID);
4350 } else {
4351 /* Set to LAP Sent state */
4352 statep->ap_state = IBCM_AP_STATE_LAP_SENT;
4353 statep->ap_done = B_FALSE;
4354 statep->remaining_retry_cnt = statep->max_cm_retries;
4355 statep->timer_stored_state = statep->state;
4356 statep->timer_stored_ap_state = statep->ap_state;
4357 IBCM_REF_CNT_INCR(statep); /* for ibcm_post_lap_complete */
4358 }
4359
4360 mutex_exit(&statep->state_mutex);
4361
4362 /* No more failure returns below */
4363
4364 /* Allocate MAD for LAP */
4365 IBTF_DPRINTF_L5(cmlog, "ibt_set_alt_path:"
4366 " statep's mad addr = 0x%p", IBCM_OUT_HDRP(statep->lapr_msg));
4367
4368 lap_msgp = (ibcm_lap_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg);
4369
4370 lap_msgp->lap_alt_l_port_lid = h2b16(alternate_slid);
4371 lap_msgp->lap_alt_r_port_lid =
4372 h2b16(alt_path->ap_alt_cep_path.cep_adds_vect.av_dlid);
4373
4374 /* Fill in remote port gid */
4375 lap_msgp->lap_alt_r_port_gid.gid_prefix =
4376 h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_dgid.gid_prefix);
4377 lap_msgp->lap_alt_r_port_gid.gid_guid =
4378 h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_dgid.gid_guid);
4379
4380 /* Fill in local port gid */
4381 lap_msgp->lap_alt_l_port_gid.gid_prefix =
4382 h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_sgid.gid_prefix);
4383 lap_msgp->lap_alt_l_port_gid.gid_guid =
4384 h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_sgid.gid_guid);
4385
4386 alt_grh = alt_path->ap_alt_cep_path.cep_adds_vect.av_send_grh;
4387
4399 alt_path->ap_alt_cep_path.cep_adds_vect.av_srvl << 4 |
4400 ((alt_grh == B_FALSE) ? 0x8 : 0);
4401
4402 lap_msgp->lap_alt_local_acktime_plus = ibt_usec2ib(
4403 (2 * statep->rc_alt_pkt_lt) +
4404 ibt_ib2usec(hcap->hca_ack_delay)) << 3;
4405
4406 lap_msgp->lap_local_comm_id = h2b32(statep->local_comid);
4407 lap_msgp->lap_remote_comm_id = h2b32(statep->remote_comid);
4408
4409 lap_msgp->lap_remote_qpn_eecn_plus =
4410 h2b32((statep->remote_qpn << 8) |
4411 ibt_usec2ib(ibcm_remote_response_time) << 3);
4412
4413 len = min(priv_data_len, IBT_LAP_PRIV_DATA_SZ);
4414 if ((len > 0) && priv_data) {
4415 bcopy(priv_data, lap_msgp->lap_private_data, len);
4416 }
4417
4418 /* only rc_alt_pkt_lt and ap_return_data fields are initialized */
4419 statep->rc_alt_pkt_lt = ibt_ib2usec(alt_path->ap_alt_pkt_lt);
4420
4421 /* return_data is filled up in the state machine code */
4422 statep->ap_return_data = ret_args;
4423
4424 IBCM_OUT_HDRP(statep->lapr_msg)->AttributeID =
4425 h2b16(IBCM_INCOMING_LAP + IBCM_ATTR_BASE_ID);
4426
4427 IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID =
4428 h2b64(ibcm_generate_tranid(IBCM_INCOMING_LAP, statep->local_comid,
4429 0));
4430 IBTF_DPRINTF_L3(cmlog, "ibt_set_alt_path: statep %p, tid %llx",
4431 statep, IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID);
4432
4433 /* Send LAP */
4434 ibcm_post_rc_mad(statep, statep->lapr_msg, ibcm_post_lap_complete,
4435 statep);
4436
4437 mutex_enter(&statep->state_mutex);
4438
4439 if (mode == IBT_BLOCKING) {
4440 IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: blocking");
4441
4442 /* wait for APR */
4443 while (statep->ap_done != B_TRUE) {
4444 cv_wait(&statep->block_client_cv,
4445 &statep->state_mutex);
4446 }
4447
4448 IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: done blocking");
4449
4450 /*
4451 * In the case that ibt_set_alt_path fails,
4452 * change retval to IBT_CM_FAILURE
4563 cm_reply_addr->grh_hdr.ig_flow_label,
4564 cm_reply_addr->grh_hdr.ig_tclass,
4565 cm_reply_addr->grh_hdr.ig_hop_limit);
4566 }
4567
4568 #endif
4569
4570 /* For MCG List search */
4571 typedef struct ibcm_mcg_list_s {
4572 struct ibcm_mcg_list_s *ml_next;
4573 ib_gid_t ml_sgid;
4574 ib_gid_t ml_mgid;
4575 ib_pkey_t ml_pkey;
4576 ib_qkey_t ml_qkey;
4577 uint_t ml_refcnt;
4578 uint8_t ml_jstate;
4579 } ibcm_mcg_list_t;
4580
4581 ibcm_mcg_list_t *ibcm_mcglist = NULL;
4582
4583 typedef struct ibcm_join_mcg_tqarg_s {
4584 ib_gid_t rgid;
4585 ibt_mcg_attr_t mcg_attr;
4586 ibt_mcg_info_t *mcg_infop;
4587 ibt_mcg_handler_t func;
4588 void *arg;
4589 } ibcm_join_mcg_tqarg_t;
4590
4591 void
4592 ibcm_add_incr_mcg_entry(sa_mcmember_record_t *mcg_req,
4593 sa_mcmember_record_t *mcg_resp)
4594 {
4595 ibcm_mcg_list_t *new = NULL;
4596 ibcm_mcg_list_t *head = NULL;
4597
4598 IBTF_DPRINTF_L3(cmlog, "ibcm_add_incr_mcg_entry: MGID %llX:%llX"
4599 "\n SGID %llX:%llX, JState %X)", mcg_req->MGID.gid_prefix,
4600 mcg_req->MGID.gid_guid, mcg_req->PortGID.gid_prefix,
4601 mcg_req->PortGID.gid_guid, mcg_req->JoinState);
4602
4603 mutex_enter(&ibcm_mcglist_lock);
4604 head = ibcm_mcglist;
4605
4606 while (head != NULL) {
4607 if ((head->ml_mgid.gid_guid == mcg_resp->MGID.gid_guid) &&
4608 (head->ml_mgid.gid_prefix == mcg_resp->MGID.gid_prefix) &&
4609 (head->ml_sgid.gid_guid == mcg_resp->PortGID.gid_guid)) {
4610 /* Increment the count */
4767 IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Request GID is required");
4768 return (IBT_INVALID_PARAM);
4769 }
4770
4771 if ((mcg_attr->mc_pkey == IB_PKEY_INVALID_LIMITED) ||
4772 (mcg_attr->mc_pkey == IB_PKEY_INVALID_FULL)) {
4773 IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Invalid P_Key specified");
4774 return (IBT_INVALID_PARAM);
4775 }
4776
4777 if (mcg_attr->mc_join_state == 0) {
4778 IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: JoinState not specified");
4779 return (IBT_INVALID_PARAM);
4780 }
4781
4782 if (mcg_info_p == NULL) {
4783 IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: mcg_info_p is NULL");
4784 return (IBT_INVALID_PARAM);
4785 }
4786
4787 mcg_tq = kmem_alloc(sizeof (ibcm_join_mcg_tqarg_t), flag);
4788 if (mcg_tq == NULL) {
4789 IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: "
4790 "Unable to allocate memory for local usage.");
4791 return (IBT_INSUFF_KERNEL_RESOURCE);
4792 }
4793
4794 mcg_tq->rgid = rgid;
4795 bcopy(mcg_attr, &mcg_tq->mcg_attr, sizeof (ibt_mcg_attr_t));
4796 mcg_tq->mcg_infop = mcg_info_p;
4797 mcg_tq->func = func;
4798 mcg_tq->arg = arg;
4799
4800 if (func != NULL) { /* Non-Blocking */
4801 IBTF_DPRINTF_L3(cmlog, "ibt_join_mcg: Non-Blocking Call");
4802 if (taskq_dispatch(ibcm_taskq, ibcm_process_async_join_mcg,
4803 mcg_tq, TQ_NOSLEEP) == 0) {
4804 IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Failed to "
4805 "Dispatch the TaskQ");
4806 kmem_free(mcg_tq, sizeof (ibcm_join_mcg_tqarg_t));
4807 return (IBT_INSUFF_KERNEL_RESOURCE);
4808 } else
4809 return (IBT_SUCCESS);
4810 } else { /* Blocking */
4811 return (ibcm_process_join_mcg(mcg_tq));
4812 }
4813 }
4814
4815 static void
4816 ibcm_process_async_join_mcg(void *tq_arg)
4817 {
4818 (void) ibcm_process_join_mcg(tq_arg);
4819 }
5716 SA_NODEINFO_COMPMASK_NODELID, &res_p, &len);
5717 if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
5718 IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
5719 "failed (%d) to get Node records", retval);
5720 continue;
5721 } else if (retval != IBT_SUCCESS) {
5722 IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
5723 "failed (%d) to get Node records", retval);
5724 ibcm_dec_hca_acc_cnt(hcap);
5725 goto gid_to_ni_exit;
5726 }
5727
5728 num_rec = len/sizeof (sa_node_record_t);
5729 nr_resp = (sa_node_record_t *)(uchar_t *)res_p;
5730
5731 /* Validate the returned number of records. */
5732 if ((nr_resp != NULL) && (num_rec > 0)) {
5733
5734 IBCM_DUMP_NODE_REC(nr_resp);
5735
5736 node_info_p->n_sys_img_guid =
5737 nr_resp->NodeInfo.SystemImageGUID;
5738 node_info_p->n_node_guid =
5739 nr_resp->NodeInfo.NodeGUID;
5740 node_info_p->n_port_guid =
5741 nr_resp->NodeInfo.PortGUID;
5742 node_info_p->n_dev_id =
5743 nr_resp->NodeInfo.DeviceID;
5744 node_info_p->n_revision =
5745 nr_resp->NodeInfo.Revision;
5746 node_info_p->n_vendor_id =
5747 nr_resp->NodeInfo.VendorID;
5748 node_info_p->n_num_ports =
5749 nr_resp->NodeInfo.NumPorts;
5750 node_info_p->n_port_num =
5751 nr_resp->NodeInfo.LocalPortNum;
5752 node_info_p->n_node_type =
5753 nr_resp->NodeInfo.NodeType;
5754 (void) strncpy(node_info_p->n_description,
5755 (char *)&nr_resp->NodeDescription, 64);
5756
5757 /*
5758 * Deallocate the memory allocated by SA for
5759 * 'nr_resp'.
5760 */
5761 ibcm_dec_hca_acc_cnt(hcap);
5762 kmem_free(nr_resp, len);
5763 retval = IBT_SUCCESS;
5764
5765 goto gid_to_ni_exit;
5766 } else {
5767 retval = IBT_NODE_RECORDS_NOT_FOUND;
5768 IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
5769 "Node Records NOT found - PortGUID %016llX",
5770 gid.gid_guid);
5771 }
5772 }
5773 ibcm_dec_hca_acc_cnt(hcap);
5774
5775 if (local_node == B_TRUE)
5776 break;
5908 SA_NODEINFO_COMPMASK_NODELID, &res_p, &len);
5909 if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
5910 IBTF_DPRINTF_L2(cmlog, "ibt_lid_to_node_info: "
5911 "failed (%d) to get Node records", retval);
5912 continue;
5913 } else if (retval != IBT_SUCCESS) {
5914 IBTF_DPRINTF_L2(cmlog, "ibt_lid_to_node_info: "
5915 "failed (%d) to get Node records", retval);
5916 ibcm_dec_hca_acc_cnt(hcap);
5917 goto lid_to_ni_exit;
5918 }
5919
5920 num_rec = len/sizeof (sa_node_record_t);
5921 nr_resp = (sa_node_record_t *)(uchar_t *)res_p;
5922
5923 /* Validate the returned number of records. */
5924 if ((nr_resp != NULL) && (num_rec > 0)) {
5925
5926 IBCM_DUMP_NODE_REC(nr_resp);
5927
5928 node_info_p->n_sys_img_guid =
5929 nr_resp->NodeInfo.SystemImageGUID;
5930 node_info_p->n_node_guid =
5931 nr_resp->NodeInfo.NodeGUID;
5932 node_info_p->n_port_guid =
5933 nr_resp->NodeInfo.PortGUID;
5934 node_info_p->n_dev_id =
5935 nr_resp->NodeInfo.DeviceID;
5936 node_info_p->n_revision =
5937 nr_resp->NodeInfo.Revision;
5938 node_info_p->n_vendor_id =
5939 nr_resp->NodeInfo.VendorID;
5940 node_info_p->n_num_ports =
5941 nr_resp->NodeInfo.NumPorts;
5942 node_info_p->n_port_num =
5943 nr_resp->NodeInfo.LocalPortNum;
5944 node_info_p->n_node_type =
5945 nr_resp->NodeInfo.NodeType;
5946 (void) strncpy(node_info_p->n_description,
5947 (char *)&nr_resp->NodeDescription, 64);
5948
5949 /*
5950 * Deallocate the memory allocated by SA for
5951 * 'nr_resp'.
5952 */
5953 ibcm_dec_hca_acc_cnt(hcap);
5954 kmem_free(nr_resp, len);
5955 retval = IBT_SUCCESS;
5956
5957 goto lid_to_ni_exit;
5958 } else {
5959 retval = IBT_NODE_RECORDS_NOT_FOUND;
5960 IBTF_DPRINTF_L3(cmlog, "ibt_lid_to_node_info: "
5961 "Node Records NOT found - LID 0x%lX",
5962 lid);
5963 }
5964 }
5965 ibcm_dec_hca_acc_cnt(hcap);
5966 }
5967
5968 lid_to_ni_exit:
6447 *src_info_p = s_ip;
6448 *entries_p = count;
6449
6450 j = 0;
6451 for (i = 0, ipp = ibds.ibcm_arp_ip; i < ibds.ibcm_arp_ibd_cnt;
6452 i++, ipp++) {
6453 if (ipp->ip_inet_family == AF_UNSPEC)
6454 continue;
6455 if ((ipp->ip_port_gid.gid_prefix ==
6456 sattr->sip_gid.gid_prefix) &&
6457 (ipp->ip_port_gid.gid_guid ==
6458 sattr->sip_gid.gid_guid)) {
6459 if ((sattr->sip_pkey) &&
6460 (ipp->ip_pkey != sattr->sip_pkey))
6461 continue;
6462
6463 if ((sattr->sip_zoneid != ALL_ZONES) &&
6464 (sattr->sip_zoneid != ipp->ip_zoneid))
6465 continue;
6466
6467 s_ip[j].ip_addr.family = ipp->ip_inet_family;
6468 if (s_ip[j].ip_addr.family == AF_INET) {
6469 bcopy(&ipp->ip_cm_sin.sin_addr,
6470 &s_ip[j].ip_addr.un.ip4addr,
6471 sizeof (in_addr_t));
6472 } else if (s_ip[j].ip_addr.family == AF_INET6) {
6473 bcopy(&ipp->ip_cm_sin6.sin6_addr,
6474 &s_ip[j].ip_addr.un.ip6addr,
6475 sizeof (in6_addr_t));
6476 /* TBD: scope_id */
6477 }
6478 IBCM_PRINT_IP("ibt_get_src_ip",
6479 &s_ip[j].ip_addr);
6480 j++;
6481 }
6482 }
6483 } else {
6484 retval = IBT_SRC_IP_NOT_FOUND;
6485 }
6486
6487 get_src_ip_end:
6557 }
6558
6559 ibcm_free_ip_sid(ip_sid);
6560
6561 return (IBT_SUCCESS);
6562 }
6563
6564
6565 uint8_t
6566 ibt_get_ip_protocol_num(ib_svc_id_t sid)
6567 {
6568 return ((sid & IB_SID_IPADDR_IPNUM_MASK) >> 16);
6569 }
6570
6571 in_port_t
6572 ibt_get_ip_dst_port(ib_svc_id_t sid)
6573 {
6574 return (sid & IB_SID_IPADDR_PORTNUM_MASK);
6575 }
6576
6577 ibt_status_t
6578 ibt_format_ip_private_data(ibt_ip_cm_info_t *ip_cm_info,
6579 ibt_priv_data_len_t priv_data_len, void *priv_data_p)
6580 {
6581 ibcm_ip_pvtdata_t ip_data;
6582
6583 IBTF_DPRINTF_L4(cmlog, "ibt_format_ip_private_data(%p, %d, %p)",
6584 ip_cm_info, priv_data_len, priv_data_p);
6585
6586 if ((ip_cm_info == NULL) || (priv_data_p == NULL) ||
6587 (priv_data_len < IBT_IP_HDR_PRIV_DATA_SZ)) {
6588 IBTF_DPRINTF_L2(cmlog, "ibt_format_ip_private_data: ERROR "
6589 "Invalid Inputs.");
6590 return (IBT_INVALID_PARAM);
6591 }
6592
6593 bzero(&ip_data, sizeof (ibcm_ip_pvtdata_t));
6594 ip_data.ip_srcport = ip_cm_info->src_port; /* Source Port */
6595
6596 IBCM_PRINT_IP("format_ip_pvt: src", &ip_cm_info->src_addr);
6646 AF_INET;
6647 ip_cm_infop->src_addr.un.ip4addr = ip_data.ip_srcv4;
6648 ip_cm_infop->dst_addr.un.ip4addr = ip_data.ip_dstv4;
6649 } else if (ip_data.ip_ipv == IBT_CM_IP_IPV_V6) {
6650 /* Copy IPv6 Addr */
6651 ip_cm_infop->src_addr.family = ip_cm_infop->dst_addr.family =
6652 AF_INET6;
6653 bcopy(&ip_data.ip_srcv6, &ip_cm_infop->src_addr.un.ip6addr,
6654 sizeof (in6_addr_t));
6655 bcopy(&ip_data.ip_dstv6, &ip_cm_infop->dst_addr.un.ip6addr,
6656 sizeof (in6_addr_t));
6657 } else {
6658 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_data: ERROR: IP Addr needs"
6659 " to be either AF_INET or AF_INET6 family.");
6660 return (IBT_INVALID_PARAM);
6661 }
6662 IBCM_PRINT_IP("ibt_get_ip_data: src", &ip_cm_infop->src_addr);
6663 IBCM_PRINT_IP("ibt_get_ip_data: dst", &ip_cm_infop->dst_addr);
6664
6665 return (IBT_SUCCESS);
6666 }
|