10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51495Shiremath * Common Development and Distribution License (the "License").
61495Shiremath * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
2212064SShantkumar.Hiremath@Sun.COM * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate #include <sys/ib/mgt/ibcm/ibcm_impl.h>
260Sstevel@tonic-gate #include <sys/ib/ibtl/ibti.h>
274703Shiremath #include <sys/ib/mgt/ibcm/ibcm_arp.h>
280Sstevel@tonic-gate
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate * ibcm_ti.c
310Sstevel@tonic-gate * These routines implement the Communication Manager's interfaces to IBTL.
320Sstevel@tonic-gate */
330Sstevel@tonic-gate
340Sstevel@tonic-gate /* CM rc recycle task args structure definition */
350Sstevel@tonic-gate typedef struct ibcm_taskq_recycle_arg_s {
360Sstevel@tonic-gate ibt_channel_hdl_t rc_chan;
370Sstevel@tonic-gate ibt_cep_flags_t control;
380Sstevel@tonic-gate uint8_t hca_port_num;
390Sstevel@tonic-gate ibt_recycle_handler_t func;
400Sstevel@tonic-gate void *arg;
410Sstevel@tonic-gate } ibcm_taskq_recycle_arg_t;
420Sstevel@tonic-gate
430Sstevel@tonic-gate _NOTE(READ_ONLY_DATA(ibcm_taskq_recycle_arg_s))
440Sstevel@tonic-gate
450Sstevel@tonic-gate static ibt_status_t ibcm_init_reply_addr(ibcm_hca_info_t *hcap,
460Sstevel@tonic-gate ibcm_mad_addr_t *reply_addr, ibt_chan_open_args_t *chan_args,
470Sstevel@tonic-gate ibt_chan_open_flags_t flags, ib_time_t *cm_pkt_lt, ib_lid_t prim_slid);
480Sstevel@tonic-gate static void ibcm_process_abort_via_taskq(void *args);
490Sstevel@tonic-gate static ibt_status_t ibcm_process_rc_recycle_ret(void *recycle_arg);
500Sstevel@tonic-gate static ibt_status_t ibcm_process_join_mcg(void *taskq_arg);
510Sstevel@tonic-gate static void ibcm_process_async_join_mcg(void *tq_arg);
520Sstevel@tonic-gate
539891SRajkumar.Sivaprakasam@Sun.COM ibt_status_t ibcm_get_node_rec(ibmf_saa_handle_t, sa_node_record_t *,
540Sstevel@tonic-gate uint64_t c_mask, void *, size_t *);
550Sstevel@tonic-gate
563241Shiremath static ibt_status_t ibcm_close_rc_channel(ibt_channel_hdl_t channel,
573241Shiremath ibcm_state_data_t *statep, ibt_execution_mode_t mode);
583241Shiremath
590Sstevel@tonic-gate /* Address Record management definitions */
600Sstevel@tonic-gate #define IBCM_DAPL_ATS_NAME "DAPL Address Translation Service"
610Sstevel@tonic-gate #define IBCM_DAPL_ATS_SID 0x10000CE100415453ULL
620Sstevel@tonic-gate #define IBCM_DAPL_ATS_NBYTES 16
630Sstevel@tonic-gate ibcm_svc_info_t *ibcm_ar_svcinfop;
640Sstevel@tonic-gate ibcm_ar_t *ibcm_ar_list;
650Sstevel@tonic-gate
663241Shiremath /*
673241Shiremath * Tunable parameter to turnoff the overriding of pi_path_mtu value.
683241Shiremath * 1 By default override the path record's pi_path_mtu value to
693241Shiremath * IB_MTU_1K for all RC channels. This is done only for the
703241Shiremath * channels established on Tavor HCA and the path's pi_path_mtu
713241Shiremath * is greater than IB_MTU_1K.
723241Shiremath * 0 Do not override, use pi_path_mtu by default.
733241Shiremath */
743241Shiremath int ibcm_override_path_mtu = 1;
753241Shiremath
760Sstevel@tonic-gate #ifdef DEBUG
770Sstevel@tonic-gate static void ibcm_print_reply_addr(ibt_channel_hdl_t channel,
780Sstevel@tonic-gate ibcm_mad_addr_t *cm_reply_addr);
790Sstevel@tonic-gate #endif
800Sstevel@tonic-gate
810Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_port_info_s::{port_ibmf_hdl}))
820Sstevel@tonic-gate
830Sstevel@tonic-gate /* access is controlled between ibcm_sm.c and ibcm_ti.c by CVs */
840Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("Serialized access by CV", {ibt_rc_returns_t
850Sstevel@tonic-gate ibt_ud_returns_t ibt_ap_returns_t ibt_ar_t}))
860Sstevel@tonic-gate
870Sstevel@tonic-gate /*
880Sstevel@tonic-gate * Typically, clients initialize these args in one api call, and use in
890Sstevel@tonic-gate * another api
900Sstevel@tonic-gate */
910Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("Expected usage of ibtl api by client",
920Sstevel@tonic-gate {ibt_path_info_s ibt_cep_path_s ibt_adds_vect_s ibt_mcg_info_s ib_gid_s
930Sstevel@tonic-gate ibt_ud_dest_attr_s ibt_ud_dest_s ibt_srv_data_s ibt_redirect_info_s}))
940Sstevel@tonic-gate
950Sstevel@tonic-gate /*
960Sstevel@tonic-gate * ibt_open_rc_channel()
970Sstevel@tonic-gate * ibt_open_rc_channel opens a communication channel on the specified
980Sstevel@tonic-gate * channel to the specified service. For connection service type qp's
990Sstevel@tonic-gate * the CM initiates the CEP to establish the connection and transitions
1000Sstevel@tonic-gate * the QP/EEC to the "Ready to send" State modifying the QP/EEC's
1010Sstevel@tonic-gate * attributes as necessary.
1020Sstevel@tonic-gate * The implementation of this function assumes that alt path is different
1030Sstevel@tonic-gate * from primary path. It is assumed that the Path functions ensure that.
1040Sstevel@tonic-gate *
1050Sstevel@tonic-gate * RETURN VALUES:
1060Sstevel@tonic-gate * IBT_SUCCESS on success (or respective failure on error)
1070Sstevel@tonic-gate */
1080Sstevel@tonic-gate ibt_status_t
ibt_open_rc_channel(ibt_channel_hdl_t channel,ibt_chan_open_flags_t flags,ibt_execution_mode_t mode,ibt_chan_open_args_t * chan_args,ibt_rc_returns_t * ret_args)1090Sstevel@tonic-gate ibt_open_rc_channel(ibt_channel_hdl_t channel, ibt_chan_open_flags_t flags,
1100Sstevel@tonic-gate ibt_execution_mode_t mode, ibt_chan_open_args_t *chan_args,
1110Sstevel@tonic-gate ibt_rc_returns_t *ret_args)
1120Sstevel@tonic-gate {
1130Sstevel@tonic-gate /* all fields that are related to REQ MAD formation */
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate ib_pkey_t prim_pkey;
1160Sstevel@tonic-gate ib_lid_t primary_slid, alternate_slid;
1170Sstevel@tonic-gate ib_qpn_t local_qpn = 0;
1180Sstevel@tonic-gate ib_guid_t hca_guid;
1190Sstevel@tonic-gate ib_qkey_t local_qkey = 0;
1200Sstevel@tonic-gate ib_eecn_t local_eecn = 0;
1210Sstevel@tonic-gate ib_eecn_t remote_eecn = 0;
1220Sstevel@tonic-gate boolean_t primary_grh;
1230Sstevel@tonic-gate boolean_t alternate_grh = B_FALSE;
1240Sstevel@tonic-gate ib_lid_t base_lid;
1250Sstevel@tonic-gate ib_com_id_t local_comid;
1263241Shiremath ibmf_msg_t *ibmf_msg, *ibmf_msg_dreq;
1270Sstevel@tonic-gate ibcm_req_msg_t *req_msgp;
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate uint8_t rdma_in, rdma_out;
1300Sstevel@tonic-gate uint8_t cm_retries;
1310Sstevel@tonic-gate uint64_t local_cm_proc_time; /* In usec */
1320Sstevel@tonic-gate uint8_t local_cm_resp_time; /* IB time */
1330Sstevel@tonic-gate uint64_t remote_cm_resp_time; /* In usec */
1340Sstevel@tonic-gate uint32_t starting_psn = 0;
1350Sstevel@tonic-gate
1360Sstevel@tonic-gate /* CM path related fields */
1370Sstevel@tonic-gate ibmf_handle_t ibmf_hdl;
1380Sstevel@tonic-gate ibcm_qp_list_t *cm_qp_entry;
1390Sstevel@tonic-gate ibcm_mad_addr_t cm_reply_addr;
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate uint8_t cm_pkt_lt;
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate /* Local args for ibtl/internal CM functions called within */
1440Sstevel@tonic-gate ibt_status_t status;
1450Sstevel@tonic-gate ibcm_status_t lkup_status;
1460Sstevel@tonic-gate ibt_qp_query_attr_t qp_query_attr;
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate /* Other misc local args */
1490Sstevel@tonic-gate ibt_priv_data_len_t len;
1500Sstevel@tonic-gate ibcm_hca_info_t *hcap;
1510Sstevel@tonic-gate ibcm_state_data_t *statep;
1520Sstevel@tonic-gate uint8_t port_no;
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_open_rc_channel(chan %p, %X, %x, %p, %p)",
1550Sstevel@tonic-gate channel, flags, mode, chan_args, ret_args);
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate if (IBCM_INVALID_CHANNEL(channel)) {
1580Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: invalid channel");
1590Sstevel@tonic-gate return (IBT_CHAN_HDL_INVALID);
1600Sstevel@tonic-gate }
1610Sstevel@tonic-gate
1620Sstevel@tonic-gate /* cm handler should always be specified */
1630Sstevel@tonic-gate if (chan_args->oc_cm_handler == NULL) {
1641093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
1650Sstevel@tonic-gate "CM handler is not be specified", channel);
1660Sstevel@tonic-gate return (IBT_INVALID_PARAM);
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate if (mode == IBT_NONBLOCKING) {
1700Sstevel@tonic-gate if (ret_args != NULL) {
1710Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
1721093Shiremath " ret_args should be NULL when called in "
1730Sstevel@tonic-gate "non-blocking mode", channel);
1740Sstevel@tonic-gate return (IBT_INVALID_PARAM);
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate } else if (mode == IBT_BLOCKING) {
1770Sstevel@tonic-gate if (ret_args == NULL) {
1780Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
1791093Shiremath " ret_args should be Non-NULL when called in "
1800Sstevel@tonic-gate "blocking mode", channel);
1810Sstevel@tonic-gate return (IBT_INVALID_PARAM);
1820Sstevel@tonic-gate }
1830Sstevel@tonic-gate if (ret_args->rc_priv_data_len > IBT_REP_PRIV_DATA_SZ) {
1840Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
1851093Shiremath " private data length is too large", channel);
1860Sstevel@tonic-gate return (IBT_INVALID_PARAM);
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate if ((ret_args->rc_priv_data_len > 0) &&
1890Sstevel@tonic-gate (ret_args->rc_priv_data == NULL)) {
1900Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
1911093Shiremath " rc_priv_data_len > 0, but rc_priv_data NULL",
1920Sstevel@tonic-gate channel);
1930Sstevel@tonic-gate return (IBT_INVALID_PARAM);
1940Sstevel@tonic-gate }
1950Sstevel@tonic-gate } else { /* any other mode is not valid for ibt_open_rc_channel */
1961093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
1970Sstevel@tonic-gate "invalid mode %x specified", channel, mode);
1980Sstevel@tonic-gate return (IBT_INVALID_PARAM);
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate /*
2020Sstevel@tonic-gate * XXX: no support yet for ibt_chan_open_flags_t - IBT_OCHAN_DUP
2030Sstevel@tonic-gate */
2040Sstevel@tonic-gate if (flags & IBT_OCHAN_DUP) {
2051093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2060Sstevel@tonic-gate "Unsupported Flags specified: 0x%X", channel, flags);
2070Sstevel@tonic-gate return (IBT_INVALID_PARAM);
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate if ((flags & IBT_OCHAN_REDIRECTED) &&
2110Sstevel@tonic-gate (flags & IBT_OCHAN_PORT_REDIRECTED)) {
2121093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2130Sstevel@tonic-gate "Illegal to specify IBT_OCHAN_REDIRECTED and "
2140Sstevel@tonic-gate "IBT_OCHAN_PORT_REDIRECTED flags together", channel);
2150Sstevel@tonic-gate return (IBT_INVALID_PARAM);
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate if (((flags & IBT_OCHAN_REDIRECTED) &&
2190Sstevel@tonic-gate (chan_args->oc_cm_redirect_info == NULL)) ||
2200Sstevel@tonic-gate ((flags & IBT_OCHAN_PORT_REDIRECTED) &&
2210Sstevel@tonic-gate (chan_args->oc_cm_cep_path == NULL))) {
2221093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2230Sstevel@tonic-gate "Redirect flag specified, but respective arg is NULL",
2240Sstevel@tonic-gate channel);
2250Sstevel@tonic-gate return (IBT_INVALID_PARAM);
2260Sstevel@tonic-gate }
2270Sstevel@tonic-gate
2280Sstevel@tonic-gate if ((flags & IBT_OCHAN_REDIRECTED) &&
2290Sstevel@tonic-gate (chan_args->oc_cm_redirect_info->rdi_dlid == 0) &&
2300Sstevel@tonic-gate (chan_args->oc_cm_redirect_info->rdi_gid.gid_guid == 0)) {
2311093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2320Sstevel@tonic-gate "Either rdi_dlid or rdi_gid must be specified for"
2330Sstevel@tonic-gate " IBT_OCHAN_REDIRECTED", channel);
2340Sstevel@tonic-gate return (IBT_INVALID_PARAM);
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate
2370Sstevel@tonic-gate /* primary dlid and hca_port_num should never be zero */
2380Sstevel@tonic-gate port_no = IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num;
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate if ((IBCM_PRIM_ADDS_VECT(chan_args).av_dlid == 0) && (port_no == 0)) {
2411093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2420Sstevel@tonic-gate "Primary Path's information is not valid", channel);
2430Sstevel@tonic-gate return (IBT_INVALID_PARAM);
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate /* validate SID */
2470Sstevel@tonic-gate if (chan_args->oc_path->pi_sid == 0) {
2481093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2490Sstevel@tonic-gate "ERROR: Service ID in path information is 0", channel);
2500Sstevel@tonic-gate return (IBT_INVALID_PARAM);
2510Sstevel@tonic-gate }
2529349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibt_open_rc_channel: chan 0x%p SID %llX",
2539349SShantkumar.Hiremath@Sun.COM channel, chan_args->oc_path->pi_sid);
2540Sstevel@tonic-gate
2550Sstevel@tonic-gate /* validate rnr_retry_cnt (enum has more than 3 bits) */
2560Sstevel@tonic-gate if ((uint_t)chan_args->oc_path_rnr_retry_cnt > IBT_RNR_INFINITE_RETRY) {
2571093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2580Sstevel@tonic-gate "ERROR: oc_path_rnr_retry_cnt(%d) is out of range",
2590Sstevel@tonic-gate channel, chan_args->oc_path_rnr_retry_cnt);
2600Sstevel@tonic-gate return (IBT_INVALID_PARAM);
2610Sstevel@tonic-gate }
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate /*
2640Sstevel@tonic-gate * Ensure that client is not re-using a QP that is still associated
2650Sstevel@tonic-gate * with a statep
2660Sstevel@tonic-gate */
2670Sstevel@tonic-gate IBCM_GET_CHAN_PRIVATE(channel, statep);
2680Sstevel@tonic-gate if (statep != NULL) {
2690Sstevel@tonic-gate IBCM_RELEASE_CHAN_PRIVATE(channel);
2701093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2710Sstevel@tonic-gate "Channel being re-used on active side", channel);
2720Sstevel@tonic-gate return (IBT_CHAN_IN_USE);
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate
2750Sstevel@tonic-gate /* Get GUID from Channel */
2760Sstevel@tonic-gate hca_guid = ibt_channel_to_hca_guid(channel);
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate /* validate QP's hca guid with that from primary path */
2790Sstevel@tonic-gate if (hca_guid != chan_args->oc_path->pi_hca_guid) {
2801093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2810Sstevel@tonic-gate "GUID from Channel and primary path don't match", channel);
2820Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2830Sstevel@tonic-gate "Channel GUID %llX primary path GUID %llX", channel,
2840Sstevel@tonic-gate hca_guid, chan_args->oc_path->pi_hca_guid);
2850Sstevel@tonic-gate return (IBT_CHAN_HDL_INVALID);
2860Sstevel@tonic-gate }
2870Sstevel@tonic-gate
2880Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
2890Sstevel@tonic-gate "Local HCA GUID %llX", channel, hca_guid);
2900Sstevel@tonic-gate
2910Sstevel@tonic-gate status = ibt_query_qp(channel, &qp_query_attr);
2920Sstevel@tonic-gate if (status != IBT_SUCCESS) {
2931093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2940Sstevel@tonic-gate "ibt_query_qp failed %d", channel, status);
2950Sstevel@tonic-gate return (status);
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate /* If client specified "no port change on QP" */
2990Sstevel@tonic-gate if ((qp_query_attr.qp_info.qp_transport.rc.rc_path.cep_hca_port_num !=
3000Sstevel@tonic-gate port_no) && (flags & IBT_OCHAN_PORT_FIXED)) {
3011093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3020Sstevel@tonic-gate "chan port %d and path port %d does not match", channel,
3030Sstevel@tonic-gate qp_query_attr.qp_info.qp_transport.rc.rc_path. \
3040Sstevel@tonic-gate cep_hca_port_num, port_no);
3050Sstevel@tonic-gate return (IBT_INVALID_PARAM);
3060Sstevel@tonic-gate }
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate if (qp_query_attr.qp_info.qp_trans != IBT_RC_SRV) {
3091093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3100Sstevel@tonic-gate "Invalid Channel type: Applicable only to RC Channel",
3110Sstevel@tonic-gate channel);
3120Sstevel@tonic-gate return (IBT_CHAN_SRV_TYPE_INVALID);
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate
3150Sstevel@tonic-gate /* Check if QP is in INIT state or not */
3160Sstevel@tonic-gate if (qp_query_attr.qp_info.qp_state != IBT_STATE_INIT) {
3171093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3180Sstevel@tonic-gate "QP is not in INIT state %x", channel,
3190Sstevel@tonic-gate qp_query_attr.qp_info.qp_state);
3200Sstevel@tonic-gate return (IBT_CHAN_STATE_INVALID);
3210Sstevel@tonic-gate }
3220Sstevel@tonic-gate
3230Sstevel@tonic-gate local_qpn = qp_query_attr.qp_qpn;
3240Sstevel@tonic-gate
3250Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p Active QPN 0x%x",
3260Sstevel@tonic-gate channel, local_qpn);
3270Sstevel@tonic-gate
3280Sstevel@tonic-gate #ifdef NO_EEC_SUPPORT_YET
3290Sstevel@tonic-gate
3300Sstevel@tonic-gate if (flags & IBT_OCHAN_RDC_EXISTS) {
3310Sstevel@tonic-gate ibt_eec_query_attr_t eec_query_attr;
3320Sstevel@tonic-gate
3330Sstevel@tonic-gate local_qkey = qp_query_attr.qp_info.qp_transport.rd_qkey;
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: RD");
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate status = ibt_query_eec(channel, &eec_query_attr);
3380Sstevel@tonic-gate if (status != IBT_SUCCESS) {
3390Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
3401093Shiremath " ibt_query_eec failed %d", channel, status);
3410Sstevel@tonic-gate return (status);
3420Sstevel@tonic-gate }
3430Sstevel@tonic-gate local_eecn = eec_query_attr.eec_eecn;
3440Sstevel@tonic-gate }
3450Sstevel@tonic-gate
3460Sstevel@tonic-gate #endif
3476709Shiremath if (chan_args->oc_path->pi_prim_pkt_lt > ibcm_max_ib_pkt_lt) {
3486709Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3496709Shiremath "Huge PktLifeTime %d, Max is %d", channel,
3506709Shiremath chan_args->oc_path->pi_prim_pkt_lt, ibcm_max_ib_pkt_lt);
3516709Shiremath return (IBT_PATH_PKT_LT_TOO_HIGH);
3526709Shiremath }
3530Sstevel@tonic-gate
3540Sstevel@tonic-gate /* If no HCA found return failure */
3550Sstevel@tonic-gate if ((hcap = ibcm_find_hca_entry(hca_guid)) == NULL) {
3560Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3570Sstevel@tonic-gate "hcap is NULL. Probably hca is not in active state",
3580Sstevel@tonic-gate channel);
3590Sstevel@tonic-gate return (IBT_CHAN_HDL_INVALID);
3600Sstevel@tonic-gate }
3610Sstevel@tonic-gate
3620Sstevel@tonic-gate rdma_out = chan_args->oc_rdma_ra_out;
3630Sstevel@tonic-gate rdma_in = chan_args->oc_rdma_ra_in;
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate if ((rdma_in > hcap->hca_max_rdma_in_qp) ||
3660Sstevel@tonic-gate (rdma_out > hcap->hca_max_rdma_out_qp)) {
3671093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3686709Shiremath "rdma in %d/out %d values exceed hca limits(%d/%d)",
3696709Shiremath channel, rdma_in, rdma_out, hcap->hca_max_rdma_in_qp,
3706709Shiremath hcap->hca_max_rdma_out_qp);
3710Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
3720Sstevel@tonic-gate return (IBT_INVALID_PARAM);
3730Sstevel@tonic-gate }
3740Sstevel@tonic-gate
3751093Shiremath IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
3760Sstevel@tonic-gate "rdma_in %d rdma_out %d", channel, rdma_in, rdma_out);
3770Sstevel@tonic-gate
3780Sstevel@tonic-gate status = ibt_get_port_state_byguid(hcap->hca_guid, port_no,
3790Sstevel@tonic-gate NULL, &base_lid);
3800Sstevel@tonic-gate if (status != IBT_SUCCESS) {
3811093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3820Sstevel@tonic-gate "primary port_num %d not active", channel, port_no);
3830Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
3840Sstevel@tonic-gate return (status);
3850Sstevel@tonic-gate }
3860Sstevel@tonic-gate
3870Sstevel@tonic-gate /* Validate P_KEY Index */
3880Sstevel@tonic-gate status = ibt_index2pkey_byguid(hcap->hca_guid, port_no,
3890Sstevel@tonic-gate IBCM_PRIM_CEP_PATH(chan_args).cep_pkey_ix, &prim_pkey);
3900Sstevel@tonic-gate if (status != IBT_SUCCESS) {
3910Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3920Sstevel@tonic-gate "Invalid Primary PKeyIx %x", channel,
3930Sstevel@tonic-gate IBCM_PRIM_CEP_PATH(chan_args).cep_pkey_ix);
3940Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
3950Sstevel@tonic-gate return (status);
3960Sstevel@tonic-gate }
3970Sstevel@tonic-gate
3981093Shiremath IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
3990Sstevel@tonic-gate "primary_port_num %d primary_pkey 0x%x", channel, port_no,
4000Sstevel@tonic-gate prim_pkey);
4010Sstevel@tonic-gate
4020Sstevel@tonic-gate if ((hcap->hca_port_info[port_no - 1].port_ibmf_hdl == NULL) &&
4030Sstevel@tonic-gate ((status = ibcm_hca_reinit_port(hcap, port_no - 1))
4040Sstevel@tonic-gate != IBT_SUCCESS)) {
4051093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
4060Sstevel@tonic-gate "ibmf reg or callback setup failed during re-initialize",
4070Sstevel@tonic-gate channel);
4080Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
4090Sstevel@tonic-gate return (status);
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate ibmf_hdl = hcap->hca_port_info[port_no - 1].port_ibmf_hdl;
4130Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
4140Sstevel@tonic-gate "primary ibmf_hdl = 0x%p", channel, ibmf_hdl);
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate primary_slid = base_lid + IBCM_PRIM_ADDS_VECT(chan_args).av_src_path;
4170Sstevel@tonic-gate
4180Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: channel 0x%p "
4190Sstevel@tonic-gate "primary SLID = %x", channel, primary_slid);
4200Sstevel@tonic-gate
4210Sstevel@tonic-gate /* check first if alternate path exists or not as it is OPTIONAL */
4220Sstevel@tonic-gate if (IBCM_ALT_CEP_PATH(chan_args).cep_hca_port_num != 0) {
4230Sstevel@tonic-gate uint8_t alt_port_no;
4240Sstevel@tonic-gate
4250Sstevel@tonic-gate alt_port_no = IBCM_ALT_CEP_PATH(chan_args).cep_hca_port_num;
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate if (chan_args->oc_path->pi_alt_pkt_lt > ibcm_max_ib_pkt_lt) {
4280Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
4290Sstevel@tonic-gate "Huge Alt Pkt lt %d", channel,
4300Sstevel@tonic-gate chan_args->oc_path->pi_alt_pkt_lt);
4310Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
4320Sstevel@tonic-gate return (IBT_PATH_PKT_LT_TOO_HIGH);
4330Sstevel@tonic-gate }
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate if (port_no != alt_port_no) {
4360Sstevel@tonic-gate
4370Sstevel@tonic-gate status = ibt_get_port_state_byguid(hcap->hca_guid,
4380Sstevel@tonic-gate alt_port_no, NULL, &base_lid);
4390Sstevel@tonic-gate if (status != IBT_SUCCESS) {
4400Sstevel@tonic-gate
4410Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: "
4420Sstevel@tonic-gate "chan 0x%p alt_port_num %d inactive %d",
4430Sstevel@tonic-gate channel, alt_port_no, status);
4440Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
4450Sstevel@tonic-gate return (status);
4460Sstevel@tonic-gate }
4470Sstevel@tonic-gate
4480Sstevel@tonic-gate }
4490Sstevel@tonic-gate alternate_slid =
4500Sstevel@tonic-gate base_lid + IBCM_ALT_ADDS_VECT(chan_args).av_src_path;
4510Sstevel@tonic-gate
4526709Shiremath IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
4530Sstevel@tonic-gate "alternate SLID = %x", channel, alternate_slid);
4540Sstevel@tonic-gate }
4550Sstevel@tonic-gate
4560Sstevel@tonic-gate /*
4570Sstevel@tonic-gate * only pkey needs to be zero'ed, because all other fields are set in
4580Sstevel@tonic-gate * in ibcm_init_reply_addr. But, let's bzero the complete struct for
4590Sstevel@tonic-gate * any future modifications.
4600Sstevel@tonic-gate */
4610Sstevel@tonic-gate bzero(&cm_reply_addr, sizeof (cm_reply_addr));
4620Sstevel@tonic-gate
4630Sstevel@tonic-gate /* Initialize the MAD destination address in stored_reply_addr */
4640Sstevel@tonic-gate if ((status = ibcm_init_reply_addr(hcap, &cm_reply_addr, chan_args,
4650Sstevel@tonic-gate flags, &cm_pkt_lt, primary_slid)) != IBT_SUCCESS) {
4660Sstevel@tonic-gate
4671093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
4680Sstevel@tonic-gate "ibcm_init_reply_addr failed status %d ", channel, status);
4690Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
4700Sstevel@tonic-gate return (status);
4710Sstevel@tonic-gate }
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate /* Initialize the pkey for CM MAD communication */
4750Sstevel@tonic-gate if (cm_reply_addr.rcvd_addr.ia_p_key == 0)
4760Sstevel@tonic-gate cm_reply_addr.rcvd_addr.ia_p_key = prim_pkey;
4770Sstevel@tonic-gate
4780Sstevel@tonic-gate #ifdef DEBUG
4790Sstevel@tonic-gate ibcm_print_reply_addr(channel, &cm_reply_addr);
4800Sstevel@tonic-gate #endif
4810Sstevel@tonic-gate
4820Sstevel@tonic-gate /* Retrieve an ibmf qp for sending CM MADs */
4830Sstevel@tonic-gate if ((cm_qp_entry = ibcm_find_qp(hcap, port_no,
4840Sstevel@tonic-gate cm_reply_addr.rcvd_addr.ia_p_key)) == NULL) {
4851093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
4860Sstevel@tonic-gate "unable to allocate ibmf qp for CM MADs", channel);
4870Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
4880Sstevel@tonic-gate return (IBT_INSUFF_RESOURCE);
4890Sstevel@tonic-gate }
4900Sstevel@tonic-gate
4910Sstevel@tonic-gate
4920Sstevel@tonic-gate if (ibcm_alloc_comid(hcap, &local_comid) != IBCM_SUCCESS) {
4930Sstevel@tonic-gate ibcm_release_qp(cm_qp_entry);
4940Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
4950Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
4960Sstevel@tonic-gate " Unable to allocate comid", channel);
4970Sstevel@tonic-gate return (IBT_INSUFF_KERNEL_RESOURCE);
4980Sstevel@tonic-gate }
4990Sstevel@tonic-gate
5003241Shiremath /* allocate an IBMF mad buffer (REQ) */
5010Sstevel@tonic-gate if ((status = ibcm_alloc_out_msg(ibmf_hdl, &ibmf_msg,
5020Sstevel@tonic-gate MAD_METHOD_SEND)) != IBT_SUCCESS) {
5030Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: "
5040Sstevel@tonic-gate "chan 0x%p ibcm_alloc_out_msg failed", channel);
5050Sstevel@tonic-gate ibcm_release_qp(cm_qp_entry);
5060Sstevel@tonic-gate ibcm_free_comid(hcap, local_comid);
5070Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
5080Sstevel@tonic-gate return (status);
5090Sstevel@tonic-gate }
5100Sstevel@tonic-gate
5113241Shiremath /* allocate an IBMF mad buffer (DREQ) */
5123241Shiremath if ((status = ibcm_alloc_out_msg(ibmf_hdl, &ibmf_msg_dreq,
5133241Shiremath MAD_METHOD_SEND)) != IBT_SUCCESS) {
5143241Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: "
5153241Shiremath "chan 0x%p ibcm_alloc_out_msg failed", channel);
5163241Shiremath (void) ibcm_free_out_msg(ibmf_hdl, &ibmf_msg);
5173241Shiremath ibcm_release_qp(cm_qp_entry);
5183241Shiremath ibcm_free_comid(hcap, local_comid);
5193241Shiremath ibcm_dec_hca_acc_cnt(hcap);
5203241Shiremath return (status);
5213241Shiremath }
5223241Shiremath
5230Sstevel@tonic-gate /* Init to Init, if QP's port does not match with path information */
5240Sstevel@tonic-gate if (qp_query_attr.qp_info.qp_transport.rc.rc_path.cep_hca_port_num !=
5250Sstevel@tonic-gate IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num) {
5260Sstevel@tonic-gate
5270Sstevel@tonic-gate ibt_qp_info_t qp_info;
5280Sstevel@tonic-gate ibt_cep_modify_flags_t cep_flags;
5290Sstevel@tonic-gate
5300Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: "
5310Sstevel@tonic-gate "chan 0x%p chan port %d", channel,
5320Sstevel@tonic-gate qp_query_attr.qp_info.qp_transport.rc.rc_path.\
5330Sstevel@tonic-gate cep_hca_port_num);
5340Sstevel@tonic-gate
5350Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: "
5360Sstevel@tonic-gate "chan 0x%p path port %d", channel, port_no);
5370Sstevel@tonic-gate
5380Sstevel@tonic-gate bzero(&qp_info, sizeof (qp_info));
5390Sstevel@tonic-gate /* For now, set it to RC type */
5400Sstevel@tonic-gate
5410Sstevel@tonic-gate qp_info.qp_trans = IBT_RC_SRV;
5420Sstevel@tonic-gate qp_info.qp_state = IBT_STATE_INIT;
5430Sstevel@tonic-gate qp_info.qp_transport.rc.rc_path.cep_hca_port_num = port_no;
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate cep_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT;
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate status = ibt_modify_qp(channel, cep_flags, &qp_info, NULL);
5480Sstevel@tonic-gate
5490Sstevel@tonic-gate if (status != IBT_SUCCESS) {
5500Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: "
5510Sstevel@tonic-gate "chan 0x%p ibt_modify_qp() = %d", channel, status);
5520Sstevel@tonic-gate ibcm_release_qp(cm_qp_entry);
5530Sstevel@tonic-gate ibcm_free_comid(hcap, local_comid);
5540Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
5550Sstevel@tonic-gate (void) ibcm_free_out_msg(ibmf_hdl, &ibmf_msg);
5563241Shiremath (void) ibcm_free_out_msg(ibmf_hdl, &ibmf_msg_dreq);
5570Sstevel@tonic-gate return (status);
5580Sstevel@tonic-gate } else
5590Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: "
5600Sstevel@tonic-gate "chan 0x%p ibt_modify_qp() = %d", channel, status);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate
5630Sstevel@tonic-gate /* allocate ibcm_state_data_t before grabbing the WRITER lock */
5640Sstevel@tonic-gate statep = kmem_zalloc(sizeof (ibcm_state_data_t), KM_SLEEP);
5650Sstevel@tonic-gate rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
5660Sstevel@tonic-gate lkup_status = ibcm_lookup_msg(IBCM_OUTGOING_REQ, local_comid, 0, 0,
5670Sstevel@tonic-gate hcap, &statep);
5680Sstevel@tonic-gate rw_exit(&hcap->hca_state_rwlock);
5690Sstevel@tonic-gate
5700Sstevel@tonic-gate /* CM should be seeing this for the first time */
5710Sstevel@tonic-gate ASSERT(lkup_status == IBCM_LOOKUP_NEW);
5720Sstevel@tonic-gate
5730Sstevel@tonic-gate /* Increment the hca's resource count */
5740Sstevel@tonic-gate ibcm_inc_hca_res_cnt(hcap);
5750Sstevel@tonic-gate
5760Sstevel@tonic-gate /* Once a resource created on hca, no need to hold the acc cnt */
5770Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
5780Sstevel@tonic-gate
5790Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
5800Sstevel@tonic-gate
5810Sstevel@tonic-gate statep->timerid = 0;
5820Sstevel@tonic-gate statep->local_hca_guid = hca_guid;
5830Sstevel@tonic-gate statep->local_qpn = local_qpn;
5840Sstevel@tonic-gate statep->stored_reply_addr.cm_qp_entry = cm_qp_entry;
5850Sstevel@tonic-gate statep->prim_port = IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num;
5860Sstevel@tonic-gate statep->alt_port = IBCM_ALT_CEP_PATH(chan_args).cep_hca_port_num;
5870Sstevel@tonic-gate
5880Sstevel@tonic-gate
5890Sstevel@tonic-gate /* Save "statep" as channel's CM private data. */
5900Sstevel@tonic-gate statep->channel = channel;
5910Sstevel@tonic-gate IBCM_SET_CHAN_PRIVATE(statep->channel, statep);
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate statep->stored_msg = ibmf_msg;
5943241Shiremath statep->dreq_msg = ibmf_msg_dreq;
5950Sstevel@tonic-gate
5960Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*req_msgp))
5970Sstevel@tonic-gate
5980Sstevel@tonic-gate /* Start filling in the REQ MAD */
5990Sstevel@tonic-gate req_msgp = (ibcm_req_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
6000Sstevel@tonic-gate req_msgp->req_local_comm_id = h2b32(local_comid);
6010Sstevel@tonic-gate req_msgp->req_svc_id = h2b64(chan_args->oc_path->pi_sid);
6020Sstevel@tonic-gate req_msgp->req_local_ca_guid = h2b64(hca_guid);
6030Sstevel@tonic-gate req_msgp->req_local_qkey = h2b32(local_qkey); /* for EEC/RD */
6040Sstevel@tonic-gate
6050Sstevel@tonic-gate /* Bytes 32-35 are req_local_qpn and req_off_resp_resources */
6060Sstevel@tonic-gate req_msgp->req_local_qpn_plus = h2b32(local_qpn << 8 | rdma_in);
6070Sstevel@tonic-gate
6080Sstevel@tonic-gate /* Bytes 36-39 are req_local_eec_no and req_off_initiator_depth */
6090Sstevel@tonic-gate req_msgp->req_local_eec_no_plus = h2b32(local_eecn << 8 | rdma_out);
6100Sstevel@tonic-gate
6110Sstevel@tonic-gate if (flags & IBT_OCHAN_REMOTE_CM_TM)
6120Sstevel@tonic-gate remote_cm_resp_time = chan_args->oc_remote_cm_time;
6130Sstevel@tonic-gate else
6140Sstevel@tonic-gate remote_cm_resp_time = ibcm_remote_response_time;
6150Sstevel@tonic-gate
6160Sstevel@tonic-gate /*
6170Sstevel@tonic-gate * Bytes 40-43 - remote_eecn, remote_cm_resp_time, tran_type,
6180Sstevel@tonic-gate * IBT_CM_FLOW_CONTROL is always set by default.
6190Sstevel@tonic-gate */
6200Sstevel@tonic-gate req_msgp->req_remote_eecn_plus = h2b32(
6210Sstevel@tonic-gate remote_eecn << 8 | (ibt_usec2ib(remote_cm_resp_time) & 0x1f) << 3 |
6220Sstevel@tonic-gate IBT_RC_SRV << 1 | IBT_CM_FLOW_CONTROL);
6230Sstevel@tonic-gate
6240Sstevel@tonic-gate if (flags & IBT_OCHAN_LOCAL_CM_TM)
6250Sstevel@tonic-gate local_cm_proc_time = chan_args->oc_local_cm_time;
6260Sstevel@tonic-gate else
6270Sstevel@tonic-gate local_cm_proc_time = ibcm_local_processing_time;
6280Sstevel@tonic-gate
6290Sstevel@tonic-gate local_cm_resp_time = ibt_usec2ib(local_cm_proc_time +
6300Sstevel@tonic-gate 2 * ibt_ib2usec(chan_args->oc_path->pi_prim_pkt_lt) +
6310Sstevel@tonic-gate ibcm_sw_delay);
6320Sstevel@tonic-gate
6330Sstevel@tonic-gate /* save retry count */
6340Sstevel@tonic-gate statep->cep_retry_cnt = chan_args->oc_path_retry_cnt;
6350Sstevel@tonic-gate
6360Sstevel@tonic-gate if (flags & IBT_OCHAN_STARTING_PSN)
6370Sstevel@tonic-gate starting_psn = chan_args->oc_starting_psn;
6380Sstevel@tonic-gate
6390Sstevel@tonic-gate if (local_cm_resp_time > 0x1f)
6400Sstevel@tonic-gate local_cm_resp_time = 0x1f;
6410Sstevel@tonic-gate
6420Sstevel@tonic-gate /* Bytes 44-47 are req_starting_psn, local_cm_resp_time and retry_cnt */
6430Sstevel@tonic-gate req_msgp->req_starting_psn_plus = h2b32(starting_psn << 8 |
6440Sstevel@tonic-gate local_cm_resp_time << 3 | statep->cep_retry_cnt);
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
6470Sstevel@tonic-gate "Prim Pkt lt (IB time) 0x%x", channel,
6480Sstevel@tonic-gate chan_args->oc_path->pi_prim_pkt_lt);
6490Sstevel@tonic-gate
6500Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
6510Sstevel@tonic-gate "local_cm_proc_time(usec) %d ", channel, local_cm_proc_time);
6520Sstevel@tonic-gate
6530Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
6540Sstevel@tonic-gate "local_cm_resp_time(ib_time) %d", channel, local_cm_resp_time);
6550Sstevel@tonic-gate
6560Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
6570Sstevel@tonic-gate "remote_cm_resp_time (usec) %d", channel, remote_cm_resp_time);
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate statep->starting_psn = starting_psn;
6600Sstevel@tonic-gate
6610Sstevel@tonic-gate /* Pkey - bytes 48-49 */
6620Sstevel@tonic-gate req_msgp->req_part_key = h2b16(prim_pkey);
6630Sstevel@tonic-gate
6640Sstevel@tonic-gate if (flags & IBT_OCHAN_CM_RETRY)
6650Sstevel@tonic-gate cm_retries = chan_args->oc_cm_retry_cnt;
6660Sstevel@tonic-gate else
6670Sstevel@tonic-gate cm_retries = ibcm_max_retries;
6680Sstevel@tonic-gate
6690Sstevel@tonic-gate statep->max_cm_retries = statep->remaining_retry_cnt = cm_retries;
6700Sstevel@tonic-gate req_msgp->req_max_cm_retries_plus = statep->max_cm_retries << 4;
6710Sstevel@tonic-gate
6720Sstevel@tonic-gate /*
6730Sstevel@tonic-gate * Check whether SRQ is associated with this Channel, if yes, then
6740Sstevel@tonic-gate * set the SRQ Exists bit in the REQ.
6750Sstevel@tonic-gate */
6760Sstevel@tonic-gate if (qp_query_attr.qp_srq != NULL) {
6770Sstevel@tonic-gate req_msgp->req_max_cm_retries_plus |= (1 << 3);
6780Sstevel@tonic-gate }
6790Sstevel@tonic-gate
6803241Shiremath /*
6813241Shiremath * By default on Tavor, we override the PathMTU to 1K.
6823241Shiremath * To turn this off, set ibcm_override_path_mtu = 0.
6833241Shiremath */
6843241Shiremath if (ibcm_override_path_mtu && IBCM_IS_HCA_TAVOR(hcap) &&
6853241Shiremath (chan_args->oc_path->pi_path_mtu > IB_MTU_1K)) {
6863241Shiremath req_msgp->req_mtu_plus = IB_MTU_1K << 4 |
6873241Shiremath chan_args->oc_path_rnr_retry_cnt;
6883241Shiremath IBTF_DPRINTF_L3(cmlog, "ibt_open_rc_channel: chan 0x%p PathMTU"
6899913SShantkumar.Hiremath@Sun.COM " overridden to IB_MTU_1K(%d) from %d", channel, IB_MTU_1K,
6903241Shiremath chan_args->oc_path->pi_path_mtu);
6913241Shiremath } else
6923241Shiremath req_msgp->req_mtu_plus = chan_args->oc_path->pi_path_mtu << 4 |
6933241Shiremath chan_args->oc_path_rnr_retry_cnt;
6940Sstevel@tonic-gate
6950Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p CM retry cnt %d"
6961093Shiremath " staring PSN %x", channel, cm_retries, starting_psn);
6970Sstevel@tonic-gate
6980Sstevel@tonic-gate
6990Sstevel@tonic-gate #ifdef NO_EEC_SUPPORT_YET
7000Sstevel@tonic-gate if (flags & IBT_OCHAN_RDC_EXISTS)
7010Sstevel@tonic-gate req_msgp->req_mtu_plus |= 8;
7020Sstevel@tonic-gate #endif
7030Sstevel@tonic-gate
7040Sstevel@tonic-gate /* Initialize the "primary" port stuff next - bytes 52-95 */
7050Sstevel@tonic-gate req_msgp->req_primary_l_port_lid = h2b16(primary_slid);
7060Sstevel@tonic-gate req_msgp->req_primary_r_port_lid =
7070Sstevel@tonic-gate h2b16(IBCM_PRIM_ADDS_VECT(chan_args).av_dlid);
7080Sstevel@tonic-gate req_msgp->req_primary_l_port_gid.gid_prefix =
7090Sstevel@tonic-gate h2b64(IBCM_PRIM_ADDS_VECT(chan_args).av_sgid.gid_prefix);
7100Sstevel@tonic-gate req_msgp->req_primary_l_port_gid.gid_guid =
7110Sstevel@tonic-gate h2b64(IBCM_PRIM_ADDS_VECT(chan_args).av_sgid.gid_guid);
7120Sstevel@tonic-gate req_msgp->req_primary_r_port_gid.gid_prefix =
7130Sstevel@tonic-gate h2b64(IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_prefix);
7140Sstevel@tonic-gate req_msgp->req_primary_r_port_gid.gid_guid =
7150Sstevel@tonic-gate h2b64(IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_guid);
7160Sstevel@tonic-gate primary_grh = IBCM_PRIM_ADDS_VECT(chan_args).av_send_grh;
7170Sstevel@tonic-gate
7181093Shiremath statep->remote_hca_guid = /* not correct, but helpful for debugging */
7191093Shiremath IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_guid;
7201093Shiremath
7210Sstevel@tonic-gate /* Bytes 88-91 - primary_flowlbl, and primary_srate */
7220Sstevel@tonic-gate req_msgp->req_primary_flow_label_plus =
7230Sstevel@tonic-gate h2b32(((primary_grh == B_TRUE) ?
7240Sstevel@tonic-gate (IBCM_PRIM_ADDS_VECT(chan_args).av_flow << 12) : 0) |
7250Sstevel@tonic-gate IBCM_PRIM_ADDS_VECT(chan_args).av_srate);
7260Sstevel@tonic-gate req_msgp->req_primary_traffic_class = (primary_grh == B_TRUE) ?
7270Sstevel@tonic-gate IBCM_PRIM_ADDS_VECT(chan_args).av_tclass : 0;
7280Sstevel@tonic-gate req_msgp->req_primary_hop_limit = (primary_grh == B_TRUE) ?
7294970Shiremath IBCM_PRIM_ADDS_VECT(chan_args).av_hop : 1;
7300Sstevel@tonic-gate req_msgp->req_primary_sl_plus =
7310Sstevel@tonic-gate IBCM_PRIM_ADDS_VECT(chan_args).av_srvl << 4 |
7320Sstevel@tonic-gate ((primary_grh == B_TRUE) ? 0 : 8);
7330Sstevel@tonic-gate
7340Sstevel@tonic-gate req_msgp->req_primary_localtime_plus =
7350Sstevel@tonic-gate ibt_usec2ib((2 * ibt_ib2usec(chan_args->oc_path->pi_prim_pkt_lt)) +
7360Sstevel@tonic-gate ibt_ib2usec(hcap->hca_ack_delay)) << 3;
7370Sstevel@tonic-gate
7380Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan %p statep %p",
7390Sstevel@tonic-gate channel, statep);
7400Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
7410Sstevel@tonic-gate "active hca_ack_delay (usec) %d", channel,
7420Sstevel@tonic-gate req_msgp->req_primary_localtime_plus);
7430Sstevel@tonic-gate
7440Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
7450Sstevel@tonic-gate "Sent primary cep timeout (IB Time) %d", channel,
7460Sstevel@tonic-gate hcap->hca_ack_delay);
7470Sstevel@tonic-gate
7480Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p prim_dlid %x ",
7490Sstevel@tonic-gate channel, IBCM_PRIM_ADDS_VECT(chan_args).av_dlid);
7500Sstevel@tonic-gate
7510Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
7521093Shiremath "prim GID %llX:%llX", channel,
7531093Shiremath IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_prefix,
7540Sstevel@tonic-gate IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_guid);
7550Sstevel@tonic-gate
7560Sstevel@tonic-gate /* Initialize the "alternate" port stuff - optional */
7570Sstevel@tonic-gate if (chan_args->oc_path->pi_alt_cep_path.cep_hca_port_num != 0) {
7580Sstevel@tonic-gate ib_gid_t tmp_gid;
7590Sstevel@tonic-gate
7600Sstevel@tonic-gate req_msgp->req_alt_l_port_lid = h2b16(alternate_slid);
7610Sstevel@tonic-gate req_msgp->req_alt_r_port_lid =
7620Sstevel@tonic-gate h2b16(IBCM_ALT_ADDS_VECT(chan_args).av_dlid);
7630Sstevel@tonic-gate /*
7640Sstevel@tonic-gate * doing all this as req_alt_r/l_port_gid is at offset
7650Sstevel@tonic-gate * 100, 116 which is not divisible by 8
7660Sstevel@tonic-gate */
7670Sstevel@tonic-gate
7680Sstevel@tonic-gate tmp_gid.gid_prefix =
7690Sstevel@tonic-gate h2b64(IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_prefix);
7700Sstevel@tonic-gate tmp_gid.gid_guid =
7710Sstevel@tonic-gate h2b64(IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_guid);
7720Sstevel@tonic-gate bcopy(&tmp_gid, &req_msgp->req_alt_r_port_gid[0],
7730Sstevel@tonic-gate sizeof (ib_gid_t));
7740Sstevel@tonic-gate tmp_gid.gid_prefix =
7750Sstevel@tonic-gate h2b64(IBCM_ALT_ADDS_VECT(chan_args).av_sgid.gid_prefix);
7760Sstevel@tonic-gate tmp_gid.gid_guid =
7770Sstevel@tonic-gate h2b64(IBCM_ALT_ADDS_VECT(chan_args).av_sgid.gid_guid);
7780Sstevel@tonic-gate
7790Sstevel@tonic-gate bcopy(&tmp_gid, &req_msgp->req_alt_l_port_gid[0],
7800Sstevel@tonic-gate sizeof (ib_gid_t));
7810Sstevel@tonic-gate alternate_grh = IBCM_ALT_ADDS_VECT(chan_args).av_send_grh;
7820Sstevel@tonic-gate
7830Sstevel@tonic-gate /* Bytes 132-135 - alternate_flow_label, and alternate srate */
7840Sstevel@tonic-gate req_msgp->req_alt_flow_label_plus = h2b32(
7850Sstevel@tonic-gate (((alternate_grh == B_TRUE) ?
7860Sstevel@tonic-gate (IBCM_ALT_ADDS_VECT(chan_args).av_flow << 12) : 0) |
7870Sstevel@tonic-gate IBCM_ALT_ADDS_VECT(chan_args).av_srate));
7880Sstevel@tonic-gate req_msgp->req_alt_traffic_class = (alternate_grh == B_TRUE) ?
7890Sstevel@tonic-gate IBCM_ALT_ADDS_VECT(chan_args).av_tclass : 0;
7900Sstevel@tonic-gate req_msgp->req_alt_hop_limit = (alternate_grh == B_TRUE) ?
7914970Shiremath IBCM_ALT_ADDS_VECT(chan_args).av_hop : 1;
7920Sstevel@tonic-gate req_msgp->req_alt_sl_plus =
7930Sstevel@tonic-gate IBCM_ALT_ADDS_VECT(chan_args).av_srvl << 4 |
7940Sstevel@tonic-gate ((alternate_grh == B_TRUE) ? 0 : 8);
7950Sstevel@tonic-gate req_msgp->req_alt_localtime_plus = ibt_usec2ib((2 *
7960Sstevel@tonic-gate ibt_ib2usec(chan_args->oc_path->pi_alt_pkt_lt)) +
7970Sstevel@tonic-gate ibt_ib2usec(hcap->hca_ack_delay)) << 3;
7980Sstevel@tonic-gate
7990Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
8000Sstevel@tonic-gate "alt_dlid %x ", channel,
8010Sstevel@tonic-gate IBCM_ALT_ADDS_VECT(chan_args).av_dlid);
8020Sstevel@tonic-gate
8030Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
8041093Shiremath "alt GID %llX:%llX", channel,
8051093Shiremath IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_prefix,
8060Sstevel@tonic-gate IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_guid);
8070Sstevel@tonic-gate }
8080Sstevel@tonic-gate
8090Sstevel@tonic-gate len = min(chan_args->oc_priv_data_len, IBT_REQ_PRIV_DATA_SZ);
8100Sstevel@tonic-gate if ((len > 0) && chan_args->oc_priv_data)
8110Sstevel@tonic-gate bcopy(chan_args->oc_priv_data, req_msgp->req_private_data, len);
8120Sstevel@tonic-gate
8130Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*req_msgp))
8140Sstevel@tonic-gate
8150Sstevel@tonic-gate /* return_data is filled up in the state machine code */
8160Sstevel@tonic-gate if (ret_args != NULL) {
8170Sstevel@tonic-gate statep->open_return_data = ret_args;
8180Sstevel@tonic-gate }
8190Sstevel@tonic-gate
8200Sstevel@tonic-gate /* initialize some statep fields here */
8210Sstevel@tonic-gate statep->mode = IBCM_ACTIVE_MODE;
8220Sstevel@tonic-gate statep->hcap = hcap;
8230Sstevel@tonic-gate
8240Sstevel@tonic-gate statep->cm_handler = chan_args->oc_cm_handler;
8250Sstevel@tonic-gate statep->state_cm_private = chan_args->oc_cm_clnt_private;
8260Sstevel@tonic-gate
8270Sstevel@tonic-gate statep->pkt_life_time =
8280Sstevel@tonic-gate ibt_ib2usec(chan_args->oc_path->pi_prim_pkt_lt);
8290Sstevel@tonic-gate
8301093Shiremath statep->timer_value = ibt_ib2usec(ibt_usec2ib(
8311093Shiremath 2 * ibt_ib2usec(cm_pkt_lt) + remote_cm_resp_time));
8320Sstevel@tonic-gate
8330Sstevel@tonic-gate /* Initialize statep->stored_reply_addr */
8340Sstevel@tonic-gate statep->stored_reply_addr.ibmf_hdl = ibmf_hdl;
8350Sstevel@tonic-gate
8360Sstevel@tonic-gate /* Initialize stored reply addr fields */
8370Sstevel@tonic-gate statep->stored_reply_addr.grh_hdr = cm_reply_addr.grh_hdr;
8380Sstevel@tonic-gate statep->stored_reply_addr.rcvd_addr = cm_reply_addr.rcvd_addr;
8390Sstevel@tonic-gate statep->stored_reply_addr.grh_exists = cm_reply_addr.grh_exists;
8400Sstevel@tonic-gate statep->stored_reply_addr.port_num = cm_reply_addr.port_num;
8410Sstevel@tonic-gate
8420Sstevel@tonic-gate /*
8430Sstevel@tonic-gate * The IPD on local/active side is calculated by path functions,
8440Sstevel@tonic-gate * hence available in the args of ibt_open_rc_channel
8450Sstevel@tonic-gate */
8460Sstevel@tonic-gate statep->local_srate = IBCM_PRIM_ADDS_VECT(chan_args).av_srate;
8470Sstevel@tonic-gate statep->local_alt_srate = IBCM_ALT_ADDS_VECT(chan_args).av_srate;
8480Sstevel@tonic-gate
8490Sstevel@tonic-gate /* Store the source path bits for primary and alt paths */
8500Sstevel@tonic-gate statep->prim_src_path_bits = IBCM_PRIM_ADDS_VECT(chan_args).av_src_path;
8510Sstevel@tonic-gate statep->alt_src_path_bits = IBCM_ALT_ADDS_VECT(chan_args).av_src_path;
8520Sstevel@tonic-gate
8531093Shiremath statep->open_flow = 1;
8540Sstevel@tonic-gate statep->open_done = B_FALSE;
8550Sstevel@tonic-gate statep->state = statep->timer_stored_state = IBCM_STATE_REQ_SENT;
8561093Shiremath IBCM_REF_CNT_INCR(statep); /* Decremented before return */
8571093Shiremath IBCM_REF_CNT_INCR(statep); /* Decremented after REQ is posted */
8580Sstevel@tonic-gate statep->send_mad_flags |= IBCM_REQ_POST_BUSY;
8590Sstevel@tonic-gate
86011369SPramod.Gunjikar@Sun.COM /*
86111369SPramod.Gunjikar@Sun.COM * Skip moving channel to error state during close, for OFUV clients.
86211369SPramod.Gunjikar@Sun.COM * OFUV clients transition the channel to error state by itself.
86311369SPramod.Gunjikar@Sun.COM */
86411369SPramod.Gunjikar@Sun.COM if (flags & IBT_OCHAN_OFUV)
86511369SPramod.Gunjikar@Sun.COM statep->is_this_ofuv_chan = B_TRUE;
86611369SPramod.Gunjikar@Sun.COM
8670Sstevel@tonic-gate IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
8680Sstevel@tonic-gate h2b16(IBCM_INCOMING_REQ + IBCM_ATTR_BASE_ID);
8690Sstevel@tonic-gate
8700Sstevel@tonic-gate IBCM_OUT_HDRP(statep->stored_msg)->TransactionID =
8710Sstevel@tonic-gate h2b64(ibcm_generate_tranid(IBCM_INCOMING_REQ, statep->local_comid,
8720Sstevel@tonic-gate 0));
8730Sstevel@tonic-gate
8740Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
8750Sstevel@tonic-gate
87611369SPramod.Gunjikar@Sun.COM ibtl_cm_chan_is_opening(channel);
87711369SPramod.Gunjikar@Sun.COM
8781093Shiremath ibcm_open_enqueue(statep);
8790Sstevel@tonic-gate
8800Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
8810Sstevel@tonic-gate
8820Sstevel@tonic-gate if (mode == IBT_BLOCKING) {
8830Sstevel@tonic-gate
8840Sstevel@tonic-gate /* wait for REQ/REP/RTU */
8850Sstevel@tonic-gate while (statep->open_done != B_TRUE) {
8860Sstevel@tonic-gate cv_wait(&statep->block_client_cv, &statep->state_mutex);
8870Sstevel@tonic-gate }
8880Sstevel@tonic-gate
8890Sstevel@tonic-gate /*
8900Sstevel@tonic-gate * In the case that open_channel() fails because of a
8910Sstevel@tonic-gate * REJ or timeout, change retval to IBT_CM_FAILURE
8920Sstevel@tonic-gate */
89312064SShantkumar.Hiremath@Sun.COM if (statep->open_return_data->rc_status != IBT_CM_ACCEPT) {
8940Sstevel@tonic-gate status = IBT_CM_FAILURE;
89512064SShantkumar.Hiremath@Sun.COM ibtl_cm_chan_open_is_aborted(channel);
89612064SShantkumar.Hiremath@Sun.COM }
8970Sstevel@tonic-gate
8980Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_open_rc_channel: chan 0x%p "
8990Sstevel@tonic-gate "ret status %d cm status %d", channel, status,
9000Sstevel@tonic-gate statep->open_return_data->rc_status);
9010Sstevel@tonic-gate }
9020Sstevel@tonic-gate
9030Sstevel@tonic-gate /* decrement the ref-count before leaving here */
9040Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
9050Sstevel@tonic-gate
9060Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
9070Sstevel@tonic-gate
9080Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_open_rc_channel: chan 0x%p done", channel);
9090Sstevel@tonic-gate return (status);
9100Sstevel@tonic-gate }
9110Sstevel@tonic-gate
9120Sstevel@tonic-gate /*
9130Sstevel@tonic-gate * ibcm_init_reply_addr:
9140Sstevel@tonic-gate *
9150Sstevel@tonic-gate * The brief description of functionality below.
9160Sstevel@tonic-gate *
9170Sstevel@tonic-gate * For IBT_OCHAN_PORT_REDIRECTED (ie., port redirected case):
9180Sstevel@tonic-gate * Build CM path from chan_args->oc_cm_cep_path
9190Sstevel@tonic-gate * Set CM pkt lt (ie.,life time) to chan_args->oc_cm_pkt_lt
9200Sstevel@tonic-gate *
9210Sstevel@tonic-gate * For IBT_OCHAN_REDIRECTED (ie., port and CM redirected case):
9220Sstevel@tonic-gate * If Redirect LID is specified,
9230Sstevel@tonic-gate * If Redirect GID is not specified or specified to be on the same
9240Sstevel@tonic-gate * subnet, then
9250Sstevel@tonic-gate * Build CM path from chan_args->oc_cm_redirect_info
9260Sstevel@tonic-gate * Set CM pkt lt to subnet timeout
9270Sstevel@tonic-gate * Else (ie., GID specified, but on a different subnet)
9280Sstevel@tonic-gate * Do a path lookup to build CM Path and set CM pkt lt
9290Sstevel@tonic-gate *
9300Sstevel@tonic-gate */
9310Sstevel@tonic-gate static ibt_status_t
ibcm_init_reply_addr(ibcm_hca_info_t * hcap,ibcm_mad_addr_t * reply_addr,ibt_chan_open_args_t * chan_args,ibt_chan_open_flags_t flags,ib_time_t * cm_pkt_lt,ib_lid_t prim_slid)9320Sstevel@tonic-gate ibcm_init_reply_addr(ibcm_hca_info_t *hcap, ibcm_mad_addr_t *reply_addr,
9330Sstevel@tonic-gate ibt_chan_open_args_t *chan_args, ibt_chan_open_flags_t flags,
9340Sstevel@tonic-gate ib_time_t *cm_pkt_lt, ib_lid_t prim_slid)
9350Sstevel@tonic-gate {
9360Sstevel@tonic-gate ibt_adds_vect_t *cm_adds;
9370Sstevel@tonic-gate ibt_path_info_t path;
9380Sstevel@tonic-gate boolean_t cm_grh;
9390Sstevel@tonic-gate ibt_status_t status;
9400Sstevel@tonic-gate
9410Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_init_reply_addr:");
9420Sstevel@tonic-gate
9430Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*reply_addr))
9440Sstevel@tonic-gate
9450Sstevel@tonic-gate /*
9460Sstevel@tonic-gate * sending side CM lid/gid/port num are not based on any redirect
9470Sstevel@tonic-gate * params. These values are set to primary RC path lid/gid/port num.
9480Sstevel@tonic-gate * In the future, these values can be set based on framework policy
9490Sstevel@tonic-gate * decisions ensuring reachability.
9500Sstevel@tonic-gate */
9510Sstevel@tonic-gate reply_addr->grh_hdr.ig_sender_gid =
9520Sstevel@tonic-gate IBCM_PRIM_ADDS_VECT(chan_args).av_sgid;
9530Sstevel@tonic-gate reply_addr->rcvd_addr.ia_local_lid = prim_slid;
9540Sstevel@tonic-gate reply_addr->port_num = IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num;
9550Sstevel@tonic-gate
9560Sstevel@tonic-gate if (flags & IBT_OCHAN_PORT_REDIRECTED) {
9570Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_init_rely_addr: "
9580Sstevel@tonic-gate "IBT_OCHAN_PORT_REDIRECTED specified");
9590Sstevel@tonic-gate
9600Sstevel@tonic-gate status = ibt_index2pkey_byguid(hcap->hca_guid,
9610Sstevel@tonic-gate chan_args->oc_cm_cep_path->cep_hca_port_num,
9620Sstevel@tonic-gate chan_args->oc_cm_cep_path->cep_pkey_ix,
9630Sstevel@tonic-gate &reply_addr->rcvd_addr.ia_p_key);
9640Sstevel@tonic-gate
9650Sstevel@tonic-gate if (status != IBT_SUCCESS) {
9660Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_init_rely_addr: Invalid "
9670Sstevel@tonic-gate "CM PKeyIx %x port_num %x",
9680Sstevel@tonic-gate chan_args->oc_cm_cep_path->cep_pkey_ix,
9690Sstevel@tonic-gate chan_args->oc_cm_cep_path->cep_hca_port_num);
9700Sstevel@tonic-gate return (status);
9710Sstevel@tonic-gate }
9720Sstevel@tonic-gate
9730Sstevel@tonic-gate cm_adds = &(chan_args->oc_cm_cep_path->cep_adds_vect);
9740Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_init_rely_addr: dlid = %x",
9750Sstevel@tonic-gate cm_adds->av_dlid);
9760Sstevel@tonic-gate
9770Sstevel@tonic-gate reply_addr->rcvd_addr.ia_q_key = IB_GSI_QKEY;
9780Sstevel@tonic-gate reply_addr->rcvd_addr.ia_remote_qno = 1;
9790Sstevel@tonic-gate *cm_pkt_lt = chan_args->oc_cm_pkt_lt;
9800Sstevel@tonic-gate
9810Sstevel@tonic-gate } else if (flags & IBT_OCHAN_REDIRECTED) {
9820Sstevel@tonic-gate ibt_redirect_info_t *redirect_info;
9830Sstevel@tonic-gate ibt_hca_portinfo_t *port_infop;
9840Sstevel@tonic-gate uint_t psize, nports;
9850Sstevel@tonic-gate
9860Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_init_rely_addr: "
9870Sstevel@tonic-gate "IBT_OCHAN_REDIRECTED specified");
9880Sstevel@tonic-gate
9890Sstevel@tonic-gate redirect_info = chan_args->oc_cm_redirect_info;
9900Sstevel@tonic-gate
9911093Shiremath if ((redirect_info->rdi_gid.gid_prefix == 0) ||
9921093Shiremath (redirect_info->rdi_gid.gid_guid == 0)) {
9931093Shiremath IBTF_DPRINTF_L2(cmlog, "ibcm_init_reply_addr: "
9941093Shiremath "ERROR: Re-direct GID value NOT Provided.");
9951093Shiremath return (IBT_INVALID_PARAM);
9961093Shiremath }
9971093Shiremath
9980Sstevel@tonic-gate /* As per spec definition 1.1, it's always IB_GSI_QKEY */
9990Sstevel@tonic-gate reply_addr->rcvd_addr.ia_q_key = redirect_info->rdi_qkey;
10000Sstevel@tonic-gate reply_addr->rcvd_addr.ia_remote_qno = redirect_info->rdi_qpn;
10010Sstevel@tonic-gate reply_addr->rcvd_addr.ia_p_key = redirect_info->rdi_pkey;
10020Sstevel@tonic-gate
10030Sstevel@tonic-gate /*
10041093Shiremath * if LID is non-zero in classportinfo then use classportinfo
10051093Shiremath * fields to form CM MAD destination address.
10060Sstevel@tonic-gate */
10071093Shiremath if (redirect_info->rdi_dlid != 0) {
10080Sstevel@tonic-gate status = ibtl_cm_query_hca_ports_byguid(hcap->hca_guid,
10090Sstevel@tonic-gate reply_addr->port_num, &port_infop, &nports, &psize);
10100Sstevel@tonic-gate if ((status != IBT_SUCCESS) || (nports == 0)) {
10110Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_init_reply_addr: "
10120Sstevel@tonic-gate "Query Ports Failed: %d", status);
10130Sstevel@tonic-gate return (status);
10140Sstevel@tonic-gate } else if (port_infop->p_subnet_timeout >
10155752Shiremath ibcm_max_ib_pkt_lt) {
10160Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_init_reply_addr: "
10170Sstevel@tonic-gate "large subnet timeout %x port_no %x",
10180Sstevel@tonic-gate port_infop->p_subnet_timeout,
10190Sstevel@tonic-gate reply_addr->port_num);
10200Sstevel@tonic-gate ibt_free_portinfo(port_infop, psize);
10210Sstevel@tonic-gate return (IBT_PATH_PKT_LT_TOO_HIGH);
10220Sstevel@tonic-gate } else {
10230Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_init_reply_addr: "
10240Sstevel@tonic-gate "subnet timeout %x port_no %x",
10250Sstevel@tonic-gate port_infop->p_subnet_timeout,
10260Sstevel@tonic-gate reply_addr->port_num);
10270Sstevel@tonic-gate
10280Sstevel@tonic-gate *cm_pkt_lt =
10290Sstevel@tonic-gate ibt_ib2usec(min(ibcm_max_ib_mad_pkt_lt,
10300Sstevel@tonic-gate port_infop->p_subnet_timeout));
10310Sstevel@tonic-gate
10320Sstevel@tonic-gate ibt_free_portinfo(port_infop, psize);
10330Sstevel@tonic-gate }
10340Sstevel@tonic-gate
10350Sstevel@tonic-gate reply_addr->rcvd_addr.ia_remote_lid =
10360Sstevel@tonic-gate redirect_info->rdi_dlid;
10370Sstevel@tonic-gate reply_addr->rcvd_addr.ia_service_level =
10380Sstevel@tonic-gate redirect_info->rdi_sl;
10391093Shiremath reply_addr->grh_exists = B_TRUE;
10401093Shiremath reply_addr->grh_hdr.ig_recver_gid =
10411093Shiremath redirect_info->rdi_gid;
10421093Shiremath reply_addr->grh_hdr.ig_tclass =
10431093Shiremath redirect_info->rdi_tclass;
10441093Shiremath reply_addr->grh_hdr.ig_flow_label =
10451093Shiremath redirect_info->rdi_flow;
10461093Shiremath
10471093Shiremath /* Classportinfo doesn't have hoplimit field */
10484970Shiremath reply_addr->grh_hdr.ig_hop_limit = 1;
10490Sstevel@tonic-gate return (IBT_SUCCESS);
10500Sstevel@tonic-gate
10511093Shiremath } else {
10520Sstevel@tonic-gate ibt_path_attr_t path_attr;
10530Sstevel@tonic-gate ib_gid_t path_dgid[1];
10540Sstevel@tonic-gate
10550Sstevel@tonic-gate /*
10560Sstevel@tonic-gate * If GID is specified, and LID is zero in classportinfo
10571093Shiremath * do a path lookup using specified GID, Pkey,
10580Sstevel@tonic-gate * in classportinfo
10590Sstevel@tonic-gate */
10600Sstevel@tonic-gate
10610Sstevel@tonic-gate bzero(&path_attr, sizeof (path_attr));
10620Sstevel@tonic-gate
10630Sstevel@tonic-gate path_attr.pa_dgids = &path_dgid[0];
10640Sstevel@tonic-gate path_attr.pa_dgids[0] = redirect_info->rdi_gid;
10650Sstevel@tonic-gate
10660Sstevel@tonic-gate /*
10670Sstevel@tonic-gate * use reply_addr below, as sender_gid in reply_addr
10680Sstevel@tonic-gate * may have been set above based on some policy decision
10690Sstevel@tonic-gate * for originating end point for CM MADs above
10700Sstevel@tonic-gate */
10710Sstevel@tonic-gate path_attr.pa_sgid = reply_addr->grh_hdr.ig_sender_gid;
10720Sstevel@tonic-gate path_attr.pa_num_dgids = 1;
10730Sstevel@tonic-gate path_attr.pa_pkey = redirect_info->rdi_pkey;
10740Sstevel@tonic-gate
10750Sstevel@tonic-gate if ((status = ibt_get_paths(ibcm_ibt_handle,
10761093Shiremath IBT_PATH_PKEY, &path_attr, 1, &path, NULL)) !=
10770Sstevel@tonic-gate IBT_SUCCESS)
10780Sstevel@tonic-gate return (status);
10790Sstevel@tonic-gate
10800Sstevel@tonic-gate /* Initialize cm_adds */
10810Sstevel@tonic-gate cm_adds = &path.pi_prim_cep_path.cep_adds_vect;
10820Sstevel@tonic-gate *cm_pkt_lt = path.pi_prim_pkt_lt;
10830Sstevel@tonic-gate }
10840Sstevel@tonic-gate
10850Sstevel@tonic-gate } else { /* cm_pkey initialized in ibt_open_rc_channel */
10860Sstevel@tonic-gate reply_addr->rcvd_addr.ia_q_key = IB_GSI_QKEY;
10870Sstevel@tonic-gate reply_addr->rcvd_addr.ia_remote_qno = 1;
10880Sstevel@tonic-gate *cm_pkt_lt = chan_args->oc_path->pi_prim_pkt_lt;
10890Sstevel@tonic-gate cm_adds = &(IBCM_PRIM_ADDS_VECT(chan_args));
10900Sstevel@tonic-gate }
10910Sstevel@tonic-gate
10920Sstevel@tonic-gate
10930Sstevel@tonic-gate cm_grh = cm_adds->av_send_grh;
10940Sstevel@tonic-gate reply_addr->grh_exists = cm_grh;
10950Sstevel@tonic-gate
10960Sstevel@tonic-gate reply_addr->rcvd_addr.ia_remote_lid =
10970Sstevel@tonic-gate cm_adds->av_dlid;
10980Sstevel@tonic-gate reply_addr->grh_hdr.ig_recver_gid =
10990Sstevel@tonic-gate cm_adds->av_dgid;
11000Sstevel@tonic-gate reply_addr->grh_hdr.ig_flow_label =
11010Sstevel@tonic-gate cm_adds->av_flow & IB_GRH_FLOW_LABEL_MASK;
11020Sstevel@tonic-gate reply_addr->grh_hdr.ig_tclass =
11030Sstevel@tonic-gate (cm_grh == B_TRUE) ? cm_adds->av_tclass : 0;
11040Sstevel@tonic-gate reply_addr->grh_hdr.ig_hop_limit =
11054970Shiremath (cm_grh == B_TRUE) ? cm_adds->av_hop : 1;
11060Sstevel@tonic-gate reply_addr->rcvd_addr.ia_service_level =
11070Sstevel@tonic-gate cm_adds->av_srvl;
11080Sstevel@tonic-gate
11090Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*reply_addr))
11100Sstevel@tonic-gate
11110Sstevel@tonic-gate return (IBT_SUCCESS);
11120Sstevel@tonic-gate }
11130Sstevel@tonic-gate
11140Sstevel@tonic-gate
11150Sstevel@tonic-gate /*
11160Sstevel@tonic-gate * ibt_prime_close_rc_channel()
11170Sstevel@tonic-gate * It allocates resources required for close channel operation, so
11180Sstevel@tonic-gate * ibt_close_rc_channel can be called from interrupt routine.
11190Sstevel@tonic-gate *
11200Sstevel@tonic-gate * INPUTS:
11210Sstevel@tonic-gate * channel The address of an ibt_channel_t struct that
11220Sstevel@tonic-gate * specifies the channel to open.
11230Sstevel@tonic-gate *
11240Sstevel@tonic-gate * RETURN VALUES:
11250Sstevel@tonic-gate * IBT_SUCCESS on success(or respective failure on error)
11260Sstevel@tonic-gate *
11270Sstevel@tonic-gate * Clients are typically expected to call this function in established state
11280Sstevel@tonic-gate */
11290Sstevel@tonic-gate ibt_status_t
ibt_prime_close_rc_channel(ibt_channel_hdl_t channel)11300Sstevel@tonic-gate ibt_prime_close_rc_channel(ibt_channel_hdl_t channel)
11310Sstevel@tonic-gate {
11320Sstevel@tonic-gate ibcm_state_data_t *statep;
11330Sstevel@tonic-gate ibt_status_t status = IBT_SUCCESS;
11340Sstevel@tonic-gate
11350Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_prime_close_rc_channel(%p)", channel);
11360Sstevel@tonic-gate
11370Sstevel@tonic-gate /* validate channel, first */
11380Sstevel@tonic-gate if (IBCM_INVALID_CHANNEL(channel)) {
11391093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_prime_close_rc_channel: chan 0x%p "
11400Sstevel@tonic-gate "invalid channel", channel);
11410Sstevel@tonic-gate return (IBT_CHAN_HDL_INVALID);
11420Sstevel@tonic-gate }
11430Sstevel@tonic-gate
11440Sstevel@tonic-gate if (ibtl_cm_get_chan_type(channel) != IBT_RC_SRV) {
11451093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_prime_close_rc_channel: chan 0x%p "
11460Sstevel@tonic-gate "Invalid Channel type: Applicable only to RC Channel",
11470Sstevel@tonic-gate channel);
11480Sstevel@tonic-gate return (IBT_CHAN_SRV_TYPE_INVALID);
11490Sstevel@tonic-gate }
11500Sstevel@tonic-gate
11510Sstevel@tonic-gate /* get the statep */
11520Sstevel@tonic-gate IBCM_GET_CHAN_PRIVATE(channel, statep);
11530Sstevel@tonic-gate
11540Sstevel@tonic-gate /*
11550Sstevel@tonic-gate * This can happen, if the statep is already gone by a DREQ from
11560Sstevel@tonic-gate * the remote side
11570Sstevel@tonic-gate */
11580Sstevel@tonic-gate
11590Sstevel@tonic-gate if (statep == NULL) {
11601093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_prime_close_rc_channel: chan 0x%p "
11610Sstevel@tonic-gate "statep NULL", channel);
11620Sstevel@tonic-gate return (IBT_SUCCESS);
11630Sstevel@tonic-gate }
11640Sstevel@tonic-gate
11650Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
11660Sstevel@tonic-gate IBCM_RELEASE_CHAN_PRIVATE(channel);
11670Sstevel@tonic-gate if (statep->state != IBCM_STATE_ESTABLISHED) {
11680Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
11690Sstevel@tonic-gate return (IBT_CHAN_STATE_INVALID);
11700Sstevel@tonic-gate }
11710Sstevel@tonic-gate IBCM_REF_CNT_INCR(statep);
11720Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_prime_close_rc_channel: chan 0x%p statep %p"
11731093Shiremath " state %x", channel, statep, statep->state);
11740Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
11750Sstevel@tonic-gate
11760Sstevel@tonic-gate /* clients could pre-allocate dreq mad, even before connection est */
11770Sstevel@tonic-gate if (statep->dreq_msg == NULL)
11780Sstevel@tonic-gate status = ibcm_alloc_out_msg(statep->stored_reply_addr.ibmf_hdl,
11790Sstevel@tonic-gate &statep->dreq_msg, MAD_METHOD_SEND);
11800Sstevel@tonic-gate
11810Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
11820Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
11830Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
11840Sstevel@tonic-gate
11850Sstevel@tonic-gate if (status != IBT_SUCCESS) {
11860Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_prime_close_rc_channel: chan 0x%p "
11870Sstevel@tonic-gate "ibcm_alloc_out_msg failed ", channel);
11880Sstevel@tonic-gate return (status);
11890Sstevel@tonic-gate }
11900Sstevel@tonic-gate
11910Sstevel@tonic-gate /* If this message isn't seen then ibt_prime_close_rc_channel failed */
11920Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_prime_close_rc_channel: chan 0x%p done",
11930Sstevel@tonic-gate channel);
11940Sstevel@tonic-gate
11950Sstevel@tonic-gate return (IBT_SUCCESS);
11960Sstevel@tonic-gate }
11970Sstevel@tonic-gate
11980Sstevel@tonic-gate /*
11990Sstevel@tonic-gate * ibt_close_rc_channel()
12000Sstevel@tonic-gate * It closes an established channel.
12010Sstevel@tonic-gate *
12020Sstevel@tonic-gate * RETURN VALUES:
12030Sstevel@tonic-gate * IBT_SUCCESS on success(or respective failure on error)
12040Sstevel@tonic-gate */
12050Sstevel@tonic-gate ibt_status_t
ibt_close_rc_channel(ibt_channel_hdl_t channel,ibt_execution_mode_t mode,void * priv_data,ibt_priv_data_len_t priv_data_len,uint8_t * ret_status,void * ret_priv_data,ibt_priv_data_len_t * ret_priv_data_len_p)12060Sstevel@tonic-gate ibt_close_rc_channel(ibt_channel_hdl_t channel, ibt_execution_mode_t mode,
12070Sstevel@tonic-gate void *priv_data, ibt_priv_data_len_t priv_data_len, uint8_t *ret_status,
12080Sstevel@tonic-gate void *ret_priv_data, ibt_priv_data_len_t *ret_priv_data_len_p)
12090Sstevel@tonic-gate {
12100Sstevel@tonic-gate ibcm_state_data_t *statep;
12110Sstevel@tonic-gate
12120Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_close_rc_channel(%p, %x, %p, %d, %p)",
12130Sstevel@tonic-gate channel, mode, priv_data, priv_data_len,
12140Sstevel@tonic-gate (ret_priv_data_len_p == NULL) ? 0 : *ret_priv_data_len_p);
12150Sstevel@tonic-gate
12160Sstevel@tonic-gate /* validate channel, first */
12170Sstevel@tonic-gate if (IBCM_INVALID_CHANNEL(channel)) {
12180Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
12190Sstevel@tonic-gate "invalid channel", channel);
12200Sstevel@tonic-gate return (IBT_CHAN_HDL_INVALID);
12210Sstevel@tonic-gate }
12220Sstevel@tonic-gate
12230Sstevel@tonic-gate if (ibtl_cm_get_chan_type(channel) != IBT_RC_SRV) {
12241093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
12250Sstevel@tonic-gate "Invalid Channel type: Applicable only to RC Channel",
12260Sstevel@tonic-gate channel);
12270Sstevel@tonic-gate return (IBT_CHAN_SRV_TYPE_INVALID);
12280Sstevel@tonic-gate }
12290Sstevel@tonic-gate
12300Sstevel@tonic-gate if (mode == IBT_BLOCKING) {
12310Sstevel@tonic-gate /* valid only for BLOCKING MODE */
12320Sstevel@tonic-gate if ((ret_priv_data_len_p != NULL) &&
12330Sstevel@tonic-gate (*ret_priv_data_len_p > IBT_DREP_PRIV_DATA_SZ)) {
12340Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p"
12351093Shiremath " private data len %d is too large", channel,
12360Sstevel@tonic-gate *ret_priv_data_len_p);
12370Sstevel@tonic-gate return (IBT_INVALID_PARAM);
12380Sstevel@tonic-gate }
12390Sstevel@tonic-gate } else if ((mode != IBT_NONBLOCKING) && (mode != IBT_NOCALLBACKS)) {
12401093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
12410Sstevel@tonic-gate "invalid mode %x specified", channel, mode);
12420Sstevel@tonic-gate return (IBT_INVALID_PARAM);
12430Sstevel@tonic-gate }
12440Sstevel@tonic-gate
12453241Shiremath if (ibtl_cm_is_chan_closing(channel) ||
12463241Shiremath ibtl_cm_is_chan_closed(channel)) {
12473241Shiremath if (ret_status)
12483241Shiremath *ret_status = IBT_CM_CLOSED_ALREADY;
12493241Shiremath
12503241Shiremath /* No private data to return to the client */
12513241Shiremath if (ret_priv_data_len_p != NULL)
12523241Shiremath *ret_priv_data_len_p = 0;
12533241Shiremath
12545214Sagiri if ((mode == IBT_BLOCKING) ||
12555214Sagiri (mode == IBT_NOCALLBACKS)) {
12565214Sagiri IBCM_GET_CHAN_PRIVATE(channel, statep);
12575214Sagiri if (statep == NULL)
12585214Sagiri return (IBT_SUCCESS);
12595214Sagiri mutex_enter(&statep->state_mutex);
12605214Sagiri IBCM_RELEASE_CHAN_PRIVATE(channel);
12615214Sagiri IBCM_REF_CNT_INCR(statep);
12625214Sagiri while (statep->close_done != B_TRUE)
12635214Sagiri cv_wait(&statep->block_client_cv,
12645214Sagiri &statep->state_mutex);
12655214Sagiri IBCM_REF_CNT_DECR(statep);
12665214Sagiri mutex_exit(&statep->state_mutex);
12675214Sagiri }
12685214Sagiri
12693241Shiremath IBTF_DPRINTF_L3(cmlog, "ibt_close_rc_channel: chan 0x%p "
12703241Shiremath "already marked for closing", channel);
12713241Shiremath
12723241Shiremath return (IBT_SUCCESS);
12733241Shiremath }
12743241Shiremath
12750Sstevel@tonic-gate /* get the statep */
12760Sstevel@tonic-gate IBCM_GET_CHAN_PRIVATE(channel, statep);
12770Sstevel@tonic-gate if (statep == NULL) {
12780Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
12790Sstevel@tonic-gate "statep NULL", channel);
12800Sstevel@tonic-gate return (IBT_CHAN_STATE_INVALID);
12810Sstevel@tonic-gate }
12820Sstevel@tonic-gate
12830Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
12843241Shiremath
12853241Shiremath if (statep->dreq_msg == NULL) {
12864703Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
12873241Shiremath "Fatal Error: dreq_msg is NULL", channel);
12883241Shiremath IBCM_RELEASE_CHAN_PRIVATE(channel);
12893241Shiremath mutex_exit(&statep->state_mutex);
12903241Shiremath return (IBT_CHAN_STATE_INVALID);
12913241Shiremath }
12923241Shiremath
12933241Shiremath if ((ret_priv_data == NULL) || (ret_priv_data_len_p == NULL)) {
12943241Shiremath statep->close_ret_priv_data = NULL;
12953241Shiremath statep->close_ret_priv_data_len = NULL;
12963241Shiremath } else {
12973241Shiremath statep->close_ret_priv_data = ret_priv_data;
12983241Shiremath statep->close_ret_priv_data_len = ret_priv_data_len_p;
12993241Shiremath }
13003241Shiremath
13013241Shiremath priv_data_len = min(priv_data_len, IBT_DREQ_PRIV_DATA_SZ);
13023241Shiremath if ((priv_data != NULL) && (priv_data_len > 0)) {
13033241Shiremath bcopy(priv_data, ((ibcm_dreq_msg_t *)
13043241Shiremath IBCM_OUT_MSGP(statep->dreq_msg))->dreq_private_data,
13053241Shiremath priv_data_len);
13063241Shiremath }
13073241Shiremath statep->close_ret_status = ret_status;
13083241Shiremath
13090Sstevel@tonic-gate IBCM_RELEASE_CHAN_PRIVATE(channel);
13100Sstevel@tonic-gate IBCM_REF_CNT_INCR(statep);
13113241Shiremath
13123241Shiremath if (mode != IBT_NONBLOCKING) {
13133241Shiremath return (ibcm_close_rc_channel(channel, statep, mode));
13143241Shiremath }
13153241Shiremath
13163241Shiremath /* IBT_NONBLOCKING */
13173241Shiremath ibcm_close_enqueue(statep);
13180Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
13190Sstevel@tonic-gate
13203241Shiremath return (IBT_SUCCESS);
13213241Shiremath }
13223241Shiremath
13233241Shiremath void
ibcm_close_start(ibcm_state_data_t * statep)13243241Shiremath ibcm_close_start(ibcm_state_data_t *statep)
13253241Shiremath {
13263241Shiremath mutex_enter(&statep->state_mutex);
13273241Shiremath (void) ibcm_close_rc_channel(statep->channel, statep, IBT_NONBLOCKING);
13283241Shiremath }
13293241Shiremath
13303241Shiremath static
13313241Shiremath ibt_status_t
ibcm_close_rc_channel(ibt_channel_hdl_t channel,ibcm_state_data_t * statep,ibt_execution_mode_t mode)13323241Shiremath ibcm_close_rc_channel(ibt_channel_hdl_t channel, ibcm_state_data_t *statep,
13333241Shiremath ibt_execution_mode_t mode)
13343241Shiremath {
13353241Shiremath ibcm_hca_info_t *hcap;
13363241Shiremath
13373241Shiremath _NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(&statep->state_mutex));
13383241Shiremath ASSERT(MUTEX_HELD(&statep->state_mutex));
13393241Shiremath
13403241Shiremath IBTF_DPRINTF_L3(cmlog, "ibcm_close_rc_channel: chan 0x%p statep %p",
13410Sstevel@tonic-gate channel, statep);
13420Sstevel@tonic-gate
13430Sstevel@tonic-gate hcap = statep->hcap;
13440Sstevel@tonic-gate
13450Sstevel@tonic-gate /* HCA must have been in active state. If not, it's a client bug */
13460Sstevel@tonic-gate if (!IBCM_ACCESS_HCA_OK(hcap)) {
13473241Shiremath IBTF_DPRINTF_L2(cmlog, "ibcm_close_rc_channel: chan 0x%p "
13480Sstevel@tonic-gate "hcap 0x%p not active", channel, hcap);
13490Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
13500Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
13510Sstevel@tonic-gate return (IBT_CHAN_HDL_INVALID);
13520Sstevel@tonic-gate }
13530Sstevel@tonic-gate
13540Sstevel@tonic-gate if (statep->state == IBCM_STATE_TRANSIENT_ESTABLISHED) {
13550Sstevel@tonic-gate while (statep->cep_in_rts == IBCM_BLOCK)
13560Sstevel@tonic-gate cv_wait(&statep->block_mad_cv, &statep->state_mutex);
13570Sstevel@tonic-gate }
13580Sstevel@tonic-gate
13590Sstevel@tonic-gate /* Do TRANSIENT_DREQ check after TRANSIENT_ESTABLISHED check */
13600Sstevel@tonic-gate while (statep->state == IBCM_STATE_TRANSIENT_DREQ_SENT)
13610Sstevel@tonic-gate cv_wait(&statep->block_mad_cv, &statep->state_mutex);
13620Sstevel@tonic-gate
13633241Shiremath IBTF_DPRINTF_L4(cmlog, "ibcm_close_rc_channel: chan 0x%p "
13640Sstevel@tonic-gate "connection state is %x", channel, statep->state);
13650Sstevel@tonic-gate
13660Sstevel@tonic-gate /* If state is in pre-established states, abort the connection est */
13670Sstevel@tonic-gate if (statep->state != IBCM_STATE_ESTABLISHED) {
13681093Shiremath statep->cm_retries++; /* ensure connection trace is dumped */
13690Sstevel@tonic-gate
13700Sstevel@tonic-gate /* No DREP private data possible */
13713241Shiremath if (statep->close_ret_priv_data_len != NULL)
13723241Shiremath *statep->close_ret_priv_data_len = 0;
13730Sstevel@tonic-gate
13740Sstevel@tonic-gate /*
13750Sstevel@tonic-gate * If waiting for a response mad, then cancel the timer,
13760Sstevel@tonic-gate * and delete the connection
13770Sstevel@tonic-gate */
13780Sstevel@tonic-gate if (statep->state == IBCM_STATE_REQ_SENT ||
13790Sstevel@tonic-gate statep->state == IBCM_STATE_REP_SENT ||
13800Sstevel@tonic-gate statep->state == IBCM_STATE_REP_WAIT ||
13810Sstevel@tonic-gate statep->state == IBCM_STATE_MRA_REP_RCVD) {
13820Sstevel@tonic-gate timeout_id_t timer_val = statep->timerid;
13830Sstevel@tonic-gate ibcm_conn_state_t old_state;
13840Sstevel@tonic-gate
13853241Shiremath IBTF_DPRINTF_L4(cmlog, "ibcm_close_rc_channel: "
13860Sstevel@tonic-gate "chan 0x%p connection aborted in state %x", channel,
13870Sstevel@tonic-gate statep->state);
13880Sstevel@tonic-gate
13890Sstevel@tonic-gate old_state = statep->state;
13900Sstevel@tonic-gate statep->state = IBCM_STATE_DELETE;
13910Sstevel@tonic-gate
13920Sstevel@tonic-gate if (mode == IBT_NONBLOCKING) {
13930Sstevel@tonic-gate if (taskq_dispatch(ibcm_taskq,
13940Sstevel@tonic-gate ibcm_process_abort_via_taskq, statep,
13950Sstevel@tonic-gate TQ_NOSLEEP) == 0) {
13960Sstevel@tonic-gate
13970Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
13980Sstevel@tonic-gate statep->state = old_state;
13990Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
14000Sstevel@tonic-gate return (IBT_INSUFF_KERNEL_RESOURCE);
14010Sstevel@tonic-gate } /* if taskq_dispatch succeeds */
14020Sstevel@tonic-gate /* Cancel the timer */
14030Sstevel@tonic-gate statep->timerid = 0;
14040Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
14050Sstevel@tonic-gate } else {
14060Sstevel@tonic-gate /* Cancel the timer */
14070Sstevel@tonic-gate statep->timerid = 0;
14080Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
14090Sstevel@tonic-gate (void) taskq_dispatch(ibcm_taskq,
14100Sstevel@tonic-gate ibcm_process_abort_via_taskq, statep,
14110Sstevel@tonic-gate TQ_SLEEP);
14120Sstevel@tonic-gate }
14130Sstevel@tonic-gate
14140Sstevel@tonic-gate /* cancel the currently running timer */
14150Sstevel@tonic-gate if (timer_val != 0)
14160Sstevel@tonic-gate (void) untimeout(timer_val);
14170Sstevel@tonic-gate
14180Sstevel@tonic-gate /* wait until cm handler returns for BLOCKING cases */
14193241Shiremath mutex_enter(&statep->state_mutex);
14200Sstevel@tonic-gate if ((mode == IBT_BLOCKING) ||
14210Sstevel@tonic-gate (mode == IBT_NOCALLBACKS)) {
14220Sstevel@tonic-gate while (statep->close_done != B_TRUE)
14230Sstevel@tonic-gate cv_wait(&statep->block_client_cv,
14240Sstevel@tonic-gate &statep->state_mutex);
14250Sstevel@tonic-gate }
14260Sstevel@tonic-gate
14273241Shiremath if (statep->close_ret_status)
14283241Shiremath *statep->close_ret_status = IBT_CM_CLOSED_ABORT;
14293241Shiremath mutex_exit(&statep->state_mutex);
14300Sstevel@tonic-gate
14310Sstevel@tonic-gate /*
14320Sstevel@tonic-gate * It would ideal to post a REJ MAD, but that would
14330Sstevel@tonic-gate * be non-conformance to spec. Hence, delete the state
14340Sstevel@tonic-gate * data. Assuming that happens quickly, any retransmits
14350Sstevel@tonic-gate * from the remote are replied by CM with reject
14360Sstevel@tonic-gate * reason " no valid com id". That would stop remote
14370Sstevel@tonic-gate * sending any more MADs.
14380Sstevel@tonic-gate */
14390Sstevel@tonic-gate ibcm_delete_state_data(statep);
14400Sstevel@tonic-gate return (IBT_SUCCESS);
14410Sstevel@tonic-gate
14420Sstevel@tonic-gate /* if CM busy in cm handler, wait until cm handler returns */
14430Sstevel@tonic-gate } else if (statep->state == IBCM_STATE_REQ_RCVD ||
14440Sstevel@tonic-gate statep->state == IBCM_STATE_REP_RCVD ||
14450Sstevel@tonic-gate statep->state == IBCM_STATE_MRA_SENT ||
14460Sstevel@tonic-gate statep->state == IBCM_STATE_MRA_REP_SENT) {
14470Sstevel@tonic-gate
14480Sstevel@tonic-gate /* take control of statep */
14490Sstevel@tonic-gate statep->abort_flag |= IBCM_ABORT_CLIENT;
14500Sstevel@tonic-gate
14513241Shiremath IBTF_DPRINTF_L4(cmlog, "ibcm_close_rc_channel: "
14520Sstevel@tonic-gate "chan 0x%p connection aborted in state = %x",
14530Sstevel@tonic-gate channel, statep->state);
14540Sstevel@tonic-gate
14550Sstevel@tonic-gate /*
14560Sstevel@tonic-gate * wait until state machine modifies qp state to error,
14570Sstevel@tonic-gate * including disassociating statep and QP
14580Sstevel@tonic-gate */
14590Sstevel@tonic-gate if ((mode == IBT_BLOCKING) || (mode == IBT_NOCALLBACKS))
14600Sstevel@tonic-gate while (statep->close_done != B_TRUE)
14610Sstevel@tonic-gate cv_wait(&statep->block_client_cv,
14620Sstevel@tonic-gate &statep->state_mutex);
14630Sstevel@tonic-gate
14640Sstevel@tonic-gate /* a sanity setting */
14650Sstevel@tonic-gate if (mode == IBT_NOCALLBACKS)
14660Sstevel@tonic-gate statep->cm_handler = NULL;
14670Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
14680Sstevel@tonic-gate
14690Sstevel@tonic-gate /*
14700Sstevel@tonic-gate * In rare situations, connection attempt could be
14710Sstevel@tonic-gate * terminated for some other reason, before abort is
14720Sstevel@tonic-gate * processed, but CM still returns ret_status as abort
14730Sstevel@tonic-gate */
14743241Shiremath if (statep->close_ret_status)
14753241Shiremath *statep->close_ret_status = IBT_CM_CLOSED_ABORT;
14763241Shiremath mutex_exit(&statep->state_mutex);
14770Sstevel@tonic-gate
14780Sstevel@tonic-gate /*
14790Sstevel@tonic-gate * REJ MAD is posted by the CM state machine for this
14800Sstevel@tonic-gate * case, hence state structure is deleted in the
14810Sstevel@tonic-gate * state machine processing.
14820Sstevel@tonic-gate */
14830Sstevel@tonic-gate return (IBT_SUCCESS);
14840Sstevel@tonic-gate
14850Sstevel@tonic-gate } else if ((statep->state == IBCM_STATE_TIMEWAIT) ||
14860Sstevel@tonic-gate (statep->state == IBCM_STATE_DELETE)) {
14870Sstevel@tonic-gate
14880Sstevel@tonic-gate /* State already in timewait, so no return priv data */
14890Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
14900Sstevel@tonic-gate
14910Sstevel@tonic-gate /* The teardown has already been done */
14923241Shiremath if (statep->close_ret_status)
14933241Shiremath *statep->close_ret_status =
14943241Shiremath IBT_CM_CLOSED_ALREADY;
14953241Shiremath mutex_exit(&statep->state_mutex);
14960Sstevel@tonic-gate
14970Sstevel@tonic-gate return (IBT_SUCCESS);
14980Sstevel@tonic-gate
14990Sstevel@tonic-gate } else if ((statep->state == IBCM_STATE_DREQ_RCVD) ||
15000Sstevel@tonic-gate (statep->state == IBCM_STATE_DREQ_SENT) ||
15010Sstevel@tonic-gate (statep->state == IBCM_STATE_DREP_RCVD) ||
15020Sstevel@tonic-gate ((statep->state == IBCM_STATE_TIMED_OUT) &&
15030Sstevel@tonic-gate (statep->timedout_state == IBCM_STATE_DREQ_SENT))) {
15040Sstevel@tonic-gate
15050Sstevel@tonic-gate /*
15060Sstevel@tonic-gate * Either the remote or local client has already
15070Sstevel@tonic-gate * initiated the teardown. IBCM_STATE_DREP_RCVD is
15080Sstevel@tonic-gate * possible, if CM initiated teardown without client's
15090Sstevel@tonic-gate * knowledge, for stale handling, etc.,
15100Sstevel@tonic-gate */
15110Sstevel@tonic-gate if (mode == IBT_NOCALLBACKS) {
15120Sstevel@tonic-gate if (statep->close_nocb_state == IBCM_UNBLOCK) {
15130Sstevel@tonic-gate statep->close_nocb_state = IBCM_FAIL;
15140Sstevel@tonic-gate /* enable free qp after return */
15150Sstevel@tonic-gate ibtl_cm_chan_is_closing(
15160Sstevel@tonic-gate statep->channel);
15170Sstevel@tonic-gate } else while (statep->close_nocb_state ==
15180Sstevel@tonic-gate IBCM_BLOCK)
15190Sstevel@tonic-gate cv_wait(&statep->block_client_cv,
15200Sstevel@tonic-gate &statep->state_mutex);
15210Sstevel@tonic-gate statep->cm_handler = NULL; /* sanity setting */
15223241Shiremath if (statep->close_ret_status)
15233241Shiremath *statep->close_ret_status =
15243241Shiremath IBT_CM_CLOSED_ALREADY;
15250Sstevel@tonic-gate } else if (mode == IBT_BLOCKING) {
15260Sstevel@tonic-gate /* wait until state is moved to timewait */
15270Sstevel@tonic-gate while (statep->close_done != B_TRUE)
15280Sstevel@tonic-gate cv_wait(&statep->block_client_cv,
15290Sstevel@tonic-gate &statep->state_mutex);
15300Sstevel@tonic-gate }
15310Sstevel@tonic-gate
15320Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
15330Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
15340Sstevel@tonic-gate
15350Sstevel@tonic-gate /* ret_status is set in state machine code */
15360Sstevel@tonic-gate return (IBT_SUCCESS);
15370Sstevel@tonic-gate
15380Sstevel@tonic-gate } else if (statep->state == IBCM_STATE_TIMED_OUT) {
15390Sstevel@tonic-gate
15400Sstevel@tonic-gate if ((mode == IBT_BLOCKING) ||
15410Sstevel@tonic-gate (mode == IBT_NOCALLBACKS)) {
15420Sstevel@tonic-gate
15430Sstevel@tonic-gate /*
15440Sstevel@tonic-gate * wait until cm handler invocation and
15450Sstevel@tonic-gate * disassociation between statep and channel
15460Sstevel@tonic-gate * is complete
15470Sstevel@tonic-gate */
15480Sstevel@tonic-gate while (statep->close_done != B_TRUE)
15490Sstevel@tonic-gate cv_wait(&statep->block_client_cv,
15500Sstevel@tonic-gate &statep->state_mutex);
15510Sstevel@tonic-gate }
15520Sstevel@tonic-gate
15533241Shiremath if (statep->close_ret_status)
15543241Shiremath *statep->close_ret_status = IBT_CM_CLOSED_ABORT;
15550Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
15560Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
15570Sstevel@tonic-gate
15580Sstevel@tonic-gate return (IBT_SUCCESS);
15590Sstevel@tonic-gate } else {
15600Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
15610Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
15620Sstevel@tonic-gate
15630Sstevel@tonic-gate return (IBT_CM_FAILURE);
15640Sstevel@tonic-gate }
15650Sstevel@tonic-gate }
15660Sstevel@tonic-gate
15670Sstevel@tonic-gate ASSERT(statep->close_nocb_state != IBCM_BLOCK);
15680Sstevel@tonic-gate
15690Sstevel@tonic-gate if (mode == IBT_NOCALLBACKS) {
15700Sstevel@tonic-gate statep->close_nocb_state = IBCM_FAIL;
15710Sstevel@tonic-gate statep->cm_handler = NULL;
15720Sstevel@tonic-gate ibtl_cm_chan_is_closing(statep->channel);
15733241Shiremath IBTF_DPRINTF_L4(cmlog, "ibcm_close_rc_channel: "
15740Sstevel@tonic-gate "NOCALLBACKS on in statep = %p", statep);
15750Sstevel@tonic-gate }
15764703Shiremath
15771093Shiremath if (statep->state != IBCM_STATE_ESTABLISHED) {
15781093Shiremath goto lost_race;
15791093Shiremath }
15800Sstevel@tonic-gate
15810Sstevel@tonic-gate /*
15820Sstevel@tonic-gate * Cancel/wait for any pending ibt_set_alt_path, and
15830Sstevel@tonic-gate * release state mutex
15840Sstevel@tonic-gate */
15850Sstevel@tonic-gate ibcm_sync_lapr_idle(statep);
15860Sstevel@tonic-gate
15871093Shiremath ibcm_close_enter();
15881093Shiremath
15891093Shiremath mutex_enter(&statep->state_mutex);
15901093Shiremath if (statep->state != IBCM_STATE_ESTABLISHED) {
15911093Shiremath ibcm_close_exit();
15921093Shiremath goto lost_race;
15931093Shiremath }
15941093Shiremath
15951093Shiremath statep->state = IBCM_STATE_TRANSIENT_DREQ_SENT;
15961093Shiremath statep->timerid = 0;
15971093Shiremath statep->close_done = B_FALSE;
15981093Shiremath statep->close_flow = 1;
15991093Shiremath mutex_exit(&statep->state_mutex);
16001093Shiremath
16011093Shiremath ibcm_post_dreq_mad(statep);
16020Sstevel@tonic-gate
16030Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
16040Sstevel@tonic-gate
16051093Shiremath lost_race:
16060Sstevel@tonic-gate if (mode == IBT_BLOCKING) {
16070Sstevel@tonic-gate
16080Sstevel@tonic-gate /* wait for DREP */
16090Sstevel@tonic-gate while (statep->close_done != B_TRUE)
16100Sstevel@tonic-gate cv_wait(&statep->block_client_cv,
16110Sstevel@tonic-gate &statep->state_mutex);
16120Sstevel@tonic-gate
16133241Shiremath IBTF_DPRINTF_L4(cmlog, "ibcm_close_rc_channel: chan 0x%p "
16140Sstevel@tonic-gate "done blocking", channel);
16150Sstevel@tonic-gate }
16160Sstevel@tonic-gate
16170Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
16180Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
16190Sstevel@tonic-gate
16200Sstevel@tonic-gate /* If this message isn't seen then ibt_close_rc_channel failed */
16213241Shiremath IBTF_DPRINTF_L5(cmlog, "ibcm_close_rc_channel: chan 0x%p done",
16220Sstevel@tonic-gate channel);
16230Sstevel@tonic-gate
16240Sstevel@tonic-gate return (IBT_SUCCESS);
16250Sstevel@tonic-gate }
16260Sstevel@tonic-gate
16270Sstevel@tonic-gate ibt_status_t
ibt_recycle_rc(ibt_channel_hdl_t rc_chan,ibt_cep_flags_t control,uint8_t hca_port_num,ibt_recycle_handler_t func,void * arg)16280Sstevel@tonic-gate ibt_recycle_rc(ibt_channel_hdl_t rc_chan, ibt_cep_flags_t control,
16290Sstevel@tonic-gate uint8_t hca_port_num, ibt_recycle_handler_t func, void *arg)
16300Sstevel@tonic-gate {
16310Sstevel@tonic-gate ibcm_state_data_t *statep;
16320Sstevel@tonic-gate ibcm_taskq_recycle_arg_t *ibcm_tq_recycle_arg;
16330Sstevel@tonic-gate ibt_qp_query_attr_t qp_attr;
16340Sstevel@tonic-gate ibt_status_t retval;
16350Sstevel@tonic-gate
16360Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_recycle_rc (%p, 0x%X, %d, %p, %p)", rc_chan,
16370Sstevel@tonic-gate control, hca_port_num, func, arg);
16380Sstevel@tonic-gate
16390Sstevel@tonic-gate if (IBCM_INVALID_CHANNEL(rc_chan)) {
16400Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_recycle_rc: invalid channel");
16410Sstevel@tonic-gate return (IBT_CHAN_HDL_INVALID);
16420Sstevel@tonic-gate }
16430Sstevel@tonic-gate
16440Sstevel@tonic-gate /* check qp state */
16450Sstevel@tonic-gate retval = ibt_query_qp(rc_chan, &qp_attr);
16460Sstevel@tonic-gate
16470Sstevel@tonic-gate if (retval != IBT_SUCCESS)
16480Sstevel@tonic-gate return (retval);
16490Sstevel@tonic-gate
16500Sstevel@tonic-gate if (qp_attr.qp_info.qp_trans != IBT_RC_SRV)
16510Sstevel@tonic-gate return (IBT_CHAN_SRV_TYPE_INVALID);
16520Sstevel@tonic-gate
16530Sstevel@tonic-gate if (qp_attr.qp_info.qp_state != IBT_STATE_ERROR)
16540Sstevel@tonic-gate return (IBT_CHAN_STATE_INVALID);
16550Sstevel@tonic-gate
16560Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ibcm_tq_recycle_arg))
16570Sstevel@tonic-gate
16580Sstevel@tonic-gate ibcm_tq_recycle_arg = kmem_alloc(sizeof (ibcm_taskq_recycle_arg_t),
16590Sstevel@tonic-gate KM_SLEEP);
16600Sstevel@tonic-gate
16610Sstevel@tonic-gate ibcm_tq_recycle_arg->rc_chan = rc_chan;
16620Sstevel@tonic-gate ibcm_tq_recycle_arg->control = control;
16630Sstevel@tonic-gate ibcm_tq_recycle_arg->hca_port_num = hca_port_num;
16640Sstevel@tonic-gate ibcm_tq_recycle_arg->func = func;
16650Sstevel@tonic-gate ibcm_tq_recycle_arg->arg = arg;
16660Sstevel@tonic-gate
16670Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ibcm_tq_recycle_arg))
16680Sstevel@tonic-gate
16690Sstevel@tonic-gate IBCM_GET_CHAN_PRIVATE(rc_chan, statep);
16700Sstevel@tonic-gate
16710Sstevel@tonic-gate /*
16720Sstevel@tonic-gate * If non-blocking ie., func specified and channel has not yet completed
16730Sstevel@tonic-gate * the timewait, then schedule the work for later
16740Sstevel@tonic-gate */
16750Sstevel@tonic-gate if ((func != NULL) && (statep != NULL)) {
16760Sstevel@tonic-gate IBCM_RELEASE_CHAN_PRIVATE(rc_chan);
16770Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
16780Sstevel@tonic-gate statep->recycle_arg = ibcm_tq_recycle_arg;
16790Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
16800Sstevel@tonic-gate return (IBT_SUCCESS);
16810Sstevel@tonic-gate }
16820Sstevel@tonic-gate
16830Sstevel@tonic-gate /*
16840Sstevel@tonic-gate * if blocking ie., func specified, and channel has not yet completed
16850Sstevel@tonic-gate * the timewait, then block until the channel completes the timewait
16860Sstevel@tonic-gate */
16870Sstevel@tonic-gate if (statep != NULL)
16880Sstevel@tonic-gate IBCM_RELEASE_CHAN_PRIVATE(rc_chan);
16890Sstevel@tonic-gate IBCM_WAIT_CHAN_PRIVATE(rc_chan);
16900Sstevel@tonic-gate
16910Sstevel@tonic-gate if (func) { /* NON BLOCKING case. Taskq for QP state change */
16920Sstevel@tonic-gate (void) taskq_dispatch(ibcm_taskq, ibcm_process_rc_recycle,
16930Sstevel@tonic-gate ibcm_tq_recycle_arg, TQ_SLEEP);
16940Sstevel@tonic-gate return (IBT_SUCCESS);
16950Sstevel@tonic-gate } else /* BLOCKING case */
16960Sstevel@tonic-gate return (ibcm_process_rc_recycle_ret(ibcm_tq_recycle_arg));
16970Sstevel@tonic-gate }
16980Sstevel@tonic-gate
16990Sstevel@tonic-gate void
ibcm_process_rc_recycle(void * recycle_arg)17000Sstevel@tonic-gate ibcm_process_rc_recycle(void *recycle_arg)
17010Sstevel@tonic-gate {
17020Sstevel@tonic-gate (void) ibcm_process_rc_recycle_ret(recycle_arg);
17030Sstevel@tonic-gate }
17040Sstevel@tonic-gate
17050Sstevel@tonic-gate static ibt_status_t
ibcm_process_rc_recycle_ret(void * recycle_arg)17060Sstevel@tonic-gate ibcm_process_rc_recycle_ret(void *recycle_arg)
17070Sstevel@tonic-gate {
17080Sstevel@tonic-gate ibt_qp_info_t qp_info;
17090Sstevel@tonic-gate ibt_status_t ibt_status = IBT_SUCCESS;
17100Sstevel@tonic-gate ibt_cep_modify_flags_t cep_flags;
17110Sstevel@tonic-gate ibt_qp_query_attr_t qp_attr;
17120Sstevel@tonic-gate ibcm_taskq_recycle_arg_t *ibcm_tq_recycle_arg =
17130Sstevel@tonic-gate (ibcm_taskq_recycle_arg_t *)recycle_arg;
17140Sstevel@tonic-gate
17150Sstevel@tonic-gate /* QP must have been in error state */
17160Sstevel@tonic-gate ibt_status = ibt_query_qp(ibcm_tq_recycle_arg->rc_chan, &qp_attr);
17170Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS)
17180Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_process_rc_recycle_ret: "
17190Sstevel@tonic-gate "chanp %p ibt_query_qp() = %d",
17200Sstevel@tonic-gate ibcm_tq_recycle_arg->rc_chan, ibt_status);
17210Sstevel@tonic-gate else {
17220Sstevel@tonic-gate /* perform the QP state change from ERROR to RESET */
17230Sstevel@tonic-gate bzero(&qp_info, sizeof (qp_info));
17240Sstevel@tonic-gate
17250Sstevel@tonic-gate qp_info.qp_trans = IBT_RC_SRV;
17260Sstevel@tonic-gate qp_info.qp_state = IBT_STATE_RESET;
17270Sstevel@tonic-gate
17280Sstevel@tonic-gate /* Call modify_qp to move to RESET state */
17290Sstevel@tonic-gate ibt_status = ibt_modify_qp(ibcm_tq_recycle_arg->rc_chan,
17300Sstevel@tonic-gate IBT_CEP_SET_STATE, &qp_info, NULL);
17310Sstevel@tonic-gate
17320Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS)
17330Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_process_rc_recycle_ret: "
17340Sstevel@tonic-gate "chanp %p ibt_modify_qp() = %d for ERROR to RESET",
17350Sstevel@tonic-gate ibcm_tq_recycle_arg->rc_chan, ibt_status);
17360Sstevel@tonic-gate }
17370Sstevel@tonic-gate
17380Sstevel@tonic-gate if (ibt_status == IBT_SUCCESS) {
17390Sstevel@tonic-gate
17400Sstevel@tonic-gate qp_info.qp_state = IBT_STATE_INIT;
17410Sstevel@tonic-gate
17420Sstevel@tonic-gate /* set flags for all mandatory args from RESET to INIT */
17430Sstevel@tonic-gate cep_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT;
17440Sstevel@tonic-gate cep_flags |= IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W;
17450Sstevel@tonic-gate cep_flags |= IBT_CEP_SET_ATOMIC;
17460Sstevel@tonic-gate
17470Sstevel@tonic-gate qp_info.qp_transport.rc.rc_path.cep_hca_port_num =
17480Sstevel@tonic-gate ibcm_tq_recycle_arg->hca_port_num;
17490Sstevel@tonic-gate qp_info.qp_flags |=
17500Sstevel@tonic-gate ibcm_tq_recycle_arg->control & IBT_CEP_RDMA_RD;
17510Sstevel@tonic-gate qp_info.qp_flags |=
17520Sstevel@tonic-gate ibcm_tq_recycle_arg->control & IBT_CEP_RDMA_WR;
17530Sstevel@tonic-gate qp_info.qp_flags |=
17540Sstevel@tonic-gate ibcm_tq_recycle_arg->control & IBT_CEP_ATOMIC;
17550Sstevel@tonic-gate
17560Sstevel@tonic-gate /* Always use the existing pkey */
17570Sstevel@tonic-gate qp_info.qp_transport.rc.rc_path.cep_pkey_ix =
17580Sstevel@tonic-gate qp_attr. qp_info.qp_transport.rc.rc_path.cep_pkey_ix;
17590Sstevel@tonic-gate
17600Sstevel@tonic-gate /* Call modify_qp to move to INIT state */
17610Sstevel@tonic-gate ibt_status = ibt_modify_qp(ibcm_tq_recycle_arg->rc_chan,
17620Sstevel@tonic-gate cep_flags, &qp_info, NULL);
17630Sstevel@tonic-gate
17640Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS)
17650Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_process_rc_recycle_ret: "
17660Sstevel@tonic-gate "chanp %p ibt_modify_qp() = %d for RESET to INIT",
17670Sstevel@tonic-gate ibcm_tq_recycle_arg->rc_chan, ibt_status);
17680Sstevel@tonic-gate }
17690Sstevel@tonic-gate
17700Sstevel@tonic-gate /* Change the QP CM state to indicate QP being re-used */
17710Sstevel@tonic-gate if (ibt_status == IBT_SUCCESS)
17720Sstevel@tonic-gate ibtl_cm_chan_is_reused(ibcm_tq_recycle_arg->rc_chan);
17730Sstevel@tonic-gate
17740Sstevel@tonic-gate /* Call func, if defined */
17750Sstevel@tonic-gate if (ibcm_tq_recycle_arg->func)
17760Sstevel@tonic-gate (*(ibcm_tq_recycle_arg->func))(ibt_status,
17770Sstevel@tonic-gate ibcm_tq_recycle_arg->arg);
17780Sstevel@tonic-gate
17790Sstevel@tonic-gate kmem_free(ibcm_tq_recycle_arg, sizeof (ibcm_taskq_recycle_arg_t));
17800Sstevel@tonic-gate
17810Sstevel@tonic-gate return (ibt_status);
17820Sstevel@tonic-gate }
17830Sstevel@tonic-gate
17840Sstevel@tonic-gate static void
ibcm_process_abort_via_taskq(void * args)17850Sstevel@tonic-gate ibcm_process_abort_via_taskq(void *args)
17860Sstevel@tonic-gate {
17870Sstevel@tonic-gate ibcm_state_data_t *statep = (ibcm_state_data_t *)args;
17880Sstevel@tonic-gate
17890Sstevel@tonic-gate ibcm_process_abort(statep);
17900Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
17910Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
17920Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
17930Sstevel@tonic-gate }
17940Sstevel@tonic-gate
17950Sstevel@tonic-gate /*
17960Sstevel@tonic-gate * Local UD CM Handler's private data, used during ibt_request_ud_dest() in
17970Sstevel@tonic-gate * Non-Blocking mode operations.
17980Sstevel@tonic-gate */
17990Sstevel@tonic-gate typedef struct ibcm_local_handler_s {
18000Sstevel@tonic-gate ibt_cm_ud_handler_t actual_cm_handler;
18010Sstevel@tonic-gate void *actual_cm_private;
18020Sstevel@tonic-gate ibt_ud_dest_t *dest_hdl;
18030Sstevel@tonic-gate } ibcm_local_handler_t;
18040Sstevel@tonic-gate
_NOTE(READ_ONLY_DATA (ibcm_local_handler_s))18050Sstevel@tonic-gate _NOTE(READ_ONLY_DATA(ibcm_local_handler_s))
18060Sstevel@tonic-gate
18070Sstevel@tonic-gate /*
18080Sstevel@tonic-gate * Local UD CM Handler, used when ibt_alloc_ud_dest() is issued in
18090Sstevel@tonic-gate * NON-Blocking mode.
18100Sstevel@tonic-gate *
18110Sstevel@tonic-gate * Out here, we update the UD Destination handle with
18120Sstevel@tonic-gate * the obtained DQPN and QKey (from SIDR REP) and invokes actual client
18130Sstevel@tonic-gate * handler that was specified by the client.
18140Sstevel@tonic-gate */
18150Sstevel@tonic-gate static ibt_cm_status_t
18160Sstevel@tonic-gate ibcm_local_cm_handler(void *priv, ibt_cm_ud_event_t *event,
18170Sstevel@tonic-gate ibt_cm_ud_return_args_t *ret_args, void *priv_data, ibt_priv_data_len_t len)
18180Sstevel@tonic-gate {
18190Sstevel@tonic-gate ibcm_local_handler_t *handler_priv = (ibcm_local_handler_t *)priv;
18200Sstevel@tonic-gate
18210Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_local_cm_handler: event %d",
18220Sstevel@tonic-gate event->cm_type);
18230Sstevel@tonic-gate
18240Sstevel@tonic-gate ASSERT(handler_priv != NULL);
18250Sstevel@tonic-gate
18260Sstevel@tonic-gate switch (event->cm_type) {
18270Sstevel@tonic-gate case IBT_CM_UD_EVENT_SIDR_REP:
18280Sstevel@tonic-gate /* Update QPN & QKey from event into destination handle. */
18290Sstevel@tonic-gate if (handler_priv->dest_hdl != NULL) {
18300Sstevel@tonic-gate handler_priv->dest_hdl->ud_dst_qpn =
18310Sstevel@tonic-gate event->cm_event.sidr_rep.srep_remote_qpn;
18320Sstevel@tonic-gate handler_priv->dest_hdl->ud_qkey =
18330Sstevel@tonic-gate event->cm_event.sidr_rep.srep_remote_qkey;
18340Sstevel@tonic-gate }
18350Sstevel@tonic-gate
18360Sstevel@tonic-gate /* Invoke the client handler - inform only, so ignore retval */
18370Sstevel@tonic-gate (void) handler_priv->actual_cm_handler(
18380Sstevel@tonic-gate handler_priv->actual_cm_private, event, ret_args, priv_data,
18390Sstevel@tonic-gate len);
18400Sstevel@tonic-gate
18410Sstevel@tonic-gate /* Free memory allocated for local handler's private data. */
18420Sstevel@tonic-gate if (handler_priv != NULL)
18430Sstevel@tonic-gate kmem_free(handler_priv, sizeof (*handler_priv));
18440Sstevel@tonic-gate
18450Sstevel@tonic-gate break;
18460Sstevel@tonic-gate default:
18470Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_local_cm_handler: ERROR");
18480Sstevel@tonic-gate break;
18490Sstevel@tonic-gate }
18500Sstevel@tonic-gate
18510Sstevel@tonic-gate return (IBT_CM_ACCEPT);
18520Sstevel@tonic-gate }
18530Sstevel@tonic-gate
18540Sstevel@tonic-gate
18550Sstevel@tonic-gate /* Validate the input UD destination attributes. */
18560Sstevel@tonic-gate static ibt_status_t
ibcm_validate_dqpn_data(ibt_ud_dest_attr_t * attr,ibt_execution_mode_t mode,ibt_ud_returns_t * ret_args)18570Sstevel@tonic-gate ibcm_validate_dqpn_data(ibt_ud_dest_attr_t *attr, ibt_execution_mode_t mode,
18580Sstevel@tonic-gate ibt_ud_returns_t *ret_args)
18590Sstevel@tonic-gate {
18600Sstevel@tonic-gate /* cm handler must always be specified */
18610Sstevel@tonic-gate if (mode == IBT_NONBLOCKING && attr->ud_cm_handler == NULL) {
18620Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18630Sstevel@tonic-gate "CM handler is not specified ");
18640Sstevel@tonic-gate return (IBT_INVALID_PARAM);
18650Sstevel@tonic-gate }
18660Sstevel@tonic-gate
18670Sstevel@tonic-gate if (mode == IBT_NONBLOCKING) {
18680Sstevel@tonic-gate if (ret_args != NULL) {
18690Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18700Sstevel@tonic-gate "ret_args should be NULL when called in "
18710Sstevel@tonic-gate "non-blocking mode");
18720Sstevel@tonic-gate return (IBT_INVALID_PARAM);
18730Sstevel@tonic-gate }
18740Sstevel@tonic-gate } else if (mode == IBT_BLOCKING) {
18750Sstevel@tonic-gate if (ret_args == NULL) {
18760Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18770Sstevel@tonic-gate "ret_args should be Non-NULL when called in "
18780Sstevel@tonic-gate "blocking mode");
18790Sstevel@tonic-gate return (IBT_INVALID_PARAM);
18800Sstevel@tonic-gate }
18810Sstevel@tonic-gate } else {
18820Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18830Sstevel@tonic-gate "invalid mode %x specified ", mode);
18840Sstevel@tonic-gate return (IBT_INVALID_PARAM);
18850Sstevel@tonic-gate }
18860Sstevel@tonic-gate
18870Sstevel@tonic-gate if (attr->ud_sid == 0) {
18880Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18890Sstevel@tonic-gate "ServiceID must be specified. ");
18900Sstevel@tonic-gate return (IBT_INVALID_PARAM);
18910Sstevel@tonic-gate }
18920Sstevel@tonic-gate
18930Sstevel@tonic-gate if (attr->ud_addr == NULL) {
18940Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18950Sstevel@tonic-gate "Address Info NULL");
18960Sstevel@tonic-gate return (IBT_INVALID_PARAM);
18970Sstevel@tonic-gate }
18980Sstevel@tonic-gate
18990Sstevel@tonic-gate /* Validate SGID */
19000Sstevel@tonic-gate if ((attr->ud_addr->av_sgid.gid_prefix == 0) ||
19010Sstevel@tonic-gate (attr->ud_addr->av_sgid.gid_guid == 0)) {
19020Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: Invalid SGID");
19030Sstevel@tonic-gate return (IBT_INVALID_PARAM);
19040Sstevel@tonic-gate }
19050Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_validate_dqpn_data: SGID<%llX:%llX>",
19060Sstevel@tonic-gate attr->ud_addr->av_sgid.gid_prefix,
19070Sstevel@tonic-gate attr->ud_addr->av_sgid.gid_guid);
19080Sstevel@tonic-gate
19090Sstevel@tonic-gate /* Validate DGID */
19100Sstevel@tonic-gate if ((attr->ud_addr->av_dgid.gid_prefix == 0) ||
19110Sstevel@tonic-gate (attr->ud_addr->av_dgid.gid_guid == 0)) {
19120Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: Invalid DGID");
19130Sstevel@tonic-gate return (IBT_INVALID_PARAM);
19140Sstevel@tonic-gate }
19150Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_validate_dqpn_data: DGID<%llX:%llX>",
19160Sstevel@tonic-gate attr->ud_addr->av_dgid.gid_prefix,
19170Sstevel@tonic-gate attr->ud_addr->av_dgid.gid_guid);
19180Sstevel@tonic-gate
19190Sstevel@tonic-gate return (IBT_SUCCESS);
19200Sstevel@tonic-gate }
19210Sstevel@tonic-gate
19220Sstevel@tonic-gate
19230Sstevel@tonic-gate /* Perform SIDR to retrieve DQPN and QKey. */
19240Sstevel@tonic-gate static ibt_status_t
ibcm_ud_get_dqpn(ibt_ud_dest_attr_t * attr,ibt_execution_mode_t mode,ibt_ud_returns_t * ret_args)19250Sstevel@tonic-gate ibcm_ud_get_dqpn(ibt_ud_dest_attr_t *attr, ibt_execution_mode_t mode,
19260Sstevel@tonic-gate ibt_ud_returns_t *ret_args)
19270Sstevel@tonic-gate {
19280Sstevel@tonic-gate ibt_status_t retval;
19290Sstevel@tonic-gate ib_pkey_t ud_pkey;
19300Sstevel@tonic-gate ibmf_handle_t ibmf_hdl;
19310Sstevel@tonic-gate ibmf_msg_t *ibmf_msg;
19320Sstevel@tonic-gate ibcm_hca_info_t *hcap;
19330Sstevel@tonic-gate ibcm_sidr_req_msg_t *sidr_req_msgp;
19340Sstevel@tonic-gate ibcm_ud_state_data_t *ud_statep;
19350Sstevel@tonic-gate ibtl_cm_hca_port_t port;
19360Sstevel@tonic-gate ibcm_sidr_srch_t sidr_entry;
19370Sstevel@tonic-gate ibcm_qp_list_t *cm_qp_entry;
19380Sstevel@tonic-gate
19390Sstevel@tonic-gate /* Retrieve HCA GUID value from the available SGID info. */
19400Sstevel@tonic-gate retval = ibtl_cm_get_hca_port(attr->ud_addr->av_sgid, 0, &port);
19410Sstevel@tonic-gate if ((retval != IBT_SUCCESS) || (port.hp_port == 0)) {
19420Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
19430Sstevel@tonic-gate "ibtl_cm_get_hca_port failed: %d", retval);
19440Sstevel@tonic-gate return (retval);
19450Sstevel@tonic-gate }
19460Sstevel@tonic-gate
19470Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: "
19480Sstevel@tonic-gate "HCA GUID:%llX, port_num:%d", port.hp_hca_guid, port.hp_port);
19490Sstevel@tonic-gate
19500Sstevel@tonic-gate /* Lookup the HCA info for this GUID */
19510Sstevel@tonic-gate if ((hcap = ibcm_find_hca_entry(port.hp_hca_guid)) == NULL) {
19520Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: hcap is NULL");
19530Sstevel@tonic-gate return (IBT_HCA_INVALID);
19540Sstevel@tonic-gate }
19550Sstevel@tonic-gate
19560Sstevel@tonic-gate /* Return failure if the HCA device or Port is not operational */
19570Sstevel@tonic-gate
19580Sstevel@tonic-gate if ((retval = ibt_get_port_state_byguid(port.hp_hca_guid, port.hp_port,
19590Sstevel@tonic-gate NULL, NULL)) != IBT_SUCCESS) {
19600Sstevel@tonic-gate /* Device Port is not in good state, don't use it. */
19610Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: Invalid "
19620Sstevel@tonic-gate "port specified or port not active");
19630Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
19640Sstevel@tonic-gate return (retval);
19650Sstevel@tonic-gate }
19660Sstevel@tonic-gate
19670Sstevel@tonic-gate retval = ibt_index2pkey_byguid(port.hp_hca_guid, port.hp_port,
19680Sstevel@tonic-gate attr->ud_pkey_ix, &ud_pkey);
19690Sstevel@tonic-gate if (retval != IBT_SUCCESS) {
19700Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
19710Sstevel@tonic-gate "Failed to convert index2pkey: %d", retval);
19720Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
19730Sstevel@tonic-gate return (retval);
19740Sstevel@tonic-gate }
19750Sstevel@tonic-gate
19760Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(sidr_entry))
19770Sstevel@tonic-gate
19780Sstevel@tonic-gate /* Allocate a new request id */
19790Sstevel@tonic-gate if (ibcm_alloc_reqid(hcap, &sidr_entry.srch_req_id) == IBCM_FAILURE) {
19800Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
19810Sstevel@tonic-gate "no req id available");
19820Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
19830Sstevel@tonic-gate return (IBT_INSUFF_KERNEL_RESOURCE);
19840Sstevel@tonic-gate }
19850Sstevel@tonic-gate
19860Sstevel@tonic-gate if ((hcap->hca_port_info[port.hp_port - 1].port_ibmf_hdl == NULL) &&
19870Sstevel@tonic-gate ((retval = ibcm_hca_reinit_port(hcap, port.hp_port - 1))
19880Sstevel@tonic-gate != IBT_SUCCESS)) {
19890Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
19900Sstevel@tonic-gate "ibmf reg or callback setup failed during re-initialize");
19910Sstevel@tonic-gate return (retval);
19920Sstevel@tonic-gate }
19930Sstevel@tonic-gate
19940Sstevel@tonic-gate ibmf_hdl = hcap->hca_port_info[port.hp_port - 1].port_ibmf_hdl;
19950Sstevel@tonic-gate
19960Sstevel@tonic-gate /* find the ibmf QP to post the SIDR REQ */
19970Sstevel@tonic-gate if ((cm_qp_entry = ibcm_find_qp(hcap, port.hp_port, ud_pkey)) ==
19980Sstevel@tonic-gate NULL) {
19990Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: IBMF QP allocation"
20000Sstevel@tonic-gate " failed");
20010Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
20020Sstevel@tonic-gate return (IBT_INSUFF_RESOURCE);
20030Sstevel@tonic-gate }
20040Sstevel@tonic-gate
20050Sstevel@tonic-gate if ((retval = ibcm_alloc_out_msg(ibmf_hdl, &ibmf_msg, MAD_METHOD_SEND))
20060Sstevel@tonic-gate != IBT_SUCCESS) {
20070Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: IBMF MSG allocation"
20080Sstevel@tonic-gate " failed");
20090Sstevel@tonic-gate ibcm_release_qp(cm_qp_entry);
20100Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
20110Sstevel@tonic-gate return (retval);
20120Sstevel@tonic-gate }
20130Sstevel@tonic-gate
20140Sstevel@tonic-gate sidr_entry.srch_lid = port.hp_base_lid;
20150Sstevel@tonic-gate sidr_entry.srch_gid = attr->ud_addr->av_sgid;
20160Sstevel@tonic-gate sidr_entry.srch_grh_exists = attr->ud_addr->av_send_grh;
20170Sstevel@tonic-gate sidr_entry.srch_mode = IBCM_ACTIVE_MODE;
20180Sstevel@tonic-gate
20190Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(sidr_entry))
20200Sstevel@tonic-gate
20210Sstevel@tonic-gate /* do various allocations needed here */
20220Sstevel@tonic-gate rw_enter(&hcap->hca_sidr_list_lock, RW_WRITER);
20230Sstevel@tonic-gate
20240Sstevel@tonic-gate (void) ibcm_find_sidr_entry(&sidr_entry, hcap, &ud_statep,
20250Sstevel@tonic-gate IBCM_FLAG_ADD);
20260Sstevel@tonic-gate rw_exit(&hcap->hca_sidr_list_lock);
20270Sstevel@tonic-gate
20280Sstevel@tonic-gate /* Increment hca's resource count */
20290Sstevel@tonic-gate ibcm_inc_hca_res_cnt(hcap);
20300Sstevel@tonic-gate
20310Sstevel@tonic-gate /* After a resource created on hca, no need to hold the acc cnt */
20320Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
20330Sstevel@tonic-gate
20340Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ud_statep))
20350Sstevel@tonic-gate
20360Sstevel@tonic-gate /* Initialize some ud_statep fields */
20370Sstevel@tonic-gate ud_statep->ud_stored_msg = ibmf_msg;
20380Sstevel@tonic-gate ud_statep->ud_svc_id = attr->ud_sid;
20390Sstevel@tonic-gate ud_statep->ud_pkt_life_time =
20400Sstevel@tonic-gate ibt_ib2usec(attr->ud_pkt_lt);
20410Sstevel@tonic-gate ud_statep->ud_stored_reply_addr.cm_qp_entry = cm_qp_entry;
20420Sstevel@tonic-gate
20430Sstevel@tonic-gate /* set remaining retry cnt */
20440Sstevel@tonic-gate ud_statep->ud_remaining_retry_cnt = ud_statep->ud_max_cm_retries;
20450Sstevel@tonic-gate
20460Sstevel@tonic-gate /*
20470Sstevel@tonic-gate * Get UD handler and corresponding args which is pass it back
20480Sstevel@tonic-gate * as first argument for the handler.
20490Sstevel@tonic-gate */
20500Sstevel@tonic-gate ud_statep->ud_state_cm_private = attr->ud_cm_private;
20510Sstevel@tonic-gate
20520Sstevel@tonic-gate if (mode == IBT_BLOCKING)
20530Sstevel@tonic-gate ud_statep->ud_return_data = ret_args;
20540Sstevel@tonic-gate else
20550Sstevel@tonic-gate ud_statep->ud_cm_handler = attr->ud_cm_handler;
20560Sstevel@tonic-gate
20570Sstevel@tonic-gate /* Initialize the fields of ud_statep->ud_stored_reply_addr */
20580Sstevel@tonic-gate ud_statep->ud_stored_reply_addr.grh_exists = attr->ud_addr->av_send_grh;
20590Sstevel@tonic-gate ud_statep->ud_stored_reply_addr.ibmf_hdl = ibmf_hdl;
20600Sstevel@tonic-gate ud_statep->ud_stored_reply_addr.grh_hdr.ig_hop_limit =
20610Sstevel@tonic-gate attr->ud_addr->av_hop;
20620Sstevel@tonic-gate ud_statep->ud_stored_reply_addr.grh_hdr.ig_sender_gid =
20630Sstevel@tonic-gate attr->ud_addr->av_sgid;
20640Sstevel@tonic-gate ud_statep->ud_stored_reply_addr.grh_hdr.ig_recver_gid =
20650Sstevel@tonic-gate attr->ud_addr->av_dgid;
20660Sstevel@tonic-gate ud_statep->ud_stored_reply_addr.grh_hdr.ig_tclass =
20670Sstevel@tonic-gate attr->ud_addr->av_tclass;
20680Sstevel@tonic-gate ud_statep->ud_stored_reply_addr.grh_hdr.ig_flow_label =
20690Sstevel@tonic-gate attr->ud_addr->av_flow & IB_GRH_FLOW_LABEL_MASK;
20700Sstevel@tonic-gate
20710Sstevel@tonic-gate /* needs to be derived based on the base LID and path bits */
20720Sstevel@tonic-gate ud_statep->ud_stored_reply_addr.rcvd_addr.ia_local_lid =
20730Sstevel@tonic-gate port.hp_base_lid;
20740Sstevel@tonic-gate ud_statep->ud_stored_reply_addr.rcvd_addr.ia_remote_lid =
20750Sstevel@tonic-gate attr->ud_addr->av_dlid;
20760Sstevel@tonic-gate ud_statep->ud_stored_reply_addr.rcvd_addr.ia_p_key = ud_pkey;
20770Sstevel@tonic-gate ud_statep->ud_stored_reply_addr.rcvd_addr.ia_q_key = IB_GSI_QKEY;
20780Sstevel@tonic-gate ud_statep->ud_stored_reply_addr.rcvd_addr.ia_service_level =
20790Sstevel@tonic-gate attr->ud_addr->av_srvl;
20800Sstevel@tonic-gate
20810Sstevel@tonic-gate /*
20820Sstevel@tonic-gate * This may be enchanced later, to use a remote qno based on past
20830Sstevel@tonic-gate * redirect rej mad responses. This would be the place to specify
20840Sstevel@tonic-gate * appropriate remote qno
20850Sstevel@tonic-gate */
20860Sstevel@tonic-gate ud_statep->ud_stored_reply_addr.rcvd_addr.ia_remote_qno = 1;
20870Sstevel@tonic-gate
20880Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_req_msgp))
20890Sstevel@tonic-gate
20900Sstevel@tonic-gate /* Initialize the SIDR REQ message fields */
20910Sstevel@tonic-gate sidr_req_msgp =
20920Sstevel@tonic-gate (ibcm_sidr_req_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg);
20930Sstevel@tonic-gate
20940Sstevel@tonic-gate sidr_req_msgp->sidr_req_request_id = h2b32(ud_statep->ud_req_id);
20950Sstevel@tonic-gate sidr_req_msgp->sidr_req_service_id = h2b64(attr->ud_sid);
20960Sstevel@tonic-gate sidr_req_msgp->sidr_req_pkey = h2b16(ud_pkey);
20970Sstevel@tonic-gate IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->AttributeID =
20980Sstevel@tonic-gate h2b16(IBCM_INCOMING_SIDR_REQ + IBCM_ATTR_BASE_ID);
20990Sstevel@tonic-gate
21000Sstevel@tonic-gate if ((attr->ud_priv_data != NULL) && (attr->ud_priv_data_len > 0)) {
21010Sstevel@tonic-gate bcopy(attr->ud_priv_data, sidr_req_msgp->sidr_req_private_data,
21020Sstevel@tonic-gate min(attr->ud_priv_data_len, IBT_SIDR_REQ_PRIV_DATA_SZ));
21030Sstevel@tonic-gate }
21040Sstevel@tonic-gate
21050Sstevel@tonic-gate /* Send out the SIDR REQ message */
21060Sstevel@tonic-gate ud_statep->ud_state = IBCM_STATE_SIDR_REQ_SENT;
21070Sstevel@tonic-gate ud_statep->ud_timer_stored_state = IBCM_STATE_SIDR_REQ_SENT;
21080Sstevel@tonic-gate IBCM_UD_REF_CNT_INCR(ud_statep); /* for non-blocking SIDR REQ post */
21090Sstevel@tonic-gate ud_statep->ud_timer_value = ibt_ib2usec(ibcm_max_sidr_rep_proctime) +
21100Sstevel@tonic-gate (ud_statep->ud_pkt_life_time * 2);
21110Sstevel@tonic-gate
21120Sstevel@tonic-gate IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->TransactionID =
21130Sstevel@tonic-gate h2b64(ibcm_generate_tranid(IBCM_INCOMING_SIDR_REQ,
21140Sstevel@tonic-gate ud_statep->ud_req_id, 0));
21150Sstevel@tonic-gate
21160Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: timer_value in HZ = %x",
21170Sstevel@tonic-gate ud_statep->ud_timer_value);
21180Sstevel@tonic-gate
21190Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ud_statep))
21200Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sidr_req_msgp))
21210Sstevel@tonic-gate
21220Sstevel@tonic-gate ibcm_post_ud_mad(ud_statep, ud_statep->ud_stored_msg,
21230Sstevel@tonic-gate ibcm_post_sidr_req_complete, ud_statep);
21240Sstevel@tonic-gate
21250Sstevel@tonic-gate mutex_enter(&ud_statep->ud_state_mutex);
21260Sstevel@tonic-gate
21270Sstevel@tonic-gate /* Wait for SIDR_REP */
21280Sstevel@tonic-gate if (mode == IBT_BLOCKING) {
21290Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: blocking");
21300Sstevel@tonic-gate
21310Sstevel@tonic-gate while (ud_statep->ud_blocking_done != B_TRUE) {
21320Sstevel@tonic-gate cv_wait(&ud_statep->ud_block_client_cv,
21330Sstevel@tonic-gate &ud_statep->ud_state_mutex);
21340Sstevel@tonic-gate }
21350Sstevel@tonic-gate
21360Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: finished blocking");
21370Sstevel@tonic-gate
21380Sstevel@tonic-gate if (ret_args->ud_status == IBT_CM_SREP_QPN_VALID) {
21390Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: DQPN = %x, "
21400Sstevel@tonic-gate "status = %x, QKey = %x", ret_args->ud_dqpn,
21410Sstevel@tonic-gate ret_args->ud_status, ret_args->ud_qkey);
21420Sstevel@tonic-gate
21430Sstevel@tonic-gate } else {
21440Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: Status<%x>",
21450Sstevel@tonic-gate ret_args->ud_status);
21460Sstevel@tonic-gate retval = IBT_CM_FAILURE;
21470Sstevel@tonic-gate }
21480Sstevel@tonic-gate }
21490Sstevel@tonic-gate
21500Sstevel@tonic-gate IBCM_UD_REF_CNT_DECR(ud_statep);
21510Sstevel@tonic-gate mutex_exit(&ud_statep->ud_state_mutex);
21520Sstevel@tonic-gate
21530Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: done");
21540Sstevel@tonic-gate
21550Sstevel@tonic-gate return (retval);
21560Sstevel@tonic-gate }
21570Sstevel@tonic-gate
21580Sstevel@tonic-gate
21590Sstevel@tonic-gate /*
21600Sstevel@tonic-gate * Function:
21610Sstevel@tonic-gate * ibt_request_ud_dest
21620Sstevel@tonic-gate * Input:
21630Sstevel@tonic-gate * ud_dest A previously allocated UD destination handle.
21640Sstevel@tonic-gate * mode This function can execute in blocking or non blocking
21650Sstevel@tonic-gate * modes.
21660Sstevel@tonic-gate * attr UD destination attributes to be modified.
21670Sstevel@tonic-gate * Output:
21680Sstevel@tonic-gate * ud_ret_args If the function is called in blocking mode, ud_ret_args
21690Sstevel@tonic-gate * should be a pointer to an ibt_ud_returns_t struct.
21700Sstevel@tonic-gate * Returns:
21710Sstevel@tonic-gate * IBT_SUCCESS
21720Sstevel@tonic-gate * Description:
21730Sstevel@tonic-gate * Modify a previously allocated UD destination handle based on the
21740Sstevel@tonic-gate * results of doing the SIDR protocol.
21750Sstevel@tonic-gate */
21760Sstevel@tonic-gate ibt_status_t
ibt_request_ud_dest(ibt_ud_dest_hdl_t ud_dest,ibt_execution_mode_t mode,ibt_ud_dest_attr_t * attr,ibt_ud_returns_t * ud_ret_args)21770Sstevel@tonic-gate ibt_request_ud_dest(ibt_ud_dest_hdl_t ud_dest, ibt_execution_mode_t mode,
21780Sstevel@tonic-gate ibt_ud_dest_attr_t *attr, ibt_ud_returns_t *ud_ret_args)
21790Sstevel@tonic-gate {
21800Sstevel@tonic-gate ibt_status_t retval;
21810Sstevel@tonic-gate ibt_ud_dest_t *ud_destp;
21820Sstevel@tonic-gate ibcm_local_handler_t *local_handler_priv = NULL;
21830Sstevel@tonic-gate
21840Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_request_ud_dest(%p, %x, %p, %p)",
21850Sstevel@tonic-gate ud_dest, mode, attr, ud_ret_args);
21860Sstevel@tonic-gate
21870Sstevel@tonic-gate retval = ibcm_validate_dqpn_data(attr, mode, ud_ret_args);
21880Sstevel@tonic-gate if (retval != IBT_SUCCESS) {
21890Sstevel@tonic-gate return (retval);
21900Sstevel@tonic-gate }
21910Sstevel@tonic-gate
21920Sstevel@tonic-gate ud_destp = ud_dest;
21930Sstevel@tonic-gate
21940Sstevel@tonic-gate /* Allocate an Address handle. */
21950Sstevel@tonic-gate retval = ibt_modify_ah(ud_destp->ud_dest_hca, ud_destp->ud_ah,
21960Sstevel@tonic-gate attr->ud_addr);
21970Sstevel@tonic-gate if (retval != IBT_SUCCESS) {
21980Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_request_ud_dest: "
21990Sstevel@tonic-gate "Address Handle Modification failed: %d", retval);
22000Sstevel@tonic-gate return (retval);
22010Sstevel@tonic-gate }
22020Sstevel@tonic-gate
22030Sstevel@tonic-gate if (mode == IBT_NONBLOCKING) {
22040Sstevel@tonic-gate /*
22050Sstevel@tonic-gate * In NON-BLOCKING mode, and we need to update the destination
22060Sstevel@tonic-gate * handle with the DQPN and QKey that are obtained from
22070Sstevel@tonic-gate * SIDR REP, hook-up our own handler, so that we can catch
22080Sstevel@tonic-gate * the event, and we ourselves call the actual client's
22090Sstevel@tonic-gate * ud_cm_handler, in our handler.
22100Sstevel@tonic-gate */
22110Sstevel@tonic-gate
22120Sstevel@tonic-gate /* Allocate memory for local handler's private data. */
22130Sstevel@tonic-gate local_handler_priv =
22140Sstevel@tonic-gate kmem_alloc(sizeof (*local_handler_priv), KM_SLEEP);
22150Sstevel@tonic-gate
22160Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*local_handler_priv))
22170Sstevel@tonic-gate
22180Sstevel@tonic-gate local_handler_priv->actual_cm_handler = attr->ud_cm_handler;
22190Sstevel@tonic-gate local_handler_priv->actual_cm_private = attr->ud_cm_private;
22200Sstevel@tonic-gate local_handler_priv->dest_hdl = ud_destp;
22210Sstevel@tonic-gate
22220Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*local_handler_priv))
22230Sstevel@tonic-gate
22240Sstevel@tonic-gate attr->ud_cm_handler = ibcm_local_cm_handler;
22250Sstevel@tonic-gate attr->ud_cm_private = local_handler_priv;
22260Sstevel@tonic-gate }
22270Sstevel@tonic-gate
22280Sstevel@tonic-gate /* In order to get DQPN and Destination QKey, perform SIDR */
22290Sstevel@tonic-gate retval = ibcm_ud_get_dqpn(attr, mode, ud_ret_args);
22300Sstevel@tonic-gate if (retval != IBT_SUCCESS) {
22310Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_request_ud_dest: "
22320Sstevel@tonic-gate "Failed to get DQPN: %d", retval);
22330Sstevel@tonic-gate
22340Sstevel@tonic-gate /* Free memory allocated for local handler's private data. */
22350Sstevel@tonic-gate if (local_handler_priv != NULL)
22360Sstevel@tonic-gate kmem_free(local_handler_priv,
22370Sstevel@tonic-gate sizeof (*local_handler_priv));
22380Sstevel@tonic-gate return (retval);
22390Sstevel@tonic-gate }
22400Sstevel@tonic-gate
22410Sstevel@tonic-gate /*
22420Sstevel@tonic-gate * Fill in the dqpn and dqkey as obtained from ud_ret_args,
22430Sstevel@tonic-gate * values will be valid only on BLOCKING mode.
22440Sstevel@tonic-gate */
22450Sstevel@tonic-gate if (mode == IBT_BLOCKING) {
22460Sstevel@tonic-gate ud_destp->ud_dst_qpn = ud_ret_args->ud_dqpn;
22470Sstevel@tonic-gate ud_destp->ud_qkey = ud_ret_args->ud_qkey;
22480Sstevel@tonic-gate }
22490Sstevel@tonic-gate
22500Sstevel@tonic-gate return (retval);
22510Sstevel@tonic-gate }
22520Sstevel@tonic-gate
22530Sstevel@tonic-gate /*
22540Sstevel@tonic-gate * Function:
22550Sstevel@tonic-gate * ibt_ud_get_dqpn
22560Sstevel@tonic-gate * Input:
22570Sstevel@tonic-gate * attr A pointer to an ibt_ud_dest_attr_t struct that are
22580Sstevel@tonic-gate * required for SIDR REQ message. Not specified attributes
22590Sstevel@tonic-gate * should be set to "NULL" or "0".
22600Sstevel@tonic-gate * ud_sid, ud_addr and ud_pkt_lt must be specified.
22610Sstevel@tonic-gate * mode This function can execute in blocking or non blocking
22620Sstevel@tonic-gate * modes.
22630Sstevel@tonic-gate * Output:
22640Sstevel@tonic-gate * returns If the function is called in blocking mode, returns
22650Sstevel@tonic-gate * should be a pointer to an ibt_ud_returns_t struct.
22660Sstevel@tonic-gate * Return:
22670Sstevel@tonic-gate * IBT_SUCCESS on success or respective failure on error.
22680Sstevel@tonic-gate * Description:
22690Sstevel@tonic-gate * Finds the destination QPN at the specified destination that the
22700Sstevel@tonic-gate * specified service can be reached on. The IBTF CM initiates the
22710Sstevel@tonic-gate * service ID resolution protocol (SIDR) to determine a destination QPN.
22720Sstevel@tonic-gate *
22730Sstevel@tonic-gate * NOTE: SIDR_REQ is initiated from active side.
22740Sstevel@tonic-gate */
22750Sstevel@tonic-gate ibt_status_t
ibt_ud_get_dqpn(ibt_ud_dest_attr_t * attr,ibt_execution_mode_t mode,ibt_ud_returns_t * returns)22760Sstevel@tonic-gate ibt_ud_get_dqpn(ibt_ud_dest_attr_t *attr, ibt_execution_mode_t mode,
22770Sstevel@tonic-gate ibt_ud_returns_t *returns)
22780Sstevel@tonic-gate {
22790Sstevel@tonic-gate ibt_status_t retval;
22800Sstevel@tonic-gate
22810Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_ud_get_dqpn(%p, %x, %p)",
22820Sstevel@tonic-gate attr, mode, returns);
22830Sstevel@tonic-gate
22840Sstevel@tonic-gate retval = ibcm_validate_dqpn_data(attr, mode, returns);
22850Sstevel@tonic-gate if (retval != IBT_SUCCESS) {
22860Sstevel@tonic-gate return (retval);
22870Sstevel@tonic-gate }
22880Sstevel@tonic-gate
22890Sstevel@tonic-gate return (ibcm_ud_get_dqpn(attr, mode, returns));
22900Sstevel@tonic-gate }
22910Sstevel@tonic-gate
22920Sstevel@tonic-gate
22930Sstevel@tonic-gate /*
22940Sstevel@tonic-gate * ibt_cm_delay:
22950Sstevel@tonic-gate * A client CM handler function can call this function
22960Sstevel@tonic-gate * to extend its response time to a CM event.
22970Sstevel@tonic-gate * INPUTS:
22980Sstevel@tonic-gate * flags Indicates what CM message processing is being delayed
22990Sstevel@tonic-gate * by the CM handler, valid values are:
23000Sstevel@tonic-gate * IBT_CM_DELAY_REQ
23010Sstevel@tonic-gate * IBT_CM_DELAY_REP
23020Sstevel@tonic-gate * IBT_CM_DELAY_LAP
23030Sstevel@tonic-gate * cm_session_id The session ID that was passed to client srv_handler
23040Sstevel@tonic-gate * by the CM
23050Sstevel@tonic-gate * service_time The extended service time
23060Sstevel@tonic-gate * priv_data Vendor specific data to be sent in the CM generated
23070Sstevel@tonic-gate * MRA message. Should be NULL if not specified.
23080Sstevel@tonic-gate * len The number of bytes of data specified by priv_data.
23090Sstevel@tonic-gate *
23100Sstevel@tonic-gate * RETURN VALUES:
23110Sstevel@tonic-gate * IBT_SUCCESS on success (or respective failure on error)
23120Sstevel@tonic-gate */
23130Sstevel@tonic-gate ibt_status_t
ibt_cm_delay(ibt_cmdelay_flags_t flags,void * cm_session_id,clock_t service_time,void * priv_data,ibt_priv_data_len_t len)23140Sstevel@tonic-gate ibt_cm_delay(ibt_cmdelay_flags_t flags, void *cm_session_id,
23150Sstevel@tonic-gate clock_t service_time, void *priv_data, ibt_priv_data_len_t len)
23160Sstevel@tonic-gate {
23170Sstevel@tonic-gate uint8_t msg_typ = 0;
23180Sstevel@tonic-gate ibcm_mra_msg_t *mra_msgp;
23190Sstevel@tonic-gate ibcm_state_data_t *statep;
23200Sstevel@tonic-gate ibt_status_t status;
23210Sstevel@tonic-gate
23221093Shiremath IBTF_DPRINTF_L3(cmlog, "ibt_cm_delay(0x%x, %p, 0x%x)",
23230Sstevel@tonic-gate flags, cm_session_id, service_time);
23240Sstevel@tonic-gate
23250Sstevel@tonic-gate /*
23260Sstevel@tonic-gate * Make sure channel is associated with a statep
23270Sstevel@tonic-gate */
23280Sstevel@tonic-gate statep = (ibcm_state_data_t *)cm_session_id;
23290Sstevel@tonic-gate
23300Sstevel@tonic-gate if (statep == NULL) {
23310Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: statep NULL");
23320Sstevel@tonic-gate return (IBT_INVALID_PARAM);
23330Sstevel@tonic-gate }
23340Sstevel@tonic-gate
23350Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_cm_delay: statep %p", statep);
23360Sstevel@tonic-gate
23370Sstevel@tonic-gate /* Allocate an ibmf msg for mra, if not allocated yet */
23380Sstevel@tonic-gate if (statep->mra_msg == NULL) {
23390Sstevel@tonic-gate if ((status = ibcm_alloc_out_msg(
23400Sstevel@tonic-gate statep->stored_reply_addr.ibmf_hdl, &statep->mra_msg,
23410Sstevel@tonic-gate MAD_METHOD_SEND)) != IBT_SUCCESS) {
23420Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: chan 0x%p"
23430Sstevel@tonic-gate "IBMF MSG allocation failed", statep->channel);
23440Sstevel@tonic-gate return (status);
23450Sstevel@tonic-gate }
23460Sstevel@tonic-gate }
23470Sstevel@tonic-gate
23480Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mra_msgp))
23490Sstevel@tonic-gate
23500Sstevel@tonic-gate mra_msgp = (ibcm_mra_msg_t *)IBCM_OUT_MSGP(statep->mra_msg);
23510Sstevel@tonic-gate mra_msgp->mra_local_comm_id = h2b32(statep->local_comid);
23520Sstevel@tonic-gate mra_msgp->mra_remote_comm_id = h2b32(statep->remote_comid);
23530Sstevel@tonic-gate
23540Sstevel@tonic-gate /* fill in rest of MRA's fields - Message MRAed and Service Timeout */
23550Sstevel@tonic-gate if (flags == IBT_CM_DELAY_REQ) {
23560Sstevel@tonic-gate msg_typ = IBT_CM_MRA_TYPE_REQ;
23570Sstevel@tonic-gate } else if (flags == IBT_CM_DELAY_REP) {
23580Sstevel@tonic-gate msg_typ = IBT_CM_MRA_TYPE_REP;
23590Sstevel@tonic-gate } else if (flags == IBT_CM_DELAY_LAP) {
23600Sstevel@tonic-gate msg_typ = IBT_CM_MRA_TYPE_LAP;
23610Sstevel@tonic-gate }
23620Sstevel@tonic-gate
23630Sstevel@tonic-gate mra_msgp->mra_message_type_plus = msg_typ << 6;
23640Sstevel@tonic-gate mra_msgp->mra_service_timeout_plus = ibt_usec2ib(service_time) << 3;
23650Sstevel@tonic-gate
23660Sstevel@tonic-gate len = min(len, IBT_MRA_PRIV_DATA_SZ);
23670Sstevel@tonic-gate if (priv_data && (len > 0))
23680Sstevel@tonic-gate bcopy(priv_data, mra_msgp->mra_private_data, len);
23690Sstevel@tonic-gate
23700Sstevel@tonic-gate IBCM_OUT_HDRP(statep->mra_msg)->AttributeID =
23710Sstevel@tonic-gate h2b16(IBCM_INCOMING_MRA + IBCM_ATTR_BASE_ID);
23720Sstevel@tonic-gate
23730Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mra_msgp))
23740Sstevel@tonic-gate
23750Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
23760Sstevel@tonic-gate
23770Sstevel@tonic-gate if ((statep->mode == IBCM_ACTIVE_MODE) &&
23780Sstevel@tonic-gate (statep->state == IBCM_STATE_REP_RCVD)) {
23790Sstevel@tonic-gate statep->state = IBCM_STATE_MRA_REP_SENT;
23800Sstevel@tonic-gate } else if (statep->mode == IBCM_PASSIVE_MODE) {
2381401Shiremath if (statep->state == IBCM_STATE_REQ_RCVD) {
23820Sstevel@tonic-gate statep->state = IBCM_STATE_MRA_SENT;
2383401Shiremath } else if (statep->ap_state == IBCM_AP_STATE_LAP_RCVD) {
23840Sstevel@tonic-gate statep->ap_state = IBCM_AP_STATE_MRA_LAP_RCVD;
2385401Shiremath } else {
23861093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: invalid state "
2387401Shiremath "/ap_state/mode %x, %x, %x", statep->state,
2388401Shiremath statep->ap_state, statep->mode);
2389401Shiremath mutex_exit(&statep->state_mutex);
2390401Shiremath return (IBT_CHAN_STATE_INVALID);
23910Sstevel@tonic-gate }
23920Sstevel@tonic-gate } else {
23931093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: invalid state "
23940Sstevel@tonic-gate "/ap_state/mode %x, %x, %x", statep->state,
23950Sstevel@tonic-gate statep->ap_state, statep->mode);
23960Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
23970Sstevel@tonic-gate
23980Sstevel@tonic-gate return (IBT_CHAN_STATE_INVALID);
23990Sstevel@tonic-gate }
2400401Shiremath /* service time is usecs, stale_clock is nsecs */
2401557Shiremath statep->stale_clock = gethrtime() +
2402557Shiremath (hrtime_t)ibt_ib2usec(ibt_usec2ib(service_time)) * (1000 *
2403401Shiremath statep->max_cm_retries);
24040Sstevel@tonic-gate
24050Sstevel@tonic-gate statep->send_mad_flags |= IBCM_MRA_POST_BUSY;
24060Sstevel@tonic-gate IBCM_REF_CNT_INCR(statep); /* for ibcm_post_mra_complete */
24070Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
24080Sstevel@tonic-gate
24090Sstevel@tonic-gate IBCM_OUT_HDRP(statep->mra_msg)->TransactionID =
24104703Shiremath IBCM_OUT_HDRP(statep->stored_msg)->TransactionID;
24110Sstevel@tonic-gate
24120Sstevel@tonic-gate /* post the MRA mad in blocking mode, as no timers involved */
24130Sstevel@tonic-gate ibcm_post_rc_mad(statep, statep->mra_msg, ibcm_post_mra_complete,
24140Sstevel@tonic-gate statep);
24151093Shiremath ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_MRA);
24160Sstevel@tonic-gate /* If this message isn't seen then ibt_cm_delay failed */
24171093Shiremath IBTF_DPRINTF_L3(cmlog, "ibt_cm_delay: done !!");
24180Sstevel@tonic-gate
24190Sstevel@tonic-gate return (IBT_SUCCESS);
24200Sstevel@tonic-gate }
24210Sstevel@tonic-gate
24220Sstevel@tonic-gate
24230Sstevel@tonic-gate /*
24240Sstevel@tonic-gate * ibt_register_service()
24250Sstevel@tonic-gate * Register a service with the IBCM
24260Sstevel@tonic-gate *
24270Sstevel@tonic-gate * INPUTS:
24280Sstevel@tonic-gate * ibt_hdl The IBT client handle returned to the client
24290Sstevel@tonic-gate * on an ibt_attach() call.
24300Sstevel@tonic-gate *
24310Sstevel@tonic-gate * srv The address of a ibt_srv_desc_t that describes
24320Sstevel@tonic-gate * the service, containing the following:
24330Sstevel@tonic-gate *
24340Sstevel@tonic-gate * sd_ud_handler The Service CM UD event Handler.
24350Sstevel@tonic-gate * sd_handler The Service CM RC/UC/RD event Handler.
24360Sstevel@tonic-gate * sd_flags Service flags (peer-to-peer, or not).
24370Sstevel@tonic-gate *
24380Sstevel@tonic-gate * sid This tells CM if the service is local (sid is 0) or
24390Sstevel@tonic-gate * wellknown (sid is the starting service id of the range).
24400Sstevel@tonic-gate *
24410Sstevel@tonic-gate * num_sids The number of contiguous service-ids to reserve.
24420Sstevel@tonic-gate *
24430Sstevel@tonic-gate * srv_hdl The address of a service identification handle, used
24440Sstevel@tonic-gate * to deregister a service, and to bind GIDs to.
24450Sstevel@tonic-gate *
24460Sstevel@tonic-gate * ret_sid The address to store the Service ID return value.
24470Sstevel@tonic-gate * If num_sids > 1, ret_sid is the first Service ID
24480Sstevel@tonic-gate * in the range.
24490Sstevel@tonic-gate *
24500Sstevel@tonic-gate * ibt_register_service() returns:
24510Sstevel@tonic-gate * IBT_SUCCESS - added a service successfully.
24520Sstevel@tonic-gate * IBT_INVALID_PARAM - invalid input parameter.
24530Sstevel@tonic-gate * IBT_CM_FAILURE - failed to add the service.
24540Sstevel@tonic-gate * IBT_CM_SERVICE_EXISTS - service already exists.
24550Sstevel@tonic-gate * IBT_INSUFF_KERNEL_RESOURCE - ran out of local service ids (should
24560Sstevel@tonic-gate * never happen).
24570Sstevel@tonic-gate */
24580Sstevel@tonic-gate ibt_status_t
ibt_register_service(ibt_clnt_hdl_t ibt_hdl,ibt_srv_desc_t * srv,ib_svc_id_t sid,int num_sids,ibt_srv_hdl_t * srv_hdl,ib_svc_id_t * ret_sid)24590Sstevel@tonic-gate ibt_register_service(ibt_clnt_hdl_t ibt_hdl, ibt_srv_desc_t *srv,
24600Sstevel@tonic-gate ib_svc_id_t sid, int num_sids, ibt_srv_hdl_t *srv_hdl, ib_svc_id_t *ret_sid)
24610Sstevel@tonic-gate {
24620Sstevel@tonic-gate ibcm_svc_info_t *svcinfop;
24630Sstevel@tonic-gate
24649349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L2(cmlog, "ibt_register_service(%p (%s), %p, 0x%llX, %d)",
24659349SShantkumar.Hiremath@Sun.COM ibt_hdl, ibtl_cm_get_clnt_name(ibt_hdl), srv, (longlong_t)sid,
24669349SShantkumar.Hiremath@Sun.COM num_sids);
24670Sstevel@tonic-gate
24680Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*svcinfop))
24690Sstevel@tonic-gate
24700Sstevel@tonic-gate *srv_hdl = NULL;
24710Sstevel@tonic-gate
24720Sstevel@tonic-gate if (num_sids <= 0) {
24730Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_register_service: "
24740Sstevel@tonic-gate "Invalid number of service-ids specified (%d)", num_sids);
24750Sstevel@tonic-gate return (IBT_INVALID_PARAM);
24760Sstevel@tonic-gate }
24770Sstevel@tonic-gate
24780Sstevel@tonic-gate if (sid == 0) {
24790Sstevel@tonic-gate if (ret_sid == NULL)
24800Sstevel@tonic-gate return (IBT_INVALID_PARAM);
24810Sstevel@tonic-gate sid = ibcm_alloc_local_sids(num_sids);
24820Sstevel@tonic-gate if (sid == 0)
24830Sstevel@tonic-gate return (IBT_INSUFF_KERNEL_RESOURCE);
24840Sstevel@tonic-gate
24850Sstevel@tonic-gate /* Make sure that the ServiceId specified is not of LOCAL AGN type. */
24860Sstevel@tonic-gate } else if ((sid & IB_SID_AGN_MASK) == IB_SID_AGN_LOCAL) {
24870Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_register_service: "
24880Sstevel@tonic-gate "Invalid non-LOCAL SID specified: 0x%llX",
24890Sstevel@tonic-gate (longlong_t)sid);
24900Sstevel@tonic-gate return (IBT_INVALID_PARAM);
24910Sstevel@tonic-gate }
24920Sstevel@tonic-gate
24930Sstevel@tonic-gate svcinfop = ibcm_create_svc_entry(sid, num_sids);
24940Sstevel@tonic-gate
24950Sstevel@tonic-gate if (svcinfop == NULL) {
24960Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_register_service: "
24970Sstevel@tonic-gate "Service-ID 0x%llx already registered", (longlong_t)sid);
24980Sstevel@tonic-gate return (IBT_CM_SERVICE_EXISTS);
24990Sstevel@tonic-gate }
25000Sstevel@tonic-gate
25010Sstevel@tonic-gate /*
25020Sstevel@tonic-gate * 'sid' and 'num_sids' are filled in ibcm_create_svc_entry()
25030Sstevel@tonic-gate */
25040Sstevel@tonic-gate svcinfop->svc_flags = srv->sd_flags;
25050Sstevel@tonic-gate svcinfop->svc_rc_handler = srv->sd_handler;
25060Sstevel@tonic-gate svcinfop->svc_ud_handler = srv->sd_ud_handler;
25070Sstevel@tonic-gate
25080Sstevel@tonic-gate if (ret_sid != NULL)
25090Sstevel@tonic-gate *ret_sid = sid;
25100Sstevel@tonic-gate
25110Sstevel@tonic-gate *srv_hdl = svcinfop;
25120Sstevel@tonic-gate
25130Sstevel@tonic-gate ibtl_cm_change_service_cnt(ibt_hdl, num_sids);
25140Sstevel@tonic-gate
25150Sstevel@tonic-gate /* If this message isn't seen, then ibt_register_service failed. */
25160Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_register_service: done (%p, %llX)",
25170Sstevel@tonic-gate svcinfop, sid);
25180Sstevel@tonic-gate
25190Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*svcinfop))
25200Sstevel@tonic-gate
25210Sstevel@tonic-gate return (IBT_SUCCESS);
25220Sstevel@tonic-gate }
25230Sstevel@tonic-gate
25240Sstevel@tonic-gate
25250Sstevel@tonic-gate static ibt_status_t
ibcm_write_service_record(ibmf_saa_handle_t saa_handle,sa_service_record_t * srv_recp,ibmf_saa_access_type_t saa_type)25260Sstevel@tonic-gate ibcm_write_service_record(ibmf_saa_handle_t saa_handle,
25270Sstevel@tonic-gate sa_service_record_t *srv_recp, ibmf_saa_access_type_t saa_type)
25280Sstevel@tonic-gate {
25290Sstevel@tonic-gate int rval;
25300Sstevel@tonic-gate int retry;
25310Sstevel@tonic-gate
25320Sstevel@tonic-gate ibcm_sa_access_enter();
25330Sstevel@tonic-gate for (retry = 0; retry < ibcm_max_sa_retries; retry++) {
25340Sstevel@tonic-gate rval = ibmf_saa_update_service_record(
25350Sstevel@tonic-gate saa_handle, srv_recp, saa_type, 0);
25360Sstevel@tonic-gate if (rval != IBMF_TRANS_TIMEOUT) {
25370Sstevel@tonic-gate break;
25380Sstevel@tonic-gate }
25390Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_write_service_record: "
25400Sstevel@tonic-gate "ibmf_saa_update_service_record timed out"
25410Sstevel@tonic-gate " SID = %llX, rval = %d, saa_type = %d",
25420Sstevel@tonic-gate (longlong_t)srv_recp->ServiceID, rval, saa_type);
25430Sstevel@tonic-gate delay(ibcm_sa_timeout_delay);
25440Sstevel@tonic-gate }
25450Sstevel@tonic-gate ibcm_sa_access_exit();
25460Sstevel@tonic-gate
25470Sstevel@tonic-gate if (rval != IBMF_SUCCESS) {
25480Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_write_service_record: "
25490Sstevel@tonic-gate "ibmf_saa_update_service_record() : Failed - %d", rval);
25500Sstevel@tonic-gate return (ibcm_ibmf_analyze_error(rval));
25510Sstevel@tonic-gate } else
25520Sstevel@tonic-gate return (IBT_SUCCESS);
25530Sstevel@tonic-gate }
25540Sstevel@tonic-gate
25550Sstevel@tonic-gate
25560Sstevel@tonic-gate static void
ibcm_rem_stale_srec(ibmf_saa_handle_t saa_handle,sa_service_record_t * srec)25570Sstevel@tonic-gate ibcm_rem_stale_srec(ibmf_saa_handle_t saa_handle, sa_service_record_t *srec)
25580Sstevel@tonic-gate {
25590Sstevel@tonic-gate ibt_status_t retval;
25600Sstevel@tonic-gate uint_t num_found;
25610Sstevel@tonic-gate size_t length;
25620Sstevel@tonic-gate sa_service_record_t *srv_resp;
25630Sstevel@tonic-gate void *results_p;
25640Sstevel@tonic-gate uint_t i;
25650Sstevel@tonic-gate uint64_t component_mask;
25660Sstevel@tonic-gate ibmf_saa_access_args_t access_args;
25670Sstevel@tonic-gate
25680Sstevel@tonic-gate component_mask =
25690Sstevel@tonic-gate SA_SR_COMPMASK_PKEY | SA_SR_COMPMASK_NAME | SA_SR_COMPMASK_GID;
25700Sstevel@tonic-gate
25710Sstevel@tonic-gate /* Call in SA Access retrieve routine to get Service Records. */
25720Sstevel@tonic-gate access_args.sq_attr_id = SA_SERVICERECORD_ATTRID;
25730Sstevel@tonic-gate access_args.sq_access_type = IBMF_SAA_RETRIEVE;
25740Sstevel@tonic-gate access_args.sq_component_mask = component_mask;
25750Sstevel@tonic-gate access_args.sq_template = srec;
25760Sstevel@tonic-gate access_args.sq_template_length = sizeof (sa_service_record_t);
25770Sstevel@tonic-gate access_args.sq_callback = NULL;
25780Sstevel@tonic-gate access_args.sq_callback_arg = NULL;
25790Sstevel@tonic-gate
25800Sstevel@tonic-gate retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
25810Sstevel@tonic-gate &results_p);
25820Sstevel@tonic-gate if (retval != IBT_SUCCESS) {
25830Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_rem_stale_srec: "
25840Sstevel@tonic-gate "SA Access Failure");
25850Sstevel@tonic-gate return;
25860Sstevel@tonic-gate }
25870Sstevel@tonic-gate
25880Sstevel@tonic-gate num_found = length / sizeof (sa_service_record_t);
25890Sstevel@tonic-gate
25900Sstevel@tonic-gate if (num_found)
25910Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_rem_stale_srec: "
25920Sstevel@tonic-gate "Found %d matching Service Records.", num_found);
25930Sstevel@tonic-gate
25940Sstevel@tonic-gate /* Validate the returned number of records. */
25950Sstevel@tonic-gate if ((results_p != NULL) && (num_found > 0)) {
25960Sstevel@tonic-gate
25970Sstevel@tonic-gate /* Remove all the records. */
25980Sstevel@tonic-gate for (i = 0; i < num_found; i++) {
25990Sstevel@tonic-gate
26000Sstevel@tonic-gate srv_resp = (sa_service_record_t *)
26010Sstevel@tonic-gate ((uchar_t *)results_p +
26020Sstevel@tonic-gate i * sizeof (sa_service_record_t));
26030Sstevel@tonic-gate
26040Sstevel@tonic-gate /*
26050Sstevel@tonic-gate * Found some matching records, but check out whether
26060Sstevel@tonic-gate * this Record is really stale or just happens to match
26070Sstevel@tonic-gate * the current session records. If yes, don't remove it.
26080Sstevel@tonic-gate */
26090Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
26100Sstevel@tonic-gate if (ibcm_find_svc_entry(srv_resp->ServiceID) != NULL) {
26110Sstevel@tonic-gate /* This record is NOT STALE. */
26120Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
26130Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_rem_stale_srec: "
26140Sstevel@tonic-gate "This is not Stale, it's an active record");
26150Sstevel@tonic-gate continue;
26160Sstevel@tonic-gate }
26170Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
26180Sstevel@tonic-gate
26190Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_rem_stale_srec: "
26200Sstevel@tonic-gate "Removing Stale Rec: %s, %llX",
26210Sstevel@tonic-gate srv_resp->ServiceName, srv_resp->ServiceID);
26220Sstevel@tonic-gate
26230Sstevel@tonic-gate IBCM_DUMP_SERVICE_REC(srv_resp);
26240Sstevel@tonic-gate
26250Sstevel@tonic-gate /*
26260Sstevel@tonic-gate * Remove the Service Record Entry from SA.
26270Sstevel@tonic-gate *
26280Sstevel@tonic-gate * Get ServiceID info from Response Buf, other
26290Sstevel@tonic-gate * attributes are already filled-in.
26300Sstevel@tonic-gate */
26310Sstevel@tonic-gate
26320Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(srec->ServiceID))
26330Sstevel@tonic-gate
26340Sstevel@tonic-gate srec->ServiceID = srv_resp->ServiceID;
26350Sstevel@tonic-gate
26360Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(srec->ServiceID))
26370Sstevel@tonic-gate
26380Sstevel@tonic-gate (void) ibcm_write_service_record(saa_handle, srec,
26390Sstevel@tonic-gate IBMF_SAA_DELETE);
26400Sstevel@tonic-gate }
26410Sstevel@tonic-gate
26420Sstevel@tonic-gate /* Deallocate the memory for results_p. */
26430Sstevel@tonic-gate kmem_free(results_p, length);
26440Sstevel@tonic-gate }
26450Sstevel@tonic-gate }
26460Sstevel@tonic-gate
26470Sstevel@tonic-gate
26480Sstevel@tonic-gate
26490Sstevel@tonic-gate /*
26500Sstevel@tonic-gate * ibt_bind_service()
26510Sstevel@tonic-gate * Register a service with the IBCM
26520Sstevel@tonic-gate *
26530Sstevel@tonic-gate * INPUTS:
26540Sstevel@tonic-gate * srv_hdl The service id handle returned to the client
26550Sstevel@tonic-gate * on an ibt_service_register() call.
26560Sstevel@tonic-gate *
26570Sstevel@tonic-gate * gid The GID to which to bind the service.
26580Sstevel@tonic-gate *
26590Sstevel@tonic-gate * srv_bind The address of a ibt_srv_bind_t that describes
26600Sstevel@tonic-gate * the service record. This should be NULL if there
26610Sstevel@tonic-gate * is to be no service record. This contains:
26620Sstevel@tonic-gate *
26630Sstevel@tonic-gate * sb_lease Lease period
26640Sstevel@tonic-gate * sb_pkey Partition
26650Sstevel@tonic-gate * sb_name pointer to ASCII string Service Name,
26660Sstevel@tonic-gate * NULL terminated.
26670Sstevel@tonic-gate * sb_key[] Key to secure the service record.
26680Sstevel@tonic-gate * sb_data Service Data structure (64-byte)
26690Sstevel@tonic-gate *
26700Sstevel@tonic-gate * cm_private First argument of Service handler.
26710Sstevel@tonic-gate *
26720Sstevel@tonic-gate * sb_hdl_p The address of a service bind handle, used
26730Sstevel@tonic-gate * to undo the service binding.
26740Sstevel@tonic-gate *
26750Sstevel@tonic-gate * ibt_bind_service() returns:
26760Sstevel@tonic-gate * IBT_SUCCESS - added a service successfully.
26770Sstevel@tonic-gate * IBT_INVALID_PARAM - invalid input parameter.
26780Sstevel@tonic-gate * IBT_CM_FAILURE - failed to add the service.
26790Sstevel@tonic-gate * IBT_CM_SERVICE_EXISTS - service already exists.
26800Sstevel@tonic-gate */
26810Sstevel@tonic-gate ibt_status_t
ibt_bind_service(ibt_srv_hdl_t srv_hdl,ib_gid_t gid,ibt_srv_bind_t * srv_bind,void * cm_private,ibt_sbind_hdl_t * sb_hdl_p)26820Sstevel@tonic-gate ibt_bind_service(ibt_srv_hdl_t srv_hdl, ib_gid_t gid, ibt_srv_bind_t *srv_bind,
26830Sstevel@tonic-gate void *cm_private, ibt_sbind_hdl_t *sb_hdl_p)
26840Sstevel@tonic-gate {
26850Sstevel@tonic-gate ibt_status_t status;
26860Sstevel@tonic-gate ibtl_cm_hca_port_t port;
26870Sstevel@tonic-gate ibcm_svc_bind_t *sbindp, *sbp;
26880Sstevel@tonic-gate ibcm_hca_info_t *hcap;
26890Sstevel@tonic-gate ib_svc_id_t sid, start_sid, end_sid;
26900Sstevel@tonic-gate ibmf_saa_handle_t saa_handle;
26910Sstevel@tonic-gate sa_service_record_t srv_rec;
26920Sstevel@tonic-gate uint16_t pkey_ix;
26930Sstevel@tonic-gate
26940Sstevel@tonic-gate if (sb_hdl_p != NULL)
26950Sstevel@tonic-gate *sb_hdl_p = NULL; /* return value for error cases */
26960Sstevel@tonic-gate
26970Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: srv_hdl %p, gid (%llX:%llX)",
26980Sstevel@tonic-gate srv_hdl, (longlong_t)gid.gid_prefix, (longlong_t)gid.gid_guid);
26990Sstevel@tonic-gate
27000Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sbindp))
27010Sstevel@tonic-gate
27020Sstevel@tonic-gate /* Call ibtl_cm_get_hca_port to get the port number and the HCA GUID. */
27030Sstevel@tonic-gate if ((status = ibtl_cm_get_hca_port(gid, 0, &port)) != IBT_SUCCESS) {
27040Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
27050Sstevel@tonic-gate "ibtl_cm_get_hca_port failed: %d", status);
27060Sstevel@tonic-gate return (status);
27070Sstevel@tonic-gate }
27080Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_bind_service: Port:%d HCA GUID:%llX",
27090Sstevel@tonic-gate port.hp_port, port.hp_hca_guid);
27100Sstevel@tonic-gate
27110Sstevel@tonic-gate hcap = ibcm_find_hca_entry(port.hp_hca_guid);
27120Sstevel@tonic-gate if (hcap == NULL) {
27130Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: NO HCA found");
27140Sstevel@tonic-gate return (IBT_HCA_BUSY_DETACHING);
27150Sstevel@tonic-gate }
27160Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_bind_service: hcap = %p", hcap);
27170Sstevel@tonic-gate
27180Sstevel@tonic-gate if (srv_bind != NULL) {
27190Sstevel@tonic-gate saa_handle = ibcm_get_saa_handle(hcap, port.hp_port);
27200Sstevel@tonic-gate if (saa_handle == NULL) {
27210Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
27220Sstevel@tonic-gate "saa_handle is NULL");
27230Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
27240Sstevel@tonic-gate return (IBT_HCA_PORT_NOT_ACTIVE);
27250Sstevel@tonic-gate }
27260Sstevel@tonic-gate if (srv_bind->sb_pkey == 0) {
27270Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
27280Sstevel@tonic-gate "P_Key must not be 0");
27290Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
27300Sstevel@tonic-gate return (IBT_INVALID_PARAM);
27310Sstevel@tonic-gate }
27320Sstevel@tonic-gate if (strlen(srv_bind->sb_name) >= IB_SVC_NAME_LEN) {
27330Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
27340Sstevel@tonic-gate "Service Name is too long");
27350Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
27360Sstevel@tonic-gate return (IBT_INVALID_PARAM);
27370Sstevel@tonic-gate } else
27380Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_bind_service: "
27390Sstevel@tonic-gate "Service Name='%s'", srv_bind->sb_name);
27400Sstevel@tonic-gate status = ibt_pkey2index_byguid(port.hp_hca_guid,
27410Sstevel@tonic-gate port.hp_port, srv_bind->sb_pkey, &pkey_ix);
27420Sstevel@tonic-gate if (status != IBT_SUCCESS) {
27430Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
27440Sstevel@tonic-gate "P_Key 0x%x not found in P_Key_Table",
27450Sstevel@tonic-gate srv_bind->sb_pkey);
27460Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
27470Sstevel@tonic-gate return (status);
27480Sstevel@tonic-gate }
27490Sstevel@tonic-gate }
27500Sstevel@tonic-gate
27510Sstevel@tonic-gate /* assume success - allocate before locking */
27520Sstevel@tonic-gate sbindp = kmem_zalloc(sizeof (*sbindp), KM_SLEEP);
27530Sstevel@tonic-gate sbindp->sbind_cm_private = cm_private;
27540Sstevel@tonic-gate sbindp->sbind_gid = gid;
27550Sstevel@tonic-gate sbindp->sbind_hcaguid = port.hp_hca_guid;
27560Sstevel@tonic-gate sbindp->sbind_port = port.hp_port;
27570Sstevel@tonic-gate
27580Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
27590Sstevel@tonic-gate
27600Sstevel@tonic-gate sbp = srv_hdl->svc_bind_list;
27610Sstevel@tonic-gate while (sbp != NULL) {
27620Sstevel@tonic-gate if (sbp->sbind_gid.gid_guid == gid.gid_guid &&
27630Sstevel@tonic-gate sbp->sbind_gid.gid_prefix == gid.gid_prefix) {
27640Sstevel@tonic-gate if (srv_bind == NULL ||
27650Sstevel@tonic-gate srv_bind->sb_pkey == sbp->sbind_pkey) {
27660Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
27671495Shiremath "failed: GID %llX:%llX and PKEY %x is "
27686709Shiremath "already bound", gid.gid_prefix,
27696709Shiremath gid.gid_guid, sbp->sbind_pkey);
27700Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
27710Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
27720Sstevel@tonic-gate kmem_free(sbindp, sizeof (*sbindp));
27730Sstevel@tonic-gate return (IBT_CM_SERVICE_EXISTS);
27740Sstevel@tonic-gate }
27750Sstevel@tonic-gate }
27760Sstevel@tonic-gate sbp = sbp->sbind_link;
27770Sstevel@tonic-gate }
27780Sstevel@tonic-gate /* no entry found */
27790Sstevel@tonic-gate
27800Sstevel@tonic-gate sbindp->sbind_link = srv_hdl->svc_bind_list;
27810Sstevel@tonic-gate srv_hdl->svc_bind_list = sbindp;
27820Sstevel@tonic-gate
27830Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
27840Sstevel@tonic-gate
27850Sstevel@tonic-gate if (srv_bind != NULL) {
27860Sstevel@tonic-gate bzero(&srv_rec, sizeof (srv_rec));
27870Sstevel@tonic-gate
27880Sstevel@tonic-gate srv_rec.ServiceLease =
27890Sstevel@tonic-gate sbindp->sbind_lease = srv_bind->sb_lease;
27900Sstevel@tonic-gate srv_rec.ServiceP_Key =
27910Sstevel@tonic-gate sbindp->sbind_pkey = srv_bind->sb_pkey;
27920Sstevel@tonic-gate srv_rec.ServiceKey_hi =
27930Sstevel@tonic-gate sbindp->sbind_key[0] = srv_bind->sb_key[0];
27940Sstevel@tonic-gate srv_rec.ServiceKey_lo =
27950Sstevel@tonic-gate sbindp->sbind_key[1] = srv_bind->sb_key[1];
27960Sstevel@tonic-gate (void) strcpy(sbindp->sbind_name, srv_bind->sb_name);
27970Sstevel@tonic-gate (void) strcpy((char *)srv_rec.ServiceName, srv_bind->sb_name);
27980Sstevel@tonic-gate srv_rec.ServiceGID = gid;
27990Sstevel@tonic-gate
28000Sstevel@tonic-gate /*
28010Sstevel@tonic-gate * Find out whether we have any stale Local Service records
28020Sstevel@tonic-gate * matching the current attributes. If yes, we shall try to
28030Sstevel@tonic-gate * remove them from SA using the current request's ServiceKey.
28040Sstevel@tonic-gate *
28050Sstevel@tonic-gate * We will perform this operation only for Local Services, as
28060Sstevel@tonic-gate * it is handled by SA automatically for WellKnown Services.
28070Sstevel@tonic-gate *
28080Sstevel@tonic-gate * Ofcourse, clients can specify NOT to do this clean-up by
28090Sstevel@tonic-gate * setting IBT_SBIND_NO_CLEANUP flag (srv_bind->sb_flag).
28100Sstevel@tonic-gate */
28110Sstevel@tonic-gate if ((srv_hdl->svc_id & IB_SID_AGN_LOCAL) &&
28120Sstevel@tonic-gate (!(srv_bind->sb_flag & IBT_SBIND_NO_CLEANUP))) {
28130Sstevel@tonic-gate ibcm_rem_stale_srec(saa_handle, &srv_rec);
28140Sstevel@tonic-gate }
28150Sstevel@tonic-gate
28160Sstevel@tonic-gate /* Handle endianess for service data. */
28170Sstevel@tonic-gate ibcm_swizzle_from_srv(&srv_bind->sb_data, sbindp->sbind_data);
28180Sstevel@tonic-gate
28190Sstevel@tonic-gate bcopy(sbindp->sbind_data, srv_rec.ServiceData, IB_SVC_DATA_LEN);
28200Sstevel@tonic-gate
28210Sstevel@tonic-gate /* insert srv record into the SA */
28220Sstevel@tonic-gate start_sid = srv_hdl->svc_id;
28230Sstevel@tonic-gate end_sid = start_sid + srv_hdl->svc_num_sids - 1;
28240Sstevel@tonic-gate for (sid = start_sid; sid <= end_sid; sid++) {
28250Sstevel@tonic-gate
28260Sstevel@tonic-gate srv_rec.ServiceID = sid;
28270Sstevel@tonic-gate
28280Sstevel@tonic-gate IBCM_DUMP_SERVICE_REC(&srv_rec);
28290Sstevel@tonic-gate
28300Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_bind_service: "
28310Sstevel@tonic-gate "ibmf_saa_write_service_record, SvcId = %llX",
28320Sstevel@tonic-gate (longlong_t)sid);
28330Sstevel@tonic-gate
28340Sstevel@tonic-gate status = ibcm_write_service_record(saa_handle, &srv_rec,
28350Sstevel@tonic-gate IBMF_SAA_UPDATE);
28360Sstevel@tonic-gate if (status != IBT_SUCCESS) {
28370Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_bind_service:"
28380Sstevel@tonic-gate " ibcm_write_service_record fails %d, "
28390Sstevel@tonic-gate "sid %llX", status, (longlong_t)sid);
28400Sstevel@tonic-gate
28410Sstevel@tonic-gate if (sid != start_sid) {
28420Sstevel@tonic-gate /*
28430Sstevel@tonic-gate * Bind failed while bind SID other than
28440Sstevel@tonic-gate * first in the sid_range. So we need
28450Sstevel@tonic-gate * to unbind those, which are passed.
28460Sstevel@tonic-gate *
28470Sstevel@tonic-gate * Need to increment svc count to
28480Sstevel@tonic-gate * compensate for ibt_unbind_service().
28490Sstevel@tonic-gate */
28500Sstevel@tonic-gate ibcm_inc_hca_svc_cnt(hcap);
28510Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
28520Sstevel@tonic-gate
28530Sstevel@tonic-gate (void) ibt_unbind_service(srv_hdl,
28540Sstevel@tonic-gate sbindp);
28550Sstevel@tonic-gate } else {
28560Sstevel@tonic-gate ibcm_svc_bind_t **sbpp;
28570Sstevel@tonic-gate
28580Sstevel@tonic-gate /*
28590Sstevel@tonic-gate * Bind failed for the first SID or the
28600Sstevel@tonic-gate * only SID in question, then no need
28610Sstevel@tonic-gate * to unbind, just free memory and
28620Sstevel@tonic-gate * return error.
28630Sstevel@tonic-gate */
28640Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
28650Sstevel@tonic-gate
28660Sstevel@tonic-gate sbpp = &srv_hdl->svc_bind_list;
28670Sstevel@tonic-gate sbp = *sbpp;
28680Sstevel@tonic-gate while (sbp != NULL) {
28690Sstevel@tonic-gate if (sbp == sbindp) {
28700Sstevel@tonic-gate *sbpp = sbp->sbind_link;
28710Sstevel@tonic-gate break;
28720Sstevel@tonic-gate }
28730Sstevel@tonic-gate sbpp = &sbp->sbind_link;
28740Sstevel@tonic-gate sbp = *sbpp;
28750Sstevel@tonic-gate }
28760Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
28770Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
28780Sstevel@tonic-gate
28790Sstevel@tonic-gate kmem_free(sbindp, sizeof (*sbindp));
28800Sstevel@tonic-gate }
28810Sstevel@tonic-gate return (status);
28820Sstevel@tonic-gate }
28830Sstevel@tonic-gate }
28840Sstevel@tonic-gate }
28850Sstevel@tonic-gate ibcm_inc_hca_svc_cnt(hcap);
28860Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
28870Sstevel@tonic-gate
28880Sstevel@tonic-gate /* If this message isn't seen then ibt_bind_service failed */
28891093Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: DONE (%p, %llX:%llX)",
28900Sstevel@tonic-gate srv_hdl, gid.gid_prefix, gid.gid_guid);
28910Sstevel@tonic-gate
28920Sstevel@tonic-gate if (sb_hdl_p != NULL)
28930Sstevel@tonic-gate *sb_hdl_p = sbindp;
28940Sstevel@tonic-gate
28950Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sbindp))
28960Sstevel@tonic-gate
28970Sstevel@tonic-gate return (IBT_SUCCESS);
28980Sstevel@tonic-gate }
28990Sstevel@tonic-gate
29000Sstevel@tonic-gate ibt_status_t
ibt_unbind_service(ibt_srv_hdl_t srv_hdl,ibt_sbind_hdl_t sbindp)29010Sstevel@tonic-gate ibt_unbind_service(ibt_srv_hdl_t srv_hdl, ibt_sbind_hdl_t sbindp)
29020Sstevel@tonic-gate {
29030Sstevel@tonic-gate ib_svc_id_t sid, end_sid;
29040Sstevel@tonic-gate ibt_status_t rval;
29050Sstevel@tonic-gate ibcm_hca_info_t *hcap;
29060Sstevel@tonic-gate ibcm_svc_bind_t *sbp, **sbpp;
29070Sstevel@tonic-gate
29080Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service(%p, %p)",
29090Sstevel@tonic-gate srv_hdl, sbindp);
29100Sstevel@tonic-gate
29110Sstevel@tonic-gate hcap = ibcm_find_hca_entry(sbindp->sbind_hcaguid);
29120Sstevel@tonic-gate
29130Sstevel@tonic-gate /* If there is a service on hca, respective hcap cannot go away */
29140Sstevel@tonic-gate ASSERT(hcap != NULL);
29150Sstevel@tonic-gate
29160Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
29170Sstevel@tonic-gate
29180Sstevel@tonic-gate sbpp = &srv_hdl->svc_bind_list;
29190Sstevel@tonic-gate sbp = *sbpp;
29200Sstevel@tonic-gate while (sbp != NULL) {
29210Sstevel@tonic-gate if (sbp == sbindp) {
29220Sstevel@tonic-gate *sbpp = sbp->sbind_link;
29230Sstevel@tonic-gate break;
29240Sstevel@tonic-gate }
29250Sstevel@tonic-gate sbpp = &sbp->sbind_link;
29260Sstevel@tonic-gate sbp = *sbpp;
29270Sstevel@tonic-gate }
29280Sstevel@tonic-gate sid = srv_hdl->svc_id;
29290Sstevel@tonic-gate end_sid = srv_hdl->svc_id + srv_hdl->svc_num_sids - 1;
29300Sstevel@tonic-gate if (sbp != NULL)
29310Sstevel@tonic-gate while (sbp->sbind_rewrite_state == IBCM_REWRITE_BUSY)
29320Sstevel@tonic-gate cv_wait(&ibcm_svc_info_cv, &ibcm_svc_info_lock);
29330Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
29340Sstevel@tonic-gate
29350Sstevel@tonic-gate if (sbp == NULL) {
29360Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: "
29370Sstevel@tonic-gate "service binding not found: srv_hdl %p, srv_bind %p",
29380Sstevel@tonic-gate srv_hdl, sbindp);
29390Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
29400Sstevel@tonic-gate return (IBT_INVALID_PARAM);
29410Sstevel@tonic-gate }
29420Sstevel@tonic-gate
29430Sstevel@tonic-gate if (sbindp->sbind_pkey != 0) { /* Are there service records? */
29440Sstevel@tonic-gate ibtl_cm_hca_port_t port;
29450Sstevel@tonic-gate sa_service_record_t srv_rec;
29460Sstevel@tonic-gate ibmf_saa_handle_t saa_handle;
29470Sstevel@tonic-gate ibt_status_t status;
29480Sstevel@tonic-gate
29490Sstevel@tonic-gate /* get the default SGID of the port */
29500Sstevel@tonic-gate if ((status = ibtl_cm_get_hca_port(sbindp->sbind_gid, 0, &port))
29510Sstevel@tonic-gate != IBT_SUCCESS) {
29520Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: "
29530Sstevel@tonic-gate "ibtl_cm_get_hca_port failed: %d", status);
29540Sstevel@tonic-gate /* we're done, but there may be stale service records */
29550Sstevel@tonic-gate goto done;
29560Sstevel@tonic-gate }
29570Sstevel@tonic-gate
29580Sstevel@tonic-gate saa_handle = ibcm_get_saa_handle(hcap, port.hp_port);
29590Sstevel@tonic-gate if (saa_handle == NULL) {
29600Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: "
29610Sstevel@tonic-gate "saa_handle is NULL");
29620Sstevel@tonic-gate /* we're done, but there may be stale service records */
29630Sstevel@tonic-gate goto done;
29640Sstevel@tonic-gate }
29650Sstevel@tonic-gate
29660Sstevel@tonic-gate /* Fill in fields of srv_rec */
29670Sstevel@tonic-gate bzero(&srv_rec, sizeof (srv_rec));
29680Sstevel@tonic-gate
29690Sstevel@tonic-gate srv_rec.ServiceP_Key = sbindp->sbind_pkey;
29700Sstevel@tonic-gate srv_rec.ServiceKey_hi = sbindp->sbind_key[0];
29710Sstevel@tonic-gate srv_rec.ServiceKey_lo = sbindp->sbind_key[1];
29720Sstevel@tonic-gate srv_rec.ServiceGID = sbindp->sbind_gid;
29730Sstevel@tonic-gate (void) strcpy((char *)srv_rec.ServiceName, sbindp->sbind_name);
29740Sstevel@tonic-gate
29750Sstevel@tonic-gate while (sid <= end_sid) {
29760Sstevel@tonic-gate
29770Sstevel@tonic-gate srv_rec.ServiceID = sid;
29780Sstevel@tonic-gate IBCM_DUMP_SERVICE_REC(&srv_rec);
29790Sstevel@tonic-gate
29800Sstevel@tonic-gate rval = ibcm_write_service_record(saa_handle, &srv_rec,
29810Sstevel@tonic-gate IBMF_SAA_DELETE);
29820Sstevel@tonic-gate
29830Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_unbind_service: "
29840Sstevel@tonic-gate "ibcm_write_service_record rval = %d, SID %llx",
29850Sstevel@tonic-gate rval, sid);
29860Sstevel@tonic-gate if (rval != IBT_SUCCESS) {
29870Sstevel@tonic-gate /* this is not considered a reason to fail */
29880Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: "
29890Sstevel@tonic-gate "ibcm_write_service_record fails %d, "
29900Sstevel@tonic-gate "sid %llx", rval, sid);
29910Sstevel@tonic-gate }
29920Sstevel@tonic-gate sid++;
29930Sstevel@tonic-gate }
29940Sstevel@tonic-gate }
29950Sstevel@tonic-gate done:
29960Sstevel@tonic-gate ibcm_dec_hca_svc_cnt(hcap);
29970Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
29980Sstevel@tonic-gate kmem_free(sbindp, sizeof (*sbindp));
29990Sstevel@tonic-gate
30000Sstevel@tonic-gate /* If this message isn't seen then ibt_unbind_service failed */
30010Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: done !!");
30020Sstevel@tonic-gate
30030Sstevel@tonic-gate return (IBT_SUCCESS);
30040Sstevel@tonic-gate }
30050Sstevel@tonic-gate
30060Sstevel@tonic-gate /*
30070Sstevel@tonic-gate * Simply pull off each binding from the list and unbind it.
30080Sstevel@tonic-gate * If any of the unbind calls fail, we fail.
30090Sstevel@tonic-gate */
30100Sstevel@tonic-gate ibt_status_t
ibt_unbind_all_services(ibt_srv_hdl_t srv_hdl)30110Sstevel@tonic-gate ibt_unbind_all_services(ibt_srv_hdl_t srv_hdl)
30120Sstevel@tonic-gate {
30130Sstevel@tonic-gate ibt_status_t status;
30140Sstevel@tonic-gate ibcm_svc_bind_t *sbp;
30150Sstevel@tonic-gate
30160Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
30170Sstevel@tonic-gate sbp = NULL;
30180Sstevel@tonic-gate
30190Sstevel@tonic-gate /* this compare keeps the loop from being infinite */
30200Sstevel@tonic-gate while (sbp != srv_hdl->svc_bind_list) {
30210Sstevel@tonic-gate sbp = srv_hdl->svc_bind_list;
30220Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
30230Sstevel@tonic-gate status = ibt_unbind_service(srv_hdl, sbp);
30240Sstevel@tonic-gate if (status != IBT_SUCCESS)
30250Sstevel@tonic-gate return (status);
30260Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
30270Sstevel@tonic-gate if (srv_hdl->svc_bind_list == NULL)
30280Sstevel@tonic-gate break;
30290Sstevel@tonic-gate }
30300Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
30310Sstevel@tonic-gate return (IBT_SUCCESS);
30320Sstevel@tonic-gate }
30330Sstevel@tonic-gate
30340Sstevel@tonic-gate /*
30350Sstevel@tonic-gate * ibt_deregister_service()
30360Sstevel@tonic-gate * Deregister a service with the IBCM
30370Sstevel@tonic-gate *
30380Sstevel@tonic-gate * INPUTS:
30390Sstevel@tonic-gate * ibt_hdl The IBT client handle returned to the client
30400Sstevel@tonic-gate * on an ibt_attach() call.
30410Sstevel@tonic-gate *
30420Sstevel@tonic-gate * srv_hdl The address of a service identification handle, used
30430Sstevel@tonic-gate * to de-register a service.
30440Sstevel@tonic-gate * RETURN VALUES:
30450Sstevel@tonic-gate * IBT_SUCCESS on success (or respective failure on error)
30460Sstevel@tonic-gate */
30470Sstevel@tonic-gate ibt_status_t
ibt_deregister_service(ibt_clnt_hdl_t ibt_hdl,ibt_srv_hdl_t srv_hdl)30480Sstevel@tonic-gate ibt_deregister_service(ibt_clnt_hdl_t ibt_hdl, ibt_srv_hdl_t srv_hdl)
30490Sstevel@tonic-gate {
30500Sstevel@tonic-gate ibcm_svc_info_t *svcp;
30510Sstevel@tonic-gate ibcm_svc_lookup_t svc;
30520Sstevel@tonic-gate
30539349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service(%p (%s), %p)",
30549349SShantkumar.Hiremath@Sun.COM ibt_hdl, ibtl_cm_get_clnt_name(ibt_hdl), srv_hdl);
30550Sstevel@tonic-gate
30560Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
30570Sstevel@tonic-gate
30580Sstevel@tonic-gate if (srv_hdl->svc_bind_list != NULL) {
30590Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service:"
30600Sstevel@tonic-gate " srv_hdl %p still has bindings", srv_hdl);
30610Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
30620Sstevel@tonic-gate return (IBT_CM_SERVICE_BUSY);
30630Sstevel@tonic-gate }
30640Sstevel@tonic-gate svc.sid = srv_hdl->svc_id;
30650Sstevel@tonic-gate svc.num_sids = 1;
3066401Shiremath IBTF_DPRINTF_L3(cmlog, "ibt_deregister_service: SID 0x%llX, numsids %d",
3067401Shiremath srv_hdl->svc_id, srv_hdl->svc_num_sids);
3068401Shiremath
30690Sstevel@tonic-gate #ifdef __lock_lint
30700Sstevel@tonic-gate ibcm_svc_compare(NULL, NULL);
30710Sstevel@tonic-gate #endif
30720Sstevel@tonic-gate svcp = avl_find(&ibcm_svc_avl_tree, &svc, NULL);
30730Sstevel@tonic-gate if (svcp != srv_hdl) {
30740Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
30750Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service(): "
30760Sstevel@tonic-gate "srv_hdl %p not found", srv_hdl);
30770Sstevel@tonic-gate return (IBT_INVALID_PARAM);
30780Sstevel@tonic-gate }
30790Sstevel@tonic-gate avl_remove(&ibcm_svc_avl_tree, svcp);
30800Sstevel@tonic-gate
30810Sstevel@tonic-gate /* wait for active REQ/SREQ handling to be done */
30820Sstevel@tonic-gate svcp->svc_to_delete = 1;
30830Sstevel@tonic-gate while (svcp->svc_ref_cnt != 0)
30840Sstevel@tonic-gate cv_wait(&ibcm_svc_info_cv, &ibcm_svc_info_lock);
30850Sstevel@tonic-gate
30860Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
30870Sstevel@tonic-gate
30880Sstevel@tonic-gate if ((srv_hdl->svc_id & IB_SID_AGN_MASK) == IB_SID_AGN_LOCAL)
30890Sstevel@tonic-gate ibcm_free_local_sids(srv_hdl->svc_id, srv_hdl->svc_num_sids);
30900Sstevel@tonic-gate
30910Sstevel@tonic-gate ibtl_cm_change_service_cnt(ibt_hdl, -srv_hdl->svc_num_sids);
30920Sstevel@tonic-gate kmem_free(srv_hdl, sizeof (*srv_hdl));
30930Sstevel@tonic-gate
30940Sstevel@tonic-gate /* If this message isn't seen then ibt_deregister_service failed */
30950Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service: done !!");
30960Sstevel@tonic-gate
30970Sstevel@tonic-gate return (IBT_SUCCESS);
30980Sstevel@tonic-gate }
30990Sstevel@tonic-gate
31000Sstevel@tonic-gate ibcm_status_t
ibcm_ar_init(void)31010Sstevel@tonic-gate ibcm_ar_init(void)
31020Sstevel@tonic-gate {
31030Sstevel@tonic-gate ib_svc_id_t sid = IBCM_DAPL_ATS_SID;
31040Sstevel@tonic-gate ibcm_svc_info_t *tmp_svcp;
31050Sstevel@tonic-gate
31060Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_ar_init()");
31070Sstevel@tonic-gate
31080Sstevel@tonic-gate /* remove this special SID from the pool of available SIDs */
31090Sstevel@tonic-gate if ((tmp_svcp = ibcm_create_svc_entry(sid, 1)) == NULL) {
31109349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibcm_ar_init: "
31110Sstevel@tonic-gate "DAPL ATS SID 0x%llx already registered", (longlong_t)sid);
31120Sstevel@tonic-gate return (IBCM_FAILURE);
31130Sstevel@tonic-gate }
31140Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
31150Sstevel@tonic-gate ibcm_ar_svcinfop = tmp_svcp;
31160Sstevel@tonic-gate ibcm_ar_list = NULL; /* no address records registered yet */
31170Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
31180Sstevel@tonic-gate return (IBCM_SUCCESS);
31190Sstevel@tonic-gate }
31200Sstevel@tonic-gate
31210Sstevel@tonic-gate ibcm_status_t
ibcm_ar_fini(void)31220Sstevel@tonic-gate ibcm_ar_fini(void)
31230Sstevel@tonic-gate {
31240Sstevel@tonic-gate ibcm_ar_t *ar_list;
31250Sstevel@tonic-gate ibcm_svc_info_t *tmp_svcp;
31260Sstevel@tonic-gate
31270Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
31280Sstevel@tonic-gate ar_list = ibcm_ar_list;
31290Sstevel@tonic-gate
31300Sstevel@tonic-gate if (ar_list == NULL &&
31310Sstevel@tonic-gate avl_numnodes(&ibcm_svc_avl_tree) == 1 &&
31320Sstevel@tonic-gate avl_first(&ibcm_svc_avl_tree) == ibcm_ar_svcinfop) {
31330Sstevel@tonic-gate avl_remove(&ibcm_svc_avl_tree, ibcm_ar_svcinfop);
31340Sstevel@tonic-gate tmp_svcp = ibcm_ar_svcinfop;
31350Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
31360Sstevel@tonic-gate kmem_free(tmp_svcp, sizeof (*ibcm_ar_svcinfop));
31370Sstevel@tonic-gate return (IBCM_SUCCESS);
31380Sstevel@tonic-gate }
31390Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
31400Sstevel@tonic-gate return (IBCM_FAILURE);
31410Sstevel@tonic-gate }
31420Sstevel@tonic-gate
31430Sstevel@tonic-gate
31440Sstevel@tonic-gate /*
31450Sstevel@tonic-gate * Return to the caller:
31460Sstevel@tonic-gate * IBT_SUCCESS Found a perfect match.
31470Sstevel@tonic-gate * *arpp is set to the record.
31480Sstevel@tonic-gate * IBT_INCONSISTENT_AR Found a record that's inconsistent.
31490Sstevel@tonic-gate * IBT_AR_NOT_REGISTERED Found no record with same GID/pkey and
31500Sstevel@tonic-gate * found no record with same data.
31510Sstevel@tonic-gate */
31520Sstevel@tonic-gate static ibt_status_t
ibcm_search_ar(ibt_ar_t * arp,ibcm_ar_t ** arpp)31530Sstevel@tonic-gate ibcm_search_ar(ibt_ar_t *arp, ibcm_ar_t **arpp)
31540Sstevel@tonic-gate {
31550Sstevel@tonic-gate ibcm_ar_t *tmp;
31560Sstevel@tonic-gate int i;
31570Sstevel@tonic-gate
31580Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibcm_svc_info_lock));
31590Sstevel@tonic-gate tmp = ibcm_ar_list;
31600Sstevel@tonic-gate while (tmp != NULL) {
31610Sstevel@tonic-gate if (tmp->ar.ar_gid.gid_prefix == arp->ar_gid.gid_prefix &&
31620Sstevel@tonic-gate tmp->ar.ar_gid.gid_guid == arp->ar_gid.gid_guid &&
31630Sstevel@tonic-gate tmp->ar.ar_pkey == arp->ar_pkey) {
31640Sstevel@tonic-gate for (i = 0; i < IBCM_DAPL_ATS_NBYTES; i++)
31650Sstevel@tonic-gate if (tmp->ar.ar_data[i] != arp->ar_data[i])
31660Sstevel@tonic-gate return (IBT_INCONSISTENT_AR);
31670Sstevel@tonic-gate *arpp = tmp;
31680Sstevel@tonic-gate return (IBT_SUCCESS);
31690Sstevel@tonic-gate } else {
31700Sstevel@tonic-gate /* if all the data bytes match, we have inconsistency */
31710Sstevel@tonic-gate for (i = 0; i < IBCM_DAPL_ATS_NBYTES; i++)
31720Sstevel@tonic-gate if (tmp->ar.ar_data[i] != arp->ar_data[i])
31730Sstevel@tonic-gate break;
31740Sstevel@tonic-gate if (i == IBCM_DAPL_ATS_NBYTES)
31750Sstevel@tonic-gate return (IBT_INCONSISTENT_AR);
31760Sstevel@tonic-gate /* try next address record */
31770Sstevel@tonic-gate }
31780Sstevel@tonic-gate tmp = tmp->ar_link;
31790Sstevel@tonic-gate }
31800Sstevel@tonic-gate return (IBT_AR_NOT_REGISTERED);
31810Sstevel@tonic-gate }
31820Sstevel@tonic-gate
31830Sstevel@tonic-gate ibt_status_t
ibt_register_ar(ibt_clnt_hdl_t ibt_hdl,ibt_ar_t * arp)31840Sstevel@tonic-gate ibt_register_ar(ibt_clnt_hdl_t ibt_hdl, ibt_ar_t *arp)
31850Sstevel@tonic-gate {
31860Sstevel@tonic-gate ibcm_ar_t *found;
31870Sstevel@tonic-gate ibcm_ar_t *tmp;
31880Sstevel@tonic-gate ibt_status_t status;
31890Sstevel@tonic-gate ibt_status_t s1, s2;
31900Sstevel@tonic-gate char *s;
31910Sstevel@tonic-gate ibcm_ar_ref_t *hdlp;
31920Sstevel@tonic-gate ibcm_ar_t *new;
31930Sstevel@tonic-gate ibcm_ar_t **linkp;
31940Sstevel@tonic-gate ibtl_cm_hca_port_t cm_port;
31950Sstevel@tonic-gate uint16_t pkey_ix;
31960Sstevel@tonic-gate ibcm_hca_info_t *hcap;
31970Sstevel@tonic-gate ibmf_saa_handle_t saa_handle;
31980Sstevel@tonic-gate sa_service_record_t *srv_recp;
31990Sstevel@tonic-gate uint64_t gid_ored;
32000Sstevel@tonic-gate
32019349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibt_register_ar: PKey 0x%X GID %llX:%llX",
32020Sstevel@tonic-gate arp->ar_pkey, (longlong_t)arp->ar_gid.gid_prefix,
32030Sstevel@tonic-gate (longlong_t)arp->ar_gid.gid_guid);
32040Sstevel@tonic-gate
32050Sstevel@tonic-gate /*
32060Sstevel@tonic-gate * If P_Key is 0, but GID is not, this query is invalid.
32070Sstevel@tonic-gate * If GID is 0, but P_Key is not, this query is invalid.
32080Sstevel@tonic-gate */
32090Sstevel@tonic-gate gid_ored = arp->ar_gid.gid_guid | arp->ar_gid.gid_prefix;
32100Sstevel@tonic-gate if ((arp->ar_pkey == 0 && gid_ored != 0ULL) ||
32110Sstevel@tonic-gate (arp->ar_pkey != 0 && gid_ored == 0ULL)) {
32120Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: "
32130Sstevel@tonic-gate "GID/P_Key is not valid");
32140Sstevel@tonic-gate return (IBT_INVALID_PARAM);
32150Sstevel@tonic-gate }
32160Sstevel@tonic-gate
32170Sstevel@tonic-gate /* assume success, so these might be needed */
32180Sstevel@tonic-gate hdlp = kmem_alloc(sizeof (*hdlp), KM_SLEEP);
32192974Srm78299 new = kmem_zalloc(sizeof (*new), KM_SLEEP);
32200Sstevel@tonic-gate
32210Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
32220Sstevel@tonic-gate /* search for existing GID/pkey (there can be at most 1) */
32230Sstevel@tonic-gate status = ibcm_search_ar(arp, &found);
32240Sstevel@tonic-gate if (status == IBT_INCONSISTENT_AR) {
32250Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
32260Sstevel@tonic-gate kmem_free(new, sizeof (*new));
32270Sstevel@tonic-gate kmem_free(hdlp, sizeof (*hdlp));
32280Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: "
32290Sstevel@tonic-gate "address record is inconsistent with a known one");
32300Sstevel@tonic-gate return (IBT_INCONSISTENT_AR);
32310Sstevel@tonic-gate } else if (status == IBT_SUCCESS) {
32320Sstevel@tonic-gate if (found->ar_flags == IBCM_AR_INITING) {
32330Sstevel@tonic-gate found->ar_waiters++;
32340Sstevel@tonic-gate cv_wait(&found->ar_cv, &ibcm_svc_info_lock);
32350Sstevel@tonic-gate found->ar_waiters--;
32360Sstevel@tonic-gate }
32370Sstevel@tonic-gate if (found->ar_flags == IBCM_AR_FAILED) {
32380Sstevel@tonic-gate if (found->ar_waiters == 0) {
32390Sstevel@tonic-gate cv_destroy(&found->ar_cv);
32400Sstevel@tonic-gate kmem_free(found, sizeof (*found));
32410Sstevel@tonic-gate }
32420Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
32430Sstevel@tonic-gate kmem_free(new, sizeof (*new));
32440Sstevel@tonic-gate kmem_free(hdlp, sizeof (*hdlp));
32450Sstevel@tonic-gate return (ibt_get_module_failure(IBT_FAILURE_IBCM, 0));
32460Sstevel@tonic-gate }
32470Sstevel@tonic-gate hdlp->ar_ibt_hdl = ibt_hdl;
32480Sstevel@tonic-gate hdlp->ar_ref_link = found->ar_ibt_hdl_list;
32490Sstevel@tonic-gate found->ar_ibt_hdl_list = hdlp;
32500Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
32510Sstevel@tonic-gate kmem_free(new, sizeof (*new));
32520Sstevel@tonic-gate ibtl_cm_change_service_cnt(ibt_hdl, 1);
32530Sstevel@tonic-gate return (IBT_SUCCESS);
32540Sstevel@tonic-gate } else {
32550Sstevel@tonic-gate ASSERT(status == IBT_AR_NOT_REGISTERED);
32560Sstevel@tonic-gate }
32570Sstevel@tonic-gate hdlp->ar_ref_link = NULL;
32580Sstevel@tonic-gate hdlp->ar_ibt_hdl = ibt_hdl;
32590Sstevel@tonic-gate new->ar_ibt_hdl_list = hdlp;
32600Sstevel@tonic-gate new->ar = *arp;
32610Sstevel@tonic-gate new->ar_flags = IBCM_AR_INITING;
32620Sstevel@tonic-gate new->ar_waiters = 0;
32630Sstevel@tonic-gate cv_init(&new->ar_cv, NULL, CV_DEFAULT, NULL);
32640Sstevel@tonic-gate new->ar_link = ibcm_ar_list;
32650Sstevel@tonic-gate ibcm_ar_list = new;
32660Sstevel@tonic-gate
32670Sstevel@tonic-gate /* verify GID/pkey is valid for a local port, etc. */
32680Sstevel@tonic-gate hcap = NULL;
32690Sstevel@tonic-gate if ((s1 = ibtl_cm_get_hca_port(arp->ar_gid, 0, &cm_port))
32704703Shiremath != IBT_SUCCESS ||
32710Sstevel@tonic-gate (s2 = ibt_pkey2index_byguid(cm_port.hp_hca_guid, cm_port.hp_port,
32724703Shiremath arp->ar_pkey, &pkey_ix)) != IBT_SUCCESS ||
32730Sstevel@tonic-gate (hcap = ibcm_find_hca_entry(cm_port.hp_hca_guid)) == NULL) {
32740Sstevel@tonic-gate cv_destroy(&new->ar_cv);
32750Sstevel@tonic-gate ibcm_ar_list = new->ar_link;
32760Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
32770Sstevel@tonic-gate kmem_free(new, sizeof (*new));
32780Sstevel@tonic-gate kmem_free(hdlp, sizeof (*hdlp));
32790Sstevel@tonic-gate status = IBT_INVALID_PARAM;
32800Sstevel@tonic-gate if (s1 == IBT_HCA_PORT_NOT_ACTIVE) {
32810Sstevel@tonic-gate s = "PORT DOWN";
32820Sstevel@tonic-gate status = IBT_HCA_PORT_NOT_ACTIVE;
32830Sstevel@tonic-gate } else if (s1 != IBT_SUCCESS)
32840Sstevel@tonic-gate s = "GID not found";
32850Sstevel@tonic-gate else if (s2 != IBT_SUCCESS)
32860Sstevel@tonic-gate s = "PKEY not found";
32870Sstevel@tonic-gate else
32880Sstevel@tonic-gate s = "CM could not find its HCA entry";
32890Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: %s, status = %d",
32900Sstevel@tonic-gate s, status);
32910Sstevel@tonic-gate return (status);
32920Sstevel@tonic-gate }
32930Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
32940Sstevel@tonic-gate saa_handle = ibcm_get_saa_handle(hcap, cm_port.hp_port);
32950Sstevel@tonic-gate
32960Sstevel@tonic-gate /* create service record */
32970Sstevel@tonic-gate srv_recp = kmem_zalloc(sizeof (*srv_recp), KM_SLEEP);
32980Sstevel@tonic-gate srv_recp->ServiceLease = 0xFFFFFFFF; /* infinite */
32990Sstevel@tonic-gate srv_recp->ServiceP_Key = arp->ar_pkey;
33000Sstevel@tonic-gate srv_recp->ServiceKey_hi = 0xDA410000ULL; /* DAPL */
33010Sstevel@tonic-gate srv_recp->ServiceKey_lo = 0xA7500000ULL; /* ATS */
33020Sstevel@tonic-gate (void) strcpy((char *)srv_recp->ServiceName, IBCM_DAPL_ATS_NAME);
33030Sstevel@tonic-gate srv_recp->ServiceGID = arp->ar_gid;
33040Sstevel@tonic-gate bcopy(arp->ar_data, srv_recp->ServiceData, IBCM_DAPL_ATS_NBYTES);
33050Sstevel@tonic-gate srv_recp->ServiceID = IBCM_DAPL_ATS_SID;
33060Sstevel@tonic-gate
33070Sstevel@tonic-gate /* insert service record into the SA */
33080Sstevel@tonic-gate
33090Sstevel@tonic-gate IBCM_DUMP_SERVICE_REC(srv_recp);
33100Sstevel@tonic-gate
33110Sstevel@tonic-gate if (saa_handle != NULL)
33120Sstevel@tonic-gate status = ibcm_write_service_record(saa_handle, srv_recp,
33130Sstevel@tonic-gate IBMF_SAA_UPDATE);
33140Sstevel@tonic-gate else
33150Sstevel@tonic-gate status = IBT_HCA_PORT_NOT_ACTIVE;
33160Sstevel@tonic-gate
33170Sstevel@tonic-gate if (status != IBT_SUCCESS) {
33180Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: sa access fails %d, "
33190Sstevel@tonic-gate "sid %llX", status, (longlong_t)srv_recp->ServiceID);
33200Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: FAILED for gid "
33210Sstevel@tonic-gate "%llX:%llX pkey 0x%X", (longlong_t)arp->ar_gid.gid_prefix,
33220Sstevel@tonic-gate (longlong_t)arp->ar_gid.gid_guid, arp->ar_pkey);
33230Sstevel@tonic-gate
33240Sstevel@tonic-gate kmem_free(srv_recp, sizeof (*srv_recp));
33250Sstevel@tonic-gate kmem_free(hdlp, sizeof (*hdlp));
33260Sstevel@tonic-gate
33270Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
33280Sstevel@tonic-gate linkp = &ibcm_ar_list;
33290Sstevel@tonic-gate tmp = *linkp;
33300Sstevel@tonic-gate while (tmp != NULL) {
33310Sstevel@tonic-gate if (tmp == new) {
33320Sstevel@tonic-gate *linkp = new->ar_link;
33330Sstevel@tonic-gate break;
33340Sstevel@tonic-gate }
33350Sstevel@tonic-gate linkp = &tmp->ar_link;
33360Sstevel@tonic-gate tmp = *linkp;
33370Sstevel@tonic-gate }
33380Sstevel@tonic-gate if (new->ar_waiters > 0) {
33390Sstevel@tonic-gate new->ar_flags = IBCM_AR_FAILED;
33400Sstevel@tonic-gate cv_broadcast(&new->ar_cv);
33410Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
33420Sstevel@tonic-gate } else {
33430Sstevel@tonic-gate cv_destroy(&new->ar_cv);
33440Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
33450Sstevel@tonic-gate kmem_free(new, sizeof (*new));
33460Sstevel@tonic-gate }
33470Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
33480Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: "
33490Sstevel@tonic-gate "IBMF_SAA failed to write address record");
33500Sstevel@tonic-gate } else { /* SUCCESS */
33510Sstevel@tonic-gate uint8_t *b;
33520Sstevel@tonic-gate
33539349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibt_register_ar: SUCCESS for gid "
33540Sstevel@tonic-gate "%llx:%llx pkey %x", (longlong_t)arp->ar_gid.gid_prefix,
33550Sstevel@tonic-gate (longlong_t)arp->ar_gid.gid_guid, arp->ar_pkey);
33560Sstevel@tonic-gate b = arp->ar_data;
33570Sstevel@tonic-gate
33589349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibt_register_ar:"
33590Sstevel@tonic-gate " data %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
33600Sstevel@tonic-gate b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9],
33610Sstevel@tonic-gate b[10], b[11], b[12], b[13], b[14], b[15]);
33620Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
33630Sstevel@tonic-gate new->ar_srv_recp = srv_recp;
33640Sstevel@tonic-gate new->ar_saa_handle = saa_handle;
33650Sstevel@tonic-gate new->ar_port = cm_port.hp_port;
33660Sstevel@tonic-gate new->ar_hcap = hcap;
33670Sstevel@tonic-gate new->ar_flags = IBCM_AR_SUCCESS;
33680Sstevel@tonic-gate if (new->ar_waiters > 0)
33690Sstevel@tonic-gate cv_broadcast(&new->ar_cv);
33700Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
33710Sstevel@tonic-gate ibtl_cm_change_service_cnt(ibt_hdl, 1);
33720Sstevel@tonic-gate /* do not call ibcm_dec_hca_acc_cnt(hcap) until deregister */
33730Sstevel@tonic-gate }
33740Sstevel@tonic-gate return (status);
33750Sstevel@tonic-gate }
33760Sstevel@tonic-gate
33770Sstevel@tonic-gate ibt_status_t
ibt_deregister_ar(ibt_clnt_hdl_t ibt_hdl,ibt_ar_t * arp)33780Sstevel@tonic-gate ibt_deregister_ar(ibt_clnt_hdl_t ibt_hdl, ibt_ar_t *arp)
33790Sstevel@tonic-gate {
33800Sstevel@tonic-gate ibcm_ar_t *found;
33810Sstevel@tonic-gate ibcm_ar_t *tmp;
33820Sstevel@tonic-gate ibcm_ar_t **linkp;
33830Sstevel@tonic-gate ibcm_ar_ref_t *hdlp;
33840Sstevel@tonic-gate ibcm_ar_ref_t **hdlpp;
33850Sstevel@tonic-gate ibt_status_t status;
33860Sstevel@tonic-gate ibmf_saa_handle_t saa_handle;
33870Sstevel@tonic-gate sa_service_record_t *srv_recp;
33880Sstevel@tonic-gate uint64_t gid_ored;
33890Sstevel@tonic-gate
33909349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibt_deregister_ar: pkey %x", arp->ar_pkey);
33919349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibt_deregister_ar: gid %llx:%llx",
33920Sstevel@tonic-gate (longlong_t)arp->ar_gid.gid_prefix,
33930Sstevel@tonic-gate (longlong_t)arp->ar_gid.gid_guid);
33940Sstevel@tonic-gate
33950Sstevel@tonic-gate /*
33960Sstevel@tonic-gate * If P_Key is 0, but GID is not, this query is invalid.
33970Sstevel@tonic-gate * If GID is 0, but P_Key is not, this query is invalid.
33980Sstevel@tonic-gate */
33990Sstevel@tonic-gate gid_ored = arp->ar_gid.gid_guid | arp->ar_gid.gid_prefix;
34000Sstevel@tonic-gate if ((arp->ar_pkey == 0 && gid_ored != 0ULL) ||
34010Sstevel@tonic-gate (arp->ar_pkey != 0 && gid_ored == 0ULL)) {
34020Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
34030Sstevel@tonic-gate "GID/P_Key is not valid");
34040Sstevel@tonic-gate return (IBT_INVALID_PARAM);
34050Sstevel@tonic-gate }
34060Sstevel@tonic-gate
34070Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
34080Sstevel@tonic-gate /* search for existing GID/pkey (there can be at most 1) */
34090Sstevel@tonic-gate status = ibcm_search_ar(arp, &found);
34100Sstevel@tonic-gate if (status == IBT_INCONSISTENT_AR || status == IBT_AR_NOT_REGISTERED) {
34110Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
34120Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
34130Sstevel@tonic-gate "address record not found");
34140Sstevel@tonic-gate return (IBT_AR_NOT_REGISTERED);
34150Sstevel@tonic-gate }
34160Sstevel@tonic-gate ASSERT(status == IBT_SUCCESS);
34170Sstevel@tonic-gate
34180Sstevel@tonic-gate hdlpp = &found->ar_ibt_hdl_list;
34190Sstevel@tonic-gate hdlp = *hdlpp;
34200Sstevel@tonic-gate while (hdlp != NULL) {
34210Sstevel@tonic-gate if (hdlp->ar_ibt_hdl == ibt_hdl)
34220Sstevel@tonic-gate break;
34230Sstevel@tonic-gate hdlpp = &hdlp->ar_ref_link;
34240Sstevel@tonic-gate hdlp = *hdlpp;
34250Sstevel@tonic-gate }
34260Sstevel@tonic-gate if (hdlp == NULL) { /* could not find ibt_hdl on list */
34270Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
34280Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
34290Sstevel@tonic-gate "address record found, but not for this client");
34300Sstevel@tonic-gate return (IBT_AR_NOT_REGISTERED);
34310Sstevel@tonic-gate }
34320Sstevel@tonic-gate *hdlpp = hdlp->ar_ref_link; /* remove ref for this client */
34330Sstevel@tonic-gate if (found->ar_ibt_hdl_list == NULL && found->ar_waiters == 0) {
34340Sstevel@tonic-gate /* last entry was removed */
34350Sstevel@tonic-gate found->ar_flags = IBCM_AR_INITING; /* hold off register_ar */
34360Sstevel@tonic-gate saa_handle = found->ar_saa_handle;
34370Sstevel@tonic-gate srv_recp = found->ar_srv_recp;
34380Sstevel@tonic-gate
34390Sstevel@tonic-gate /* wait if this service record is being rewritten */
34400Sstevel@tonic-gate while (found->ar_rewrite_state == IBCM_REWRITE_BUSY)
34410Sstevel@tonic-gate cv_wait(&ibcm_svc_info_cv, &ibcm_svc_info_lock);
34420Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
34430Sstevel@tonic-gate
34440Sstevel@tonic-gate /* remove service record */
34450Sstevel@tonic-gate status = ibcm_write_service_record(saa_handle, srv_recp,
34460Sstevel@tonic-gate IBMF_SAA_DELETE);
34470Sstevel@tonic-gate if (status != IBT_SUCCESS)
34480Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
34490Sstevel@tonic-gate "IBMF_SAA failed to delete address record");
34500Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
34510Sstevel@tonic-gate if (found->ar_waiters == 0) { /* still no waiters */
34520Sstevel@tonic-gate linkp = &ibcm_ar_list;
34530Sstevel@tonic-gate tmp = *linkp;
34540Sstevel@tonic-gate while (tmp != found) {
34550Sstevel@tonic-gate linkp = &tmp->ar_link;
34560Sstevel@tonic-gate tmp = *linkp;
34570Sstevel@tonic-gate }
34580Sstevel@tonic-gate *linkp = tmp->ar_link;
34590Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(found->ar_hcap);
34600Sstevel@tonic-gate kmem_free(srv_recp, sizeof (*srv_recp));
34610Sstevel@tonic-gate cv_destroy(&found->ar_cv);
34620Sstevel@tonic-gate kmem_free(found, sizeof (*found));
34630Sstevel@tonic-gate } else {
34640Sstevel@tonic-gate /* add service record back in for the waiters */
34650Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
34660Sstevel@tonic-gate status = ibcm_write_service_record(saa_handle, srv_recp,
34670Sstevel@tonic-gate IBMF_SAA_UPDATE);
34680Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
34690Sstevel@tonic-gate if (status == IBT_SUCCESS)
34700Sstevel@tonic-gate found->ar_flags = IBCM_AR_SUCCESS;
34710Sstevel@tonic-gate else {
34720Sstevel@tonic-gate found->ar_flags = IBCM_AR_FAILED;
34730Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
34740Sstevel@tonic-gate "IBMF_SAA failed to write address record");
34750Sstevel@tonic-gate }
34760Sstevel@tonic-gate cv_broadcast(&found->ar_cv);
34770Sstevel@tonic-gate }
34780Sstevel@tonic-gate }
34790Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
34800Sstevel@tonic-gate kmem_free(hdlp, sizeof (*hdlp));
34810Sstevel@tonic-gate ibtl_cm_change_service_cnt(ibt_hdl, -1);
34820Sstevel@tonic-gate return (status);
34830Sstevel@tonic-gate }
34840Sstevel@tonic-gate
34850Sstevel@tonic-gate ibt_status_t
ibt_query_ar(ib_gid_t * sgid,ibt_ar_t * queryp,ibt_ar_t * resultp)34860Sstevel@tonic-gate ibt_query_ar(ib_gid_t *sgid, ibt_ar_t *queryp, ibt_ar_t *resultp)
34870Sstevel@tonic-gate {
34880Sstevel@tonic-gate sa_service_record_t svcrec_req;
34890Sstevel@tonic-gate sa_service_record_t *svcrec_resp;
34900Sstevel@tonic-gate void *results_p;
34910Sstevel@tonic-gate uint64_t component_mask = 0;
34920Sstevel@tonic-gate uint64_t gid_ored;
34930Sstevel@tonic-gate size_t length;
34940Sstevel@tonic-gate int num_rec;
34950Sstevel@tonic-gate int i;
34960Sstevel@tonic-gate ibmf_saa_access_args_t access_args;
34970Sstevel@tonic-gate ibt_status_t retval;
34980Sstevel@tonic-gate ibtl_cm_hca_port_t cm_port;
34990Sstevel@tonic-gate ibcm_hca_info_t *hcap;
35000Sstevel@tonic-gate ibmf_saa_handle_t saa_handle;
35010Sstevel@tonic-gate
35020Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_query_ar(%p, %p)", queryp, resultp);
35030Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: sgid %llx:%llx",
35040Sstevel@tonic-gate (longlong_t)sgid->gid_prefix, (longlong_t)sgid->gid_guid);
35050Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: query_pkey %x", queryp->ar_pkey);
35060Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: query_gid %llx:%llx",
35070Sstevel@tonic-gate (longlong_t)queryp->ar_gid.gid_prefix,
35080Sstevel@tonic-gate (longlong_t)queryp->ar_gid.gid_guid);
35090Sstevel@tonic-gate
35100Sstevel@tonic-gate /*
35110Sstevel@tonic-gate * If P_Key is 0, but GID is not, this query is invalid.
35120Sstevel@tonic-gate * If GID is 0, but P_Key is not, this query is invalid.
35130Sstevel@tonic-gate */
35140Sstevel@tonic-gate gid_ored = queryp->ar_gid.gid_guid | queryp->ar_gid.gid_prefix;
35150Sstevel@tonic-gate if ((queryp->ar_pkey == 0 && gid_ored != 0ULL) ||
35160Sstevel@tonic-gate (queryp->ar_pkey != 0 && gid_ored == 0ULL)) {
35170Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_query_ar: GID/P_Key is not valid");
35180Sstevel@tonic-gate return (IBT_INVALID_PARAM);
35190Sstevel@tonic-gate }
35200Sstevel@tonic-gate
35210Sstevel@tonic-gate hcap = NULL;
35220Sstevel@tonic-gate if (ibtl_cm_get_hca_port(*sgid, 0, &cm_port) != IBT_SUCCESS ||
35230Sstevel@tonic-gate (hcap = ibcm_find_hca_entry(cm_port.hp_hca_guid)) == NULL ||
35240Sstevel@tonic-gate (saa_handle = ibcm_get_saa_handle(hcap, cm_port.hp_port)) == NULL) {
35250Sstevel@tonic-gate if (hcap != NULL)
35260Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
35270Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_query_ar: sgid is not valid");
35280Sstevel@tonic-gate return (IBT_INVALID_PARAM);
35290Sstevel@tonic-gate }
35300Sstevel@tonic-gate
35310Sstevel@tonic-gate bzero(&svcrec_req, sizeof (svcrec_req));
35320Sstevel@tonic-gate
35330Sstevel@tonic-gate /* Is GID/P_Key Specified. */
35340Sstevel@tonic-gate if (queryp->ar_pkey != 0) { /* GID is non-zero from check above */
35350Sstevel@tonic-gate svcrec_req.ServiceP_Key = queryp->ar_pkey;
35360Sstevel@tonic-gate component_mask |= SA_SR_COMPMASK_PKEY;
35370Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: P_Key %X",
35380Sstevel@tonic-gate queryp->ar_pkey);
35390Sstevel@tonic-gate svcrec_req.ServiceGID = queryp->ar_gid;
35400Sstevel@tonic-gate component_mask |= SA_SR_COMPMASK_GID;
35410Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: GID %llX:%llX",
35420Sstevel@tonic-gate (longlong_t)queryp->ar_gid.gid_prefix,
35430Sstevel@tonic-gate (longlong_t)queryp->ar_gid.gid_guid);
35440Sstevel@tonic-gate }
35450Sstevel@tonic-gate
35460Sstevel@tonic-gate /* Is ServiceData Specified. */
35470Sstevel@tonic-gate for (i = 0; i < IBCM_DAPL_ATS_NBYTES; i++) {
35480Sstevel@tonic-gate if (queryp->ar_data[i] != 0) {
35490Sstevel@tonic-gate bcopy(queryp->ar_data, svcrec_req.ServiceData,
35500Sstevel@tonic-gate IBCM_DAPL_ATS_NBYTES);
35510Sstevel@tonic-gate component_mask |= 0xFFFF << 7; /* all 16 Data8 */
35520Sstevel@tonic-gate /* components */
35530Sstevel@tonic-gate break;
35540Sstevel@tonic-gate }
35550Sstevel@tonic-gate }
35560Sstevel@tonic-gate
35570Sstevel@tonic-gate /* Service Name */
35580Sstevel@tonic-gate (void) strcpy((char *)svcrec_req.ServiceName, IBCM_DAPL_ATS_NAME);
35590Sstevel@tonic-gate component_mask |= SA_SR_COMPMASK_NAME;
35600Sstevel@tonic-gate
35610Sstevel@tonic-gate svcrec_req.ServiceID = IBCM_DAPL_ATS_SID;
35620Sstevel@tonic-gate component_mask |= SA_SR_COMPMASK_ID;
35630Sstevel@tonic-gate
35640Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: "
35650Sstevel@tonic-gate "Perform SA Access: Mask: 0x%X", component_mask);
35660Sstevel@tonic-gate
35670Sstevel@tonic-gate /*
35680Sstevel@tonic-gate * Call in SA Access retrieve routine to get Service Records.
35690Sstevel@tonic-gate *
35700Sstevel@tonic-gate * SA Access framework allocated memory for the "results_p".
35710Sstevel@tonic-gate * Make sure to deallocate once we are done with the results_p.
35720Sstevel@tonic-gate * The size of the buffer allocated will be as returned in
35730Sstevel@tonic-gate * "length" field.
35740Sstevel@tonic-gate */
35750Sstevel@tonic-gate access_args.sq_attr_id = SA_SERVICERECORD_ATTRID;
35760Sstevel@tonic-gate access_args.sq_access_type = IBMF_SAA_RETRIEVE;
35770Sstevel@tonic-gate access_args.sq_component_mask = component_mask;
35780Sstevel@tonic-gate access_args.sq_template = &svcrec_req;
35790Sstevel@tonic-gate access_args.sq_template_length = sizeof (sa_service_record_t);
35800Sstevel@tonic-gate access_args.sq_callback = NULL;
35810Sstevel@tonic-gate access_args.sq_callback_arg = NULL;
35820Sstevel@tonic-gate
35830Sstevel@tonic-gate retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
35840Sstevel@tonic-gate &results_p);
35850Sstevel@tonic-gate
35860Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
35870Sstevel@tonic-gate if (retval != IBT_SUCCESS) {
35880Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_query_ar: SA Access Failed");
35890Sstevel@tonic-gate return (retval);
35900Sstevel@tonic-gate }
35910Sstevel@tonic-gate
35920Sstevel@tonic-gate num_rec = length / sizeof (sa_service_record_t);
35930Sstevel@tonic-gate
35940Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: "
35950Sstevel@tonic-gate "Found %d Service Records.", num_rec);
35960Sstevel@tonic-gate
35970Sstevel@tonic-gate /* Validate the returned number of records. */
35980Sstevel@tonic-gate if ((results_p != NULL) && (num_rec > 0)) {
35990Sstevel@tonic-gate uint8_t *b;
36000Sstevel@tonic-gate
36010Sstevel@tonic-gate /* Just return info from the first service record. */
36020Sstevel@tonic-gate svcrec_resp = (sa_service_record_t *)results_p;
36030Sstevel@tonic-gate
36040Sstevel@tonic-gate /* The Service GID and Service ID */
36050Sstevel@tonic-gate resultp->ar_gid = svcrec_resp->ServiceGID;
36060Sstevel@tonic-gate resultp->ar_pkey = svcrec_resp->ServiceP_Key;
36070Sstevel@tonic-gate bcopy(svcrec_resp->ServiceData,
36080Sstevel@tonic-gate resultp->ar_data, IBCM_DAPL_ATS_NBYTES);
36090Sstevel@tonic-gate
36109349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: "
36110Sstevel@tonic-gate "Found: pkey %x dgid %llX:%llX", resultp->ar_pkey,
36120Sstevel@tonic-gate (longlong_t)resultp->ar_gid.gid_prefix,
36130Sstevel@tonic-gate (longlong_t)resultp->ar_gid.gid_guid);
36140Sstevel@tonic-gate b = resultp->ar_data;
36159349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibt_query_ar:"
36160Sstevel@tonic-gate " data %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
36170Sstevel@tonic-gate b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9],
36180Sstevel@tonic-gate b[10], b[11], b[12], b[13], b[14], b[15]);
36190Sstevel@tonic-gate
36200Sstevel@tonic-gate /* Deallocate the memory for results_p. */
36210Sstevel@tonic-gate kmem_free(results_p, length);
36220Sstevel@tonic-gate if (num_rec > 1)
36230Sstevel@tonic-gate retval = IBT_MULTIPLE_AR;
36240Sstevel@tonic-gate else
36250Sstevel@tonic-gate retval = IBT_SUCCESS;
36260Sstevel@tonic-gate } else {
36270Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_query_ar: "
36280Sstevel@tonic-gate "ibmf_sa_access found 0 matching records");
36290Sstevel@tonic-gate retval = IBT_AR_NOT_REGISTERED;
36300Sstevel@tonic-gate }
36310Sstevel@tonic-gate return (retval);
36320Sstevel@tonic-gate }
36330Sstevel@tonic-gate
36340Sstevel@tonic-gate /* mark all ATS service records associated with the port */
36350Sstevel@tonic-gate static void
ibcm_mark_ar(ib_guid_t hca_guid,uint8_t port)36360Sstevel@tonic-gate ibcm_mark_ar(ib_guid_t hca_guid, uint8_t port)
36370Sstevel@tonic-gate {
36380Sstevel@tonic-gate ibcm_ar_t *tmp;
36390Sstevel@tonic-gate
36400Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibcm_svc_info_lock));
36410Sstevel@tonic-gate for (tmp = ibcm_ar_list; tmp != NULL; tmp = tmp->ar_link) {
36425724Sagiri if (tmp->ar_hcap == NULL)
36435724Sagiri continue;
36440Sstevel@tonic-gate if (tmp->ar_hcap->hca_guid == hca_guid &&
36450Sstevel@tonic-gate tmp->ar_port == port) {
36460Sstevel@tonic-gate /* even if it's busy, we mark it for rewrite */
36470Sstevel@tonic-gate tmp->ar_rewrite_state = IBCM_REWRITE_NEEDED;
36480Sstevel@tonic-gate }
36490Sstevel@tonic-gate }
36500Sstevel@tonic-gate }
36510Sstevel@tonic-gate
36520Sstevel@tonic-gate /* rewrite all ATS service records */
36530Sstevel@tonic-gate static int
ibcm_rewrite_ar(void)36540Sstevel@tonic-gate ibcm_rewrite_ar(void)
36550Sstevel@tonic-gate {
36560Sstevel@tonic-gate ibcm_ar_t *tmp;
36570Sstevel@tonic-gate ibmf_saa_handle_t saa_handle;
36580Sstevel@tonic-gate sa_service_record_t *srv_recp;
36590Sstevel@tonic-gate ibt_status_t rval;
36600Sstevel@tonic-gate int did_something = 0;
36610Sstevel@tonic-gate
36620Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibcm_svc_info_lock));
36630Sstevel@tonic-gate check_for_work:
36640Sstevel@tonic-gate for (tmp = ibcm_ar_list; tmp != NULL; tmp = tmp->ar_link) {
36650Sstevel@tonic-gate if (tmp->ar_rewrite_state == IBCM_REWRITE_NEEDED) {
36660Sstevel@tonic-gate tmp->ar_rewrite_state = IBCM_REWRITE_BUSY;
36670Sstevel@tonic-gate saa_handle = tmp->ar_saa_handle;
36680Sstevel@tonic-gate srv_recp = tmp->ar_srv_recp;
36690Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
36700Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_rewrite_ar: "
36710Sstevel@tonic-gate "rewriting ar @ %p", tmp);
36720Sstevel@tonic-gate did_something = 1;
36730Sstevel@tonic-gate rval = ibcm_write_service_record(saa_handle, srv_recp,
36740Sstevel@tonic-gate IBMF_SAA_UPDATE);
36750Sstevel@tonic-gate if (rval != IBT_SUCCESS)
36760Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_rewrite_ar: "
36770Sstevel@tonic-gate "ibcm_write_service_record failed: "
36780Sstevel@tonic-gate "status = %d", rval);
36790Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
36800Sstevel@tonic-gate /* if it got marked again, then we want to rewrite */
36810Sstevel@tonic-gate if (tmp->ar_rewrite_state == IBCM_REWRITE_BUSY)
36820Sstevel@tonic-gate tmp->ar_rewrite_state = IBCM_REWRITE_IDLE;
36830Sstevel@tonic-gate /* in case there was a waiter... */
36840Sstevel@tonic-gate cv_broadcast(&ibcm_svc_info_cv);
36850Sstevel@tonic-gate goto check_for_work;
36860Sstevel@tonic-gate }
36870Sstevel@tonic-gate }
36880Sstevel@tonic-gate return (did_something);
36890Sstevel@tonic-gate }
36900Sstevel@tonic-gate
36910Sstevel@tonic-gate static void
ibcm_rewrite_svc_record(ibcm_svc_info_t * srv_hdl,ibcm_svc_bind_t * sbindp)36920Sstevel@tonic-gate ibcm_rewrite_svc_record(ibcm_svc_info_t *srv_hdl, ibcm_svc_bind_t *sbindp)
36930Sstevel@tonic-gate {
36940Sstevel@tonic-gate ibcm_hca_info_t *hcap;
36950Sstevel@tonic-gate ib_svc_id_t sid, start_sid, end_sid;
36960Sstevel@tonic-gate ibmf_saa_handle_t saa_handle;
36970Sstevel@tonic-gate sa_service_record_t srv_rec;
36980Sstevel@tonic-gate ibt_status_t rval;
36990Sstevel@tonic-gate
37000Sstevel@tonic-gate hcap = ibcm_find_hca_entry(sbindp->sbind_hcaguid);
37010Sstevel@tonic-gate if (hcap == NULL) {
37020Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_rewrite_svc_record: "
37030Sstevel@tonic-gate "NO HCA found for HCA GUID %llX", sbindp->sbind_hcaguid);
37040Sstevel@tonic-gate return;
37050Sstevel@tonic-gate }
37060Sstevel@tonic-gate
37070Sstevel@tonic-gate saa_handle = ibcm_get_saa_handle(hcap, sbindp->sbind_port);
37080Sstevel@tonic-gate if (saa_handle == NULL) {
37090Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_rewrite_svc_record: "
37100Sstevel@tonic-gate "saa_handle is NULL");
37110Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
37120Sstevel@tonic-gate return;
37130Sstevel@tonic-gate }
37140Sstevel@tonic-gate
37150Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_rewrite_svc_record: "
37160Sstevel@tonic-gate "rewriting svc '%s', port_guid = %llX", sbindp->sbind_name,
37170Sstevel@tonic-gate sbindp->sbind_gid.gid_guid);
37180Sstevel@tonic-gate
37190Sstevel@tonic-gate bzero(&srv_rec, sizeof (srv_rec));
37200Sstevel@tonic-gate
37210Sstevel@tonic-gate srv_rec.ServiceLease = sbindp->sbind_lease;
37220Sstevel@tonic-gate srv_rec.ServiceP_Key = sbindp->sbind_pkey;
37230Sstevel@tonic-gate srv_rec.ServiceKey_hi = sbindp->sbind_key[0];
37240Sstevel@tonic-gate srv_rec.ServiceKey_lo = sbindp->sbind_key[1];
37250Sstevel@tonic-gate (void) strcpy((char *)srv_rec.ServiceName, sbindp->sbind_name);
37260Sstevel@tonic-gate srv_rec.ServiceGID = sbindp->sbind_gid;
37270Sstevel@tonic-gate
37280Sstevel@tonic-gate bcopy(sbindp->sbind_data, srv_rec.ServiceData, IB_SVC_DATA_LEN);
37290Sstevel@tonic-gate
37300Sstevel@tonic-gate /* insert srv record into the SA */
37310Sstevel@tonic-gate start_sid = srv_hdl->svc_id;
37320Sstevel@tonic-gate end_sid = start_sid + srv_hdl->svc_num_sids - 1;
37330Sstevel@tonic-gate for (sid = start_sid; sid <= end_sid; sid++) {
37340Sstevel@tonic-gate srv_rec.ServiceID = sid;
37350Sstevel@tonic-gate
37360Sstevel@tonic-gate rval = ibcm_write_service_record(saa_handle, &srv_rec,
37370Sstevel@tonic-gate IBMF_SAA_UPDATE);
37380Sstevel@tonic-gate
37390Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_rewrite_svc_record: "
37400Sstevel@tonic-gate "ibcm_write_service_record, SvcId = %llX, "
37410Sstevel@tonic-gate "rval = %d", (longlong_t)sid, rval);
37420Sstevel@tonic-gate if (rval != IBT_SUCCESS) {
37430Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_rewrite_svc_record:"
37440Sstevel@tonic-gate " ibcm_write_service_record fails %d sid %llX",
37450Sstevel@tonic-gate rval, (longlong_t)sid);
37460Sstevel@tonic-gate }
37470Sstevel@tonic-gate }
37480Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
37490Sstevel@tonic-gate }
37500Sstevel@tonic-gate
37510Sstevel@tonic-gate /*
37520Sstevel@tonic-gate * Task to mark all service records as needing to be rewritten to the SM/SA.
37530Sstevel@tonic-gate * This task does not return until all of them have been rewritten.
37540Sstevel@tonic-gate */
37550Sstevel@tonic-gate void
ibcm_service_record_rewrite_task(void * arg)37560Sstevel@tonic-gate ibcm_service_record_rewrite_task(void *arg)
37570Sstevel@tonic-gate {
37580Sstevel@tonic-gate ibcm_port_up_t *pup = (ibcm_port_up_t *)arg;
37590Sstevel@tonic-gate ib_guid_t hca_guid = pup->pup_hca_guid;
37600Sstevel@tonic-gate uint8_t port = pup->pup_port;
37610Sstevel@tonic-gate ibcm_svc_info_t *svcp;
37620Sstevel@tonic-gate ibcm_svc_bind_t *sbp;
37630Sstevel@tonic-gate avl_tree_t *avl_tree = &ibcm_svc_avl_tree;
37640Sstevel@tonic-gate static int task_is_running = 0;
37650Sstevel@tonic-gate
37669349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibcm_service_record_rewrite_task STARTED "
37670Sstevel@tonic-gate "for hca_guid %llX, port %d", hca_guid, port);
37680Sstevel@tonic-gate
37690Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
37700Sstevel@tonic-gate ibcm_mark_ar(hca_guid, port);
37710Sstevel@tonic-gate for (svcp = avl_first(avl_tree); svcp != NULL;
37720Sstevel@tonic-gate svcp = avl_walk(avl_tree, svcp, AVL_AFTER)) {
37730Sstevel@tonic-gate sbp = svcp->svc_bind_list;
37740Sstevel@tonic-gate while (sbp != NULL) {
37750Sstevel@tonic-gate if (sbp->sbind_pkey != 0 &&
37760Sstevel@tonic-gate sbp->sbind_port == port &&
37770Sstevel@tonic-gate sbp->sbind_hcaguid == hca_guid) {
37780Sstevel@tonic-gate /* even if it's busy, we mark it for rewrite */
37790Sstevel@tonic-gate sbp->sbind_rewrite_state = IBCM_REWRITE_NEEDED;
37800Sstevel@tonic-gate }
37810Sstevel@tonic-gate sbp = sbp->sbind_link;
37820Sstevel@tonic-gate }
37830Sstevel@tonic-gate }
37840Sstevel@tonic-gate if (task_is_running) {
37850Sstevel@tonic-gate /* let the other task thread finish the work */
37860Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
37870Sstevel@tonic-gate return;
37880Sstevel@tonic-gate }
37890Sstevel@tonic-gate task_is_running = 1;
37900Sstevel@tonic-gate
37910Sstevel@tonic-gate (void) ibcm_rewrite_ar();
37920Sstevel@tonic-gate
37930Sstevel@tonic-gate check_for_work:
37940Sstevel@tonic-gate for (svcp = avl_first(avl_tree); svcp != NULL;
37950Sstevel@tonic-gate svcp = avl_walk(avl_tree, svcp, AVL_AFTER)) {
37960Sstevel@tonic-gate sbp = svcp->svc_bind_list;
37970Sstevel@tonic-gate while (sbp != NULL) {
37980Sstevel@tonic-gate if (sbp->sbind_rewrite_state == IBCM_REWRITE_NEEDED) {
37990Sstevel@tonic-gate sbp->sbind_rewrite_state = IBCM_REWRITE_BUSY;
38000Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
38010Sstevel@tonic-gate ibcm_rewrite_svc_record(svcp, sbp);
38020Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
38030Sstevel@tonic-gate /* if it got marked again, we want to rewrite */
38040Sstevel@tonic-gate if (sbp->sbind_rewrite_state ==
38050Sstevel@tonic-gate IBCM_REWRITE_BUSY)
38060Sstevel@tonic-gate sbp->sbind_rewrite_state =
38070Sstevel@tonic-gate IBCM_REWRITE_IDLE;
38080Sstevel@tonic-gate /* in case there was a waiter... */
38090Sstevel@tonic-gate cv_broadcast(&ibcm_svc_info_cv);
38100Sstevel@tonic-gate goto check_for_work;
38110Sstevel@tonic-gate }
38120Sstevel@tonic-gate sbp = sbp->sbind_link;
38130Sstevel@tonic-gate }
38140Sstevel@tonic-gate }
38150Sstevel@tonic-gate /*
38160Sstevel@tonic-gate * If there were no service records to write, and we failed to
38170Sstevel@tonic-gate * have to rewrite any more ATS service records, then we're done.
38180Sstevel@tonic-gate */
38190Sstevel@tonic-gate if (ibcm_rewrite_ar() != 0)
38200Sstevel@tonic-gate goto check_for_work;
38210Sstevel@tonic-gate task_is_running = 0;
38220Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
38230Sstevel@tonic-gate
38249349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibcm_service_record_rewrite_task DONE");
38250Sstevel@tonic-gate kmem_free(pup, sizeof (ibcm_port_up_t));
38260Sstevel@tonic-gate }
38270Sstevel@tonic-gate
38289913SShantkumar.Hiremath@Sun.COM ibt_status_t
ibt_ofuvcm_get_req_data(void * session_id,ibt_ofuvcm_req_data_t * req_data)38299913SShantkumar.Hiremath@Sun.COM ibt_ofuvcm_get_req_data(void *session_id, ibt_ofuvcm_req_data_t *req_data)
38309913SShantkumar.Hiremath@Sun.COM {
38319913SShantkumar.Hiremath@Sun.COM ibcm_state_data_t *statep = (ibcm_state_data_t *)session_id;
38329913SShantkumar.Hiremath@Sun.COM ibcm_req_msg_t *req_msgp;
38339913SShantkumar.Hiremath@Sun.COM
38349913SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibt_get_ofuvcm_req_data: session_id %p",
38359913SShantkumar.Hiremath@Sun.COM session_id);
38369913SShantkumar.Hiremath@Sun.COM mutex_enter(&statep->state_mutex);
38379913SShantkumar.Hiremath@Sun.COM if ((statep->state != IBCM_STATE_REQ_RCVD) &&
38389913SShantkumar.Hiremath@Sun.COM (statep->state != IBCM_STATE_MRA_SENT)) {
38399913SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L2(cmlog, "ibt_get_ofuvcm_req_data: Invalid "
38409913SShantkumar.Hiremath@Sun.COM "State %x", statep->state);
38419913SShantkumar.Hiremath@Sun.COM mutex_exit(&statep->state_mutex);
38429913SShantkumar.Hiremath@Sun.COM return (IBT_CHAN_STATE_INVALID);
38439913SShantkumar.Hiremath@Sun.COM }
38449913SShantkumar.Hiremath@Sun.COM if (statep->mode == IBCM_ACTIVE_MODE) {
38459913SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L2(cmlog, "ibt_get_ofuvcm_req_data: Active mode "
38469913SShantkumar.Hiremath@Sun.COM "not supported");
38479913SShantkumar.Hiremath@Sun.COM mutex_exit(&statep->state_mutex);
38489913SShantkumar.Hiremath@Sun.COM return (IBT_INVALID_PARAM);
38499913SShantkumar.Hiremath@Sun.COM }
38509913SShantkumar.Hiremath@Sun.COM ASSERT(statep->req_msgp);
38519913SShantkumar.Hiremath@Sun.COM
38529913SShantkumar.Hiremath@Sun.COM /*
38539913SShantkumar.Hiremath@Sun.COM * Fill in the additional req message values reqired for
38549913SShantkumar.Hiremath@Sun.COM * RTR transition.
38559913SShantkumar.Hiremath@Sun.COM * Should the PSN be same as the active side??
38569913SShantkumar.Hiremath@Sun.COM */
38579913SShantkumar.Hiremath@Sun.COM req_msgp = (ibcm_req_msg_t *)statep->req_msgp;
38589913SShantkumar.Hiremath@Sun.COM req_data->req_rnr_nak_time = ibcm_default_rnr_nak_time;
38599913SShantkumar.Hiremath@Sun.COM req_data->req_path_mtu = req_msgp->req_mtu_plus >> 4;
38609913SShantkumar.Hiremath@Sun.COM req_data->req_rq_psn = b2h32(req_msgp->req_starting_psn_plus) >> 8;
38619913SShantkumar.Hiremath@Sun.COM mutex_exit(&statep->state_mutex);
38629913SShantkumar.Hiremath@Sun.COM return (IBT_SUCCESS);
38639913SShantkumar.Hiremath@Sun.COM }
38649913SShantkumar.Hiremath@Sun.COM
38659913SShantkumar.Hiremath@Sun.COM ibt_status_t
ibt_ofuvcm_proceed(ibt_cm_event_type_t event,void * session_id,ibt_cm_status_t status,ibt_cm_proceed_reply_t * cm_event_data,void * priv_data,ibt_priv_data_len_t priv_data_len)38669913SShantkumar.Hiremath@Sun.COM ibt_ofuvcm_proceed(ibt_cm_event_type_t event, void *session_id,
38679913SShantkumar.Hiremath@Sun.COM ibt_cm_status_t status, ibt_cm_proceed_reply_t *cm_event_data,
38689913SShantkumar.Hiremath@Sun.COM void *priv_data, ibt_priv_data_len_t priv_data_len)
38699913SShantkumar.Hiremath@Sun.COM {
38709913SShantkumar.Hiremath@Sun.COM ibcm_state_data_t *statep = (ibcm_state_data_t *)session_id;
38719913SShantkumar.Hiremath@Sun.COM ibt_status_t ret;
38729913SShantkumar.Hiremath@Sun.COM
38739913SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibt_ofuvcm_proceed chan 0x%p event %x "
38749913SShantkumar.Hiremath@Sun.COM "status %x session_id %p", statep->channel, event, status,
38759913SShantkumar.Hiremath@Sun.COM session_id);
38769913SShantkumar.Hiremath@Sun.COM
38779913SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L5(cmlog, "ibt_ofuvcm_proceed chan 0x%p "
38789913SShantkumar.Hiremath@Sun.COM "cm_event_data %p, priv_data %p priv_data_len %x",
38799913SShantkumar.Hiremath@Sun.COM statep->channel, cm_event_data, priv_data, priv_data_len);
38809913SShantkumar.Hiremath@Sun.COM
38819913SShantkumar.Hiremath@Sun.COM /* validate session_id and status */
38829913SShantkumar.Hiremath@Sun.COM if ((statep == NULL) || (status == IBT_CM_DEFER)) {
38839913SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L2(cmlog, "ibt_ofuvcm_proceed : Invalid Args");
38849913SShantkumar.Hiremath@Sun.COM return (IBT_INVALID_PARAM);
38859913SShantkumar.Hiremath@Sun.COM }
38869913SShantkumar.Hiremath@Sun.COM
38879913SShantkumar.Hiremath@Sun.COM if (event != IBT_CM_EVENT_REQ_RCV) {
38889913SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L2(cmlog, "ibt_ofuvcm_proceed : only for REQ_RCV");
38899913SShantkumar.Hiremath@Sun.COM return (IBT_INVALID_PARAM);
38909913SShantkumar.Hiremath@Sun.COM }
38919913SShantkumar.Hiremath@Sun.COM mutex_enter(&statep->state_mutex);
389211369SPramod.Gunjikar@Sun.COM statep->is_this_ofuv_chan = B_TRUE;
38939913SShantkumar.Hiremath@Sun.COM mutex_exit(&statep->state_mutex);
38949913SShantkumar.Hiremath@Sun.COM
38959913SShantkumar.Hiremath@Sun.COM ret = ibt_cm_proceed(event, session_id, status, cm_event_data,
38969913SShantkumar.Hiremath@Sun.COM priv_data, priv_data_len);
38979913SShantkumar.Hiremath@Sun.COM return (ret);
38989913SShantkumar.Hiremath@Sun.COM }
38990Sstevel@tonic-gate
39000Sstevel@tonic-gate /*
39010Sstevel@tonic-gate * Function:
39020Sstevel@tonic-gate * ibt_cm_proceed
39030Sstevel@tonic-gate *
39040Sstevel@tonic-gate * Verifies the arguments and dispatches the cm state machine processing
39050Sstevel@tonic-gate * via taskq
39060Sstevel@tonic-gate */
39070Sstevel@tonic-gate
39080Sstevel@tonic-gate ibt_status_t
ibt_cm_proceed(ibt_cm_event_type_t event,void * session_id,ibt_cm_status_t status,ibt_cm_proceed_reply_t * cm_event_data,void * priv_data,ibt_priv_data_len_t priv_data_len)39090Sstevel@tonic-gate ibt_cm_proceed(ibt_cm_event_type_t event, void *session_id,
39100Sstevel@tonic-gate ibt_cm_status_t status, ibt_cm_proceed_reply_t *cm_event_data,
39110Sstevel@tonic-gate void *priv_data, ibt_priv_data_len_t priv_data_len)
39120Sstevel@tonic-gate {
39130Sstevel@tonic-gate ibcm_state_data_t *statep = (ibcm_state_data_t *)session_id;
39140Sstevel@tonic-gate ibcm_proceed_targs_t *proceed_targs;
39150Sstevel@tonic-gate ibcm_proceed_error_t proceed_error;
39160Sstevel@tonic-gate
39170Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_cm_proceed chan 0x%p event %x status %x "
39180Sstevel@tonic-gate "session_id %p", statep->channel, event, status, session_id);
39190Sstevel@tonic-gate
39200Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_cm_proceed chan 0x%p cm_event_data %p, "
39210Sstevel@tonic-gate "priv_data %p priv_data_len %x", statep->channel, cm_event_data,
39220Sstevel@tonic-gate priv_data, priv_data_len);
39230Sstevel@tonic-gate
39240Sstevel@tonic-gate /* validate session_id and status */
39250Sstevel@tonic-gate if ((statep == NULL) || (status == IBT_CM_DEFER)) {
39260Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : Invalid Args");
39270Sstevel@tonic-gate return (IBT_INVALID_PARAM);
39280Sstevel@tonic-gate }
39290Sstevel@tonic-gate
39300Sstevel@tonic-gate /* If priv data len specified, then priv_data cannot be NULL */
39310Sstevel@tonic-gate if ((priv_data_len > 0) && (priv_data == NULL))
39320Sstevel@tonic-gate return (IBT_INVALID_PARAM);
39330Sstevel@tonic-gate
39340Sstevel@tonic-gate proceed_error = IBCM_PROCEED_INVALID_NONE;
39350Sstevel@tonic-gate
39360Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
39370Sstevel@tonic-gate if (event == IBT_CM_EVENT_REQ_RCV) {
39380Sstevel@tonic-gate
39390Sstevel@tonic-gate if ((statep->state != IBCM_STATE_REQ_RCVD) &&
39400Sstevel@tonic-gate (statep->state != IBCM_STATE_MRA_SENT))
39410Sstevel@tonic-gate proceed_error = IBCM_PROCEED_INVALID_EVENT_STATE;
39420Sstevel@tonic-gate else if (priv_data_len > IBT_REP_PRIV_DATA_SZ)
39430Sstevel@tonic-gate proceed_error = IBCM_PROCEED_INVALID_PRIV_SZ;
39440Sstevel@tonic-gate
39450Sstevel@tonic-gate } else if (event == IBT_CM_EVENT_REP_RCV) {
39460Sstevel@tonic-gate if ((statep->state != IBCM_STATE_REP_RCVD) &&
39470Sstevel@tonic-gate (statep->state != IBCM_STATE_MRA_REP_SENT))
39480Sstevel@tonic-gate proceed_error = IBCM_PROCEED_INVALID_EVENT_STATE;
39490Sstevel@tonic-gate else if (priv_data_len > IBT_RTU_PRIV_DATA_SZ)
39500Sstevel@tonic-gate proceed_error = IBCM_PROCEED_INVALID_PRIV_SZ;
39510Sstevel@tonic-gate } else if (event == IBT_CM_EVENT_LAP_RCV) {
39520Sstevel@tonic-gate if ((statep->ap_state != IBCM_AP_STATE_LAP_RCVD) &&
39530Sstevel@tonic-gate (statep->ap_state != IBCM_AP_STATE_MRA_LAP_SENT))
39540Sstevel@tonic-gate proceed_error = IBCM_PROCEED_INVALID_EVENT_STATE;
39550Sstevel@tonic-gate else if (priv_data_len > IBT_APR_PRIV_DATA_SZ)
39560Sstevel@tonic-gate proceed_error = IBCM_PROCEED_INVALID_PRIV_SZ;
39570Sstevel@tonic-gate } else if (event == IBT_CM_EVENT_CONN_CLOSED) {
39580Sstevel@tonic-gate if (statep->state != IBCM_STATE_DREQ_RCVD)
39590Sstevel@tonic-gate proceed_error = IBCM_PROCEED_INVALID_EVENT_STATE;
39600Sstevel@tonic-gate else if (priv_data_len > IBT_DREP_PRIV_DATA_SZ)
39610Sstevel@tonic-gate proceed_error = IBCM_PROCEED_INVALID_PRIV_SZ;
39620Sstevel@tonic-gate } else {
39630Sstevel@tonic-gate proceed_error = IBCM_PROCEED_INVALID_EVENT;
39640Sstevel@tonic-gate }
39650Sstevel@tonic-gate
39660Sstevel@tonic-gate /* if there is an error, print an error message and return */
39670Sstevel@tonic-gate if (proceed_error != IBCM_PROCEED_INVALID_NONE) {
39680Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
39690Sstevel@tonic-gate if (proceed_error == IBCM_PROCEED_INVALID_EVENT_STATE) {
39700Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p"
39710Sstevel@tonic-gate "Invalid Event/State combination specified",
39720Sstevel@tonic-gate statep->channel);
39730Sstevel@tonic-gate return (IBT_INVALID_PARAM);
39740Sstevel@tonic-gate } else if (proceed_error == IBCM_PROCEED_INVALID_PRIV_SZ) {
39750Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p"
39760Sstevel@tonic-gate "Invalid Event/priv len combination specified",
39770Sstevel@tonic-gate statep->channel);
39780Sstevel@tonic-gate return (IBT_INVALID_PARAM);
39790Sstevel@tonic-gate } else if (proceed_error == IBCM_PROCEED_INVALID_EVENT) {
39800Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p"
39810Sstevel@tonic-gate "Invalid Event specified", statep->channel);
39820Sstevel@tonic-gate return (IBT_INVALID_PARAM);
39830Sstevel@tonic-gate } else {
39840Sstevel@tonic-gate ASSERT(proceed_error == IBCM_PROCEED_INVALID_LAP);
39850Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p"
39860Sstevel@tonic-gate "IBT_CM_EVENT_LAP_RCV not supported",
39870Sstevel@tonic-gate statep->channel);
39880Sstevel@tonic-gate /* UNTIL HCA DRIVER ENABLES AP SUPPORT, FAIL THE CALL */
39890Sstevel@tonic-gate return (IBT_APM_NOT_SUPPORTED);
39900Sstevel@tonic-gate }
39910Sstevel@tonic-gate }
39920Sstevel@tonic-gate
39930Sstevel@tonic-gate
39940Sstevel@tonic-gate /* wait until client's CM handler returns DEFER status back to CM */
39950Sstevel@tonic-gate
39960Sstevel@tonic-gate while (statep->clnt_proceed == IBCM_BLOCK) {
39970Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_cm_proceed : chan 0x%p blocked for "
39980Sstevel@tonic-gate "return of client's cm handler", statep->channel);
39990Sstevel@tonic-gate cv_wait(&statep->block_client_cv, &statep->state_mutex);
40000Sstevel@tonic-gate }
40010Sstevel@tonic-gate
40020Sstevel@tonic-gate if (statep->clnt_proceed == IBCM_FAIL) {
40030Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
40040Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p Failed as "
40050Sstevel@tonic-gate "client returned non-DEFER status from cm handler",
40060Sstevel@tonic-gate statep->channel);
40070Sstevel@tonic-gate return (IBT_CHAN_STATE_INVALID);
40080Sstevel@tonic-gate }
40090Sstevel@tonic-gate
40100Sstevel@tonic-gate ASSERT(statep->clnt_proceed == IBCM_UNBLOCK);
40110Sstevel@tonic-gate statep->clnt_proceed = IBCM_FAIL;
40120Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
40130Sstevel@tonic-gate
40140Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*proceed_targs))
40150Sstevel@tonic-gate
40160Sstevel@tonic-gate /* the state machine processing is done in a separate thread */
40170Sstevel@tonic-gate
40180Sstevel@tonic-gate /* proceed_targs is freed in ibcm_proceed_via_taskq */
40190Sstevel@tonic-gate proceed_targs = kmem_alloc(sizeof (ibcm_proceed_targs_t),
40200Sstevel@tonic-gate KM_SLEEP);
40210Sstevel@tonic-gate
40220Sstevel@tonic-gate proceed_targs->event = event;
40230Sstevel@tonic-gate proceed_targs->status = status;
40240Sstevel@tonic-gate proceed_targs->priv_data_len = priv_data_len;
40250Sstevel@tonic-gate
40260Sstevel@tonic-gate bcopy(priv_data, proceed_targs->priv_data, priv_data_len);
40270Sstevel@tonic-gate
40280Sstevel@tonic-gate proceed_targs->tst.rc.statep = statep;
40290Sstevel@tonic-gate bcopy(cm_event_data, &proceed_targs->tst.rc.rc_cm_event_data,
40300Sstevel@tonic-gate sizeof (ibt_cm_proceed_reply_t));
40310Sstevel@tonic-gate
40320Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*proceed_targs))
40330Sstevel@tonic-gate
40340Sstevel@tonic-gate (void) taskq_dispatch(ibcm_taskq, ibcm_proceed_via_taskq,
40350Sstevel@tonic-gate proceed_targs, TQ_SLEEP);
40360Sstevel@tonic-gate
40370Sstevel@tonic-gate return (IBT_SUCCESS);
40380Sstevel@tonic-gate }
40390Sstevel@tonic-gate
40400Sstevel@tonic-gate /*
40410Sstevel@tonic-gate * Function:
40420Sstevel@tonic-gate * ibcm_proceed_via_taskq
40430Sstevel@tonic-gate *
40440Sstevel@tonic-gate * Called from taskq, dispatched by ibt_cm_proceed
40450Sstevel@tonic-gate * Completes the cm state processing for ibt_cm_proceed
40460Sstevel@tonic-gate */
40470Sstevel@tonic-gate void
ibcm_proceed_via_taskq(void * targs)40480Sstevel@tonic-gate ibcm_proceed_via_taskq(void *targs)
40490Sstevel@tonic-gate {
40500Sstevel@tonic-gate ibcm_proceed_targs_t *proceed_targs = (ibcm_proceed_targs_t *)targs;
40510Sstevel@tonic-gate ibcm_state_data_t *statep = proceed_targs->tst.rc.statep;
40520Sstevel@tonic-gate ibt_cm_reason_t reject_reason;
40530Sstevel@tonic-gate uint8_t arej_len;
40540Sstevel@tonic-gate ibcm_status_t response;
40550Sstevel@tonic-gate ibcm_clnt_reply_info_t clnt_info;
40560Sstevel@tonic-gate
40570Sstevel@tonic-gate clnt_info.reply_event = &proceed_targs->tst.rc.rc_cm_event_data;
40580Sstevel@tonic-gate clnt_info.priv_data = proceed_targs->priv_data;
40590Sstevel@tonic-gate clnt_info.priv_data_len = proceed_targs->priv_data_len;
40600Sstevel@tonic-gate
40610Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_proceed_via_taskq chan 0x%p targs %x",
40620Sstevel@tonic-gate statep->channel, targs);
40630Sstevel@tonic-gate
40640Sstevel@tonic-gate if (proceed_targs->event == IBT_CM_EVENT_REQ_RCV) {
40650Sstevel@tonic-gate response =
40660Sstevel@tonic-gate ibcm_process_cep_req_cm_hdlr(statep, proceed_targs->status,
40670Sstevel@tonic-gate &clnt_info, &reject_reason, &arej_len,
40680Sstevel@tonic-gate (ibcm_req_msg_t *)statep->defer_cm_msg);
40690Sstevel@tonic-gate
40700Sstevel@tonic-gate ibcm_handle_cep_req_response(statep, response, reject_reason,
40710Sstevel@tonic-gate arej_len);
40720Sstevel@tonic-gate
40730Sstevel@tonic-gate } else if (proceed_targs->event == IBT_CM_EVENT_REP_RCV) {
40740Sstevel@tonic-gate response =
40750Sstevel@tonic-gate ibcm_process_cep_rep_cm_hdlr(statep, proceed_targs->status,
40760Sstevel@tonic-gate &clnt_info, &reject_reason, &arej_len,
40770Sstevel@tonic-gate (ibcm_rep_msg_t *)statep->defer_cm_msg);
40780Sstevel@tonic-gate
40790Sstevel@tonic-gate ibcm_handle_cep_rep_response(statep, response, reject_reason,
40800Sstevel@tonic-gate arej_len, (ibcm_rep_msg_t *)statep->defer_cm_msg);
40810Sstevel@tonic-gate
40820Sstevel@tonic-gate } else if (proceed_targs->event == IBT_CM_EVENT_LAP_RCV) {
40830Sstevel@tonic-gate ibcm_process_cep_lap_cm_hdlr(statep, proceed_targs->status,
40840Sstevel@tonic-gate &clnt_info, (ibcm_lap_msg_t *)statep->defer_cm_msg,
40850Sstevel@tonic-gate (ibcm_apr_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg));
40860Sstevel@tonic-gate
40870Sstevel@tonic-gate ibcm_post_apr_mad(statep);
40880Sstevel@tonic-gate
40890Sstevel@tonic-gate } else {
40900Sstevel@tonic-gate ASSERT(proceed_targs->event == IBT_CM_EVENT_CONN_CLOSED);
40910Sstevel@tonic-gate ibcm_handle_cep_dreq_response(statep, proceed_targs->priv_data,
40920Sstevel@tonic-gate proceed_targs->priv_data_len);
40930Sstevel@tonic-gate }
40940Sstevel@tonic-gate
40950Sstevel@tonic-gate kmem_free(targs, sizeof (ibcm_proceed_targs_t));
40960Sstevel@tonic-gate }
40970Sstevel@tonic-gate
40980Sstevel@tonic-gate /*
40990Sstevel@tonic-gate * Function:
41000Sstevel@tonic-gate * ibt_cm_ud_proceed
41010Sstevel@tonic-gate *
41020Sstevel@tonic-gate * Verifies the arguments and dispatches the cm state machine processing
41030Sstevel@tonic-gate * via taskq
41040Sstevel@tonic-gate */
41050Sstevel@tonic-gate ibt_status_t
ibt_cm_ud_proceed(void * session_id,ibt_channel_hdl_t ud_channel,ibt_cm_status_t status,ibt_redirect_info_t * redirect_infop,void * priv_data,ibt_priv_data_len_t priv_data_len)41060Sstevel@tonic-gate ibt_cm_ud_proceed(void *session_id, ibt_channel_hdl_t ud_channel,
41070Sstevel@tonic-gate ibt_cm_status_t status, ibt_redirect_info_t *redirect_infop,
41080Sstevel@tonic-gate void *priv_data, ibt_priv_data_len_t priv_data_len)
41090Sstevel@tonic-gate {
41100Sstevel@tonic-gate ibcm_ud_state_data_t *ud_statep = (ibcm_ud_state_data_t *)session_id;
41110Sstevel@tonic-gate ibcm_proceed_targs_t *proceed_targs;
41120Sstevel@tonic-gate ibt_qp_query_attr_t qp_attr;
41130Sstevel@tonic-gate ibt_status_t retval;
41140Sstevel@tonic-gate
41150Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_cm_ud_proceed session_id %p "
41160Sstevel@tonic-gate "ud_channel %p ", session_id, ud_channel);
41170Sstevel@tonic-gate
41180Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_cm_ud_proceed status %x priv_data %p "
41190Sstevel@tonic-gate "priv_data_len %x", status, priv_data, priv_data_len);
41200Sstevel@tonic-gate
41210Sstevel@tonic-gate /* validate session_id and status */
41220Sstevel@tonic-gate if ((ud_statep == NULL) || (status == IBT_CM_DEFER)) {
41230Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed : Invalid Args");
41240Sstevel@tonic-gate return (IBT_INVALID_PARAM);
41250Sstevel@tonic-gate }
41260Sstevel@tonic-gate
41270Sstevel@tonic-gate /* If priv data len specified, then priv_data cannot be NULL */
41280Sstevel@tonic-gate if ((priv_data_len > 0) && (priv_data == NULL))
41290Sstevel@tonic-gate return (IBT_INVALID_PARAM);
41300Sstevel@tonic-gate
41310Sstevel@tonic-gate if (priv_data_len > IBT_SIDR_REP_PRIV_DATA_SZ)
41320Sstevel@tonic-gate return (IBT_INVALID_PARAM);
41330Sstevel@tonic-gate
41340Sstevel@tonic-gate /* retrieve qpn and qkey from ud channel */
41350Sstevel@tonic-gate
41360Sstevel@tonic-gate /* validate event and statep's state */
41370Sstevel@tonic-gate
41380Sstevel@tonic-gate if (status == IBT_CM_ACCEPT) {
41390Sstevel@tonic-gate retval = ibt_query_qp(ud_channel, &qp_attr);
41400Sstevel@tonic-gate if ((retval != IBT_SUCCESS) ||
41410Sstevel@tonic-gate (qp_attr.qp_info.qp_trans != IBT_UD_SRV)) {
41420Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed: "
41430Sstevel@tonic-gate "Failed to retrieve QPN from the channel: %d",
41440Sstevel@tonic-gate retval);
41450Sstevel@tonic-gate return (IBT_INVALID_PARAM);
41460Sstevel@tonic-gate }
41470Sstevel@tonic-gate }
41480Sstevel@tonic-gate
41490Sstevel@tonic-gate
41500Sstevel@tonic-gate mutex_enter(&ud_statep->ud_state_mutex);
41510Sstevel@tonic-gate
41520Sstevel@tonic-gate if (ud_statep->ud_state != IBCM_STATE_SIDR_REQ_RCVD) {
41530Sstevel@tonic-gate mutex_exit(&ud_statep->ud_state_mutex);
41540Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed : Invalid State "
41550Sstevel@tonic-gate "specified");
41560Sstevel@tonic-gate return (IBT_INVALID_PARAM);
41570Sstevel@tonic-gate }
41580Sstevel@tonic-gate
41590Sstevel@tonic-gate /* wait until client's CM handler returns DEFER status back to CM */
41600Sstevel@tonic-gate
41610Sstevel@tonic-gate while (ud_statep->ud_clnt_proceed == IBCM_BLOCK) {
41620Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_cm_ud_proceed : Blocked for return"
41630Sstevel@tonic-gate " of client's ud cm handler");
41640Sstevel@tonic-gate cv_wait(&ud_statep->ud_block_client_cv,
41650Sstevel@tonic-gate &ud_statep->ud_state_mutex);
41660Sstevel@tonic-gate }
41670Sstevel@tonic-gate
41680Sstevel@tonic-gate if (ud_statep->ud_clnt_proceed == IBCM_FAIL) {
41690Sstevel@tonic-gate mutex_exit(&ud_statep->ud_state_mutex);
41700Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed : Failed as client "
41710Sstevel@tonic-gate "returned non-DEFER status from cm handler");
41720Sstevel@tonic-gate return (IBT_INVALID_PARAM);
41730Sstevel@tonic-gate }
41740Sstevel@tonic-gate
41750Sstevel@tonic-gate ASSERT(ud_statep->ud_clnt_proceed == IBCM_UNBLOCK);
41760Sstevel@tonic-gate ud_statep->ud_clnt_proceed = IBCM_FAIL;
41770Sstevel@tonic-gate mutex_exit(&ud_statep->ud_state_mutex);
41780Sstevel@tonic-gate
41790Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*proceed_targs))
41800Sstevel@tonic-gate
41810Sstevel@tonic-gate /* the state machine processing is done in a separate thread */
41820Sstevel@tonic-gate
41830Sstevel@tonic-gate /* proceed_targs is freed in ibcm_proceed_via_taskq */
41843241Shiremath proceed_targs = kmem_zalloc(sizeof (ibcm_proceed_targs_t),
41850Sstevel@tonic-gate KM_SLEEP);
41860Sstevel@tonic-gate
41870Sstevel@tonic-gate proceed_targs->status = status;
41880Sstevel@tonic-gate proceed_targs->priv_data_len = priv_data_len;
41890Sstevel@tonic-gate
41900Sstevel@tonic-gate bcopy(priv_data, proceed_targs->priv_data, priv_data_len);
41910Sstevel@tonic-gate
41920Sstevel@tonic-gate if (status == IBT_CM_ACCEPT) {
41930Sstevel@tonic-gate proceed_targs->tst.ud.ud_qkey =
41940Sstevel@tonic-gate qp_attr.qp_info.qp_transport.ud.ud_qkey;
41950Sstevel@tonic-gate proceed_targs->tst.ud.ud_qpn = qp_attr.qp_qpn;
41960Sstevel@tonic-gate }
41970Sstevel@tonic-gate
41980Sstevel@tonic-gate proceed_targs->tst.ud.ud_statep = ud_statep;
41990Sstevel@tonic-gate
42000Sstevel@tonic-gate /* copy redirect info based on status */
42010Sstevel@tonic-gate if (status == IBT_CM_REDIRECT)
42020Sstevel@tonic-gate bcopy(redirect_infop, &proceed_targs->tst.ud.ud_redirect_info,
42030Sstevel@tonic-gate sizeof (ibt_redirect_info_t));
42040Sstevel@tonic-gate
42050Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*proceed_targs))
42060Sstevel@tonic-gate
42070Sstevel@tonic-gate (void) taskq_dispatch(ibcm_taskq, ibcm_ud_proceed_via_taskq,
42080Sstevel@tonic-gate proceed_targs, TQ_SLEEP);
42090Sstevel@tonic-gate
42100Sstevel@tonic-gate return (IBT_SUCCESS);
42110Sstevel@tonic-gate }
42120Sstevel@tonic-gate
42130Sstevel@tonic-gate /*
42140Sstevel@tonic-gate * Function:
42150Sstevel@tonic-gate * ibcm_ud_proceed_via_taskq
42160Sstevel@tonic-gate *
42170Sstevel@tonic-gate * Called from taskq, dispatched by ibt_cm_ud_proceed
42180Sstevel@tonic-gate * Completes the cm state processing for ibt_cm_ud_proceed
42190Sstevel@tonic-gate */
42200Sstevel@tonic-gate void
ibcm_ud_proceed_via_taskq(void * targs)42210Sstevel@tonic-gate ibcm_ud_proceed_via_taskq(void *targs)
42220Sstevel@tonic-gate {
42230Sstevel@tonic-gate ibcm_proceed_targs_t *proceed_targs = (ibcm_proceed_targs_t *)targs;
42240Sstevel@tonic-gate ibcm_ud_state_data_t *ud_statep = proceed_targs->tst.ud.ud_statep;
42250Sstevel@tonic-gate ibcm_ud_clnt_reply_info_t ud_clnt_info;
42260Sstevel@tonic-gate ibt_sidr_status_t sidr_status;
42270Sstevel@tonic-gate
42280Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_ud_proceed_via_taskq(%p)", targs);
42290Sstevel@tonic-gate
42300Sstevel@tonic-gate ud_clnt_info.ud_qpn = proceed_targs->tst.ud.ud_qpn;
42310Sstevel@tonic-gate ud_clnt_info.ud_qkey = proceed_targs->tst.ud.ud_qkey;
42320Sstevel@tonic-gate ud_clnt_info.priv_data = proceed_targs->priv_data;
42330Sstevel@tonic-gate ud_clnt_info.priv_data_len = proceed_targs->priv_data_len;
42340Sstevel@tonic-gate ud_clnt_info.redirect_infop = &proceed_targs->tst.ud.ud_redirect_info;
42350Sstevel@tonic-gate
42360Sstevel@tonic-gate /* validate event and statep's state */
42370Sstevel@tonic-gate ibcm_process_sidr_req_cm_hdlr(ud_statep, proceed_targs->status,
42380Sstevel@tonic-gate &ud_clnt_info, &sidr_status,
42390Sstevel@tonic-gate (ibcm_sidr_rep_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg));
42400Sstevel@tonic-gate
42410Sstevel@tonic-gate ibcm_post_sidr_rep_mad(ud_statep, sidr_status);
42420Sstevel@tonic-gate
42430Sstevel@tonic-gate /* decr the statep ref cnt incremented in ibcm_process_sidr_req_msg */
42440Sstevel@tonic-gate mutex_enter(&ud_statep->ud_state_mutex);
42450Sstevel@tonic-gate IBCM_UD_REF_CNT_DECR(ud_statep);
42460Sstevel@tonic-gate mutex_exit(&ud_statep->ud_state_mutex);
42470Sstevel@tonic-gate
42480Sstevel@tonic-gate kmem_free(targs, sizeof (ibcm_proceed_targs_t));
42490Sstevel@tonic-gate }
42500Sstevel@tonic-gate
42510Sstevel@tonic-gate /*
42520Sstevel@tonic-gate * Function:
42530Sstevel@tonic-gate * ibt_set_alt_path
42540Sstevel@tonic-gate * Input:
42550Sstevel@tonic-gate * channel Channel handle returned from ibt_alloc_rc_channel(9F).
42560Sstevel@tonic-gate *
42570Sstevel@tonic-gate * mode Execute in blocking or non blocking mode.
42580Sstevel@tonic-gate *
42590Sstevel@tonic-gate * alt_path A pointer to an ibt_alt_path_info_t as returned from an
42600Sstevel@tonic-gate * ibt_get_alt_path(9F) call that specifies the new
42610Sstevel@tonic-gate * alternate path.
42620Sstevel@tonic-gate *
42630Sstevel@tonic-gate * priv_data A pointer to a buffer specified by caller for the
42640Sstevel@tonic-gate * private data in the outgoing CM Load Alternate Path
42650Sstevel@tonic-gate * (LAP) message sent to the remote host. This can be NULL
42660Sstevel@tonic-gate * if no private data is available to communicate to the
42670Sstevel@tonic-gate * remote node.
42680Sstevel@tonic-gate *
42690Sstevel@tonic-gate * priv_data_len Length of valid data in priv_data, this should be less
42700Sstevel@tonic-gate * than or equal to IBT_LAP_PRIV_DATA_SZ.
42710Sstevel@tonic-gate *
42720Sstevel@tonic-gate * Output:
42730Sstevel@tonic-gate * ret_args If called in blocking mode, points to a return argument
42740Sstevel@tonic-gate * structure of type ibt_ap_returns_t.
42750Sstevel@tonic-gate *
42760Sstevel@tonic-gate * Returns:
42770Sstevel@tonic-gate * IBT_SUCCESS on Success else appropriate error.
42780Sstevel@tonic-gate * Description:
42790Sstevel@tonic-gate * Load the specified alternate path. Causes the CM to send an LAP message
42800Sstevel@tonic-gate * to the remote node.
42810Sstevel@tonic-gate * Can only be called on a previously opened RC channel.
42820Sstevel@tonic-gate */
42830Sstevel@tonic-gate ibt_status_t
ibt_set_alt_path(ibt_channel_hdl_t channel,ibt_execution_mode_t mode,ibt_alt_path_info_t * alt_path,void * priv_data,ibt_priv_data_len_t priv_data_len,ibt_ap_returns_t * ret_args)42840Sstevel@tonic-gate ibt_set_alt_path(ibt_channel_hdl_t channel, ibt_execution_mode_t mode,
42850Sstevel@tonic-gate ibt_alt_path_info_t *alt_path, void *priv_data,
42860Sstevel@tonic-gate ibt_priv_data_len_t priv_data_len, ibt_ap_returns_t *ret_args)
42870Sstevel@tonic-gate {
42880Sstevel@tonic-gate ibmf_handle_t ibmf_hdl;
42890Sstevel@tonic-gate ibt_status_t status = IBT_SUCCESS;
42900Sstevel@tonic-gate ibcm_lap_msg_t *lap_msgp;
42910Sstevel@tonic-gate ibcm_hca_info_t *hcap;
42920Sstevel@tonic-gate ibcm_state_data_t *statep;
42930Sstevel@tonic-gate uint8_t port_no;
42940Sstevel@tonic-gate ib_lid_t alternate_slid;
42950Sstevel@tonic-gate ibt_priv_data_len_t len;
42960Sstevel@tonic-gate ib_lid_t base_lid;
42970Sstevel@tonic-gate boolean_t alt_grh;
42980Sstevel@tonic-gate
42990Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_set_alt_path(%p, %x, %p, %p, %x, %p)",
43000Sstevel@tonic-gate channel, mode, alt_path, priv_data, priv_data_len, ret_args);
43010Sstevel@tonic-gate
43020Sstevel@tonic-gate /* validate channel */
43030Sstevel@tonic-gate if (IBCM_INVALID_CHANNEL(channel)) {
43040Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: invalid channel");
43050Sstevel@tonic-gate return (IBT_CHAN_HDL_INVALID);
43060Sstevel@tonic-gate }
43070Sstevel@tonic-gate
43080Sstevel@tonic-gate if (ibtl_cm_get_chan_type(channel) != IBT_RC_SRV) {
43090Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43100Sstevel@tonic-gate "Invalid Channel type: Applicable only to RC Channel");
43110Sstevel@tonic-gate return (IBT_CHAN_SRV_TYPE_INVALID);
43120Sstevel@tonic-gate }
43130Sstevel@tonic-gate
43140Sstevel@tonic-gate if (mode == IBT_NONBLOCKING) {
43150Sstevel@tonic-gate if (ret_args != NULL) {
43160Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43170Sstevel@tonic-gate "ret_args should be NULL when called in "
43180Sstevel@tonic-gate "non-blocking mode");
43190Sstevel@tonic-gate return (IBT_INVALID_PARAM);
43200Sstevel@tonic-gate }
43210Sstevel@tonic-gate } else if (mode == IBT_BLOCKING) {
43220Sstevel@tonic-gate if (ret_args == NULL) {
43230Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43240Sstevel@tonic-gate "ret_args should be Non-NULL when called in "
43250Sstevel@tonic-gate "blocking mode");
43260Sstevel@tonic-gate return (IBT_INVALID_PARAM);
43270Sstevel@tonic-gate }
43280Sstevel@tonic-gate if (ret_args->ap_priv_data_len > IBT_APR_PRIV_DATA_SZ) {
43290Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43300Sstevel@tonic-gate "expected private data length is too large");
43310Sstevel@tonic-gate return (IBT_INVALID_PARAM);
43320Sstevel@tonic-gate }
43330Sstevel@tonic-gate if ((ret_args->ap_priv_data_len > 0) &&
43340Sstevel@tonic-gate (ret_args->ap_priv_data == NULL)) {
43350Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43360Sstevel@tonic-gate "apr_priv_data_len > 0, but apr_priv_data NULL");
43370Sstevel@tonic-gate return (IBT_INVALID_PARAM);
43380Sstevel@tonic-gate }
43390Sstevel@tonic-gate } else { /* any other mode is not valid for ibt_set_alt_path */
43400Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43410Sstevel@tonic-gate "invalid mode %x specified", mode);
43420Sstevel@tonic-gate return (IBT_INVALID_PARAM);
43430Sstevel@tonic-gate }
43440Sstevel@tonic-gate
43450Sstevel@tonic-gate if ((port_no = alt_path->ap_alt_cep_path.cep_hca_port_num) == 0)
43460Sstevel@tonic-gate return (IBT_INVALID_PARAM);
43470Sstevel@tonic-gate
43480Sstevel@tonic-gate /* get the statep */
43490Sstevel@tonic-gate IBCM_GET_CHAN_PRIVATE(channel, statep);
43500Sstevel@tonic-gate if (statep == NULL) {
43510Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: statep NULL");
43520Sstevel@tonic-gate return (IBT_CM_FAILURE);
43530Sstevel@tonic-gate }
43540Sstevel@tonic-gate
43550Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
43560Sstevel@tonic-gate IBCM_RELEASE_CHAN_PRIVATE(channel);
43570Sstevel@tonic-gate IBCM_REF_CNT_INCR(statep);
43580Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
43590Sstevel@tonic-gate
43600Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: statep %p", statep);
43610Sstevel@tonic-gate
43620Sstevel@tonic-gate hcap = statep->hcap;
43630Sstevel@tonic-gate
43640Sstevel@tonic-gate /* HCA must have been in active state. If not, it's a client bug */
43650Sstevel@tonic-gate if (!IBCM_ACCESS_HCA_OK(hcap))
43660Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: hca in error state");
43670Sstevel@tonic-gate
43680Sstevel@tonic-gate ASSERT(statep->cm_handler != NULL);
43690Sstevel@tonic-gate
43700Sstevel@tonic-gate /* Check Alternate port */
43710Sstevel@tonic-gate status = ibt_get_port_state_byguid(hcap->hca_guid, port_no, NULL,
43720Sstevel@tonic-gate &base_lid);
43730Sstevel@tonic-gate if (status != IBT_SUCCESS) {
43740Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43750Sstevel@tonic-gate "ibt_get_port_state_byguid status %d ", status);
43760Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
43770Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
43780Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
43790Sstevel@tonic-gate return (status);
43800Sstevel@tonic-gate }
43810Sstevel@tonic-gate
43820Sstevel@tonic-gate if ((hcap->hca_port_info[port_no - 1].port_ibmf_hdl == NULL) &&
43830Sstevel@tonic-gate ((status = ibcm_hca_reinit_port(hcap, port_no - 1))
43840Sstevel@tonic-gate != IBT_SUCCESS)) {
43850Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43860Sstevel@tonic-gate "ibmf reg or callback setup failed during re-initialize");
43870Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
43880Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
43890Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
43900Sstevel@tonic-gate return (status);
43910Sstevel@tonic-gate }
43920Sstevel@tonic-gate
43930Sstevel@tonic-gate ibmf_hdl = statep->stored_reply_addr.ibmf_hdl;
43940Sstevel@tonic-gate
43950Sstevel@tonic-gate alternate_slid = base_lid +
43960Sstevel@tonic-gate alt_path->ap_alt_cep_path.cep_adds_vect.av_src_path;
43970Sstevel@tonic-gate
43980Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: alternate SLID = %x",
43990Sstevel@tonic-gate h2b16(alternate_slid));
44000Sstevel@tonic-gate
44011093Shiremath ibcm_lapr_enter(); /* limit how many run simultaneously */
44020Sstevel@tonic-gate
44030Sstevel@tonic-gate /* Allocate MAD for LAP */
44040Sstevel@tonic-gate if (statep->lapr_msg == NULL)
44050Sstevel@tonic-gate if ((status = ibcm_alloc_out_msg(ibmf_hdl, &statep->lapr_msg,
44060Sstevel@tonic-gate MAD_METHOD_SEND)) != IBT_SUCCESS) {
44071093Shiremath ibcm_lapr_exit();
44080Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
44090Sstevel@tonic-gate "chan 0x%p ibcm_alloc_out_msg failed", channel);
44100Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
44110Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
44120Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
44130Sstevel@tonic-gate return (status);
44140Sstevel@tonic-gate }
44150Sstevel@tonic-gate
44160Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
44170Sstevel@tonic-gate
44180Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: connection state is"
44190Sstevel@tonic-gate " %x", statep->state);
44200Sstevel@tonic-gate
44210Sstevel@tonic-gate /* Check state */
44220Sstevel@tonic-gate if ((statep->state != IBCM_STATE_ESTABLISHED) ||
44230Sstevel@tonic-gate (statep->ap_state != IBCM_AP_STATE_IDLE)) {
44240Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
44250Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
44260Sstevel@tonic-gate (void) ibcm_free_out_msg(ibmf_hdl, &statep->lapr_msg);
44271093Shiremath ibcm_lapr_exit();
44280Sstevel@tonic-gate return (IBT_CHAN_STATE_INVALID);
44290Sstevel@tonic-gate } else {
44300Sstevel@tonic-gate /* Set to LAP Sent state */
44310Sstevel@tonic-gate statep->ap_state = IBCM_AP_STATE_LAP_SENT;
44320Sstevel@tonic-gate statep->ap_done = B_FALSE;
44330Sstevel@tonic-gate statep->remaining_retry_cnt = statep->max_cm_retries;
44340Sstevel@tonic-gate statep->timer_stored_state = statep->state;
44350Sstevel@tonic-gate statep->timer_stored_ap_state = statep->ap_state;
44360Sstevel@tonic-gate IBCM_REF_CNT_INCR(statep); /* for ibcm_post_lap_complete */
44370Sstevel@tonic-gate }
44380Sstevel@tonic-gate
44390Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
44400Sstevel@tonic-gate
44410Sstevel@tonic-gate /* No more failure returns below */
44420Sstevel@tonic-gate
44430Sstevel@tonic-gate /* Allocate MAD for LAP */
44440Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibt_set_alt_path:"
44450Sstevel@tonic-gate " statep's mad addr = 0x%p", IBCM_OUT_HDRP(statep->lapr_msg));
44460Sstevel@tonic-gate
44470Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lap_msgp))
44480Sstevel@tonic-gate
44490Sstevel@tonic-gate lap_msgp = (ibcm_lap_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg);
44500Sstevel@tonic-gate
44510Sstevel@tonic-gate lap_msgp->lap_alt_l_port_lid = h2b16(alternate_slid);
44520Sstevel@tonic-gate lap_msgp->lap_alt_r_port_lid =
44530Sstevel@tonic-gate h2b16(alt_path->ap_alt_cep_path.cep_adds_vect.av_dlid);
44540Sstevel@tonic-gate
44550Sstevel@tonic-gate /* Fill in remote port gid */
44560Sstevel@tonic-gate lap_msgp->lap_alt_r_port_gid.gid_prefix =
44570Sstevel@tonic-gate h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_dgid.gid_prefix);
44580Sstevel@tonic-gate lap_msgp->lap_alt_r_port_gid.gid_guid =
44590Sstevel@tonic-gate h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_dgid.gid_guid);
44600Sstevel@tonic-gate
44610Sstevel@tonic-gate /* Fill in local port gid */
44620Sstevel@tonic-gate lap_msgp->lap_alt_l_port_gid.gid_prefix =
44630Sstevel@tonic-gate h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_sgid.gid_prefix);
44640Sstevel@tonic-gate lap_msgp->lap_alt_l_port_gid.gid_guid =
44650Sstevel@tonic-gate h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_sgid.gid_guid);
44660Sstevel@tonic-gate
44670Sstevel@tonic-gate alt_grh = alt_path->ap_alt_cep_path.cep_adds_vect.av_send_grh;
44680Sstevel@tonic-gate
44690Sstevel@tonic-gate /* alternate_flow_label, and alternate srate, alternate traffic class */
44700Sstevel@tonic-gate lap_msgp->lap_alt_srate_plus =
44710Sstevel@tonic-gate alt_path->ap_alt_cep_path.cep_adds_vect.av_srate & 0x3f;
44720Sstevel@tonic-gate lap_msgp->lap_alt_flow_label_plus = h2b32(((alt_grh == B_TRUE) ?
44730Sstevel@tonic-gate (alt_path->ap_alt_cep_path.cep_adds_vect.av_flow << 12) : 0) |
44740Sstevel@tonic-gate alt_path->ap_alt_cep_path.cep_adds_vect.av_tclass);
44750Sstevel@tonic-gate
44760Sstevel@tonic-gate /* Alternate hop limit, service level */
44770Sstevel@tonic-gate lap_msgp->lap_alt_hop_limit = (alt_grh == B_TRUE) ?
44784970Shiremath alt_path->ap_alt_cep_path.cep_adds_vect.av_hop : 1;
44790Sstevel@tonic-gate lap_msgp->lap_alt_sl_plus =
44800Sstevel@tonic-gate alt_path->ap_alt_cep_path.cep_adds_vect.av_srvl << 4 |
44810Sstevel@tonic-gate ((alt_grh == B_FALSE) ? 0x8 : 0);
44820Sstevel@tonic-gate
44830Sstevel@tonic-gate lap_msgp->lap_alt_local_acktime_plus = ibt_usec2ib(
44840Sstevel@tonic-gate (2 * statep->rc_alt_pkt_lt) +
44850Sstevel@tonic-gate ibt_ib2usec(hcap->hca_ack_delay)) << 3;
44860Sstevel@tonic-gate
44870Sstevel@tonic-gate lap_msgp->lap_local_comm_id = h2b32(statep->local_comid);
44880Sstevel@tonic-gate lap_msgp->lap_remote_comm_id = h2b32(statep->remote_comid);
44890Sstevel@tonic-gate
44900Sstevel@tonic-gate lap_msgp->lap_remote_qpn_eecn_plus =
44910Sstevel@tonic-gate h2b32((statep->remote_qpn << 8) |
44920Sstevel@tonic-gate ibt_usec2ib(ibcm_remote_response_time) << 3);
44930Sstevel@tonic-gate
44940Sstevel@tonic-gate len = min(priv_data_len, IBT_LAP_PRIV_DATA_SZ);
44950Sstevel@tonic-gate if ((len > 0) && priv_data) {
44960Sstevel@tonic-gate bcopy(priv_data, lap_msgp->lap_private_data, len);
44970Sstevel@tonic-gate }
44980Sstevel@tonic-gate
44990Sstevel@tonic-gate /* only rc_alt_pkt_lt and ap_return_data fields are initialized */
45000Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
45010Sstevel@tonic-gate
45020Sstevel@tonic-gate statep->rc_alt_pkt_lt = ibt_ib2usec(alt_path->ap_alt_pkt_lt);
45030Sstevel@tonic-gate
45040Sstevel@tonic-gate /* return_data is filled up in the state machine code */
45050Sstevel@tonic-gate statep->ap_return_data = ret_args;
45060Sstevel@tonic-gate
45070Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
45080Sstevel@tonic-gate
45090Sstevel@tonic-gate IBCM_OUT_HDRP(statep->lapr_msg)->AttributeID =
45100Sstevel@tonic-gate h2b16(IBCM_INCOMING_LAP + IBCM_ATTR_BASE_ID);
45110Sstevel@tonic-gate
45120Sstevel@tonic-gate IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID =
45130Sstevel@tonic-gate h2b64(ibcm_generate_tranid(IBCM_INCOMING_LAP, statep->local_comid,
45140Sstevel@tonic-gate 0));
45150Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_set_alt_path: statep %p, tid %llx",
45160Sstevel@tonic-gate statep, IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID);
45170Sstevel@tonic-gate
45180Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*lap_msgp))
45190Sstevel@tonic-gate
45200Sstevel@tonic-gate /* Send LAP */
45210Sstevel@tonic-gate ibcm_post_rc_mad(statep, statep->lapr_msg, ibcm_post_lap_complete,
45220Sstevel@tonic-gate statep);
45230Sstevel@tonic-gate
45240Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
45250Sstevel@tonic-gate
45260Sstevel@tonic-gate if (mode == IBT_BLOCKING) {
45270Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: blocking");
45280Sstevel@tonic-gate
45290Sstevel@tonic-gate /* wait for APR */
45300Sstevel@tonic-gate while (statep->ap_done != B_TRUE) {
45310Sstevel@tonic-gate cv_wait(&statep->block_client_cv,
45320Sstevel@tonic-gate &statep->state_mutex);
45330Sstevel@tonic-gate }
45340Sstevel@tonic-gate
45350Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: done blocking");
45360Sstevel@tonic-gate
45370Sstevel@tonic-gate /*
45380Sstevel@tonic-gate * In the case that ibt_set_alt_path fails,
45390Sstevel@tonic-gate * change retval to IBT_CM_FAILURE
45400Sstevel@tonic-gate */
45410Sstevel@tonic-gate if (statep->ap_return_data->ap_status != IBT_CM_AP_LOADED)
45420Sstevel@tonic-gate status = IBT_CM_FAILURE;
45430Sstevel@tonic-gate
45440Sstevel@tonic-gate }
45450Sstevel@tonic-gate
45460Sstevel@tonic-gate /* decrement the ref-count before leaving here */
45470Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
45480Sstevel@tonic-gate
45490Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
45500Sstevel@tonic-gate
45511093Shiremath ibcm_lapr_exit();
45521093Shiremath
45530Sstevel@tonic-gate /* If this message isn't seen then ibt_set_alt_path failed */
45540Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: done");
45550Sstevel@tonic-gate
45560Sstevel@tonic-gate return (status);
45570Sstevel@tonic-gate }
45580Sstevel@tonic-gate
45590Sstevel@tonic-gate
45600Sstevel@tonic-gate #ifdef DEBUG
45610Sstevel@tonic-gate
45620Sstevel@tonic-gate /*
45630Sstevel@tonic-gate * ibcm_query_classport_info:
45640Sstevel@tonic-gate * Query classportinfo
45650Sstevel@tonic-gate *
45660Sstevel@tonic-gate * INPUTS:
45670Sstevel@tonic-gate * channel - Channel that is associated with a statep
45680Sstevel@tonic-gate *
45690Sstevel@tonic-gate * RETURN VALUE: NONE
45700Sstevel@tonic-gate * This function is currently used to generate a valid get method classport
45710Sstevel@tonic-gate * info, and test CM functionality. There is no ibtl client interface to
45720Sstevel@tonic-gate * generate a classportinfo. It is possible that CM may use classportinfo
45730Sstevel@tonic-gate * from other nodes in the future, and most of the code below could be re-used.
45740Sstevel@tonic-gate */
45750Sstevel@tonic-gate void
ibcm_query_classport_info(ibt_channel_hdl_t channel)45760Sstevel@tonic-gate ibcm_query_classport_info(ibt_channel_hdl_t channel)
45770Sstevel@tonic-gate {
45780Sstevel@tonic-gate ibcm_state_data_t *statep;
45790Sstevel@tonic-gate ibmf_msg_t *msgp;
45800Sstevel@tonic-gate
45819349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibcm_query_classport_info(%p)", channel);
45820Sstevel@tonic-gate
45830Sstevel@tonic-gate /* validate channel, first */
45840Sstevel@tonic-gate if (IBCM_INVALID_CHANNEL(channel)) {
45850Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_query_classport_info: "
45860Sstevel@tonic-gate "invalid channel (%p)", channel);
45870Sstevel@tonic-gate return;
45880Sstevel@tonic-gate }
45890Sstevel@tonic-gate
45900Sstevel@tonic-gate /* get the statep */
45910Sstevel@tonic-gate IBCM_GET_CHAN_PRIVATE(channel, statep);
45920Sstevel@tonic-gate
45930Sstevel@tonic-gate /*
45940Sstevel@tonic-gate * This can happen, if the statep is already gone by a DREQ from
45950Sstevel@tonic-gate * the remote side
45960Sstevel@tonic-gate */
45970Sstevel@tonic-gate if (statep == NULL) {
45980Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_query_classport_info: "
45990Sstevel@tonic-gate "statep NULL");
46000Sstevel@tonic-gate return;
46010Sstevel@tonic-gate }
46020Sstevel@tonic-gate
46030Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
46040Sstevel@tonic-gate IBCM_RELEASE_CHAN_PRIVATE(channel);
46050Sstevel@tonic-gate IBCM_REF_CNT_INCR(statep);
46060Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
46070Sstevel@tonic-gate
46080Sstevel@tonic-gate /* Debug/test code, so don't care about return status */
46090Sstevel@tonic-gate (void) ibcm_alloc_out_msg(statep->stored_reply_addr.ibmf_hdl, &msgp,
46100Sstevel@tonic-gate MAD_METHOD_GET);
46110Sstevel@tonic-gate
46120Sstevel@tonic-gate IBCM_OUT_HDRP(msgp)->TransactionID = h2b64(ibcm_generate_tranid(
46130Sstevel@tonic-gate MAD_ATTR_ID_CLASSPORTINFO, statep->local_comid, 0));
46140Sstevel@tonic-gate IBCM_OUT_HDRP(msgp)->AttributeID = h2b16(MAD_ATTR_ID_CLASSPORTINFO);
46150Sstevel@tonic-gate
46160Sstevel@tonic-gate (void) ibcm_post_mad(msgp, &statep->stored_reply_addr, NULL, NULL);
46170Sstevel@tonic-gate
46189349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibcm_query_classport_info(%p) "
46190Sstevel@tonic-gate "Get method MAD posted ", channel);
46200Sstevel@tonic-gate
46210Sstevel@tonic-gate (void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl, &msgp);
46220Sstevel@tonic-gate
46230Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
46240Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
46250Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
46260Sstevel@tonic-gate }
46270Sstevel@tonic-gate
46280Sstevel@tonic-gate static void
ibcm_print_reply_addr(ibt_channel_hdl_t channel,ibcm_mad_addr_t * cm_reply_addr)46290Sstevel@tonic-gate ibcm_print_reply_addr(ibt_channel_hdl_t channel, ibcm_mad_addr_t *cm_reply_addr)
46300Sstevel@tonic-gate {
46310Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: chan 0x%p, SLID %x, "
46320Sstevel@tonic-gate "DLID %x", channel, cm_reply_addr->rcvd_addr.ia_local_lid,
46330Sstevel@tonic-gate cm_reply_addr->rcvd_addr.ia_remote_lid);
46340Sstevel@tonic-gate
46350Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: QKEY %x, PKEY %x, "
46360Sstevel@tonic-gate "RQPN %x SL %x", cm_reply_addr->rcvd_addr.ia_q_key,
46370Sstevel@tonic-gate cm_reply_addr->rcvd_addr.ia_p_key,
46380Sstevel@tonic-gate cm_reply_addr->rcvd_addr.ia_remote_qno,
46390Sstevel@tonic-gate cm_reply_addr->rcvd_addr.ia_service_level);
46400Sstevel@tonic-gate
46410Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: CM SGID %llX:%llX ",
46420Sstevel@tonic-gate cm_reply_addr->grh_hdr.ig_sender_gid.gid_prefix,
46430Sstevel@tonic-gate cm_reply_addr->grh_hdr.ig_sender_gid.gid_guid);
46440Sstevel@tonic-gate
46450Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: CM DGID %llX:%llX",
46460Sstevel@tonic-gate cm_reply_addr->grh_hdr.ig_recver_gid.gid_prefix,
46470Sstevel@tonic-gate cm_reply_addr->grh_hdr.ig_recver_gid.gid_guid);
46480Sstevel@tonic-gate
46490Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: CM FL %x TC %x HL %x",
46500Sstevel@tonic-gate cm_reply_addr->grh_hdr.ig_flow_label,
46510Sstevel@tonic-gate cm_reply_addr->grh_hdr.ig_tclass,
46520Sstevel@tonic-gate cm_reply_addr->grh_hdr.ig_hop_limit);
46530Sstevel@tonic-gate }
46540Sstevel@tonic-gate
46550Sstevel@tonic-gate #endif
46560Sstevel@tonic-gate
46579913SShantkumar.Hiremath@Sun.COM /* For MCG List search */
46589913SShantkumar.Hiremath@Sun.COM typedef struct ibcm_mcg_list_s {
46599913SShantkumar.Hiremath@Sun.COM struct ibcm_mcg_list_s *ml_next;
46609913SShantkumar.Hiremath@Sun.COM ib_gid_t ml_sgid;
46619913SShantkumar.Hiremath@Sun.COM ib_gid_t ml_mgid;
46629913SShantkumar.Hiremath@Sun.COM ib_pkey_t ml_pkey;
46639913SShantkumar.Hiremath@Sun.COM ib_qkey_t ml_qkey;
46649913SShantkumar.Hiremath@Sun.COM uint_t ml_refcnt;
46659913SShantkumar.Hiremath@Sun.COM uint8_t ml_jstate;
46669913SShantkumar.Hiremath@Sun.COM } ibcm_mcg_list_t;
46679913SShantkumar.Hiremath@Sun.COM
46689913SShantkumar.Hiremath@Sun.COM ibcm_mcg_list_t *ibcm_mcglist = NULL;
46699913SShantkumar.Hiremath@Sun.COM
46709913SShantkumar.Hiremath@Sun.COM _NOTE(MUTEX_PROTECTS_DATA(ibcm_mcglist_lock, ibcm_mcg_list_s))
46719913SShantkumar.Hiremath@Sun.COM _NOTE(MUTEX_PROTECTS_DATA(ibcm_mcglist_lock, ibcm_mcglist))
46729913SShantkumar.Hiremath@Sun.COM
46730Sstevel@tonic-gate typedef struct ibcm_join_mcg_tqarg_s {
46740Sstevel@tonic-gate ib_gid_t rgid;
46750Sstevel@tonic-gate ibt_mcg_attr_t mcg_attr;
46760Sstevel@tonic-gate ibt_mcg_info_t *mcg_infop;
46770Sstevel@tonic-gate ibt_mcg_handler_t func;
46780Sstevel@tonic-gate void *arg;
46790Sstevel@tonic-gate } ibcm_join_mcg_tqarg_t;
46800Sstevel@tonic-gate
_NOTE(READ_ONLY_DATA (ibcm_join_mcg_tqarg_s))46810Sstevel@tonic-gate _NOTE(READ_ONLY_DATA(ibcm_join_mcg_tqarg_s))
46820Sstevel@tonic-gate
46839913SShantkumar.Hiremath@Sun.COM void
46849913SShantkumar.Hiremath@Sun.COM ibcm_add_incr_mcg_entry(sa_mcmember_record_t *mcg_req,
46859913SShantkumar.Hiremath@Sun.COM sa_mcmember_record_t *mcg_resp)
46869913SShantkumar.Hiremath@Sun.COM {
46879913SShantkumar.Hiremath@Sun.COM ibcm_mcg_list_t *new = NULL;
46889913SShantkumar.Hiremath@Sun.COM ibcm_mcg_list_t *head = NULL;
46899913SShantkumar.Hiremath@Sun.COM
46909913SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibcm_add_incr_mcg_entry: MGID %llX:%llX"
46919913SShantkumar.Hiremath@Sun.COM "\n SGID %llX:%llX, JState %X)", mcg_req->MGID.gid_prefix,
46929913SShantkumar.Hiremath@Sun.COM mcg_req->MGID.gid_guid, mcg_req->PortGID.gid_prefix,
46939913SShantkumar.Hiremath@Sun.COM mcg_req->PortGID.gid_guid, mcg_req->JoinState);
46949913SShantkumar.Hiremath@Sun.COM
46959913SShantkumar.Hiremath@Sun.COM mutex_enter(&ibcm_mcglist_lock);
46969913SShantkumar.Hiremath@Sun.COM head = ibcm_mcglist;
46979913SShantkumar.Hiremath@Sun.COM
46989913SShantkumar.Hiremath@Sun.COM while (head != NULL) {
46999913SShantkumar.Hiremath@Sun.COM if ((head->ml_mgid.gid_guid == mcg_resp->MGID.gid_guid) &&
47009913SShantkumar.Hiremath@Sun.COM (head->ml_mgid.gid_prefix == mcg_resp->MGID.gid_prefix) &&
47019913SShantkumar.Hiremath@Sun.COM (head->ml_sgid.gid_guid == mcg_resp->PortGID.gid_guid)) {
47029913SShantkumar.Hiremath@Sun.COM /* Increment the count */
47039913SShantkumar.Hiremath@Sun.COM head->ml_refcnt++;
47049913SShantkumar.Hiremath@Sun.COM /* OR the join_state value, we need this during leave */
47059913SShantkumar.Hiremath@Sun.COM head->ml_jstate |= mcg_req->JoinState;
47069913SShantkumar.Hiremath@Sun.COM
47079913SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibcm_add_incr_mcg_entry: Entry "
47089913SShantkumar.Hiremath@Sun.COM "FOUND: refcnt %d JState %X", head->ml_refcnt,
47099913SShantkumar.Hiremath@Sun.COM head->ml_jstate);
47109913SShantkumar.Hiremath@Sun.COM
47119913SShantkumar.Hiremath@Sun.COM mutex_exit(&ibcm_mcglist_lock);
47129913SShantkumar.Hiremath@Sun.COM return;
47139913SShantkumar.Hiremath@Sun.COM }
47149913SShantkumar.Hiremath@Sun.COM head = head->ml_next;
47159913SShantkumar.Hiremath@Sun.COM }
47169913SShantkumar.Hiremath@Sun.COM mutex_exit(&ibcm_mcglist_lock);
47179913SShantkumar.Hiremath@Sun.COM
47189913SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibcm_add_incr_mcg_entry: Create NEW Entry ");
47199913SShantkumar.Hiremath@Sun.COM
47209913SShantkumar.Hiremath@Sun.COM /* If we are here, either list is empty or match couldn't be found */
47219913SShantkumar.Hiremath@Sun.COM new = kmem_zalloc(sizeof (ibcm_mcg_list_t), KM_SLEEP);
47229913SShantkumar.Hiremath@Sun.COM
47239913SShantkumar.Hiremath@Sun.COM mutex_enter(&ibcm_mcglist_lock);
47249913SShantkumar.Hiremath@Sun.COM /* Initialize the fields */
47259913SShantkumar.Hiremath@Sun.COM new->ml_sgid = mcg_resp->PortGID;
47269913SShantkumar.Hiremath@Sun.COM new->ml_mgid = mcg_resp->MGID;
47279913SShantkumar.Hiremath@Sun.COM new->ml_qkey = mcg_req->Q_Key;
47289913SShantkumar.Hiremath@Sun.COM new->ml_pkey = mcg_req->P_Key;
47299913SShantkumar.Hiremath@Sun.COM new->ml_refcnt = 1; /* As this is the first entry */
47309913SShantkumar.Hiremath@Sun.COM new->ml_jstate = mcg_req->JoinState;
47319913SShantkumar.Hiremath@Sun.COM new->ml_next = NULL;
47329913SShantkumar.Hiremath@Sun.COM
47339913SShantkumar.Hiremath@Sun.COM new->ml_next = ibcm_mcglist;
47349913SShantkumar.Hiremath@Sun.COM ibcm_mcglist = new;
47359913SShantkumar.Hiremath@Sun.COM mutex_exit(&ibcm_mcglist_lock);
47369913SShantkumar.Hiremath@Sun.COM }
47379913SShantkumar.Hiremath@Sun.COM
47389913SShantkumar.Hiremath@Sun.COM /*
47399913SShantkumar.Hiremath@Sun.COM * ibcm_del_decr_mcg_entry
47409913SShantkumar.Hiremath@Sun.COM *
47419913SShantkumar.Hiremath@Sun.COM * Return value:
47429913SShantkumar.Hiremath@Sun.COM * IBCM_SUCCESS Entry found and ref_cnt is now zero. So go-ahead and
47439913SShantkumar.Hiremath@Sun.COM * leave the MCG group. The return arg *jstate will have
47449913SShantkumar.Hiremath@Sun.COM * a valid join_state value that needed to be used by
47459913SShantkumar.Hiremath@Sun.COM * xxx_leave_mcg().
47469913SShantkumar.Hiremath@Sun.COM * IBCM_LOOKUP_EXISTS Entry found and ref_cnt is decremented but is NOT zero.
47479913SShantkumar.Hiremath@Sun.COM * So do not leave the MCG group yet.
47489913SShantkumar.Hiremath@Sun.COM * IBCM_LOOKUP_FAIL Entry is NOT found.
47499913SShantkumar.Hiremath@Sun.COM */
47509913SShantkumar.Hiremath@Sun.COM ibcm_status_t
ibcm_del_decr_mcg_entry(sa_mcmember_record_t * mcg_req,uint8_t * jstate)47519913SShantkumar.Hiremath@Sun.COM ibcm_del_decr_mcg_entry(sa_mcmember_record_t *mcg_req, uint8_t *jstate)
47529913SShantkumar.Hiremath@Sun.COM {
47539913SShantkumar.Hiremath@Sun.COM ibcm_mcg_list_t *head, *prev;
47549913SShantkumar.Hiremath@Sun.COM
47559913SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibcm_del_decr_mcg_entry: MGID %llX:%llX"
47569913SShantkumar.Hiremath@Sun.COM "\n SGID %llX:%llX, JState %X)", mcg_req->MGID.gid_prefix,
47579913SShantkumar.Hiremath@Sun.COM mcg_req->MGID.gid_guid, mcg_req->PortGID.gid_prefix,
47589913SShantkumar.Hiremath@Sun.COM mcg_req->PortGID.gid_guid, mcg_req->JoinState);
47599913SShantkumar.Hiremath@Sun.COM
47609913SShantkumar.Hiremath@Sun.COM *jstate = 0;
47619913SShantkumar.Hiremath@Sun.COM
47629913SShantkumar.Hiremath@Sun.COM mutex_enter(&ibcm_mcglist_lock);
47639913SShantkumar.Hiremath@Sun.COM head = ibcm_mcglist;
47649913SShantkumar.Hiremath@Sun.COM prev = NULL;
47659913SShantkumar.Hiremath@Sun.COM
47669913SShantkumar.Hiremath@Sun.COM while (head != NULL) {
47679913SShantkumar.Hiremath@Sun.COM if ((head->ml_mgid.gid_guid == mcg_req->MGID.gid_guid) &&
47689913SShantkumar.Hiremath@Sun.COM (head->ml_mgid.gid_prefix == mcg_req->MGID.gid_prefix) &&
47699913SShantkumar.Hiremath@Sun.COM (head->ml_sgid.gid_guid == mcg_req->PortGID.gid_guid)) {
47709913SShantkumar.Hiremath@Sun.COM if (!(head->ml_jstate & mcg_req->JoinState)) {
47719913SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L2(cmlog, "ibcm_del_decr_mcg_entry"
47729913SShantkumar.Hiremath@Sun.COM ": JoinState mismatch %X %X)",
47739913SShantkumar.Hiremath@Sun.COM head->ml_jstate, mcg_req->JoinState);
47749913SShantkumar.Hiremath@Sun.COM }
47759913SShantkumar.Hiremath@Sun.COM /* Decrement the count */
47769913SShantkumar.Hiremath@Sun.COM head->ml_refcnt--;
47779913SShantkumar.Hiremath@Sun.COM
47789913SShantkumar.Hiremath@Sun.COM if (head->ml_refcnt == 0) {
47799913SShantkumar.Hiremath@Sun.COM *jstate = head->ml_jstate;
47809913SShantkumar.Hiremath@Sun.COM
47819913SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibcm_del_decr_mcg_entry"
47829913SShantkumar.Hiremath@Sun.COM ": refcnt is ZERO, so delete the entry ");
47839913SShantkumar.Hiremath@Sun.COM if ((head == ibcm_mcglist) || (prev == NULL)) {
47849913SShantkumar.Hiremath@Sun.COM ibcm_mcglist = head->ml_next;
47859913SShantkumar.Hiremath@Sun.COM } else if (prev != NULL) {
47869913SShantkumar.Hiremath@Sun.COM prev->ml_next = head->ml_next;
47879913SShantkumar.Hiremath@Sun.COM }
47889913SShantkumar.Hiremath@Sun.COM mutex_exit(&ibcm_mcglist_lock);
47899913SShantkumar.Hiremath@Sun.COM
47909913SShantkumar.Hiremath@Sun.COM kmem_free(head, sizeof (ibcm_mcg_list_t));
47919913SShantkumar.Hiremath@Sun.COM return (IBCM_SUCCESS);
47929913SShantkumar.Hiremath@Sun.COM }
47939913SShantkumar.Hiremath@Sun.COM mutex_exit(&ibcm_mcglist_lock);
47949913SShantkumar.Hiremath@Sun.COM return (IBCM_LOOKUP_EXISTS);
47959913SShantkumar.Hiremath@Sun.COM }
47969913SShantkumar.Hiremath@Sun.COM prev = head;
47979913SShantkumar.Hiremath@Sun.COM head = head->ml_next;
47989913SShantkumar.Hiremath@Sun.COM }
47999913SShantkumar.Hiremath@Sun.COM mutex_exit(&ibcm_mcglist_lock);
48009913SShantkumar.Hiremath@Sun.COM
48019913SShantkumar.Hiremath@Sun.COM /*
48029913SShantkumar.Hiremath@Sun.COM * If we are here, something went wrong, we don't have the entry
48039913SShantkumar.Hiremath@Sun.COM * for that MCG being joined.
48049913SShantkumar.Hiremath@Sun.COM */
48059913SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L2(cmlog, "ibcm_del_decr_mcg_entry: Match NOT "
48069913SShantkumar.Hiremath@Sun.COM "Found ");
48079913SShantkumar.Hiremath@Sun.COM
48089913SShantkumar.Hiremath@Sun.COM return (IBCM_LOOKUP_FAIL);
48099913SShantkumar.Hiremath@Sun.COM }
48109913SShantkumar.Hiremath@Sun.COM
48119913SShantkumar.Hiremath@Sun.COM
48120Sstevel@tonic-gate /*
48130Sstevel@tonic-gate * Function:
48140Sstevel@tonic-gate * ibt_join_mcg
48150Sstevel@tonic-gate * Input:
48160Sstevel@tonic-gate * rgid The request GID that defines the HCA port from which a
48170Sstevel@tonic-gate * contact to SA Access is performed to add the specified
48180Sstevel@tonic-gate * endport GID ((mcg_attr->mc_pgid) to a multicast group.
48190Sstevel@tonic-gate * If mcg_attr->mc_pgid is null, then this (rgid) will be
48200Sstevel@tonic-gate * treated as endport GID that is to be added to the
48210Sstevel@tonic-gate * multicast group.
48220Sstevel@tonic-gate *
48230Sstevel@tonic-gate * mcg_attr A pointer to an ibt_mcg_attr_t structure that defines
48240Sstevel@tonic-gate * the attributes of the desired multicast group to be
48250Sstevel@tonic-gate * created or joined.
48260Sstevel@tonic-gate *
48270Sstevel@tonic-gate * func NULL or a pointer to a function to call when
48280Sstevel@tonic-gate * ibt_join_mcg() completes. If 'func' is not NULL then
48290Sstevel@tonic-gate * ibt_join_mcg() will return as soon as possible after
48300Sstevel@tonic-gate * initiating the multicast group join/create process.
48310Sstevel@tonic-gate * 'func' is then called when the process completes.
48320Sstevel@tonic-gate *
48330Sstevel@tonic-gate * arg Argument to the 'func'.
48340Sstevel@tonic-gate *
48350Sstevel@tonic-gate * Output:
48360Sstevel@tonic-gate * mcg_info_p A pointer to the ibt_mcg_info_t structure, allocated
48370Sstevel@tonic-gate * by the caller, where the attributes of the created or
48380Sstevel@tonic-gate * joined multicast group are copied.
48390Sstevel@tonic-gate * Returns:
48400Sstevel@tonic-gate * IBT_SUCCESS
48410Sstevel@tonic-gate * IBT_INVALID_PARAM
48420Sstevel@tonic-gate * IBT_MCG_RECORDS_NOT_FOUND
48430Sstevel@tonic-gate * IBT_INSUFF_RESOURCE
48440Sstevel@tonic-gate * Description:
48450Sstevel@tonic-gate * Join a multicast group. The first full member "join" causes the MCG
48460Sstevel@tonic-gate * to be created.
48470Sstevel@tonic-gate */
48480Sstevel@tonic-gate ibt_status_t
ibt_join_mcg(ib_gid_t rgid,ibt_mcg_attr_t * mcg_attr,ibt_mcg_info_t * mcg_info_p,ibt_mcg_handler_t func,void * arg)48490Sstevel@tonic-gate ibt_join_mcg(ib_gid_t rgid, ibt_mcg_attr_t *mcg_attr,
48500Sstevel@tonic-gate ibt_mcg_info_t *mcg_info_p, ibt_mcg_handler_t func, void *arg)
48510Sstevel@tonic-gate {
48520Sstevel@tonic-gate ibcm_join_mcg_tqarg_t *mcg_tq;
48530Sstevel@tonic-gate int flag = ((func == NULL) ? KM_SLEEP : KM_NOSLEEP);
48540Sstevel@tonic-gate
48550Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_join_mcg(%llX:%llX, %p)", rgid.gid_prefix,
48560Sstevel@tonic-gate rgid.gid_guid, mcg_attr);
48570Sstevel@tonic-gate
48580Sstevel@tonic-gate if ((rgid.gid_prefix == 0) || (rgid.gid_guid == 0)) {
48590Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Request GID is required");
48600Sstevel@tonic-gate return (IBT_INVALID_PARAM);
48610Sstevel@tonic-gate }
48620Sstevel@tonic-gate
48630Sstevel@tonic-gate if ((mcg_attr->mc_pkey == IB_PKEY_INVALID_LIMITED) ||
48640Sstevel@tonic-gate (mcg_attr->mc_pkey == IB_PKEY_INVALID_FULL)) {
48650Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Invalid P_Key specified");
48660Sstevel@tonic-gate return (IBT_INVALID_PARAM);
48670Sstevel@tonic-gate }
48680Sstevel@tonic-gate
48690Sstevel@tonic-gate if (mcg_attr->mc_join_state == 0) {
48700Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: JoinState not specified");
48710Sstevel@tonic-gate return (IBT_INVALID_PARAM);
48720Sstevel@tonic-gate }
48730Sstevel@tonic-gate
48740Sstevel@tonic-gate if (mcg_info_p == NULL) {
48750Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: mcg_info_p is NULL");
48760Sstevel@tonic-gate return (IBT_INVALID_PARAM);
48770Sstevel@tonic-gate }
48780Sstevel@tonic-gate
48790Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mcg_tq))
48800Sstevel@tonic-gate
48810Sstevel@tonic-gate mcg_tq = kmem_alloc(sizeof (ibcm_join_mcg_tqarg_t), flag);
48820Sstevel@tonic-gate if (mcg_tq == NULL) {
48830Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: "
48840Sstevel@tonic-gate "Unable to allocate memory for local usage.");
48850Sstevel@tonic-gate return (IBT_INSUFF_KERNEL_RESOURCE);
48860Sstevel@tonic-gate }
48870Sstevel@tonic-gate
48880Sstevel@tonic-gate mcg_tq->rgid = rgid;
48890Sstevel@tonic-gate bcopy(mcg_attr, &mcg_tq->mcg_attr, sizeof (ibt_mcg_attr_t));
48900Sstevel@tonic-gate mcg_tq->mcg_infop = mcg_info_p;
48910Sstevel@tonic-gate mcg_tq->func = func;
48920Sstevel@tonic-gate mcg_tq->arg = arg;
48930Sstevel@tonic-gate
48940Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mcg_tq))
48950Sstevel@tonic-gate
48960Sstevel@tonic-gate if (func != NULL) { /* Non-Blocking */
48970Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_join_mcg: Non-Blocking Call");
48980Sstevel@tonic-gate if (taskq_dispatch(ibcm_taskq, ibcm_process_async_join_mcg,
48990Sstevel@tonic-gate mcg_tq, TQ_NOSLEEP) == 0) {
49000Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Failed to "
49010Sstevel@tonic-gate "Dispatch the TaskQ");
49020Sstevel@tonic-gate kmem_free(mcg_tq, sizeof (ibcm_join_mcg_tqarg_t));
49030Sstevel@tonic-gate return (IBT_INSUFF_KERNEL_RESOURCE);
49040Sstevel@tonic-gate } else
49050Sstevel@tonic-gate return (IBT_SUCCESS);
49060Sstevel@tonic-gate } else { /* Blocking */
49070Sstevel@tonic-gate return (ibcm_process_join_mcg(mcg_tq));
49080Sstevel@tonic-gate }
49090Sstevel@tonic-gate }
49100Sstevel@tonic-gate
49110Sstevel@tonic-gate static void
ibcm_process_async_join_mcg(void * tq_arg)49120Sstevel@tonic-gate ibcm_process_async_join_mcg(void *tq_arg)
49130Sstevel@tonic-gate {
49140Sstevel@tonic-gate (void) ibcm_process_join_mcg(tq_arg);
49150Sstevel@tonic-gate }
49160Sstevel@tonic-gate
49170Sstevel@tonic-gate static ibt_status_t
ibcm_process_join_mcg(void * taskq_arg)49180Sstevel@tonic-gate ibcm_process_join_mcg(void *taskq_arg)
49190Sstevel@tonic-gate {
49200Sstevel@tonic-gate sa_mcmember_record_t mcg_req;
49210Sstevel@tonic-gate sa_mcmember_record_t *mcg_resp;
49220Sstevel@tonic-gate ibmf_saa_access_args_t access_args;
49230Sstevel@tonic-gate ibmf_saa_handle_t saa_handle;
49240Sstevel@tonic-gate uint64_t component_mask = 0;
49250Sstevel@tonic-gate ibt_status_t retval;
49260Sstevel@tonic-gate ibtl_cm_hca_port_t hca_port;
49270Sstevel@tonic-gate uint_t num_records;
49280Sstevel@tonic-gate size_t length;
49290Sstevel@tonic-gate ibcm_hca_info_t *hcap;
49300Sstevel@tonic-gate ibcm_join_mcg_tqarg_t *mcg_arg = (ibcm_join_mcg_tqarg_t *)taskq_arg;
49310Sstevel@tonic-gate ibt_mcg_info_t *mcg_info_p = mcg_arg->mcg_infop;
49320Sstevel@tonic-gate
49330Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg(%p)", mcg_arg);
49340Sstevel@tonic-gate
49350Sstevel@tonic-gate retval = ibtl_cm_get_hca_port(mcg_arg->rgid, 0, &hca_port);
49360Sstevel@tonic-gate if (retval != IBT_SUCCESS) {
49370Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: Failed to get "
49380Sstevel@tonic-gate "port info from specified RGID: status = %d", retval);
49390Sstevel@tonic-gate goto ibcm_join_mcg_exit1;
49400Sstevel@tonic-gate }
49410Sstevel@tonic-gate
49420Sstevel@tonic-gate bzero(&mcg_req, sizeof (sa_mcmember_record_t));
49430Sstevel@tonic-gate
49440Sstevel@tonic-gate if ((mcg_arg->mcg_attr.mc_pgid.gid_prefix == 0) ||
49450Sstevel@tonic-gate (mcg_arg->mcg_attr.mc_pgid.gid_guid == 0)) {
49460Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg: "
49470Sstevel@tonic-gate "Request GID is Port GID");
49480Sstevel@tonic-gate mcg_req.PortGID = mcg_arg->rgid;
49490Sstevel@tonic-gate } else {
49500Sstevel@tonic-gate mcg_req.PortGID = mcg_arg->mcg_attr.mc_pgid;
49510Sstevel@tonic-gate }
49520Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_PORTGID;
49530Sstevel@tonic-gate
49540Sstevel@tonic-gate mcg_req.Q_Key = mcg_arg->mcg_attr.mc_qkey;
49550Sstevel@tonic-gate mcg_req.P_Key = mcg_arg->mcg_attr.mc_pkey;
49560Sstevel@tonic-gate mcg_req.JoinState = mcg_arg->mcg_attr.mc_join_state;
49570Sstevel@tonic-gate mcg_req.TClass = mcg_arg->mcg_attr.mc_tclass;
49580Sstevel@tonic-gate mcg_req.FlowLabel = mcg_arg->mcg_attr.mc_flow;
49590Sstevel@tonic-gate mcg_req.SL = mcg_arg->mcg_attr.mc_sl;
49600Sstevel@tonic-gate
49610Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_QKEY | SA_MC_COMPMASK_PKEY |
49620Sstevel@tonic-gate SA_MC_COMPMASK_JOINSTATE | SA_MC_COMPMASK_TCLASS |
49630Sstevel@tonic-gate SA_MC_COMPMASK_FLOWLABEL | SA_MC_COMPMASK_SL;
49640Sstevel@tonic-gate
49650Sstevel@tonic-gate /* If client has specified MGID, use it else SA will assign one. */
49660Sstevel@tonic-gate if ((mcg_arg->mcg_attr.mc_mgid.gid_prefix >> 56ULL & 0xFF) == 0xFF) {
49670Sstevel@tonic-gate mcg_req.MGID = mcg_arg->mcg_attr.mc_mgid;
49680Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_MGID;
49690Sstevel@tonic-gate }
49700Sstevel@tonic-gate
49719349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg: ");
49729349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "PGID=%016llX:%016llX, ",
49739349SShantkumar.Hiremath@Sun.COM mcg_req.PortGID.gid_prefix, mcg_req.PortGID.gid_guid);
49749349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "MGID=%016llX:%016llX",
49759349SShantkumar.Hiremath@Sun.COM mcg_req.MGID.gid_prefix, mcg_req.MGID.gid_guid);
49769349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "JoinState = %X",
49779349SShantkumar.Hiremath@Sun.COM mcg_arg->mcg_attr.mc_join_state);
49789349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L5(cmlog, "QKey %lX, PKey %lX",
49799349SShantkumar.Hiremath@Sun.COM mcg_arg->mcg_attr.mc_qkey, mcg_arg->mcg_attr.mc_pkey);
49809349SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L5(cmlog, "Scope %X, MLID %X",
49819349SShantkumar.Hiremath@Sun.COM mcg_arg->mcg_attr.mc_scope, mcg_arg->mcg_attr.mc_mlid);
49820Sstevel@tonic-gate
49830Sstevel@tonic-gate /* Is MTU specified. */
49840Sstevel@tonic-gate if (mcg_arg->mcg_attr.mc_mtu_req.r_mtu) {
49850Sstevel@tonic-gate mcg_req.MTU = mcg_arg->mcg_attr.mc_mtu_req.r_mtu;
49860Sstevel@tonic-gate mcg_req.MTUSelector = mcg_arg->mcg_attr.mc_mtu_req.r_selector;
49870Sstevel@tonic-gate
49880Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_MTUSELECTOR |
49890Sstevel@tonic-gate SA_MC_COMPMASK_MTU;
49900Sstevel@tonic-gate }
49910Sstevel@tonic-gate
49920Sstevel@tonic-gate /* Is RATE specified. */
49930Sstevel@tonic-gate if (mcg_arg->mcg_attr.mc_rate_req.r_srate) {
49940Sstevel@tonic-gate mcg_req.Rate = mcg_arg->mcg_attr.mc_rate_req.r_srate;
49950Sstevel@tonic-gate mcg_req.RateSelector =
49960Sstevel@tonic-gate mcg_arg->mcg_attr.mc_rate_req.r_selector;
49970Sstevel@tonic-gate
49980Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_RATESELECTOR |
49990Sstevel@tonic-gate SA_MC_COMPMASK_RATE;
50000Sstevel@tonic-gate }
50010Sstevel@tonic-gate
50020Sstevel@tonic-gate /* Is Packet Life Time specified. */
50030Sstevel@tonic-gate if (mcg_arg->mcg_attr.mc_pkt_lt_req.p_pkt_lt) {
50040Sstevel@tonic-gate mcg_req.Rate = mcg_arg->mcg_attr.mc_pkt_lt_req.p_pkt_lt;
50050Sstevel@tonic-gate mcg_req.RateSelector =
50060Sstevel@tonic-gate mcg_arg->mcg_attr.mc_pkt_lt_req.p_selector;
50070Sstevel@tonic-gate
50080Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_PKTLTSELECTOR |
50090Sstevel@tonic-gate SA_MC_COMPMASK_PKTLT;
50100Sstevel@tonic-gate }
50110Sstevel@tonic-gate
50120Sstevel@tonic-gate if (mcg_arg->mcg_attr.mc_hop) {
50130Sstevel@tonic-gate mcg_req.HopLimit = mcg_arg->mcg_attr.mc_hop;
50140Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_HOPLIMIT;
50150Sstevel@tonic-gate }
50160Sstevel@tonic-gate
50170Sstevel@tonic-gate if (mcg_arg->mcg_attr.mc_scope) {
50180Sstevel@tonic-gate mcg_req.Scope = mcg_arg->mcg_attr.mc_scope;
50190Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_SCOPE;
50200Sstevel@tonic-gate }
50210Sstevel@tonic-gate
50220Sstevel@tonic-gate if (mcg_arg->mcg_attr.mc_mlid) {
50230Sstevel@tonic-gate mcg_req.MLID = mcg_arg->mcg_attr.mc_mlid;
50240Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_MLID;
50250Sstevel@tonic-gate }
50260Sstevel@tonic-gate
50270Sstevel@tonic-gate /* Get SA Access Handle. */
50280Sstevel@tonic-gate hcap = ibcm_find_hca_entry(hca_port.hp_hca_guid);
50290Sstevel@tonic-gate if (hcap == NULL) {
50300Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: NO HCA found");
50310Sstevel@tonic-gate
50320Sstevel@tonic-gate retval = IBT_HCA_BUSY_DETACHING;
50330Sstevel@tonic-gate goto ibcm_join_mcg_exit1;
50340Sstevel@tonic-gate }
50350Sstevel@tonic-gate
50360Sstevel@tonic-gate saa_handle = ibcm_get_saa_handle(hcap, hca_port.hp_port);
50370Sstevel@tonic-gate if (saa_handle == NULL) {
50380Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: SA Handle NULL");
50390Sstevel@tonic-gate
50400Sstevel@tonic-gate retval = IBT_HCA_PORT_NOT_ACTIVE;
50410Sstevel@tonic-gate goto ibcm_join_mcg_exit;
50420Sstevel@tonic-gate }
50430Sstevel@tonic-gate
50440Sstevel@tonic-gate if ((mcg_arg->mcg_attr.mc_pgid.gid_prefix != 0) &&
50450Sstevel@tonic-gate (mcg_arg->mcg_attr.mc_pgid.gid_guid != 0)) {
50460Sstevel@tonic-gate retval = ibtl_cm_get_hca_port(mcg_arg->mcg_attr.mc_pgid, 0,
50470Sstevel@tonic-gate &hca_port);
50480Sstevel@tonic-gate if (retval != IBT_SUCCESS) {
50490Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: Failed "
50500Sstevel@tonic-gate "to get PortInfo of specified PGID: status = %d",
50510Sstevel@tonic-gate retval);
50520Sstevel@tonic-gate goto ibcm_join_mcg_exit1;
50530Sstevel@tonic-gate }
50540Sstevel@tonic-gate }
50550Sstevel@tonic-gate
50560Sstevel@tonic-gate /* Contact SA Access */
50570Sstevel@tonic-gate access_args.sq_attr_id = SA_MCMEMBERRECORD_ATTRID;
50580Sstevel@tonic-gate access_args.sq_access_type = IBMF_SAA_UPDATE;
50590Sstevel@tonic-gate access_args.sq_component_mask = component_mask;
50600Sstevel@tonic-gate access_args.sq_template = &mcg_req;
50610Sstevel@tonic-gate access_args.sq_template_length = sizeof (sa_mcmember_record_t);
50620Sstevel@tonic-gate access_args.sq_callback = NULL;
50630Sstevel@tonic-gate access_args.sq_callback_arg = NULL;
50640Sstevel@tonic-gate
50650Sstevel@tonic-gate retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
50660Sstevel@tonic-gate (void **)&mcg_resp);
50670Sstevel@tonic-gate if (retval != IBT_SUCCESS) {
50680Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: "
50690Sstevel@tonic-gate "SA Access Failed");
50700Sstevel@tonic-gate goto ibcm_join_mcg_exit;
50710Sstevel@tonic-gate }
50720Sstevel@tonic-gate
50730Sstevel@tonic-gate num_records = length/sizeof (sa_mcmember_record_t);
50740Sstevel@tonic-gate
50750Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_process_join_mcg: "
50760Sstevel@tonic-gate "Found %d MCMember Records", num_records);
50770Sstevel@tonic-gate
50780Sstevel@tonic-gate /* Validate the returned number of records. */
50790Sstevel@tonic-gate if ((mcg_resp != NULL) && (num_records > 0)) {
50800Sstevel@tonic-gate /* Update the return values. */
50810Sstevel@tonic-gate mcg_info_p->mc_adds_vect.av_dgid = mcg_resp->MGID;
50820Sstevel@tonic-gate mcg_info_p->mc_adds_vect.av_sgid = mcg_resp->PortGID;
50830Sstevel@tonic-gate mcg_info_p->mc_adds_vect.av_srate = mcg_resp->Rate;
50840Sstevel@tonic-gate mcg_info_p->mc_adds_vect.av_srvl = mcg_resp->SL;
50850Sstevel@tonic-gate mcg_info_p->mc_adds_vect.av_flow = mcg_resp->FlowLabel;
50860Sstevel@tonic-gate mcg_info_p->mc_adds_vect.av_tclass = mcg_resp->TClass;
50870Sstevel@tonic-gate mcg_info_p->mc_adds_vect.av_hop = mcg_resp->HopLimit;
50880Sstevel@tonic-gate mcg_info_p->mc_adds_vect.av_send_grh = B_TRUE;
50890Sstevel@tonic-gate mcg_info_p->mc_adds_vect.av_dlid = mcg_resp->MLID;
50900Sstevel@tonic-gate mcg_info_p->mc_mtu = mcg_resp->MTU;
50910Sstevel@tonic-gate mcg_info_p->mc_qkey = mcg_resp->Q_Key;
50920Sstevel@tonic-gate
50930Sstevel@tonic-gate retval = ibt_pkey2index_byguid(hca_port.hp_hca_guid,
50940Sstevel@tonic-gate hca_port.hp_port, mcg_resp->P_Key, &mcg_info_p->mc_pkey_ix);
50950Sstevel@tonic-gate if (retval != IBT_SUCCESS) {
50960Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg: "
50970Sstevel@tonic-gate "Pkey2Index Conversion failed<%d>", retval);
50980Sstevel@tonic-gate mcg_info_p->mc_pkey_ix = 0;
50990Sstevel@tonic-gate }
51000Sstevel@tonic-gate
51010Sstevel@tonic-gate mcg_info_p->mc_scope = mcg_resp->Scope;
51020Sstevel@tonic-gate mcg_info_p->mc_pkt_lt = mcg_resp->PacketLifeTime;
51030Sstevel@tonic-gate
51040Sstevel@tonic-gate mcg_info_p->mc_adds_vect.av_port_num = hca_port.hp_port;
51050Sstevel@tonic-gate mcg_info_p->mc_adds_vect.av_sgid_ix = hca_port.hp_sgid_ix;
51060Sstevel@tonic-gate mcg_info_p->mc_adds_vect.av_src_path = 0;
51070Sstevel@tonic-gate
51089913SShantkumar.Hiremath@Sun.COM /* Add or Incr the matching MCG entry. */
51099913SShantkumar.Hiremath@Sun.COM ibcm_add_incr_mcg_entry(&mcg_req, mcg_resp);
51100Sstevel@tonic-gate /* Deallocate the memory allocated by SA for mcg_resp. */
51110Sstevel@tonic-gate kmem_free(mcg_resp, length);
51129913SShantkumar.Hiremath@Sun.COM
51130Sstevel@tonic-gate retval = IBT_SUCCESS;
51140Sstevel@tonic-gate } else {
51150Sstevel@tonic-gate retval = IBT_MCG_RECORDS_NOT_FOUND;
51160Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg: "
51170Sstevel@tonic-gate "MCG RECORDS NOT FOUND");
51180Sstevel@tonic-gate }
51190Sstevel@tonic-gate
51200Sstevel@tonic-gate ibcm_join_mcg_exit:
51210Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
51220Sstevel@tonic-gate
51230Sstevel@tonic-gate ibcm_join_mcg_exit1:
51240Sstevel@tonic-gate if (mcg_arg->func)
51250Sstevel@tonic-gate (*(mcg_arg->func))(mcg_arg->arg, retval, mcg_info_p);
51260Sstevel@tonic-gate
51270Sstevel@tonic-gate kmem_free(mcg_arg, sizeof (ibcm_join_mcg_tqarg_t));
51280Sstevel@tonic-gate
51290Sstevel@tonic-gate return (retval);
51300Sstevel@tonic-gate }
51310Sstevel@tonic-gate
51320Sstevel@tonic-gate
51330Sstevel@tonic-gate /*
51340Sstevel@tonic-gate * Function:
51350Sstevel@tonic-gate * ibt_leave_mcg
51360Sstevel@tonic-gate * Input:
51370Sstevel@tonic-gate * rgid The request GID that defines the HCA port upon which
51380Sstevel@tonic-gate * to send the request to the Subnet Administrator, to
51390Sstevel@tonic-gate * remove the specified port (port_gid) from the multicast
51400Sstevel@tonic-gate * group. If 'port_gid' is the Reserved GID (i.e.
51410Sstevel@tonic-gate * port_gid.gid_prefix = 0 and port_gid.gid_guid = 0),
51420Sstevel@tonic-gate * then the end-port associated with 'rgid' is removed
51430Sstevel@tonic-gate * from the multicast group.
51440Sstevel@tonic-gate *
51450Sstevel@tonic-gate * mc_gid A multicast group GID as returned from ibt_join_mcg()
51460Sstevel@tonic-gate * call. This is optional, if not specified (i.e.
51470Sstevel@tonic-gate * mc_gid.gid_prefix has 0xFF in its upper 8 bits to
51480Sstevel@tonic-gate * identify this as being a multicast GID), then the
51490Sstevel@tonic-gate * port is removed from all the multicast groups of
51500Sstevel@tonic-gate * which it is a member.
51510Sstevel@tonic-gate *
51520Sstevel@tonic-gate * port_gid This is optional, if not the Reserved GID (gid_prefix
51530Sstevel@tonic-gate * and gid_guid not equal to 0), then this specifies the
51540Sstevel@tonic-gate * endport GID of the multicast group member being deleted
51550Sstevel@tonic-gate * from the group. If it is the Reserved GID (gid_prefix
51560Sstevel@tonic-gate * and gid_guid equal to 0) then the member endport GID is
51570Sstevel@tonic-gate * determined from 'rgid'.
51580Sstevel@tonic-gate *
51590Sstevel@tonic-gate * mc_join_state The Join State attribute used when the group was joined
51600Sstevel@tonic-gate * using ibt_join_mcg(). This Join State component must
51610Sstevel@tonic-gate * contains at least one bit set to 1 in the same position
51620Sstevel@tonic-gate * as that used during ibt_join_mcg(). i.e. the logical
51630Sstevel@tonic-gate * AND of the two JoinState components is not all zeros.
51640Sstevel@tonic-gate * This Join State component must not have some bits set
51650Sstevel@tonic-gate * which are not set using ibt_join_mcg().
51660Sstevel@tonic-gate * Output:
51670Sstevel@tonic-gate * None.
51680Sstevel@tonic-gate * Returns:
51690Sstevel@tonic-gate * IBT_SUCCESS
51700Sstevel@tonic-gate * IBT_INVALID_PARAM
51710Sstevel@tonic-gate * IBT_MC_GROUP_INVALID
51720Sstevel@tonic-gate * IBT_INSUFF_RESOURCE
51730Sstevel@tonic-gate * Description:
51740Sstevel@tonic-gate * The port associated with the port GID shall be removed from the
51750Sstevel@tonic-gate * multicast group specified by MGID (mc_gid) or from all the multicast
51760Sstevel@tonic-gate * groups of which it is a member if the MGID (mc_gid) is not specified.
51770Sstevel@tonic-gate *
51780Sstevel@tonic-gate * The last full member to leave causes the destruction of the Multicast
51790Sstevel@tonic-gate * Group.
51800Sstevel@tonic-gate */
51810Sstevel@tonic-gate ibt_status_t
ibt_leave_mcg(ib_gid_t rgid,ib_gid_t mc_gid,ib_gid_t port_gid,uint8_t mc_join_state)51820Sstevel@tonic-gate ibt_leave_mcg(ib_gid_t rgid, ib_gid_t mc_gid, ib_gid_t port_gid,
51830Sstevel@tonic-gate uint8_t mc_join_state)
51840Sstevel@tonic-gate {
51850Sstevel@tonic-gate sa_mcmember_record_t mcg_req;
51860Sstevel@tonic-gate ibmf_saa_access_args_t access_args;
51870Sstevel@tonic-gate ibmf_saa_handle_t saa_handle;
51880Sstevel@tonic-gate uint64_t component_mask = 0;
51890Sstevel@tonic-gate int sa_retval;
51900Sstevel@tonic-gate ibt_status_t retval;
51919913SShantkumar.Hiremath@Sun.COM ibcm_status_t ret;
51920Sstevel@tonic-gate ibtl_cm_hca_port_t hca_port;
51930Sstevel@tonic-gate size_t length;
51940Sstevel@tonic-gate void *results_p;
51950Sstevel@tonic-gate ibcm_hca_info_t *hcap;
51969913SShantkumar.Hiremath@Sun.COM uint8_t jstate = 0;
51970Sstevel@tonic-gate
51980Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg(%llX:%llX, %llX:%llX)",
51990Sstevel@tonic-gate rgid.gid_prefix, rgid.gid_guid, mc_gid.gid_prefix, mc_gid.gid_guid);
52000Sstevel@tonic-gate
52010Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg(%llX:%llX, 0x%X)",
52020Sstevel@tonic-gate port_gid.gid_prefix, port_gid.gid_guid, mc_join_state);
52030Sstevel@tonic-gate
52040Sstevel@tonic-gate if ((rgid.gid_prefix == 0) || (rgid.gid_guid == 0)) {
52050Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: RequestGID is required");
52060Sstevel@tonic-gate return (IBT_INVALID_PARAM);
52070Sstevel@tonic-gate }
52080Sstevel@tonic-gate
52090Sstevel@tonic-gate bzero(&mcg_req, sizeof (sa_mcmember_record_t));
52100Sstevel@tonic-gate
52110Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: MGID: %llX%llX",
52120Sstevel@tonic-gate mc_gid.gid_prefix, mc_gid.gid_guid);
52130Sstevel@tonic-gate
52140Sstevel@tonic-gate /* Validate MGID */
52150Sstevel@tonic-gate if ((mc_gid.gid_prefix >> 56ULL & 0xFF) == 0xFF) {
52160Sstevel@tonic-gate mcg_req.MGID = mc_gid;
52170Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_MGID;
52180Sstevel@tonic-gate } else if ((mc_gid.gid_prefix != 0) || (mc_gid.gid_guid != 0)) {
52190Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: Invalid MGID specified");
52200Sstevel@tonic-gate return (IBT_MC_MGID_INVALID);
52210Sstevel@tonic-gate }
52220Sstevel@tonic-gate
52230Sstevel@tonic-gate if ((port_gid.gid_prefix == 0) || (port_gid.gid_guid == 0)) {
52240Sstevel@tonic-gate mcg_req.PortGID = rgid;
52250Sstevel@tonic-gate } else {
52260Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: Performing PROXY Leave");
52270Sstevel@tonic-gate mcg_req.PortGID = port_gid;
52280Sstevel@tonic-gate }
52290Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_PORTGID;
52300Sstevel@tonic-gate
52310Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: Port GID <%llX:%llX>",
52320Sstevel@tonic-gate mcg_req.PortGID.gid_prefix, mcg_req.PortGID.gid_guid);
52330Sstevel@tonic-gate
52340Sstevel@tonic-gate /* Join State */
52350Sstevel@tonic-gate mcg_req.JoinState = mc_join_state;
52360Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_JOINSTATE;
52370Sstevel@tonic-gate
52389913SShantkumar.Hiremath@Sun.COM ret = ibcm_del_decr_mcg_entry(&mcg_req, &jstate);
52399913SShantkumar.Hiremath@Sun.COM if (ret == IBCM_LOOKUP_EXISTS) {
52409913SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: Multiple JoinMCG record "
52419913SShantkumar.Hiremath@Sun.COM " still exists, we shall leave for last leave_mcg call");
52429913SShantkumar.Hiremath@Sun.COM return (IBT_SUCCESS);
52439913SShantkumar.Hiremath@Sun.COM } else if (ret == IBCM_LOOKUP_FAIL) {
52449913SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: No Record found, "
52459913SShantkumar.Hiremath@Sun.COM "continue with leave_mcg call");
52469913SShantkumar.Hiremath@Sun.COM } else if ((ret == IBCM_SUCCESS) && (jstate != 0)) {
52479913SShantkumar.Hiremath@Sun.COM /*
52489913SShantkumar.Hiremath@Sun.COM * Update with cached "jstate", as this will be OR'ed of
52499913SShantkumar.Hiremath@Sun.COM * all ibt_join_mcg() calls for this record.
52509913SShantkumar.Hiremath@Sun.COM */
52519913SShantkumar.Hiremath@Sun.COM mcg_req.JoinState = jstate;
52529913SShantkumar.Hiremath@Sun.COM }
52539913SShantkumar.Hiremath@Sun.COM
52540Sstevel@tonic-gate retval = ibtl_cm_get_hca_port(rgid, 0, &hca_port);
52550Sstevel@tonic-gate if (retval != IBT_SUCCESS) {
52560Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: Failed to get port info "
52570Sstevel@tonic-gate "from specified RGID : status = %d", retval);
52580Sstevel@tonic-gate return (retval);
52590Sstevel@tonic-gate }
52600Sstevel@tonic-gate
52610Sstevel@tonic-gate /* Get SA Access Handle. */
52620Sstevel@tonic-gate hcap = ibcm_find_hca_entry(hca_port.hp_hca_guid);
52630Sstevel@tonic-gate if (hcap == NULL) {
52640Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: "
52650Sstevel@tonic-gate "NO HCA found");
52660Sstevel@tonic-gate return (IBT_HCA_BUSY_DETACHING);
52670Sstevel@tonic-gate }
52680Sstevel@tonic-gate
52690Sstevel@tonic-gate saa_handle = ibcm_get_saa_handle(hcap, hca_port.hp_port);
52700Sstevel@tonic-gate if (saa_handle == NULL) {
52710Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: saa_handle is NULL");
52720Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
52730Sstevel@tonic-gate return (IBT_HCA_PORT_NOT_ACTIVE);
52740Sstevel@tonic-gate }
52750Sstevel@tonic-gate
52760Sstevel@tonic-gate /* Contact SA Access */
52770Sstevel@tonic-gate access_args.sq_attr_id = SA_MCMEMBERRECORD_ATTRID;
52780Sstevel@tonic-gate access_args.sq_access_type = IBMF_SAA_DELETE;
52790Sstevel@tonic-gate access_args.sq_component_mask = component_mask;
52800Sstevel@tonic-gate access_args.sq_template = &mcg_req;
52810Sstevel@tonic-gate access_args.sq_template_length = sizeof (sa_mcmember_record_t);
52820Sstevel@tonic-gate access_args.sq_callback = NULL;
52830Sstevel@tonic-gate access_args.sq_callback_arg = NULL;
52840Sstevel@tonic-gate
52850Sstevel@tonic-gate ibcm_sa_access_enter();
52860Sstevel@tonic-gate
52870Sstevel@tonic-gate sa_retval = ibmf_sa_access(saa_handle, &access_args, 0, &length,
52880Sstevel@tonic-gate &results_p);
52890Sstevel@tonic-gate if (sa_retval != IBMF_SUCCESS) {
52900Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: SA access Failed: %d",
52910Sstevel@tonic-gate sa_retval);
52920Sstevel@tonic-gate (void) ibcm_ibmf_analyze_error(sa_retval);
52930Sstevel@tonic-gate retval = IBT_MC_GROUP_INVALID;
52940Sstevel@tonic-gate }
52950Sstevel@tonic-gate
52960Sstevel@tonic-gate ibcm_sa_access_exit();
52970Sstevel@tonic-gate
52980Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
52990Sstevel@tonic-gate
53000Sstevel@tonic-gate return (retval);
53010Sstevel@tonic-gate }
53020Sstevel@tonic-gate
53030Sstevel@tonic-gate
53040Sstevel@tonic-gate /*
53050Sstevel@tonic-gate * Function:
53060Sstevel@tonic-gate * ibt_query_mcg
53070Sstevel@tonic-gate * Input:
53080Sstevel@tonic-gate * rgid The request GID that defines the HCA port upon which
53090Sstevel@tonic-gate * to send the request to the Subnet Administrator, to
53100Sstevel@tonic-gate * retrieve Multicast Records matching attributes as
53110Sstevel@tonic-gate * specified through 'mcg_attr' argument.
53120Sstevel@tonic-gate *
53130Sstevel@tonic-gate * mcg_attr NULL or a pointer to an ibt_mcg_attr_t structure that
53140Sstevel@tonic-gate * specifies MCG attributes that are to be matched.
53150Sstevel@tonic-gate * Attributes that are not required can be wild carded
53160Sstevel@tonic-gate * by specifying as '0'.
53170Sstevel@tonic-gate *
53180Sstevel@tonic-gate * mcgs_max_num The maximum number of matching multicast groups to
53190Sstevel@tonic-gate * return. If zero, then all available matching multicast
53200Sstevel@tonic-gate * groups are returned.
53210Sstevel@tonic-gate * Output:
53220Sstevel@tonic-gate * mcgs_info_p The address of an ibt_mcg_info_t pointer, where
53230Sstevel@tonic-gate * multicast group information is returned. The actual
53240Sstevel@tonic-gate * number of entries filled in the array is returned in
53250Sstevel@tonic-gate * entries_p.
53260Sstevel@tonic-gate *
53270Sstevel@tonic-gate * entries_p The number of ibt_mcg_attr_t entries returned.
53280Sstevel@tonic-gate * Returns:
53290Sstevel@tonic-gate * IBT_SUCCESS
53300Sstevel@tonic-gate * IBT_INVALID_PARAM
53310Sstevel@tonic-gate * IBT_MCG_RECORDS_NOT_FOUND
53320Sstevel@tonic-gate * Description:
53330Sstevel@tonic-gate * Request information on multicast groups that match the parameters
53340Sstevel@tonic-gate * specified in mcg_attr. Information on each multicast group is returned
53350Sstevel@tonic-gate * to the caller in the form of an array of ibt_mcg_info_t.
53360Sstevel@tonic-gate * ibt_query_mcg() allocates the memory for this array and returns a
53370Sstevel@tonic-gate * pointer to the array (mcgs_p) and the number of entries in the array
53380Sstevel@tonic-gate * (entries_p). This memory should be freed by the client using
53390Sstevel@tonic-gate * ibt_free_mcg_info().
53400Sstevel@tonic-gate */
53410Sstevel@tonic-gate ibt_status_t
ibt_query_mcg(ib_gid_t rgid,ibt_mcg_attr_t * mcg_attr,uint_t mcgs_max_num,ibt_mcg_info_t ** mcgs_info_p,uint_t * entries_p)53420Sstevel@tonic-gate ibt_query_mcg(ib_gid_t rgid, ibt_mcg_attr_t *mcg_attr, uint_t mcgs_max_num,
53430Sstevel@tonic-gate ibt_mcg_info_t **mcgs_info_p, uint_t *entries_p)
53440Sstevel@tonic-gate {
53450Sstevel@tonic-gate sa_mcmember_record_t mcg_req;
53460Sstevel@tonic-gate sa_mcmember_record_t *mcg_resp;
53470Sstevel@tonic-gate ibt_mcg_info_t *mcg_infop;
53480Sstevel@tonic-gate ibmf_saa_access_args_t access_args;
53490Sstevel@tonic-gate ibmf_saa_handle_t saa_handle;
53500Sstevel@tonic-gate uint64_t component_mask = 0;
53510Sstevel@tonic-gate ibt_status_t retval;
53520Sstevel@tonic-gate ibtl_cm_hca_port_t hport;
53530Sstevel@tonic-gate uint_t num_records;
53540Sstevel@tonic-gate size_t length;
53550Sstevel@tonic-gate void *results_p;
53560Sstevel@tonic-gate ib_gid_t port_gid;
53570Sstevel@tonic-gate ibcm_hca_info_t *hcap;
53580Sstevel@tonic-gate
53590Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_query_mcg(%p, %d)", mcg_attr, mcgs_max_num);
53600Sstevel@tonic-gate
53610Sstevel@tonic-gate if ((entries_p == NULL) || (mcgs_info_p == NULL)) {
53620Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: "
53630Sstevel@tonic-gate "entries_p or mcgs_info_p is NULL");
53640Sstevel@tonic-gate return (IBT_INVALID_PARAM);
53650Sstevel@tonic-gate }
53660Sstevel@tonic-gate
53670Sstevel@tonic-gate if ((rgid.gid_prefix == 0) || (rgid.gid_guid == 0)) {
53680Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: RequestGID is required");
53690Sstevel@tonic-gate return (IBT_INVALID_PARAM);
53700Sstevel@tonic-gate }
53710Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_query_mcg: Request GID <%llX:%llX>",
53720Sstevel@tonic-gate rgid.gid_prefix, rgid.gid_guid);
53730Sstevel@tonic-gate
53740Sstevel@tonic-gate bzero(&mcg_req, sizeof (sa_mcmember_record_t));
53750Sstevel@tonic-gate port_gid.gid_prefix = port_gid.gid_guid = 0;
53760Sstevel@tonic-gate
53770Sstevel@tonic-gate if (mcg_attr != NULL) {
53780Sstevel@tonic-gate port_gid = mcg_attr->mc_pgid;
53790Sstevel@tonic-gate
53800Sstevel@tonic-gate if ((port_gid.gid_prefix != 0) && (port_gid.gid_guid != 0)) {
53810Sstevel@tonic-gate mcg_req.PortGID = mcg_attr->mc_pgid;
53820Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_PORTGID;
53830Sstevel@tonic-gate
53840Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_query_mcg: PGID %llX:%llX",
53850Sstevel@tonic-gate port_gid.gid_prefix, port_gid.gid_guid);
53860Sstevel@tonic-gate }
53870Sstevel@tonic-gate
53880Sstevel@tonic-gate /* Is Q_Key specified. */
53890Sstevel@tonic-gate if (mcg_attr->mc_qkey != 0) {
53900Sstevel@tonic-gate mcg_req.Q_Key = mcg_attr->mc_qkey;
53910Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_QKEY;
53920Sstevel@tonic-gate }
53930Sstevel@tonic-gate
53940Sstevel@tonic-gate /* Is P_Key specified. */
53950Sstevel@tonic-gate if (mcg_attr->mc_pkey != 0) {
53960Sstevel@tonic-gate mcg_req.P_Key = mcg_attr->mc_pkey;
53970Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_PKEY;
53980Sstevel@tonic-gate }
53990Sstevel@tonic-gate
54000Sstevel@tonic-gate /* Is MGID specified. */
54010Sstevel@tonic-gate if ((mcg_attr->mc_mgid.gid_prefix >> 56ULL & 0xFF) == 0xFF) {
54020Sstevel@tonic-gate mcg_req.MGID = mcg_attr->mc_mgid;
54030Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_MGID;
54040Sstevel@tonic-gate }
54050Sstevel@tonic-gate
54060Sstevel@tonic-gate /* Is MTU specified. */
54070Sstevel@tonic-gate if (mcg_attr->mc_mtu_req.r_mtu) {
54080Sstevel@tonic-gate mcg_req.MTU = mcg_attr->mc_mtu_req.r_mtu;
54090Sstevel@tonic-gate mcg_req.MTUSelector = mcg_attr->mc_mtu_req.r_selector;
54100Sstevel@tonic-gate
54110Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_MTUSELECTOR |
54120Sstevel@tonic-gate SA_MC_COMPMASK_MTU;
54130Sstevel@tonic-gate }
54140Sstevel@tonic-gate
54150Sstevel@tonic-gate if (mcg_attr->mc_tclass) {
54160Sstevel@tonic-gate mcg_req.TClass = mcg_attr->mc_tclass;
54170Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_TCLASS;
54180Sstevel@tonic-gate }
54190Sstevel@tonic-gate
54200Sstevel@tonic-gate /* Is RATE specified. */
54210Sstevel@tonic-gate if (mcg_attr->mc_rate_req.r_srate) {
54220Sstevel@tonic-gate mcg_req.Rate = mcg_attr->mc_rate_req.r_srate;
54230Sstevel@tonic-gate mcg_req.RateSelector = mcg_attr->mc_rate_req.r_selector;
54240Sstevel@tonic-gate
54250Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_RATESELECTOR |
54260Sstevel@tonic-gate SA_MC_COMPMASK_RATE;
54270Sstevel@tonic-gate }
54280Sstevel@tonic-gate
54290Sstevel@tonic-gate /* Is Packet Life Time specified. */
54300Sstevel@tonic-gate if (mcg_attr->mc_pkt_lt_req.p_pkt_lt) {
54310Sstevel@tonic-gate mcg_req.Rate = mcg_attr->mc_pkt_lt_req.p_pkt_lt;
54320Sstevel@tonic-gate mcg_req.RateSelector =
54330Sstevel@tonic-gate mcg_attr->mc_pkt_lt_req.p_selector;
54340Sstevel@tonic-gate
54350Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_PKTLTSELECTOR |
54360Sstevel@tonic-gate SA_MC_COMPMASK_PKTLT;
54370Sstevel@tonic-gate }
54380Sstevel@tonic-gate
54390Sstevel@tonic-gate if (mcg_attr->mc_hop) {
54400Sstevel@tonic-gate mcg_req.HopLimit = mcg_attr->mc_hop;
54410Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_HOPLIMIT;
54420Sstevel@tonic-gate }
54430Sstevel@tonic-gate
54440Sstevel@tonic-gate if (mcg_attr->mc_flow) {
54450Sstevel@tonic-gate mcg_req.FlowLabel = mcg_attr->mc_flow;
54460Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_FLOWLABEL;
54470Sstevel@tonic-gate }
54480Sstevel@tonic-gate
54490Sstevel@tonic-gate if (mcg_attr->mc_sl) {
54500Sstevel@tonic-gate mcg_req.SL = mcg_attr->mc_sl;
54510Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_SL;
54520Sstevel@tonic-gate }
54530Sstevel@tonic-gate
54540Sstevel@tonic-gate if (mcg_attr->mc_scope) {
54550Sstevel@tonic-gate mcg_req.Scope = mcg_attr->mc_scope;
54560Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_SCOPE;
54570Sstevel@tonic-gate }
54580Sstevel@tonic-gate
54590Sstevel@tonic-gate if (mcg_attr->mc_join_state) {
54600Sstevel@tonic-gate mcg_req.JoinState = mcg_attr->mc_join_state;
54610Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_JOINSTATE;
54620Sstevel@tonic-gate }
54630Sstevel@tonic-gate
54640Sstevel@tonic-gate if (mcg_attr->mc_mlid) {
54650Sstevel@tonic-gate mcg_req.MLID = mcg_attr->mc_mlid;
54660Sstevel@tonic-gate component_mask |= SA_MC_COMPMASK_MLID;
54670Sstevel@tonic-gate }
54680Sstevel@tonic-gate }
54690Sstevel@tonic-gate
54700Sstevel@tonic-gate retval = ibtl_cm_get_hca_port(rgid, 0, &hport);
54710Sstevel@tonic-gate if (retval != IBT_SUCCESS) {
54720Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: Failed to get port info "
54730Sstevel@tonic-gate "from specified RGID : status = %d", retval);
54740Sstevel@tonic-gate return (retval);
54750Sstevel@tonic-gate }
54760Sstevel@tonic-gate
54770Sstevel@tonic-gate /* Get SA Access Handle. */
54780Sstevel@tonic-gate hcap = ibcm_find_hca_entry(hport.hp_hca_guid);
54790Sstevel@tonic-gate if (hcap == NULL) {
54800Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: NO HCA found");
54810Sstevel@tonic-gate return (IBT_HCA_BUSY_DETACHING);
54820Sstevel@tonic-gate }
54830Sstevel@tonic-gate
54840Sstevel@tonic-gate saa_handle = ibcm_get_saa_handle(hcap, hport.hp_port);
54850Sstevel@tonic-gate if (saa_handle == NULL) {
54860Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: saa_handle is NULL");
54870Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
54880Sstevel@tonic-gate return (IBT_HCA_PORT_NOT_ACTIVE);
54890Sstevel@tonic-gate }
54900Sstevel@tonic-gate
54910Sstevel@tonic-gate /* Contact SA Access */
54920Sstevel@tonic-gate access_args.sq_attr_id = SA_MCMEMBERRECORD_ATTRID;
54930Sstevel@tonic-gate access_args.sq_access_type = IBMF_SAA_RETRIEVE;
54940Sstevel@tonic-gate access_args.sq_component_mask = component_mask;
54950Sstevel@tonic-gate access_args.sq_template = &mcg_req;
54960Sstevel@tonic-gate access_args.sq_template_length = sizeof (sa_mcmember_record_t);
54970Sstevel@tonic-gate access_args.sq_callback = NULL;
54980Sstevel@tonic-gate access_args.sq_callback_arg = NULL;
54990Sstevel@tonic-gate
55000Sstevel@tonic-gate retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
55010Sstevel@tonic-gate &results_p);
55020Sstevel@tonic-gate if (retval != IBT_SUCCESS) {
55030Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: SA access Failed");
55040Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
55050Sstevel@tonic-gate return (retval);
55060Sstevel@tonic-gate }
55070Sstevel@tonic-gate
55080Sstevel@tonic-gate num_records = length/sizeof (sa_mcmember_record_t);
55090Sstevel@tonic-gate
55100Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_query_mcg: Found %d MCMember Records",
55110Sstevel@tonic-gate num_records);
55120Sstevel@tonic-gate
55130Sstevel@tonic-gate /* Validate the returned number of records. */
55140Sstevel@tonic-gate if ((results_p != NULL) && (num_records > 0)) {
55150Sstevel@tonic-gate uint_t i;
55160Sstevel@tonic-gate
55170Sstevel@tonic-gate /*
55180Sstevel@tonic-gate * If mcgs_max_num is zero, then return all records else
55190Sstevel@tonic-gate * return only requested number of records
55200Sstevel@tonic-gate */
55210Sstevel@tonic-gate if ((mcgs_max_num != 0) && (num_records > mcgs_max_num)) {
55220Sstevel@tonic-gate /* we are interested in only mcgs_max_num records */
55230Sstevel@tonic-gate num_records = mcgs_max_num;
55240Sstevel@tonic-gate }
55250Sstevel@tonic-gate
55260Sstevel@tonic-gate /*
55270Sstevel@tonic-gate * The SGID returned in "mcg_info_p" buffer should be PortGID,
55280Sstevel@tonic-gate * (mcg_attr->mc_pgid), if 'mcg_attr->mc_pgid' was specified,
55290Sstevel@tonic-gate * else RequestGID (rgid) should be returned.
55300Sstevel@tonic-gate */
55310Sstevel@tonic-gate if ((port_gid.gid_prefix != 0) && (port_gid.gid_guid != 0)) {
55320Sstevel@tonic-gate
55330Sstevel@tonic-gate /* Get sgid_ix and port number of 'port_gid' */
55340Sstevel@tonic-gate retval = ibtl_cm_get_hca_port(port_gid, 0, &hport);
55350Sstevel@tonic-gate if (retval != IBT_SUCCESS) {
55360Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: "
55370Sstevel@tonic-gate "Failed to Get Portinfo for PortGID :"
55380Sstevel@tonic-gate "status = %d", retval);
55390Sstevel@tonic-gate return (retval);
55400Sstevel@tonic-gate }
55410Sstevel@tonic-gate } else {
55420Sstevel@tonic-gate /*
55430Sstevel@tonic-gate * The sgid_ix and port number related to RequestGID
55440Sstevel@tonic-gate * are already obtained at the beginning.
55450Sstevel@tonic-gate */
55460Sstevel@tonic-gate port_gid = rgid;
55470Sstevel@tonic-gate }
55480Sstevel@tonic-gate
55490Sstevel@tonic-gate /*
55500Sstevel@tonic-gate * Allocate memory for return buffer, to be freed in
55510Sstevel@tonic-gate * ibt_free_mcg_info().
55520Sstevel@tonic-gate */
55530Sstevel@tonic-gate mcg_infop = kmem_alloc((num_records * sizeof (ibt_mcg_info_t)),
55540Sstevel@tonic-gate KM_SLEEP);
55550Sstevel@tonic-gate
55560Sstevel@tonic-gate *mcgs_info_p = mcg_infop;
55570Sstevel@tonic-gate *entries_p = num_records;
55580Sstevel@tonic-gate
55590Sstevel@tonic-gate /* Update the return values. */
55600Sstevel@tonic-gate for (i = 0; i < num_records; i++) {
55610Sstevel@tonic-gate
55620Sstevel@tonic-gate mcg_resp = (sa_mcmember_record_t *)((uchar_t *)
55630Sstevel@tonic-gate results_p + i * sizeof (sa_mcmember_record_t));
55640Sstevel@tonic-gate
55650Sstevel@tonic-gate mcg_infop[i].mc_adds_vect.av_dgid = mcg_resp->MGID;
55660Sstevel@tonic-gate mcg_infop[i].mc_adds_vect.av_sgid = port_gid;
55670Sstevel@tonic-gate mcg_infop[i].mc_adds_vect.av_srate = mcg_resp->Rate;
55680Sstevel@tonic-gate mcg_infop[i].mc_adds_vect.av_srvl = mcg_resp->SL;
55690Sstevel@tonic-gate mcg_infop[i].mc_adds_vect.av_flow = mcg_resp->FlowLabel;
55700Sstevel@tonic-gate mcg_infop[i].mc_adds_vect.av_tclass = mcg_resp->TClass;
55710Sstevel@tonic-gate mcg_infop[i].mc_adds_vect.av_hop = mcg_resp->HopLimit;
55720Sstevel@tonic-gate mcg_infop[i].mc_adds_vect.av_port_num = hport.hp_port;
55730Sstevel@tonic-gate mcg_infop[i].mc_adds_vect.av_send_grh = B_TRUE;
55740Sstevel@tonic-gate mcg_infop[i].mc_adds_vect.av_dlid = mcg_resp->MLID;
55750Sstevel@tonic-gate mcg_infop[i].mc_adds_vect.av_sgid_ix = hport.hp_sgid_ix;
55760Sstevel@tonic-gate mcg_infop[i].mc_adds_vect.av_src_path = 0;
55770Sstevel@tonic-gate mcg_infop[i].mc_mtu = mcg_resp->MTU;
55780Sstevel@tonic-gate mcg_infop[i].mc_qkey = mcg_resp->Q_Key;
55790Sstevel@tonic-gate mcg_infop[i].mc_scope = mcg_resp->Scope;
55800Sstevel@tonic-gate mcg_infop[i].mc_pkt_lt = mcg_resp->PacketLifeTime;
55810Sstevel@tonic-gate
55820Sstevel@tonic-gate if (ibt_pkey2index_byguid(hport.hp_hca_guid,
55830Sstevel@tonic-gate hport.hp_port, mcg_resp->P_Key,
55840Sstevel@tonic-gate &mcg_infop[i].mc_pkey_ix) != IBT_SUCCESS) {
55850Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_query_mcg: "
55860Sstevel@tonic-gate "Pkey2Index Conversion failed");
55870Sstevel@tonic-gate mcg_infop[i].mc_pkey_ix = 0;
55880Sstevel@tonic-gate }
55890Sstevel@tonic-gate }
55900Sstevel@tonic-gate
55910Sstevel@tonic-gate /*
55920Sstevel@tonic-gate * Deallocate the memory allocated by SA for results_p.
55930Sstevel@tonic-gate */
55940Sstevel@tonic-gate kmem_free(results_p, length);
55950Sstevel@tonic-gate retval = IBT_SUCCESS;
55960Sstevel@tonic-gate
55970Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_query_mcg: returning %d MCGRecords",
55980Sstevel@tonic-gate num_records);
55990Sstevel@tonic-gate
56000Sstevel@tonic-gate } else {
56010Sstevel@tonic-gate retval = IBT_MCG_RECORDS_NOT_FOUND;
56020Sstevel@tonic-gate *entries_p = 0;
56030Sstevel@tonic-gate
56040Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_query_mcg: MCG RECORDS NOT FOUND");
56050Sstevel@tonic-gate }
56060Sstevel@tonic-gate
56070Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
56080Sstevel@tonic-gate
56090Sstevel@tonic-gate return (retval);
56100Sstevel@tonic-gate }
56110Sstevel@tonic-gate
56120Sstevel@tonic-gate
56130Sstevel@tonic-gate /*
56140Sstevel@tonic-gate * ibt_free_mcg_info()
56150Sstevel@tonic-gate * Free the memory allocated by successful ibt_query_mcg()
56160Sstevel@tonic-gate *
56170Sstevel@tonic-gate * mcgs_info Pointer returned by ibt_query_mcg().
56180Sstevel@tonic-gate *
56190Sstevel@tonic-gate * entries The number of ibt_mcg_info_t entries to free.
56200Sstevel@tonic-gate */
56210Sstevel@tonic-gate void
ibt_free_mcg_info(ibt_mcg_info_t * mcgs_info,uint_t entries)56220Sstevel@tonic-gate ibt_free_mcg_info(ibt_mcg_info_t *mcgs_info, uint_t entries)
56230Sstevel@tonic-gate {
56240Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_free_mcg_info: "
56250Sstevel@tonic-gate "Free <%d> entries from 0x%p", entries, mcgs_info);
56260Sstevel@tonic-gate
56270Sstevel@tonic-gate if ((mcgs_info != NULL) && (entries > 0))
56280Sstevel@tonic-gate kmem_free(mcgs_info, entries * sizeof (ibt_mcg_info_t));
56290Sstevel@tonic-gate else
56300Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_free_mcg_info: "
56310Sstevel@tonic-gate "ERROR: NULL buf pointer or length specified.");
56320Sstevel@tonic-gate }
56330Sstevel@tonic-gate
56340Sstevel@tonic-gate
56350Sstevel@tonic-gate /*
56360Sstevel@tonic-gate * Function:
56370Sstevel@tonic-gate * ibt_gid_to_node_info()
56380Sstevel@tonic-gate * Input:
56390Sstevel@tonic-gate * gid Identifies the IB Node and port for which to obtain
56400Sstevel@tonic-gate * Node information.
56410Sstevel@tonic-gate * Output:
56420Sstevel@tonic-gate * node_info_p A pointer to an ibt_node_info_t structure (allocated
56430Sstevel@tonic-gate * by the caller) in which to return the node information.
56440Sstevel@tonic-gate * Returns:
56450Sstevel@tonic-gate * IBT_SUCCESS
56460Sstevel@tonic-gate * IBT_INVALID_PARAM
56470Sstevel@tonic-gate * IBT_NODE_RECORDS_NOT_FOUND
56480Sstevel@tonic-gate * IBT_NO_HCAS_AVAILABLE
56490Sstevel@tonic-gate * Description:
56500Sstevel@tonic-gate * Retrieve Node Information for the specified GID.
56510Sstevel@tonic-gate */
56520Sstevel@tonic-gate ibt_status_t
ibt_gid_to_node_info(ib_gid_t gid,ibt_node_info_t * node_info_p)56530Sstevel@tonic-gate ibt_gid_to_node_info(ib_gid_t gid, ibt_node_info_t *node_info_p)
56540Sstevel@tonic-gate {
56550Sstevel@tonic-gate sa_node_record_t nr_req, *nr_resp;
56560Sstevel@tonic-gate ibmf_saa_handle_t saa_handle;
56570Sstevel@tonic-gate ibt_status_t retval;
56580Sstevel@tonic-gate ibcm_hca_info_t *hcap;
56590Sstevel@tonic-gate ibtl_cm_hca_port_t hport;
56600Sstevel@tonic-gate int i, j;
56610Sstevel@tonic-gate uint_t num_rec;
56620Sstevel@tonic-gate ib_guid_t *guid_array = NULL;
56630Sstevel@tonic-gate sa_path_record_t *path;
56640Sstevel@tonic-gate size_t len;
56650Sstevel@tonic-gate uint8_t npaths;
56660Sstevel@tonic-gate uint32_t num_hcas = 0;
56670Sstevel@tonic-gate ib_lid_t node_lid;
56680Sstevel@tonic-gate boolean_t local_node = B_FALSE;
56690Sstevel@tonic-gate void *res_p;
56700Sstevel@tonic-gate uint8_t num_ports = 0;
56710Sstevel@tonic-gate
56720Sstevel@tonic-gate
56730Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_gid_to_node_info(%llX:%llX, %p)",
56740Sstevel@tonic-gate gid.gid_prefix, gid.gid_guid, node_info_p);
56750Sstevel@tonic-gate
56760Sstevel@tonic-gate if ((gid.gid_prefix == 0) || (gid.gid_guid == 0)) {
56770Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: GID is required");
56780Sstevel@tonic-gate return (IBT_INVALID_PARAM);
56790Sstevel@tonic-gate }
56800Sstevel@tonic-gate
56810Sstevel@tonic-gate if (node_info_p == NULL) {
56820Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
56830Sstevel@tonic-gate "Return Buf (node_info_p) is NULL.");
56840Sstevel@tonic-gate return (IBT_INVALID_PARAM);
56850Sstevel@tonic-gate }
56860Sstevel@tonic-gate
56870Sstevel@tonic-gate /*
56880Sstevel@tonic-gate * If 'gid' is on local node, then get node lid (i.e. base lid of the
56890Sstevel@tonic-gate * associated port) info via ibtl_cm_get_hca_port() call.
56900Sstevel@tonic-gate */
56910Sstevel@tonic-gate bzero(&hport, sizeof (ibtl_cm_hca_port_t));
56920Sstevel@tonic-gate if (ibtl_cm_get_hca_port(gid, 0, &hport) == IBT_SUCCESS) {
56930Sstevel@tonic-gate
56940Sstevel@tonic-gate hcap = ibcm_find_hca_entry(hport.hp_hca_guid);
56950Sstevel@tonic-gate if (hcap == NULL) {
56960Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
56970Sstevel@tonic-gate "HCA(%llX) info not found", hport.hp_hca_guid);
56980Sstevel@tonic-gate return (IBT_NO_HCAS_AVAILABLE);
56990Sstevel@tonic-gate }
57000Sstevel@tonic-gate num_ports = 1;
57010Sstevel@tonic-gate num_hcas = 1;
57020Sstevel@tonic-gate node_lid = hport.hp_base_lid;
57030Sstevel@tonic-gate local_node = B_TRUE;
57040Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_gid_to_node_info: Local Node: "
57050Sstevel@tonic-gate "LID = 0x%X", node_lid);
57060Sstevel@tonic-gate } else {
57070Sstevel@tonic-gate /* Get the number of HCAs and their GUIDs */
57080Sstevel@tonic-gate num_hcas = ibt_get_hca_list(&guid_array);
57090Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_gid_to_node_info: ibt_get_hca_list "
57100Sstevel@tonic-gate "returned %d hcas", num_hcas);
57110Sstevel@tonic-gate
57120Sstevel@tonic-gate if (num_hcas == 0) {
57130Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
57140Sstevel@tonic-gate "NO HCA's Found on this system");
57150Sstevel@tonic-gate return (IBT_NO_HCAS_AVAILABLE);
57160Sstevel@tonic-gate }
57170Sstevel@tonic-gate }
57180Sstevel@tonic-gate
57190Sstevel@tonic-gate for (i = 0; i < num_hcas; i++) {
57200Sstevel@tonic-gate if (local_node == B_FALSE) {
57210Sstevel@tonic-gate hcap = ibcm_find_hca_entry(guid_array[i]);
57220Sstevel@tonic-gate if (hcap == NULL) {
57230Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
57240Sstevel@tonic-gate "HCA(%llX) info not found", guid_array[i]);
57250Sstevel@tonic-gate retval = IBT_NO_HCAS_AVAILABLE;
57260Sstevel@tonic-gate continue;
57270Sstevel@tonic-gate }
57280Sstevel@tonic-gate num_ports = hcap->hca_num_ports;
57290Sstevel@tonic-gate }
57300Sstevel@tonic-gate
57310Sstevel@tonic-gate for (j = 0; j < num_ports; j++) {
57320Sstevel@tonic-gate uint8_t port = 0;
57330Sstevel@tonic-gate
57340Sstevel@tonic-gate if (local_node == B_TRUE)
57350Sstevel@tonic-gate port = hport.hp_port;
57360Sstevel@tonic-gate else
57370Sstevel@tonic-gate port = j + 1;
57380Sstevel@tonic-gate
57390Sstevel@tonic-gate /* Get SA Access Handle. */
57400Sstevel@tonic-gate saa_handle = ibcm_get_saa_handle(hcap, port);
57410Sstevel@tonic-gate if (saa_handle == NULL) {
57420Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
57430Sstevel@tonic-gate "Port %d of HCA (%llX) is NOT ACTIVE",
57440Sstevel@tonic-gate port, hport.hp_hca_guid);
57450Sstevel@tonic-gate retval = IBT_NODE_RECORDS_NOT_FOUND;
57460Sstevel@tonic-gate continue;
57470Sstevel@tonic-gate }
57480Sstevel@tonic-gate
57490Sstevel@tonic-gate if (local_node == B_FALSE) {
57500Sstevel@tonic-gate ib_gid_t sgid;
57510Sstevel@tonic-gate int sa_ret;
57520Sstevel@tonic-gate
57530Sstevel@tonic-gate /*
57540Sstevel@tonic-gate * Check whether 'gid' and this port has same
57550Sstevel@tonic-gate * subnet prefix. If not, then there is no use
57560Sstevel@tonic-gate * in searching from this port.
57570Sstevel@tonic-gate */
57580Sstevel@tonic-gate sgid = hcap->hca_port_info[j].port_sgid0;
57590Sstevel@tonic-gate if (gid.gid_prefix != sgid.gid_prefix) {
57600Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog,
57610Sstevel@tonic-gate "ibt_gid_to_node_info:Sn_Prefix of "
57620Sstevel@tonic-gate "GID(%llX) and Port's(%llX) differ",
57630Sstevel@tonic-gate gid.gid_prefix, sgid.gid_prefix);
57640Sstevel@tonic-gate retval = IBT_NODE_RECORDS_NOT_FOUND;
57650Sstevel@tonic-gate continue;
57660Sstevel@tonic-gate }
57670Sstevel@tonic-gate
57680Sstevel@tonic-gate /*
57690Sstevel@tonic-gate * First Get Path Records for the specified DGID
57700Sstevel@tonic-gate * from this port (SGID). From Path Records,
57710Sstevel@tonic-gate * note down DLID, then use this DLID as Input
57720Sstevel@tonic-gate * attribute to get NodeRecords from SA Access.
57730Sstevel@tonic-gate */
57740Sstevel@tonic-gate npaths = 1;
57750Sstevel@tonic-gate path = NULL;
57760Sstevel@tonic-gate
57770Sstevel@tonic-gate sa_ret = ibmf_saa_gid_to_pathrecords(saa_handle,
57780Sstevel@tonic-gate sgid, gid, 0, 0, B_TRUE, &npaths, 0, &len,
57790Sstevel@tonic-gate &path);
57800Sstevel@tonic-gate if (sa_ret != IBMF_SUCCESS) {
57810Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog,
57820Sstevel@tonic-gate "ibt_gid_to_node_info: "
57830Sstevel@tonic-gate "ibmf_saa_gid_to_pathrecords() "
57840Sstevel@tonic-gate "returned error: %d ", sa_ret);
57850Sstevel@tonic-gate retval =
57860Sstevel@tonic-gate ibcm_ibmf_analyze_error(sa_ret);
57870Sstevel@tonic-gate continue;
57880Sstevel@tonic-gate } else if ((npaths == 0) || (path == NULL)) {
57890Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog,
57900Sstevel@tonic-gate "ibt_gid_to_node_info: failed (%d) "
57910Sstevel@tonic-gate "to get path records for the DGID "
57920Sstevel@tonic-gate "0x%llX from SGID 0x%llX", sa_ret,
57930Sstevel@tonic-gate gid.gid_guid, sgid.gid_guid);
57940Sstevel@tonic-gate retval = IBT_NODE_RECORDS_NOT_FOUND;
57950Sstevel@tonic-gate continue;
57960Sstevel@tonic-gate }
57970Sstevel@tonic-gate node_lid = path->DLID; /* LID */
57980Sstevel@tonic-gate
57990Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
58000Sstevel@tonic-gate "Remote Node: LID = 0x%X", node_lid);
58010Sstevel@tonic-gate
58020Sstevel@tonic-gate /* Free SA_Access memory for path record. */
58030Sstevel@tonic-gate kmem_free(path, len);
58040Sstevel@tonic-gate }
58050Sstevel@tonic-gate
58060Sstevel@tonic-gate /* Retrieve Node Records from SA Access. */
58070Sstevel@tonic-gate bzero(&nr_req, sizeof (sa_node_record_t));
58080Sstevel@tonic-gate
58090Sstevel@tonic-gate nr_req.LID = node_lid; /* LID */
58100Sstevel@tonic-gate
58110Sstevel@tonic-gate retval = ibcm_get_node_rec(saa_handle, &nr_req,
58120Sstevel@tonic-gate SA_NODEINFO_COMPMASK_NODELID, &res_p, &len);
58130Sstevel@tonic-gate if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
58140Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
58150Sstevel@tonic-gate "failed (%d) to get Node records", retval);
58160Sstevel@tonic-gate continue;
58170Sstevel@tonic-gate } else if (retval != IBT_SUCCESS) {
58180Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
58190Sstevel@tonic-gate "failed (%d) to get Node records", retval);
58200Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
58210Sstevel@tonic-gate goto gid_to_ni_exit;
58220Sstevel@tonic-gate }
58230Sstevel@tonic-gate
58240Sstevel@tonic-gate num_rec = len/sizeof (sa_node_record_t);
58250Sstevel@tonic-gate nr_resp = (sa_node_record_t *)(uchar_t *)res_p;
58260Sstevel@tonic-gate
58270Sstevel@tonic-gate /* Validate the returned number of records. */
58280Sstevel@tonic-gate if ((nr_resp != NULL) && (num_rec > 0)) {
58290Sstevel@tonic-gate
58300Sstevel@tonic-gate IBCM_DUMP_NODE_REC(nr_resp);
58310Sstevel@tonic-gate
58320Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(
58330Sstevel@tonic-gate *node_info_p))
58340Sstevel@tonic-gate
58350Sstevel@tonic-gate node_info_p->n_sys_img_guid =
58360Sstevel@tonic-gate nr_resp->NodeInfo.SystemImageGUID;
58370Sstevel@tonic-gate node_info_p->n_node_guid =
58380Sstevel@tonic-gate nr_resp->NodeInfo.NodeGUID;
58390Sstevel@tonic-gate node_info_p->n_port_guid =
58400Sstevel@tonic-gate nr_resp->NodeInfo.PortGUID;
58410Sstevel@tonic-gate node_info_p->n_dev_id =
58420Sstevel@tonic-gate nr_resp->NodeInfo.DeviceID;
58430Sstevel@tonic-gate node_info_p->n_revision =
58440Sstevel@tonic-gate nr_resp->NodeInfo.Revision;
58450Sstevel@tonic-gate node_info_p->n_vendor_id =
58460Sstevel@tonic-gate nr_resp->NodeInfo.VendorID;
58470Sstevel@tonic-gate node_info_p->n_num_ports =
58480Sstevel@tonic-gate nr_resp->NodeInfo.NumPorts;
58490Sstevel@tonic-gate node_info_p->n_port_num =
58500Sstevel@tonic-gate nr_resp->NodeInfo.LocalPortNum;
58510Sstevel@tonic-gate node_info_p->n_node_type =
58520Sstevel@tonic-gate nr_resp->NodeInfo.NodeType;
58530Sstevel@tonic-gate (void) strncpy(node_info_p->n_description,
58540Sstevel@tonic-gate (char *)&nr_resp->NodeDescription, 64);
58550Sstevel@tonic-gate
58560Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(
58570Sstevel@tonic-gate *node_info_p))
58580Sstevel@tonic-gate
58590Sstevel@tonic-gate /*
58600Sstevel@tonic-gate * Deallocate the memory allocated by SA for
58610Sstevel@tonic-gate * 'nr_resp'.
58620Sstevel@tonic-gate */
58630Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
58640Sstevel@tonic-gate kmem_free(nr_resp, len);
58650Sstevel@tonic-gate retval = IBT_SUCCESS;
58660Sstevel@tonic-gate
58670Sstevel@tonic-gate goto gid_to_ni_exit;
58680Sstevel@tonic-gate } else {
58690Sstevel@tonic-gate retval = IBT_NODE_RECORDS_NOT_FOUND;
58700Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
58710Sstevel@tonic-gate "Node Records NOT found - PortGUID %016llX",
58720Sstevel@tonic-gate gid.gid_guid);
58730Sstevel@tonic-gate }
58740Sstevel@tonic-gate }
58750Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
58760Sstevel@tonic-gate
58770Sstevel@tonic-gate if (local_node == B_TRUE)
58780Sstevel@tonic-gate break;
58790Sstevel@tonic-gate }
58800Sstevel@tonic-gate
58810Sstevel@tonic-gate gid_to_ni_exit:
58820Sstevel@tonic-gate if (guid_array)
58830Sstevel@tonic-gate ibt_free_hca_list(guid_array, num_hcas);
58840Sstevel@tonic-gate
58850Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: done. Status %d", retval);
58860Sstevel@tonic-gate
58870Sstevel@tonic-gate return (retval);
58880Sstevel@tonic-gate }
58890Sstevel@tonic-gate
58900Sstevel@tonic-gate
58919891SRajkumar.Sivaprakasam@Sun.COM ibt_status_t
ibcm_get_node_rec(ibmf_saa_handle_t saa_handle,sa_node_record_t * nr_req,uint64_t component_mask,void * result_p,size_t * len)58920Sstevel@tonic-gate ibcm_get_node_rec(ibmf_saa_handle_t saa_handle, sa_node_record_t *nr_req,
58930Sstevel@tonic-gate uint64_t component_mask, void *result_p, size_t *len)
58940Sstevel@tonic-gate {
58950Sstevel@tonic-gate ibmf_saa_access_args_t args;
58960Sstevel@tonic-gate size_t length;
58970Sstevel@tonic-gate ibt_status_t retval;
58980Sstevel@tonic-gate
58990Sstevel@tonic-gate args.sq_attr_id = SA_NODERECORD_ATTRID;
59000Sstevel@tonic-gate args.sq_template = nr_req;
59010Sstevel@tonic-gate args.sq_access_type = IBMF_SAA_RETRIEVE;
59020Sstevel@tonic-gate args.sq_template_length = sizeof (sa_node_record_t);
59030Sstevel@tonic-gate args.sq_component_mask = component_mask;
59040Sstevel@tonic-gate args.sq_callback = NULL;
59050Sstevel@tonic-gate args.sq_callback_arg = NULL;
59060Sstevel@tonic-gate
59070Sstevel@tonic-gate retval = ibcm_contact_sa_access(saa_handle, &args, &length, result_p);
59080Sstevel@tonic-gate if (retval != IBT_SUCCESS) {
59090Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_get_node_rec: SA Call Failed");
59100Sstevel@tonic-gate return (retval);
59110Sstevel@tonic-gate }
59120Sstevel@tonic-gate
59130Sstevel@tonic-gate *len = length;
59140Sstevel@tonic-gate
59150Sstevel@tonic-gate /* Validate the returned number of records. */
59160Sstevel@tonic-gate if ((result_p != NULL) && (length > 0)) {
59170Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_get_node_rec: Node Records FOUND");
59180Sstevel@tonic-gate
59190Sstevel@tonic-gate /* Got it, done!. */
59200Sstevel@tonic-gate return (IBT_SUCCESS);
59210Sstevel@tonic-gate } else {
59220Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_get_node_rec: Node Rec NOT found");
59230Sstevel@tonic-gate return (IBT_NODE_RECORDS_NOT_FOUND);
59240Sstevel@tonic-gate }
59250Sstevel@tonic-gate }
59260Sstevel@tonic-gate
59270Sstevel@tonic-gate
59280Sstevel@tonic-gate /*
59290Sstevel@tonic-gate * Function:
5930*12965SWilliam.Taylor@Oracle.COM * ibt_lid_to_node_info()
5931*12965SWilliam.Taylor@Oracle.COM * Input:
5932*12965SWilliam.Taylor@Oracle.COM * lid Identifies the IB Node and port for which to obtain
5933*12965SWilliam.Taylor@Oracle.COM * Node information.
5934*12965SWilliam.Taylor@Oracle.COM * Output:
5935*12965SWilliam.Taylor@Oracle.COM * node_info_p A pointer to an ibt_node_info_t structure (allocated
5936*12965SWilliam.Taylor@Oracle.COM * by the caller) in which to return the node information.
5937*12965SWilliam.Taylor@Oracle.COM * Returns:
5938*12965SWilliam.Taylor@Oracle.COM * IBT_SUCCESS
5939*12965SWilliam.Taylor@Oracle.COM * IBT_INVALID_PARAM
5940*12965SWilliam.Taylor@Oracle.COM * IBT_NODE_RECORDS_NOT_FOUND
5941*12965SWilliam.Taylor@Oracle.COM * IBT_NO_HCAS_AVAILABLE
5942*12965SWilliam.Taylor@Oracle.COM * Description:
5943*12965SWilliam.Taylor@Oracle.COM * Retrieve Node Information for the specified LID.
5944*12965SWilliam.Taylor@Oracle.COM */
5945*12965SWilliam.Taylor@Oracle.COM ibt_status_t
ibt_lid_to_node_info(ib_lid_t lid,ibt_node_info_t * node_info_p)5946*12965SWilliam.Taylor@Oracle.COM ibt_lid_to_node_info(ib_lid_t lid, ibt_node_info_t *node_info_p)
5947*12965SWilliam.Taylor@Oracle.COM {
5948*12965SWilliam.Taylor@Oracle.COM ibt_status_t retval;
5949*12965SWilliam.Taylor@Oracle.COM ibcm_hca_info_t *hcap;
5950*12965SWilliam.Taylor@Oracle.COM uint8_t i, j;
5951*12965SWilliam.Taylor@Oracle.COM ib_guid_t *guid_array = NULL;
5952*12965SWilliam.Taylor@Oracle.COM uint_t num_hcas = 0;
5953*12965SWilliam.Taylor@Oracle.COM
5954*12965SWilliam.Taylor@Oracle.COM
5955*12965SWilliam.Taylor@Oracle.COM IBTF_DPRINTF_L4(cmlog, "ibt_lid_to_node_info(0x%lX, %p)",
5956*12965SWilliam.Taylor@Oracle.COM lid, node_info_p);
5957*12965SWilliam.Taylor@Oracle.COM
5958*12965SWilliam.Taylor@Oracle.COM if ((lid == 0) || (node_info_p == NULL)) {
5959*12965SWilliam.Taylor@Oracle.COM IBTF_DPRINTF_L2(cmlog, "ibt_lid_to_node_info: "
5960*12965SWilliam.Taylor@Oracle.COM "Lid is zero, or node_info_p is NULL.");
5961*12965SWilliam.Taylor@Oracle.COM return (IBT_INVALID_PARAM);
5962*12965SWilliam.Taylor@Oracle.COM }
5963*12965SWilliam.Taylor@Oracle.COM
5964*12965SWilliam.Taylor@Oracle.COM /* Get the number of HCAs and their GUIDs */
5965*12965SWilliam.Taylor@Oracle.COM num_hcas = ibt_get_hca_list(&guid_array);
5966*12965SWilliam.Taylor@Oracle.COM IBTF_DPRINTF_L4(cmlog, "ibt_lid_to_node_info: ibt_get_hca_list "
5967*12965SWilliam.Taylor@Oracle.COM "returned %d hcas", num_hcas);
5968*12965SWilliam.Taylor@Oracle.COM
5969*12965SWilliam.Taylor@Oracle.COM if (num_hcas == 0) {
5970*12965SWilliam.Taylor@Oracle.COM IBTF_DPRINTF_L2(cmlog, "ibt_lid_to_node_info: "
5971*12965SWilliam.Taylor@Oracle.COM "NO HCA's Found on this system");
5972*12965SWilliam.Taylor@Oracle.COM return (IBT_NO_HCAS_AVAILABLE);
5973*12965SWilliam.Taylor@Oracle.COM }
5974*12965SWilliam.Taylor@Oracle.COM
5975*12965SWilliam.Taylor@Oracle.COM for (i = 0; i < num_hcas; i++) {
5976*12965SWilliam.Taylor@Oracle.COM hcap = ibcm_find_hca_entry(guid_array[i]);
5977*12965SWilliam.Taylor@Oracle.COM if (hcap == NULL) {
5978*12965SWilliam.Taylor@Oracle.COM IBTF_DPRINTF_L3(cmlog, "ibt_lid_to_node_info: "
5979*12965SWilliam.Taylor@Oracle.COM "HCA(%llX) info not found", guid_array[i]);
5980*12965SWilliam.Taylor@Oracle.COM retval = IBT_NO_HCAS_AVAILABLE;
5981*12965SWilliam.Taylor@Oracle.COM continue;
5982*12965SWilliam.Taylor@Oracle.COM }
5983*12965SWilliam.Taylor@Oracle.COM
5984*12965SWilliam.Taylor@Oracle.COM for (j = 0; j < hcap->hca_num_ports; j++) {
5985*12965SWilliam.Taylor@Oracle.COM uint8_t port;
5986*12965SWilliam.Taylor@Oracle.COM ibmf_saa_handle_t saa_handle;
5987*12965SWilliam.Taylor@Oracle.COM uint_t num_rec;
5988*12965SWilliam.Taylor@Oracle.COM size_t len;
5989*12965SWilliam.Taylor@Oracle.COM void *res_p;
5990*12965SWilliam.Taylor@Oracle.COM sa_node_record_t nr_req, *nr_resp;
5991*12965SWilliam.Taylor@Oracle.COM
5992*12965SWilliam.Taylor@Oracle.COM port = j + 1;
5993*12965SWilliam.Taylor@Oracle.COM
5994*12965SWilliam.Taylor@Oracle.COM /* Get SA Access Handle. */
5995*12965SWilliam.Taylor@Oracle.COM saa_handle = ibcm_get_saa_handle(hcap, port);
5996*12965SWilliam.Taylor@Oracle.COM if (saa_handle == NULL) {
5997*12965SWilliam.Taylor@Oracle.COM IBTF_DPRINTF_L3(cmlog, "ibt_lid_to_node_info: "
5998*12965SWilliam.Taylor@Oracle.COM "Port %d of HCA (%llX) is NOT ACTIVE",
5999*12965SWilliam.Taylor@Oracle.COM port, guid_array[i]);
6000*12965SWilliam.Taylor@Oracle.COM retval = IBT_NODE_RECORDS_NOT_FOUND;
6001*12965SWilliam.Taylor@Oracle.COM continue;
6002*12965SWilliam.Taylor@Oracle.COM }
6003*12965SWilliam.Taylor@Oracle.COM
6004*12965SWilliam.Taylor@Oracle.COM /* Retrieve Node Records from SA Access. */
6005*12965SWilliam.Taylor@Oracle.COM bzero(&nr_req, sizeof (sa_node_record_t));
6006*12965SWilliam.Taylor@Oracle.COM
6007*12965SWilliam.Taylor@Oracle.COM nr_req.LID = lid; /* LID */
6008*12965SWilliam.Taylor@Oracle.COM
6009*12965SWilliam.Taylor@Oracle.COM retval = ibcm_get_node_rec(saa_handle, &nr_req,
6010*12965SWilliam.Taylor@Oracle.COM SA_NODEINFO_COMPMASK_NODELID, &res_p, &len);
6011*12965SWilliam.Taylor@Oracle.COM if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
6012*12965SWilliam.Taylor@Oracle.COM IBTF_DPRINTF_L2(cmlog, "ibt_lid_to_node_info: "
6013*12965SWilliam.Taylor@Oracle.COM "failed (%d) to get Node records", retval);
6014*12965SWilliam.Taylor@Oracle.COM continue;
6015*12965SWilliam.Taylor@Oracle.COM } else if (retval != IBT_SUCCESS) {
6016*12965SWilliam.Taylor@Oracle.COM IBTF_DPRINTF_L2(cmlog, "ibt_lid_to_node_info: "
6017*12965SWilliam.Taylor@Oracle.COM "failed (%d) to get Node records", retval);
6018*12965SWilliam.Taylor@Oracle.COM ibcm_dec_hca_acc_cnt(hcap);
6019*12965SWilliam.Taylor@Oracle.COM goto lid_to_ni_exit;
6020*12965SWilliam.Taylor@Oracle.COM }
6021*12965SWilliam.Taylor@Oracle.COM
6022*12965SWilliam.Taylor@Oracle.COM num_rec = len/sizeof (sa_node_record_t);
6023*12965SWilliam.Taylor@Oracle.COM nr_resp = (sa_node_record_t *)(uchar_t *)res_p;
6024*12965SWilliam.Taylor@Oracle.COM
6025*12965SWilliam.Taylor@Oracle.COM /* Validate the returned number of records. */
6026*12965SWilliam.Taylor@Oracle.COM if ((nr_resp != NULL) && (num_rec > 0)) {
6027*12965SWilliam.Taylor@Oracle.COM
6028*12965SWilliam.Taylor@Oracle.COM IBCM_DUMP_NODE_REC(nr_resp);
6029*12965SWilliam.Taylor@Oracle.COM
6030*12965SWilliam.Taylor@Oracle.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(
6031*12965SWilliam.Taylor@Oracle.COM *node_info_p))
6032*12965SWilliam.Taylor@Oracle.COM
6033*12965SWilliam.Taylor@Oracle.COM node_info_p->n_sys_img_guid =
6034*12965SWilliam.Taylor@Oracle.COM nr_resp->NodeInfo.SystemImageGUID;
6035*12965SWilliam.Taylor@Oracle.COM node_info_p->n_node_guid =
6036*12965SWilliam.Taylor@Oracle.COM nr_resp->NodeInfo.NodeGUID;
6037*12965SWilliam.Taylor@Oracle.COM node_info_p->n_port_guid =
6038*12965SWilliam.Taylor@Oracle.COM nr_resp->NodeInfo.PortGUID;
6039*12965SWilliam.Taylor@Oracle.COM node_info_p->n_dev_id =
6040*12965SWilliam.Taylor@Oracle.COM nr_resp->NodeInfo.DeviceID;
6041*12965SWilliam.Taylor@Oracle.COM node_info_p->n_revision =
6042*12965SWilliam.Taylor@Oracle.COM nr_resp->NodeInfo.Revision;
6043*12965SWilliam.Taylor@Oracle.COM node_info_p->n_vendor_id =
6044*12965SWilliam.Taylor@Oracle.COM nr_resp->NodeInfo.VendorID;
6045*12965SWilliam.Taylor@Oracle.COM node_info_p->n_num_ports =
6046*12965SWilliam.Taylor@Oracle.COM nr_resp->NodeInfo.NumPorts;
6047*12965SWilliam.Taylor@Oracle.COM node_info_p->n_port_num =
6048*12965SWilliam.Taylor@Oracle.COM nr_resp->NodeInfo.LocalPortNum;
6049*12965SWilliam.Taylor@Oracle.COM node_info_p->n_node_type =
6050*12965SWilliam.Taylor@Oracle.COM nr_resp->NodeInfo.NodeType;
6051*12965SWilliam.Taylor@Oracle.COM (void) strncpy(node_info_p->n_description,
6052*12965SWilliam.Taylor@Oracle.COM (char *)&nr_resp->NodeDescription, 64);
6053*12965SWilliam.Taylor@Oracle.COM
6054*12965SWilliam.Taylor@Oracle.COM _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(
6055*12965SWilliam.Taylor@Oracle.COM *node_info_p))
6056*12965SWilliam.Taylor@Oracle.COM
6057*12965SWilliam.Taylor@Oracle.COM /*
6058*12965SWilliam.Taylor@Oracle.COM * Deallocate the memory allocated by SA for
6059*12965SWilliam.Taylor@Oracle.COM * 'nr_resp'.
6060*12965SWilliam.Taylor@Oracle.COM */
6061*12965SWilliam.Taylor@Oracle.COM ibcm_dec_hca_acc_cnt(hcap);
6062*12965SWilliam.Taylor@Oracle.COM kmem_free(nr_resp, len);
6063*12965SWilliam.Taylor@Oracle.COM retval = IBT_SUCCESS;
6064*12965SWilliam.Taylor@Oracle.COM
6065*12965SWilliam.Taylor@Oracle.COM goto lid_to_ni_exit;
6066*12965SWilliam.Taylor@Oracle.COM } else {
6067*12965SWilliam.Taylor@Oracle.COM retval = IBT_NODE_RECORDS_NOT_FOUND;
6068*12965SWilliam.Taylor@Oracle.COM IBTF_DPRINTF_L3(cmlog, "ibt_lid_to_node_info: "
6069*12965SWilliam.Taylor@Oracle.COM "Node Records NOT found - LID 0x%lX",
6070*12965SWilliam.Taylor@Oracle.COM lid);
6071*12965SWilliam.Taylor@Oracle.COM }
6072*12965SWilliam.Taylor@Oracle.COM }
6073*12965SWilliam.Taylor@Oracle.COM ibcm_dec_hca_acc_cnt(hcap);
6074*12965SWilliam.Taylor@Oracle.COM }
6075*12965SWilliam.Taylor@Oracle.COM
6076*12965SWilliam.Taylor@Oracle.COM lid_to_ni_exit:
6077*12965SWilliam.Taylor@Oracle.COM if (guid_array)
6078*12965SWilliam.Taylor@Oracle.COM ibt_free_hca_list(guid_array, num_hcas);
6079*12965SWilliam.Taylor@Oracle.COM
6080*12965SWilliam.Taylor@Oracle.COM IBTF_DPRINTF_L3(cmlog, "ibt_lid_to_node_info: done. Status %d", retval);
6081*12965SWilliam.Taylor@Oracle.COM
6082*12965SWilliam.Taylor@Oracle.COM return (retval);
6083*12965SWilliam.Taylor@Oracle.COM }
6084*12965SWilliam.Taylor@Oracle.COM
6085*12965SWilliam.Taylor@Oracle.COM /*
6086*12965SWilliam.Taylor@Oracle.COM * Function:
60870Sstevel@tonic-gate * ibt_get_companion_port_gids()
60880Sstevel@tonic-gate * Description:
60890Sstevel@tonic-gate * Get list of GID's available on a companion port(s) of the specified
60900Sstevel@tonic-gate * GID or list of GIDs available on a specified Node GUID/SystemImage GUID.
60910Sstevel@tonic-gate */
60920Sstevel@tonic-gate ibt_status_t
ibt_get_companion_port_gids(ib_gid_t gid,ib_guid_t hca_guid,ib_guid_t sysimg_guid,ib_gid_t ** gids_p,uint_t * num_gids_p)60930Sstevel@tonic-gate ibt_get_companion_port_gids(ib_gid_t gid, ib_guid_t hca_guid,
60940Sstevel@tonic-gate ib_guid_t sysimg_guid, ib_gid_t **gids_p, uint_t *num_gids_p)
60950Sstevel@tonic-gate {
60960Sstevel@tonic-gate sa_node_record_t nr_req, *nr_resp;
60970Sstevel@tonic-gate void *res_p;
60980Sstevel@tonic-gate ibmf_saa_handle_t saa_handle;
60990Sstevel@tonic-gate int sa_ret;
61001495Shiremath ibt_status_t retval = IBT_SUCCESS;
61010Sstevel@tonic-gate ibcm_hca_info_t *hcap;
61020Sstevel@tonic-gate ibtl_cm_hca_port_t hport;
61030Sstevel@tonic-gate int i, j;
61040Sstevel@tonic-gate uint_t num_rec;
61050Sstevel@tonic-gate ib_guid_t *guid_array = NULL;
61060Sstevel@tonic-gate sa_path_record_t *path;
61070Sstevel@tonic-gate size_t len;
61080Sstevel@tonic-gate uint8_t npaths;
61090Sstevel@tonic-gate uint32_t num_hcas = 0;
61100Sstevel@tonic-gate boolean_t local_node = B_FALSE;
61110Sstevel@tonic-gate boolean_t local_hca = B_FALSE;
61120Sstevel@tonic-gate ib_guid_t h_guid = hca_guid;
61130Sstevel@tonic-gate ib_gid_t *gidp = NULL, *t_gidp = NULL;
6114401Shiremath int multi_hca_loop = 0;
61150Sstevel@tonic-gate
61160Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_get_companion_port_gids(%llX:%llX, %llX, "
61170Sstevel@tonic-gate "%llX)", gid.gid_prefix, gid.gid_guid, hca_guid, sysimg_guid);
61180Sstevel@tonic-gate
61190Sstevel@tonic-gate if (((gid.gid_prefix == 0) || (gid.gid_guid == 0)) && (hca_guid == 0) &&
61200Sstevel@tonic-gate (sysimg_guid == 0)) {
61210Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_get_companion_port_gids: "
61220Sstevel@tonic-gate "Null Input attribute specified.");
61230Sstevel@tonic-gate return (IBT_INVALID_PARAM);
61240Sstevel@tonic-gate }
61250Sstevel@tonic-gate
61260Sstevel@tonic-gate if ((num_gids_p == NULL) || (gids_p == NULL)) {
61270Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_get_companion_port_gids: "
61280Sstevel@tonic-gate "num_gids_p or gids_p is NULL");
61290Sstevel@tonic-gate return (IBT_INVALID_PARAM);
61300Sstevel@tonic-gate }
61310Sstevel@tonic-gate
61320Sstevel@tonic-gate *num_gids_p = 0;
61330Sstevel@tonic-gate
61340Sstevel@tonic-gate /* Get the number of HCAs and their GUIDs */
61350Sstevel@tonic-gate if ((num_hcas = ibt_get_hca_list(&guid_array)) == 0) {
61360Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_get_companion_port_gids: "
61370Sstevel@tonic-gate "NO HCA's Found on this system");
61380Sstevel@tonic-gate return (IBT_NO_HCAS_AVAILABLE);
61390Sstevel@tonic-gate }
61400Sstevel@tonic-gate
61410Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_get_companion_port_gids: "
61420Sstevel@tonic-gate "ibt_get_hca_list() returned %d hcas", num_hcas);
61430Sstevel@tonic-gate
61440Sstevel@tonic-gate /*
61450Sstevel@tonic-gate * If 'gid' is on local node, then get node lid (i.e. base lid of the
61460Sstevel@tonic-gate * associated port) info via ibtl_cm_get_hca_port() call.
61470Sstevel@tonic-gate */
61480Sstevel@tonic-gate bzero(&hport, sizeof (ibtl_cm_hca_port_t));
61490Sstevel@tonic-gate if ((gid.gid_prefix != 0) && (gid.gid_guid != 0) &&
61500Sstevel@tonic-gate (ibtl_cm_get_hca_port(gid, 0, &hport) == IBT_SUCCESS)) {
61510Sstevel@tonic-gate
61520Sstevel@tonic-gate if ((hca_guid != 0) && (hca_guid != hport.hp_hca_guid)) {
61530Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibt_get_companion_port_gids: "
61540Sstevel@tonic-gate "Invalid GID<->HCAGUID combination specified.");
61550Sstevel@tonic-gate retval = IBT_INVALID_PARAM;
61560Sstevel@tonic-gate goto get_comp_pgid_exit;
61570Sstevel@tonic-gate }
61580Sstevel@tonic-gate h_guid = hport.hp_hca_guid;
61590Sstevel@tonic-gate local_node = B_TRUE;
61600Sstevel@tonic-gate
61610Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibt_get_companion_port_gids: "
61620Sstevel@tonic-gate "Local Node: HCA (0x%llX)", h_guid);
61630Sstevel@tonic-gate } else if (h_guid) { /* Is specified HCA GUID - local? */
61640Sstevel@tonic-gate for (i = 0; i < num_hcas; i++) {
61650Sstevel@tonic-gate if (h_guid == guid_array[i]) {
61660Sstevel@tonic-gate local_hca = B_TRUE;
61670Sstevel@tonic-gate break;
61680Sstevel@tonic-gate }
61690Sstevel@tonic-gate }
61700Sstevel@tonic-gate } else if (sysimg_guid) { /* Is specified SystemImage GUID - local? */
61710Sstevel@tonic-gate for (i = 0; i < num_hcas; i++) {
61720Sstevel@tonic-gate ibt_status_t ret;
61730Sstevel@tonic-gate ibt_hca_attr_t hca_attr;
61740Sstevel@tonic-gate
61750Sstevel@tonic-gate ret = ibt_query_hca_byguid(guid_array[i], &hca_attr);
61760Sstevel@tonic-gate if (ret != IBT_SUCCESS) {
61770Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog,
61780Sstevel@tonic-gate "ibt_get_companion_port_gids: HCA(%llX) "
61790Sstevel@tonic-gate "info not found", guid_array[i]);
61800Sstevel@tonic-gate retval = IBT_NO_HCAS_AVAILABLE;
61810Sstevel@tonic-gate continue;
61820Sstevel@tonic-gate }
61830Sstevel@tonic-gate if (hca_attr.hca_si_guid == sysimg_guid) {
61840Sstevel@tonic-gate if ((hca_guid != 0) &&
61850Sstevel@tonic-gate (hca_guid != hca_attr.hca_node_guid)) {
61860Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog,
61870Sstevel@tonic-gate "ibt_get_companion_port_gids: "
61880Sstevel@tonic-gate "Invalid SysImg<->HCA GUID "
61890Sstevel@tonic-gate "combination specified.");
61900Sstevel@tonic-gate retval = IBT_INVALID_PARAM;
61910Sstevel@tonic-gate goto get_comp_pgid_exit;
61920Sstevel@tonic-gate }
61930Sstevel@tonic-gate local_hca = B_TRUE;
61940Sstevel@tonic-gate h_guid = hca_attr.hca_node_guid;
61950Sstevel@tonic-gate break;
61960Sstevel@tonic-gate }
61970Sstevel@tonic-gate }
61980Sstevel@tonic-gate }
61990Sstevel@tonic-gate
62000Sstevel@tonic-gate if ((local_node == B_TRUE) || (local_hca == B_TRUE)) {
62010Sstevel@tonic-gate retval = ibtl_cm_get_local_comp_gids(h_guid, gid, gids_p,
62020Sstevel@tonic-gate num_gids_p);
62030Sstevel@tonic-gate goto get_comp_pgid_exit;
62040Sstevel@tonic-gate }
62050Sstevel@tonic-gate
6206401Shiremath get_comp_for_multihca:
62070Sstevel@tonic-gate /* We will be here, if request is for remote node */
62080Sstevel@tonic-gate for (i = 0; i < num_hcas; i++) {
62090Sstevel@tonic-gate int multism;
62106709Shiremath uint_t count = 0;
62110Sstevel@tonic-gate int multi_sm_loop = 0;
62120Sstevel@tonic-gate uint_t k = 0, l;
62130Sstevel@tonic-gate
62140Sstevel@tonic-gate hcap = ibcm_find_hca_entry(guid_array[i]);
62150Sstevel@tonic-gate if (hcap == NULL) {
62160Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_get_companion_port_gids: "
62170Sstevel@tonic-gate "HCA(%llX) info not found", guid_array[i]);
62180Sstevel@tonic-gate retval = IBT_NO_HCAS_AVAILABLE;
62190Sstevel@tonic-gate continue;
62200Sstevel@tonic-gate }
62210Sstevel@tonic-gate
62220Sstevel@tonic-gate /* 1 - MultiSM, 0 - Single SM */
62230Sstevel@tonic-gate multism = ibtl_cm_is_multi_sm(guid_array[i]);
62240Sstevel@tonic-gate
62250Sstevel@tonic-gate for (j = 0; j < hcap->hca_num_ports; j++) {
62260Sstevel@tonic-gate ib_gid_t sgid;
62270Sstevel@tonic-gate uint64_t c_mask = 0;
62280Sstevel@tonic-gate ib_guid_t pg;
62290Sstevel@tonic-gate uint_t port = j;
62300Sstevel@tonic-gate
62310Sstevel@tonic-gate get_comp_for_multism:
62320Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_get_companion_port_gids: "
62330Sstevel@tonic-gate "Port %d, HCA %llX, MultiSM= %d, Loop=%d",
62340Sstevel@tonic-gate port + 1, h_guid, multism, multi_sm_loop);
62350Sstevel@tonic-gate
62360Sstevel@tonic-gate /* Get SA Access Handle. */
62370Sstevel@tonic-gate saa_handle = ibcm_get_saa_handle(hcap, port + 1);
62380Sstevel@tonic-gate if (saa_handle == NULL) {
62390Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog,
62400Sstevel@tonic-gate "ibt_get_companion_port_gids: "
62411495Shiremath "Port (%d) - NOT ACTIVE", port + 1);
62421495Shiremath retval = IBT_GIDS_NOT_FOUND;
62430Sstevel@tonic-gate continue;
62440Sstevel@tonic-gate }
62450Sstevel@tonic-gate
62460Sstevel@tonic-gate /*
62470Sstevel@tonic-gate * Check whether 'gid' and this port has same subnet
62480Sstevel@tonic-gate * prefix. If not, then there is no use in searching
62490Sstevel@tonic-gate * from this port.
62500Sstevel@tonic-gate */
62510Sstevel@tonic-gate sgid = hcap->hca_port_info[port].port_sgid0;
6252401Shiremath if ((h_guid == 0) && (gid.gid_prefix != 0) &&
6253401Shiremath (multi_sm_loop == 0) &&
62540Sstevel@tonic-gate (gid.gid_prefix != sgid.gid_prefix)) {
62550Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog,
62560Sstevel@tonic-gate "ibt_get_companion_port_gids: SnPrefix of "
62570Sstevel@tonic-gate "GID(%llX) and Port SN_Pfx(%llX) differ",
62580Sstevel@tonic-gate gid.gid_prefix, sgid.gid_prefix);
62591495Shiremath retval = IBT_GIDS_NOT_FOUND;
62600Sstevel@tonic-gate continue;
62610Sstevel@tonic-gate }
62620Sstevel@tonic-gate
62630Sstevel@tonic-gate /*
62640Sstevel@tonic-gate * If HCA GUID or System Image GUID is specified, then
62650Sstevel@tonic-gate * we can achieve our goal sooner!.
62660Sstevel@tonic-gate */
62670Sstevel@tonic-gate if ((h_guid == 0) && (sysimg_guid == 0)) {
62680Sstevel@tonic-gate /* So only GID info is provided. */
62690Sstevel@tonic-gate
62700Sstevel@tonic-gate /*
62710Sstevel@tonic-gate * First Get Path Records for the specified DGID
62720Sstevel@tonic-gate * from this port (SGID). From Path Records,
62730Sstevel@tonic-gate * note down DLID, then use this DLID as Input
62740Sstevel@tonic-gate * attribute to get NodeRecords.
62750Sstevel@tonic-gate */
62760Sstevel@tonic-gate npaths = 1;
62770Sstevel@tonic-gate path = NULL;
62780Sstevel@tonic-gate
62790Sstevel@tonic-gate sa_ret = ibmf_saa_gid_to_pathrecords(saa_handle,
62800Sstevel@tonic-gate sgid, gid, 0, 0, B_TRUE, &npaths, 0, &len,
62810Sstevel@tonic-gate &path);
62820Sstevel@tonic-gate if (sa_ret != IBMF_SUCCESS) {
62830Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog,
62840Sstevel@tonic-gate "ibt_get_companion_port_gids: "
62850Sstevel@tonic-gate "ibmf_saa_gid_to_pathrecords() "
62860Sstevel@tonic-gate "returned error: %d ", sa_ret);
62870Sstevel@tonic-gate retval =
62880Sstevel@tonic-gate ibcm_ibmf_analyze_error(sa_ret);
62890Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
62900Sstevel@tonic-gate goto get_comp_pgid_exit;
62910Sstevel@tonic-gate } else if ((npaths == 0) || (path == NULL)) {
62920Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog,
62930Sstevel@tonic-gate "ibt_get_companion_port_gids: "
62940Sstevel@tonic-gate "failed (%d) to get path records "
62950Sstevel@tonic-gate "for the DGID (0x%llX) from SGID "
62960Sstevel@tonic-gate "(0x%llX)", sa_ret, gid.gid_guid,
62970Sstevel@tonic-gate sgid.gid_guid);
62981495Shiremath retval = IBT_GIDS_NOT_FOUND;
62990Sstevel@tonic-gate continue;
63000Sstevel@tonic-gate }
6301401Shiremath
6302401Shiremath bzero(&nr_req, sizeof (sa_node_record_t));
63030Sstevel@tonic-gate nr_req.LID = path->DLID; /* LID */
63040Sstevel@tonic-gate
63050Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog,
63060Sstevel@tonic-gate "ibt_get_companion_port_gids: "
63070Sstevel@tonic-gate "Remote Node: LID = 0x%X", nr_req.LID);
63080Sstevel@tonic-gate
63090Sstevel@tonic-gate /* Free SA_Access memory for path record. */
63100Sstevel@tonic-gate kmem_free(path, len);
63110Sstevel@tonic-gate
63120Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog,
63130Sstevel@tonic-gate "ibt_get_companion_port_gids: SAA Call: "
63140Sstevel@tonic-gate "based on LID ");
63150Sstevel@tonic-gate
63160Sstevel@tonic-gate retval = ibcm_get_node_rec(saa_handle, &nr_req,
63170Sstevel@tonic-gate SA_NODEINFO_COMPMASK_NODELID, &res_p, &len);
63180Sstevel@tonic-gate if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
63190Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog,
63200Sstevel@tonic-gate "ibt_get_companion_port_gids: "
63210Sstevel@tonic-gate "failed (%d) to get Node records",
63220Sstevel@tonic-gate retval);
63230Sstevel@tonic-gate continue;
63240Sstevel@tonic-gate } else if (retval != IBT_SUCCESS) {
63250Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog,
63260Sstevel@tonic-gate "ibt_get_companion_port_gids: "
63270Sstevel@tonic-gate "failed (%d) to get Node records",
63280Sstevel@tonic-gate retval);
63290Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
63300Sstevel@tonic-gate goto get_comp_pgid_exit;
63310Sstevel@tonic-gate }
63320Sstevel@tonic-gate
63330Sstevel@tonic-gate nr_resp = (sa_node_record_t *)(uchar_t *)res_p;
63340Sstevel@tonic-gate /* Note down HCA GUID info. */
63350Sstevel@tonic-gate h_guid = nr_resp->NodeInfo.NodeGUID;
63360Sstevel@tonic-gate
63370Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog,
63380Sstevel@tonic-gate "ibt_get_companion_port_gids: "
63390Sstevel@tonic-gate "Remote HCA GUID: 0x%llX", h_guid);
63400Sstevel@tonic-gate
63410Sstevel@tonic-gate IBCM_DUMP_NODE_REC(nr_resp);
63420Sstevel@tonic-gate
63430Sstevel@tonic-gate kmem_free(res_p, len);
63440Sstevel@tonic-gate }
63450Sstevel@tonic-gate
6346401Shiremath bzero(&nr_req, sizeof (sa_node_record_t));
63470Sstevel@tonic-gate if (h_guid != 0) {
63480Sstevel@tonic-gate nr_req.NodeInfo.NodeGUID = h_guid;
63490Sstevel@tonic-gate c_mask = SA_NODEINFO_COMPMASK_NODEGUID;
63500Sstevel@tonic-gate }
63510Sstevel@tonic-gate
63520Sstevel@tonic-gate if (sysimg_guid != 0) {
63530Sstevel@tonic-gate nr_req.NodeInfo.SystemImageGUID = sysimg_guid;
63540Sstevel@tonic-gate c_mask |= SA_NODEINFO_COMPMASK_SYSIMAGEGUID;
63550Sstevel@tonic-gate }
63560Sstevel@tonic-gate
63570Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_get_companion_port_gids: "
63580Sstevel@tonic-gate "SAA Call: CMASK= 0x%llX", c_mask);
63590Sstevel@tonic-gate
63600Sstevel@tonic-gate retval = ibcm_get_node_rec(saa_handle, &nr_req, c_mask,
63610Sstevel@tonic-gate &res_p, &len);
63620Sstevel@tonic-gate if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
63630Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog,
63640Sstevel@tonic-gate "ibt_get_companion_port_gids: "
63650Sstevel@tonic-gate "failed (%d) to get Node records", retval);
63660Sstevel@tonic-gate continue;
63670Sstevel@tonic-gate } else if (retval != IBT_SUCCESS) {
63680Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog,
63690Sstevel@tonic-gate "ibt_get_companion_port_gids: Error: (%d) "
63700Sstevel@tonic-gate "while getting Node records", retval);
63710Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
63720Sstevel@tonic-gate goto get_comp_pgid_exit;
63730Sstevel@tonic-gate }
63740Sstevel@tonic-gate
63750Sstevel@tonic-gate num_rec = len/sizeof (sa_node_record_t);
63760Sstevel@tonic-gate
63770Sstevel@tonic-gate /* We will be here, only if we found some NodeRec */
63780Sstevel@tonic-gate if (gid.gid_prefix && gid.gid_guid) {
63790Sstevel@tonic-gate nr_resp = (sa_node_record_t *)res_p;
63800Sstevel@tonic-gate for (l = 0; l < num_rec; l++, nr_resp++) {
63810Sstevel@tonic-gate pg = nr_resp->NodeInfo.PortGUID;
63820Sstevel@tonic-gate if (gid.gid_guid != pg)
63830Sstevel@tonic-gate count++;
63840Sstevel@tonic-gate }
63850Sstevel@tonic-gate } else {
63860Sstevel@tonic-gate count = num_rec;
63870Sstevel@tonic-gate }
63880Sstevel@tonic-gate
63890Sstevel@tonic-gate if (count != 0) {
63900Sstevel@tonic-gate if (multi_sm_loop == 1) {
63910Sstevel@tonic-gate count += k;
63920Sstevel@tonic-gate t_gidp = kmem_zalloc(count *
63930Sstevel@tonic-gate sizeof (ib_gid_t), KM_SLEEP);
63940Sstevel@tonic-gate
63950Sstevel@tonic-gate if ((k != 0) && (gidp != NULL)) {
63960Sstevel@tonic-gate bcopy(gidp, t_gidp,
63970Sstevel@tonic-gate k * sizeof (ib_gid_t));
63980Sstevel@tonic-gate kmem_free(gidp,
63990Sstevel@tonic-gate k * sizeof (ib_gid_t));
64000Sstevel@tonic-gate }
64010Sstevel@tonic-gate gidp = t_gidp;
64020Sstevel@tonic-gate } else {
64030Sstevel@tonic-gate gidp = kmem_zalloc(count *
64040Sstevel@tonic-gate sizeof (ib_gid_t), KM_SLEEP);
64050Sstevel@tonic-gate }
64060Sstevel@tonic-gate *num_gids_p = count;
64070Sstevel@tonic-gate *gids_p = gidp;
64080Sstevel@tonic-gate
64090Sstevel@tonic-gate nr_resp = (sa_node_record_t *)res_p;
64100Sstevel@tonic-gate for (l = 0; l < num_rec; l++, nr_resp++) {
64110Sstevel@tonic-gate IBCM_DUMP_NODE_REC(nr_resp);
64120Sstevel@tonic-gate
64130Sstevel@tonic-gate pg = nr_resp->NodeInfo.PortGUID;
64140Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog,
64150Sstevel@tonic-gate "ibt_get_companion_port_gids: "
64160Sstevel@tonic-gate "PortGID %llX", pg);
64170Sstevel@tonic-gate
64180Sstevel@tonic-gate if (pg != gid.gid_guid) {
64190Sstevel@tonic-gate gidp[k].gid_prefix =
64200Sstevel@tonic-gate sgid.gid_prefix;
64210Sstevel@tonic-gate gidp[k].gid_guid = pg;
64220Sstevel@tonic-gate
64230Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog,
64240Sstevel@tonic-gate "ibt_get_companion_pgids: "
64250Sstevel@tonic-gate "GID[%d] = %llX:%llX", k,
64260Sstevel@tonic-gate gidp[k].gid_prefix,
64270Sstevel@tonic-gate gidp[k].gid_guid);
64280Sstevel@tonic-gate
64290Sstevel@tonic-gate k++;
64300Sstevel@tonic-gate if (k == count)
64310Sstevel@tonic-gate break;
64320Sstevel@tonic-gate }
64330Sstevel@tonic-gate }
64340Sstevel@tonic-gate retval = IBT_SUCCESS; /* done!. */
6435401Shiremath kmem_free(res_p, len);
6436401Shiremath ibcm_dec_hca_acc_cnt(hcap);
6437401Shiremath goto get_comp_pgid_exit;
64380Sstevel@tonic-gate } else {
64390Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog,
64400Sstevel@tonic-gate "ibt_get_companion_port_gids: "
64410Sstevel@tonic-gate "Companion PortGIDs not available");
64420Sstevel@tonic-gate retval = IBT_GIDS_NOT_FOUND;
64430Sstevel@tonic-gate }
64440Sstevel@tonic-gate /* Deallocate the memory for 'res_p'. */
64450Sstevel@tonic-gate kmem_free(res_p, len);
64460Sstevel@tonic-gate
64470Sstevel@tonic-gate /*
64480Sstevel@tonic-gate * If we are on MultiSM setup, then we need to lookout
64490Sstevel@tonic-gate * from that subnet port too.
64500Sstevel@tonic-gate */
64510Sstevel@tonic-gate if (multism) {
64520Sstevel@tonic-gate /* break if already searched both the subnet */
64530Sstevel@tonic-gate if (multi_sm_loop == 1)
64540Sstevel@tonic-gate break;
64550Sstevel@tonic-gate
64560Sstevel@tonic-gate port = (j == 0) ? 1 : 0;
64570Sstevel@tonic-gate multi_sm_loop = 1;
64580Sstevel@tonic-gate goto get_comp_for_multism;
64590Sstevel@tonic-gate } else {
64600Sstevel@tonic-gate break;
64610Sstevel@tonic-gate }
64620Sstevel@tonic-gate }
64630Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(hcap);
6464401Shiremath
6465401Shiremath /*
6466401Shiremath * We may be on dual HCA with dual SM configured system. And
6467401Shiremath * the input attr GID was visible from second HCA. So in order
6468401Shiremath * to get the companion portgid we need to re-look from the
6469401Shiremath * first HCA ports.
6470401Shiremath */
6471401Shiremath if ((num_hcas > 1) && (i > 0) && (h_guid != 0) &&
6472401Shiremath (multi_hca_loop != 1)) {
6473401Shiremath multi_hca_loop = 1;
6474401Shiremath goto get_comp_for_multihca;
6475401Shiremath }
64760Sstevel@tonic-gate }
64771495Shiremath if (*num_gids_p == 0)
64781495Shiremath retval = IBT_GIDS_NOT_FOUND;
64790Sstevel@tonic-gate
64800Sstevel@tonic-gate get_comp_pgid_exit:
64810Sstevel@tonic-gate if (guid_array)
64820Sstevel@tonic-gate ibt_free_hca_list(guid_array, num_hcas);
64830Sstevel@tonic-gate
64840Sstevel@tonic-gate if ((retval != IBT_SUCCESS) && (*num_gids_p != 0)) {
64850Sstevel@tonic-gate retval = IBT_SUCCESS;
64860Sstevel@tonic-gate }
64870Sstevel@tonic-gate
64880Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibt_get_companion_port_gids: done. Status %d, "
64890Sstevel@tonic-gate "Found %d GIDs", retval, *num_gids_p);
64900Sstevel@tonic-gate
64910Sstevel@tonic-gate return (retval);
64920Sstevel@tonic-gate }
64930Sstevel@tonic-gate
64944703Shiremath /* RDMA IP CM Support routines */
64954703Shiremath ibt_status_t
ibt_get_src_ip(ibt_srcip_attr_t * sattr,ibt_srcip_info_t ** src_info_p,uint_t * entries_p)6496*12965SWilliam.Taylor@Oracle.COM ibt_get_src_ip(ibt_srcip_attr_t *sattr, ibt_srcip_info_t **src_info_p,
6497*12965SWilliam.Taylor@Oracle.COM uint_t *entries_p)
64984703Shiremath {
6499*12965SWilliam.Taylor@Oracle.COM ibt_srcip_info_t *s_ip;
65004703Shiremath ibcm_arp_ip_t *ipp;
65014703Shiremath ibcm_arp_ibd_insts_t ibds;
6502*12965SWilliam.Taylor@Oracle.COM uint8_t i, j;
6503*12965SWilliam.Taylor@Oracle.COM uint_t count;
65044703Shiremath ibt_status_t retval = IBT_SUCCESS;
65054703Shiremath
6506*12965SWilliam.Taylor@Oracle.COM IBTF_DPRINTF_L4(cmlog, "ibt_get_src_ip(%p, %p, %p)",
6507*12965SWilliam.Taylor@Oracle.COM sattr, src_info_p, entries_p);
6508*12965SWilliam.Taylor@Oracle.COM
6509*12965SWilliam.Taylor@Oracle.COM if (sattr == NULL || entries_p == NULL) {
6510*12965SWilliam.Taylor@Oracle.COM IBTF_DPRINTF_L3(cmlog, "ibt_get_src_ip: Invalid I/P Args.");
6511*12965SWilliam.Taylor@Oracle.COM return (IBT_INVALID_PARAM);
6512*12965SWilliam.Taylor@Oracle.COM }
6513*12965SWilliam.Taylor@Oracle.COM
6514*12965SWilliam.Taylor@Oracle.COM if (sattr->sip_gid.gid_prefix == 0 || sattr->sip_gid.gid_guid == 0) {
65154703Shiremath IBTF_DPRINTF_L3(cmlog, "ibt_get_src_ip: Invalid GID.");
65164703Shiremath return (IBT_INVALID_PARAM);
65174703Shiremath }
65184703Shiremath
6519*12965SWilliam.Taylor@Oracle.COM /* TBD: Zoneid */
6520*12965SWilliam.Taylor@Oracle.COM retval = ibcm_arp_get_ibds(&ibds, sattr->sip_family);
65214703Shiremath if (retval != IBT_SUCCESS) {
65224703Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_get_src_ip: ibcm_arp_get_ibds "
65234703Shiremath "failed to get IBD Instances: ret 0x%x", retval);
65244703Shiremath goto get_src_ip_end;
65254703Shiremath }
65264703Shiremath
6527*12965SWilliam.Taylor@Oracle.COM count = 0;
65284703Shiremath for (i = 0, ipp = ibds.ibcm_arp_ip; i < ibds.ibcm_arp_ibd_cnt;
65294703Shiremath i++, ipp++) {
653011369SPramod.Gunjikar@Sun.COM if (ipp->ip_inet_family == AF_UNSPEC)
653111369SPramod.Gunjikar@Sun.COM continue;
6532*12965SWilliam.Taylor@Oracle.COM if (ipp->ip_port_gid.gid_prefix == sattr->sip_gid.gid_prefix &&
6533*12965SWilliam.Taylor@Oracle.COM ipp->ip_port_gid.gid_guid == sattr->sip_gid.gid_guid) {
6534*12965SWilliam.Taylor@Oracle.COM if ((sattr->sip_pkey) &&
6535*12965SWilliam.Taylor@Oracle.COM (ipp->ip_pkey != sattr->sip_pkey))
6536*12965SWilliam.Taylor@Oracle.COM continue;
6537*12965SWilliam.Taylor@Oracle.COM
6538*12965SWilliam.Taylor@Oracle.COM if ((sattr->sip_zoneid != ALL_ZONES) &&
6539*12965SWilliam.Taylor@Oracle.COM (sattr->sip_zoneid != ipp->ip_zoneid))
6540*12965SWilliam.Taylor@Oracle.COM continue;
6541*12965SWilliam.Taylor@Oracle.COM
6542*12965SWilliam.Taylor@Oracle.COM count++;
65434703Shiremath break;
65444703Shiremath }
65454703Shiremath }
65464703Shiremath
6547*12965SWilliam.Taylor@Oracle.COM if (count) {
6548*12965SWilliam.Taylor@Oracle.COM /*
6549*12965SWilliam.Taylor@Oracle.COM * Allocate memory for return buffer, to be freed by
6550*12965SWilliam.Taylor@Oracle.COM * ibt_free_srcip_info().
6551*12965SWilliam.Taylor@Oracle.COM */
6552*12965SWilliam.Taylor@Oracle.COM s_ip = kmem_alloc((count * sizeof (ibt_srcip_info_t)),
6553*12965SWilliam.Taylor@Oracle.COM KM_SLEEP);
6554*12965SWilliam.Taylor@Oracle.COM
6555*12965SWilliam.Taylor@Oracle.COM *src_info_p = s_ip;
6556*12965SWilliam.Taylor@Oracle.COM *entries_p = count;
6557*12965SWilliam.Taylor@Oracle.COM
6558*12965SWilliam.Taylor@Oracle.COM j = 0;
6559*12965SWilliam.Taylor@Oracle.COM for (i = 0, ipp = ibds.ibcm_arp_ip; i < ibds.ibcm_arp_ibd_cnt;
6560*12965SWilliam.Taylor@Oracle.COM i++, ipp++) {
6561*12965SWilliam.Taylor@Oracle.COM if (ipp->ip_inet_family == AF_UNSPEC)
6562*12965SWilliam.Taylor@Oracle.COM continue;
6563*12965SWilliam.Taylor@Oracle.COM if ((ipp->ip_port_gid.gid_prefix ==
6564*12965SWilliam.Taylor@Oracle.COM sattr->sip_gid.gid_prefix) &&
6565*12965SWilliam.Taylor@Oracle.COM (ipp->ip_port_gid.gid_guid ==
6566*12965SWilliam.Taylor@Oracle.COM sattr->sip_gid.gid_guid)) {
6567*12965SWilliam.Taylor@Oracle.COM if ((sattr->sip_pkey) &&
6568*12965SWilliam.Taylor@Oracle.COM (ipp->ip_pkey != sattr->sip_pkey))
6569*12965SWilliam.Taylor@Oracle.COM continue;
6570*12965SWilliam.Taylor@Oracle.COM
6571*12965SWilliam.Taylor@Oracle.COM if ((sattr->sip_zoneid != ALL_ZONES) &&
6572*12965SWilliam.Taylor@Oracle.COM (sattr->sip_zoneid != ipp->ip_zoneid))
6573*12965SWilliam.Taylor@Oracle.COM continue;
6574*12965SWilliam.Taylor@Oracle.COM
6575*12965SWilliam.Taylor@Oracle.COM _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s_ip))
6576*12965SWilliam.Taylor@Oracle.COM s_ip[j].ip_addr.family = ipp->ip_inet_family;
6577*12965SWilliam.Taylor@Oracle.COM _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*s_ip))
6578*12965SWilliam.Taylor@Oracle.COM if (s_ip[j].ip_addr.family == AF_INET) {
6579*12965SWilliam.Taylor@Oracle.COM bcopy(&ipp->ip_cm_sin.sin_addr,
6580*12965SWilliam.Taylor@Oracle.COM &s_ip[j].ip_addr.un.ip4addr,
6581*12965SWilliam.Taylor@Oracle.COM sizeof (in_addr_t));
6582*12965SWilliam.Taylor@Oracle.COM } else if (s_ip[j].ip_addr.family == AF_INET6) {
6583*12965SWilliam.Taylor@Oracle.COM bcopy(&ipp->ip_cm_sin6.sin6_addr,
6584*12965SWilliam.Taylor@Oracle.COM &s_ip[j].ip_addr.un.ip6addr,
6585*12965SWilliam.Taylor@Oracle.COM sizeof (in6_addr_t));
6586*12965SWilliam.Taylor@Oracle.COM /* TBD: scope_id */
6587*12965SWilliam.Taylor@Oracle.COM }
6588*12965SWilliam.Taylor@Oracle.COM IBCM_PRINT_IP("ibt_get_src_ip",
6589*12965SWilliam.Taylor@Oracle.COM &s_ip[j].ip_addr);
6590*12965SWilliam.Taylor@Oracle.COM j++;
6591*12965SWilliam.Taylor@Oracle.COM }
6592*12965SWilliam.Taylor@Oracle.COM }
65934703Shiremath } else {
6594*12965SWilliam.Taylor@Oracle.COM retval = IBT_SRC_IP_NOT_FOUND;
65954703Shiremath }
65964703Shiremath
65974703Shiremath get_src_ip_end:
659812163SRamaswamy.Tummala@Sun.COM ibcm_arp_free_ibds(&ibds);
65994703Shiremath return (retval);
66004703Shiremath }
66014703Shiremath
6602*12965SWilliam.Taylor@Oracle.COM /*
6603*12965SWilliam.Taylor@Oracle.COM * ibt_free_srcip_info()
6604*12965SWilliam.Taylor@Oracle.COM * Free the memory allocated by successful ibt_get_src_ip()
6605*12965SWilliam.Taylor@Oracle.COM *
6606*12965SWilliam.Taylor@Oracle.COM * src_info Pointer returned by ibt_get_src_ip().
6607*12965SWilliam.Taylor@Oracle.COM *
6608*12965SWilliam.Taylor@Oracle.COM * entries The number of ibt_ip_addr_t entries to free.
6609*12965SWilliam.Taylor@Oracle.COM */
6610*12965SWilliam.Taylor@Oracle.COM void
ibt_free_srcip_info(ibt_srcip_info_t * src_info,uint_t entries)6611*12965SWilliam.Taylor@Oracle.COM ibt_free_srcip_info(ibt_srcip_info_t *src_info, uint_t entries)
6612*12965SWilliam.Taylor@Oracle.COM {
6613*12965SWilliam.Taylor@Oracle.COM IBTF_DPRINTF_L3(cmlog, "ibt_free_srcip_info: "
6614*12965SWilliam.Taylor@Oracle.COM "Free <%d> entries from 0x%p", entries, src_info);
6615*12965SWilliam.Taylor@Oracle.COM
6616*12965SWilliam.Taylor@Oracle.COM if ((src_info != NULL) && (entries > 0))
6617*12965SWilliam.Taylor@Oracle.COM kmem_free(src_info, entries * sizeof (ibt_srcip_info_t));
6618*12965SWilliam.Taylor@Oracle.COM else
6619*12965SWilliam.Taylor@Oracle.COM IBTF_DPRINTF_L2(cmlog, "ibt_free_srcip_info: "
6620*12965SWilliam.Taylor@Oracle.COM "ERROR: NULL buf pointer or ZERO length specified.");
6621*12965SWilliam.Taylor@Oracle.COM }
6622*12965SWilliam.Taylor@Oracle.COM
6623*12965SWilliam.Taylor@Oracle.COM
66244703Shiremath ib_svc_id_t
ibt_get_ip_sid(uint8_t protocol_num,in_port_t dst_port)66254703Shiremath ibt_get_ip_sid(uint8_t protocol_num, in_port_t dst_port)
66264703Shiremath {
66274703Shiremath ib_svc_id_t sid;
66284703Shiremath
66294703Shiremath IBTF_DPRINTF_L4(cmlog, "ibt_get_ip_sid(%X, %lX)", protocol_num,
66304703Shiremath dst_port);
66314703Shiremath
66324703Shiremath /*
66334703Shiremath * If protocol_num is non-zero, then formulate the SID and return it.
66344703Shiremath * If protocol_num is zero, then we need to assign a locally generated
66354703Shiremath * IP SID with IB_SID_IPADDR_PREFIX.
66364703Shiremath */
66374703Shiremath if (protocol_num) {
66384703Shiremath sid = IB_SID_IPADDR_PREFIX | protocol_num << 16 | dst_port;
66394703Shiremath } else {
66404703Shiremath sid = ibcm_alloc_ip_sid();
66414703Shiremath }
66424703Shiremath
66434703Shiremath IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_sid: SID: 0x%016llX", sid);
66444703Shiremath return (sid);
66454703Shiremath }
66464703Shiremath
66474703Shiremath ibt_status_t
ibt_release_ip_sid(ib_svc_id_t ip_sid)66484703Shiremath ibt_release_ip_sid(ib_svc_id_t ip_sid)
66494703Shiremath {
66504703Shiremath IBTF_DPRINTF_L4(cmlog, "ibt_release_ip_sid(%llX)", ip_sid);
66514703Shiremath
66524703Shiremath if (((ip_sid & IB_SID_IPADDR_PREFIX_MASK) != 0) ||
66534703Shiremath (!(ip_sid & IB_SID_IPADDR_PREFIX))) {
66544703Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_release_ip_sid(0x%016llX): ERROR: "
66554703Shiremath "Called for Non-RDMA IP SID", ip_sid);
66564703Shiremath return (IBT_INVALID_PARAM);
66574703Shiremath }
66584703Shiremath
66594703Shiremath /*
66604703Shiremath * If protocol_num in ip_sid are all ZEROs, then this SID is allocated
66614703Shiremath * by IBTF. If not, then the specified ip_sid is invalid.
66624703Shiremath */
66634703Shiremath if (ip_sid & IB_SID_IPADDR_IPNUM_MASK) {
66644703Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_release_ip_sid(0x%016llX): ERROR: "
66654703Shiremath "Called for Non-IBTF assigned RDMA IP SID", ip_sid);
66664703Shiremath return (IBT_INVALID_PARAM);
66674703Shiremath }
66684703Shiremath
66694703Shiremath ibcm_free_ip_sid(ip_sid);
66704703Shiremath
66714703Shiremath return (IBT_SUCCESS);
66724703Shiremath }
66734703Shiremath
66744703Shiremath
66754703Shiremath uint8_t
ibt_get_ip_protocol_num(ib_svc_id_t sid)66764703Shiremath ibt_get_ip_protocol_num(ib_svc_id_t sid)
66774703Shiremath {
66784703Shiremath return ((sid & IB_SID_IPADDR_IPNUM_MASK) >> 16);
66794703Shiremath }
66804703Shiremath
66814703Shiremath in_port_t
ibt_get_ip_dst_port(ib_svc_id_t sid)66824703Shiremath ibt_get_ip_dst_port(ib_svc_id_t sid)
66834703Shiremath {
66844703Shiremath return (sid & IB_SID_IPADDR_PORTNUM_MASK);
66854703Shiremath }
66864703Shiremath
66874703Shiremath _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibt_ip_cm_info_t))
66884703Shiremath _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibcm_ip_pvtdata_t))
66894703Shiremath
66904703Shiremath ibt_status_t
ibt_format_ip_private_data(ibt_ip_cm_info_t * ip_cm_info,ibt_priv_data_len_t priv_data_len,void * priv_data_p)66914703Shiremath ibt_format_ip_private_data(ibt_ip_cm_info_t *ip_cm_info,
66924703Shiremath ibt_priv_data_len_t priv_data_len, void *priv_data_p)
66934703Shiremath {
66946243Shiremath ibcm_ip_pvtdata_t ip_data;
66954703Shiremath
66964703Shiremath IBTF_DPRINTF_L4(cmlog, "ibt_format_ip_private_data(%p, %d, %p)",
66974703Shiremath ip_cm_info, priv_data_len, priv_data_p);
66984703Shiremath
66994703Shiremath if ((ip_cm_info == NULL) || (priv_data_p == NULL) ||
67004703Shiremath (priv_data_len < IBT_IP_HDR_PRIV_DATA_SZ)) {
67014703Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_format_ip_private_data: ERROR "
67024703Shiremath "Invalid Inputs.");
67034703Shiremath return (IBT_INVALID_PARAM);
67044703Shiremath }
67054703Shiremath
67066243Shiremath bzero(&ip_data, sizeof (ibcm_ip_pvtdata_t));
67076243Shiremath ip_data.ip_srcport = ip_cm_info->src_port; /* Source Port */
67084703Shiremath
67099349SShantkumar.Hiremath@Sun.COM IBCM_PRINT_IP("format_ip_pvt: src", &ip_cm_info->src_addr);
67109349SShantkumar.Hiremath@Sun.COM IBCM_PRINT_IP("format_ip_pvt: dst", &ip_cm_info->dst_addr);
67114703Shiremath /* IPV = 0x4, if IP-Addr are IPv4 format, else 0x6 for IPv6 */
67124703Shiremath if (ip_cm_info->src_addr.family == AF_INET) {
67136243Shiremath ip_data.ip_ipv = IBT_CM_IP_IPV_V4;
67146243Shiremath ip_data.ip_srcv4 = ip_cm_info->src_addr.un.ip4addr;
67156243Shiremath ip_data.ip_dstv4 = ip_cm_info->dst_addr.un.ip4addr;
67164703Shiremath } else if (ip_cm_info->src_addr.family == AF_INET6) {
67176243Shiremath ip_data.ip_ipv = IBT_CM_IP_IPV_V6;
67184703Shiremath bcopy(&ip_cm_info->src_addr.un.ip6addr,
67196243Shiremath &ip_data.ip_srcv6, sizeof (in6_addr_t));
67204703Shiremath bcopy(&ip_cm_info->dst_addr.un.ip6addr,
67216243Shiremath &ip_data.ip_dstv6, sizeof (in6_addr_t));
67224703Shiremath } else {
67234703Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_format_ip_private_data: ERROR "
67244703Shiremath "IP Addr needs to be either AF_INET or AF_INET6 family.");
67254703Shiremath return (IBT_INVALID_PARAM);
67264703Shiremath }
67274703Shiremath
67286243Shiremath ip_data.ip_MajV = IBT_CM_IP_MAJ_VER;
67296243Shiremath ip_data.ip_MinV = IBT_CM_IP_MIN_VER;
67306243Shiremath
67316243Shiremath bcopy(&ip_data, priv_data_p, IBT_IP_HDR_PRIV_DATA_SZ);
67324703Shiremath
67334703Shiremath return (IBT_SUCCESS);
67344703Shiremath }
67354703Shiremath
67364703Shiremath
67374703Shiremath ibt_status_t
ibt_get_ip_data(ibt_priv_data_len_t priv_data_len,void * priv_data,ibt_ip_cm_info_t * ip_cm_infop)67384703Shiremath ibt_get_ip_data(ibt_priv_data_len_t priv_data_len, void *priv_data,
67394703Shiremath ibt_ip_cm_info_t *ip_cm_infop)
67404703Shiremath {
67416243Shiremath ibcm_ip_pvtdata_t ip_data;
67424703Shiremath
67434703Shiremath IBTF_DPRINTF_L4(cmlog, "ibt_get_ip_data(%d, %p, %p)",
67444703Shiremath priv_data_len, priv_data, ip_cm_infop);
67454703Shiremath
67464703Shiremath if ((ip_cm_infop == NULL) || (priv_data == NULL) ||
67474703Shiremath (priv_data_len < IBT_IP_HDR_PRIV_DATA_SZ)) {
67484703Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_data: ERROR Invalid Inputs");
67494703Shiremath return (IBT_INVALID_PARAM);
67504703Shiremath }
67514703Shiremath
67526243Shiremath bcopy(priv_data, &ip_data, IBT_IP_HDR_PRIV_DATA_SZ);
67536243Shiremath ip_cm_infop->src_port = ip_data.ip_srcport; /* Source Port */
67544703Shiremath
67554703Shiremath /* IPV = 0x4, if IP Address are IPv4 format, else 0x6 for IPv6 */
67566243Shiremath if (ip_data.ip_ipv == IBT_CM_IP_IPV_V4) {
67574703Shiremath /* Copy IPv4 Addr */
67589349SShantkumar.Hiremath@Sun.COM ip_cm_infop->src_addr.family = ip_cm_infop->dst_addr.family =
67599349SShantkumar.Hiremath@Sun.COM AF_INET;
67606243Shiremath ip_cm_infop->src_addr.un.ip4addr = ip_data.ip_srcv4;
67616243Shiremath ip_cm_infop->dst_addr.un.ip4addr = ip_data.ip_dstv4;
67626243Shiremath } else if (ip_data.ip_ipv == IBT_CM_IP_IPV_V6) {
67634703Shiremath /* Copy IPv6 Addr */
67649349SShantkumar.Hiremath@Sun.COM ip_cm_infop->src_addr.family = ip_cm_infop->dst_addr.family =
67659349SShantkumar.Hiremath@Sun.COM AF_INET6;
67666243Shiremath bcopy(&ip_data.ip_srcv6, &ip_cm_infop->src_addr.un.ip6addr,
67674703Shiremath sizeof (in6_addr_t));
67686243Shiremath bcopy(&ip_data.ip_dstv6, &ip_cm_infop->dst_addr.un.ip6addr,
67694703Shiremath sizeof (in6_addr_t));
67704703Shiremath } else {
67714703Shiremath IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_data: ERROR: IP Addr needs"
67724703Shiremath " to be either AF_INET or AF_INET6 family.");
67734703Shiremath return (IBT_INVALID_PARAM);
67744703Shiremath }
67759349SShantkumar.Hiremath@Sun.COM IBCM_PRINT_IP("ibt_get_ip_data: src", &ip_cm_infop->src_addr);
67769349SShantkumar.Hiremath@Sun.COM IBCM_PRINT_IP("ibt_get_ip_data: dst", &ip_cm_infop->dst_addr);
67774703Shiremath
67784703Shiremath return (IBT_SUCCESS);
67794703Shiremath }
67804703Shiremath
67810Sstevel@tonic-gate
67820Sstevel@tonic-gate /* Routines for warlock */
67830Sstevel@tonic-gate
67840Sstevel@tonic-gate /* ARGSUSED */
67850Sstevel@tonic-gate static void
ibcm_dummy_mcg_handler(void * arg,ibt_status_t retval,ibt_mcg_info_t * minfo)67860Sstevel@tonic-gate ibcm_dummy_mcg_handler(void *arg, ibt_status_t retval, ibt_mcg_info_t *minfo)
67870Sstevel@tonic-gate {
67880Sstevel@tonic-gate ibcm_join_mcg_tqarg_t dummy_mcg;
67890Sstevel@tonic-gate
67900Sstevel@tonic-gate dummy_mcg.func = ibcm_dummy_mcg_handler;
67910Sstevel@tonic-gate
67920Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_mcg_handler: "
67930Sstevel@tonic-gate "dummy_mcg.func %p", dummy_mcg.func);
67940Sstevel@tonic-gate }
67950Sstevel@tonic-gate
67960Sstevel@tonic-gate
67970Sstevel@tonic-gate /* ARGSUSED */
67980Sstevel@tonic-gate static void
ibcm_dummy_recycle_rc_handler(ibt_status_t retval,void * arg)67990Sstevel@tonic-gate ibcm_dummy_recycle_rc_handler(ibt_status_t retval, void *arg)
68000Sstevel@tonic-gate {
68010Sstevel@tonic-gate ibcm_taskq_recycle_arg_t dummy_rc_recycle;
68020Sstevel@tonic-gate
68030Sstevel@tonic-gate dummy_rc_recycle.func = ibcm_dummy_recycle_rc_handler;
68040Sstevel@tonic-gate
68050Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_recycle_rc_handler: "
68060Sstevel@tonic-gate "dummy_rc_recycle.func %p", dummy_rc_recycle.func);
68070Sstevel@tonic-gate }
68080Sstevel@tonic-gate
68090Sstevel@tonic-gate
68100Sstevel@tonic-gate /* ARGSUSED */
68110Sstevel@tonic-gate static ibt_cm_status_t
ibcm_dummy_ud_handler(void * priv,ibt_cm_ud_event_t * event,ibt_cm_ud_return_args_t * ret_args,void * priv_data,ibt_priv_data_len_t len)68120Sstevel@tonic-gate ibcm_dummy_ud_handler(void *priv, ibt_cm_ud_event_t *event,
68130Sstevel@tonic-gate ibt_cm_ud_return_args_t *ret_args,
68140Sstevel@tonic-gate void *priv_data, ibt_priv_data_len_t len)
68150Sstevel@tonic-gate {
68160Sstevel@tonic-gate /*
68170Sstevel@tonic-gate * Let warlock see that ibcm_local_handler_s::actual_cm_handler
68180Sstevel@tonic-gate * points to this routine.
68190Sstevel@tonic-gate */
68200Sstevel@tonic-gate ibcm_local_handler_t p;
68210Sstevel@tonic-gate ibcm_ud_state_data_t dummy_ud;
68220Sstevel@tonic-gate
68230Sstevel@tonic-gate p.actual_cm_handler = ibcm_dummy_ud_handler;
68240Sstevel@tonic-gate dummy_ud.ud_cm_handler = ibcm_dummy_ud_handler;
68250Sstevel@tonic-gate
68260Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_ud_handler: p.actual_cm_handler %p"
68270Sstevel@tonic-gate "dummy_ud.ud_cm_handler %p", p.actual_cm_handler,
68280Sstevel@tonic-gate dummy_ud.ud_cm_handler);
68290Sstevel@tonic-gate /*
68300Sstevel@tonic-gate * Call all routines that the client's callback routine could call.
68310Sstevel@tonic-gate */
68320Sstevel@tonic-gate
68330Sstevel@tonic-gate return (IBT_CM_ACCEPT);
68340Sstevel@tonic-gate }
68350Sstevel@tonic-gate
68360Sstevel@tonic-gate /* ARGSUSED */
68370Sstevel@tonic-gate static ibt_cm_status_t
ibcm_dummy_rc_handler(void * priv,ibt_cm_event_t * event,ibt_cm_return_args_t * ret_args,void * priv_data,ibt_priv_data_len_t len)68380Sstevel@tonic-gate ibcm_dummy_rc_handler(void *priv, ibt_cm_event_t *event,
68390Sstevel@tonic-gate ibt_cm_return_args_t *ret_args, void *priv_data, ibt_priv_data_len_t len)
68400Sstevel@tonic-gate {
68410Sstevel@tonic-gate ibcm_state_data_t dummy_rc;
68420Sstevel@tonic-gate
68430Sstevel@tonic-gate dummy_rc.cm_handler = ibcm_dummy_rc_handler;
68440Sstevel@tonic-gate
68450Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_rc_handler: "
68460Sstevel@tonic-gate "dummy_ud.ud_cm_handler %p", dummy_rc.cm_handler);
68470Sstevel@tonic-gate /*
68480Sstevel@tonic-gate * Call all routines that the client's callback routine could call.
68490Sstevel@tonic-gate */
68500Sstevel@tonic-gate
68510Sstevel@tonic-gate return (IBT_CM_ACCEPT);
68520Sstevel@tonic-gate }
6853