xref: /onnv-gate/usr/src/uts/common/io/ib/ibtl/ibtl_chan.c (revision 12965:b65a8427f8fe)
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
59913SShantkumar.Hiremath@Sun.COM  * Common Development and Distribution License (the "License").
69913SShantkumar.Hiremath@Sun.COM  * 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 /*
2212574SWilliam.Taylor@Oracle.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate  * ibtl_chan.c
270Sstevel@tonic-gate  *
280Sstevel@tonic-gate  * This file contains Transport API functions related to Channel Functions
290Sstevel@tonic-gate  * and internal Protection Domain and Address Handle Verbs functions.
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl.h>
330Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl_cm.h>
340Sstevel@tonic-gate #include <sys/ib/ib_pkt_hdrs.h>
350Sstevel@tonic-gate 
360Sstevel@tonic-gate static char ibtl_chan[] = "ibtl_chan";
370Sstevel@tonic-gate 
380Sstevel@tonic-gate /*
390Sstevel@tonic-gate  * RC Channel.
400Sstevel@tonic-gate  */
410Sstevel@tonic-gate /*
420Sstevel@tonic-gate  * Function:
430Sstevel@tonic-gate  *	ibt_alloc_rc_channel
440Sstevel@tonic-gate  * Input:
450Sstevel@tonic-gate  *	hca_hdl		HCA Handle.
460Sstevel@tonic-gate  *	flags		Channel allocate flags.
470Sstevel@tonic-gate  *	args		A pointer to an ibt_rc_chan_alloc_args_t struct that
480Sstevel@tonic-gate  *			specifies required channel attributes.
490Sstevel@tonic-gate  * Output:
500Sstevel@tonic-gate  *	rc_chan_p	The returned RC Channel handle.
510Sstevel@tonic-gate  *	sizes		NULL or a pointer to ibt_chan_sizes_s struct where
520Sstevel@tonic-gate  *			new SendQ/RecvQ, and WR SGL sizes are returned.
530Sstevel@tonic-gate  * Returns:
540Sstevel@tonic-gate  *	IBT_SUCCESS
550Sstevel@tonic-gate  *	IBT_INVALID_PARAM
560Sstevel@tonic-gate  * Description:
570Sstevel@tonic-gate  *	Allocates a RC communication channels that satisfy the specified
580Sstevel@tonic-gate  *	channel attributes.
590Sstevel@tonic-gate  */
600Sstevel@tonic-gate ibt_status_t
ibt_alloc_rc_channel(ibt_hca_hdl_t hca_hdl,ibt_chan_alloc_flags_t flags,ibt_rc_chan_alloc_args_t * args,ibt_channel_hdl_t * rc_chan_p,ibt_chan_sizes_t * sizes)610Sstevel@tonic-gate ibt_alloc_rc_channel(ibt_hca_hdl_t hca_hdl, ibt_chan_alloc_flags_t flags,
620Sstevel@tonic-gate     ibt_rc_chan_alloc_args_t *args, ibt_channel_hdl_t *rc_chan_p,
630Sstevel@tonic-gate     ibt_chan_sizes_t *sizes)
640Sstevel@tonic-gate {
650Sstevel@tonic-gate 	ibt_status_t		retval;
660Sstevel@tonic-gate 	ibt_qp_alloc_attr_t	qp_attr;
670Sstevel@tonic-gate 	ibt_qp_info_t		qp_modify_attr;
680Sstevel@tonic-gate 	ibt_channel_hdl_t	chanp;
690Sstevel@tonic-gate 
700Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_rc_channel(%p, %x, %p, %p)",
710Sstevel@tonic-gate 	    hca_hdl, flags, args, sizes);
720Sstevel@tonic-gate 
730Sstevel@tonic-gate 	bzero(&qp_modify_attr, sizeof (ibt_qp_info_t));
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	qp_attr.qp_alloc_flags = IBT_QP_NO_FLAGS;
760Sstevel@tonic-gate 	if (flags & IBT_ACHAN_USER_MAP)
770Sstevel@tonic-gate 		qp_attr.qp_alloc_flags |= IBT_QP_USER_MAP;
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 	if (flags & IBT_ACHAN_DEFER_ALLOC)
800Sstevel@tonic-gate 		qp_attr.qp_alloc_flags |= IBT_QP_DEFER_ALLOC;
810Sstevel@tonic-gate 
820Sstevel@tonic-gate 	if (flags & IBT_ACHAN_USES_SRQ) {
830Sstevel@tonic-gate 		if (args->rc_srq == NULL) {
840Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: "
850Sstevel@tonic-gate 			    "NULL SRQ Handle specified.");
860Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
870Sstevel@tonic-gate 		}
880Sstevel@tonic-gate 		qp_attr.qp_alloc_flags |= IBT_QP_USES_SRQ;
890Sstevel@tonic-gate 	}
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	/*
920Sstevel@tonic-gate 	 * Check if this request is to clone the channel, or to allocate a
930Sstevel@tonic-gate 	 * fresh one.
940Sstevel@tonic-gate 	 */
950Sstevel@tonic-gate 	if (flags & IBT_ACHAN_CLONE) {
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 		ibt_rc_chan_query_attr_t	chan_attrs;
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 		if (args->rc_clone_chan == NULL) {
1000Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: "
1010Sstevel@tonic-gate 			    "Clone Channel info not available.");
1020Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
1030Sstevel@tonic-gate 		} else if (args->rc_clone_chan->ch_qp.qp_hca != hca_hdl) {
1040Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: "
1050Sstevel@tonic-gate 			    "Clone Channel's & requested HCA Handle mismatch");
1060Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
1070Sstevel@tonic-gate 		}
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 		IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_rc_channel: "
1100Sstevel@tonic-gate 		    "Clone <%p> - RC Channel", args->rc_clone_chan);
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 		/*
1130Sstevel@tonic-gate 		 * Query the source channel, to obtained the attributes
1140Sstevel@tonic-gate 		 * so that the new channel share the same attributes.
1150Sstevel@tonic-gate 		 */
1160Sstevel@tonic-gate 		retval = ibt_query_rc_channel(args->rc_clone_chan, &chan_attrs);
1170Sstevel@tonic-gate 		if (retval != IBT_SUCCESS) {
1180Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: "
1190Sstevel@tonic-gate 			    "Failed to query the source channel: %d", retval);
1200Sstevel@tonic-gate 			return (retval);
1210Sstevel@tonic-gate 		}
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 		/* Setup QP alloc attributes. */
1240Sstevel@tonic-gate 		qp_attr.qp_scq_hdl = chan_attrs.rc_scq;
1250Sstevel@tonic-gate 		qp_attr.qp_rcq_hdl = chan_attrs.rc_rcq;
1260Sstevel@tonic-gate 		qp_attr.qp_pd_hdl = chan_attrs.rc_pd;
1270Sstevel@tonic-gate 		qp_attr.qp_flags = chan_attrs.rc_flags;
1280Sstevel@tonic-gate 		qp_attr.qp_srq_hdl = chan_attrs.rc_srq;
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 		bcopy(&chan_attrs.rc_chan_sizes, &qp_attr.qp_sizes,
1310Sstevel@tonic-gate 		    sizeof (ibt_chan_sizes_t));
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate 		qp_modify_attr.qp_flags = chan_attrs.rc_control;
1340Sstevel@tonic-gate 		qp_modify_attr.qp_transport.rc.rc_path.cep_hca_port_num =
1350Sstevel@tonic-gate 		    chan_attrs.rc_prim_path.cep_hca_port_num;
1360Sstevel@tonic-gate 		qp_modify_attr.qp_transport.rc.rc_path.cep_pkey_ix =
1370Sstevel@tonic-gate 		    chan_attrs.rc_prim_path.cep_pkey_ix;
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	} else {
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 		/* Setup QP alloc attributes. */
1420Sstevel@tonic-gate 		qp_attr.qp_scq_hdl = args->rc_scq;
1430Sstevel@tonic-gate 		qp_attr.qp_rcq_hdl = args->rc_rcq;
1440Sstevel@tonic-gate 		qp_attr.qp_pd_hdl = args->rc_pd;
1450Sstevel@tonic-gate 		qp_attr.qp_flags = args->rc_flags;
1460Sstevel@tonic-gate 		qp_attr.qp_srq_hdl = args->rc_srq;
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 		bcopy(&args->rc_sizes, &qp_attr.qp_sizes,
1490Sstevel@tonic-gate 		    sizeof (ibt_chan_sizes_t));
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 		qp_modify_attr.qp_flags = args->rc_control;
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 		if ((args->rc_hca_port_num == 0) ||
1540Sstevel@tonic-gate 		    (args->rc_hca_port_num > IBTL_HCA2NPORTS(hca_hdl))) {
1550Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: "
1560Sstevel@tonic-gate 			    "Invalid port_num %d, range is (1 to %d)",
1570Sstevel@tonic-gate 			    args->rc_hca_port_num, IBTL_HCA2NPORTS(hca_hdl));
1580Sstevel@tonic-gate 			return (IBT_HCA_PORT_INVALID);
1590Sstevel@tonic-gate 		}
1600Sstevel@tonic-gate 		qp_modify_attr.qp_transport.rc.rc_path.cep_hca_port_num =
1610Sstevel@tonic-gate 		    args->rc_hca_port_num;
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate 		/*
1640Sstevel@tonic-gate 		 * We allocate the Channel initially with the default PKey,
1650Sstevel@tonic-gate 		 * and later client can update this when the channel is opened
1660Sstevel@tonic-gate 		 * with the pkey returned from a path record lookup.
1670Sstevel@tonic-gate 		 */
1680Sstevel@tonic-gate 		mutex_enter(&ibtl_clnt_list_mutex);
1690Sstevel@tonic-gate 		qp_modify_attr.qp_transport.rc.rc_path.cep_pkey_ix =
1700Sstevel@tonic-gate 		    hca_hdl->ha_hca_devp->
1710Sstevel@tonic-gate 		    hd_portinfop[args->rc_hca_port_num - 1].p_def_pkey_ix;
1720Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
1730Sstevel@tonic-gate 	}
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	/* Allocate Channel and Initialize the channel. */
1760Sstevel@tonic-gate 	retval = ibt_alloc_qp(hca_hdl, IBT_RC_RQP, &qp_attr, sizes, NULL,
1770Sstevel@tonic-gate 	    &chanp);
1780Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
1790Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: "
1800Sstevel@tonic-gate 		    "Failed to allocate QP: %d", retval);
1810Sstevel@tonic-gate 		*rc_chan_p = NULL;
1820Sstevel@tonic-gate 		return (retval);
1830Sstevel@tonic-gate 	}
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 	qp_modify_attr.qp_trans = IBT_RC_SRV;
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 	/* Initialize RC Channel by transitioning it to INIT State. */
1880Sstevel@tonic-gate 	retval = ibt_initialize_qp(chanp, &qp_modify_attr);
1890Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
1900Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_rc_channel: "
1910Sstevel@tonic-gate 		    "Failed to Initialize QP: %d", retval);
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 		/* Free the QP as we failed to initialize it. */
1940Sstevel@tonic-gate 		(void) ibt_free_qp(chanp);
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 		*rc_chan_p = NULL;
1970Sstevel@tonic-gate 		return (retval);
1980Sstevel@tonic-gate 	}
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	*rc_chan_p = chanp;
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_rc_channel(%p): - SUCCESS (%p)",
2030Sstevel@tonic-gate 	    hca_hdl, chanp);
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	return (IBT_SUCCESS);
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate /*
2100Sstevel@tonic-gate  * Function:
2110Sstevel@tonic-gate  *	ibt_query_rc_channel
2120Sstevel@tonic-gate  * Input:
2130Sstevel@tonic-gate  *	rc_chan		A previously allocated channel handle.
2140Sstevel@tonic-gate  *	chan_attrs	A pointer to an ibt_rc_chan_query_args_t struct where
2150Sstevel@tonic-gate  *			Channel's current attributes are returned.
2160Sstevel@tonic-gate  * Output:
2170Sstevel@tonic-gate  *	chan_attrs	A pointer to an ibt_rc_chan_query_args_t struct where
2180Sstevel@tonic-gate  *			Channel's current attributes are returned.
2190Sstevel@tonic-gate  * Returns:
2200Sstevel@tonic-gate  *	IBT_SUCCESS
2210Sstevel@tonic-gate  * Description:
2220Sstevel@tonic-gate  *	Query an RC channel's attributes.
2230Sstevel@tonic-gate  */
2240Sstevel@tonic-gate ibt_status_t
ibt_query_rc_channel(ibt_channel_hdl_t rc_chan,ibt_rc_chan_query_attr_t * chan_attrs)2250Sstevel@tonic-gate ibt_query_rc_channel(ibt_channel_hdl_t rc_chan,
2260Sstevel@tonic-gate     ibt_rc_chan_query_attr_t *chan_attrs)
2270Sstevel@tonic-gate {
2280Sstevel@tonic-gate 	ibt_status_t		retval;
2290Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_attr;
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_query_rc_channel(%p, %p)",
2320Sstevel@tonic-gate 	    rc_chan, chan_attrs);
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
2350Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_query_rc_channel: "
2360Sstevel@tonic-gate 		    "type of channel (%d) is not RC", rc_chan->ch_qp.qp_type);
2370Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
2380Sstevel@tonic-gate 	}
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	bzero(&qp_attr, sizeof (ibt_qp_query_attr_t));
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	/* Query the channel (QP) */
2430Sstevel@tonic-gate 	retval = ibt_query_qp(rc_chan, &qp_attr);
2440Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
2450Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_query_rc_channel: "
2460Sstevel@tonic-gate 		    "ibt_query_qp failed on QP %p: %d", rc_chan, retval);
2470Sstevel@tonic-gate 		return (retval);
2480Sstevel@tonic-gate 	}
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	chan_attrs->rc_hca_guid = IBTL_HCA2HCAGUID(IBTL_CHAN2HCA(rc_chan));
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 	chan_attrs->rc_scq = qp_attr.qp_sq_cq;
2530Sstevel@tonic-gate 	chan_attrs->rc_rcq = qp_attr.qp_rq_cq;
2540Sstevel@tonic-gate 	chan_attrs->rc_pd = rc_chan->ch_qp.qp_pd_hdl;
2550Sstevel@tonic-gate 	chan_attrs->rc_state = qp_attr.qp_info.qp_state;
2560Sstevel@tonic-gate 	chan_attrs->rc_path_mtu = qp_attr.qp_info.qp_transport.rc.rc_path_mtu;
2570Sstevel@tonic-gate 	chan_attrs->rc_path_retry_cnt =
2580Sstevel@tonic-gate 	    qp_attr.qp_info.qp_transport.rc.rc_retry_cnt;
2590Sstevel@tonic-gate 	chan_attrs->rc_path_rnr_retry_cnt =
2600Sstevel@tonic-gate 	    qp_attr.qp_info.qp_transport.rc.rc_rnr_retry_cnt;
2610Sstevel@tonic-gate 	chan_attrs->rc_min_rnr_nak =
2620Sstevel@tonic-gate 	    qp_attr.qp_info.qp_transport.rc.rc_min_rnr_nak;
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 	chan_attrs->rc_prim_path = qp_attr.qp_info.qp_transport.rc.rc_path;
2650Sstevel@tonic-gate 	chan_attrs->rc_alt_path = qp_attr.qp_info.qp_transport.rc.rc_alt_path;
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	chan_attrs->rc_chan_sizes.cs_sq = qp_attr.qp_info.qp_sq_sz;
2680Sstevel@tonic-gate 	chan_attrs->rc_chan_sizes.cs_rq = qp_attr.qp_info.qp_rq_sz;
2690Sstevel@tonic-gate 	chan_attrs->rc_chan_sizes.cs_sq_sgl = qp_attr.qp_sq_sgl;
2700Sstevel@tonic-gate 	chan_attrs->rc_chan_sizes.cs_rq_sgl = qp_attr.qp_rq_sgl;
2710Sstevel@tonic-gate 	chan_attrs->rc_srq = qp_attr.qp_srq;
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 	chan_attrs->rc_rdma_ra_out =
2740Sstevel@tonic-gate 	    qp_attr.qp_info.qp_transport.rc.rc_rdma_ra_out;
2750Sstevel@tonic-gate 	chan_attrs->rc_rdma_ra_in =
2760Sstevel@tonic-gate 	    qp_attr.qp_info.qp_transport.rc.rc_rdma_ra_in;
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 	chan_attrs->rc_flags = rc_chan->ch_qp.qp_flags;
2790Sstevel@tonic-gate 	chan_attrs->rc_control = qp_attr.qp_info.qp_flags;
2800Sstevel@tonic-gate 	chan_attrs->rc_mig_state = qp_attr.qp_info.qp_transport.rc.rc_mig_state;
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate 	chan_attrs->rc_qpn = qp_attr.qp_qpn & IB_QPN_MASK;
2830Sstevel@tonic-gate 	chan_attrs->rc_dst_qpn =
2840Sstevel@tonic-gate 	    qp_attr.qp_info.qp_transport.rc.rc_dst_qpn & IB_QPN_MASK;
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 	return (retval);
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate /*
2910Sstevel@tonic-gate  * Function:
2920Sstevel@tonic-gate  *	ibt_modify_rc_channel
2930Sstevel@tonic-gate  * Input:
2940Sstevel@tonic-gate  *	rc_chan		A previously allocated channel handle.
2950Sstevel@tonic-gate  *	flags		Specifies which attributes in ibt_rc_chan_modify_attr_t
2960Sstevel@tonic-gate  *			are to be modified.
2970Sstevel@tonic-gate  *	attrs		Attributes to be modified.
2980Sstevel@tonic-gate  * Output:
2990Sstevel@tonic-gate  *	actual_sz	On return contains the new send and receive queue sizes.
3000Sstevel@tonic-gate  * Returns:
3010Sstevel@tonic-gate  *	IBT_SUCCESS
3020Sstevel@tonic-gate  * Description:
3030Sstevel@tonic-gate  *	Modifies an RC channel's attributes, as specified by a
3040Sstevel@tonic-gate  *	ibt_cep_modify_flags_t parameter to those specified in the
3050Sstevel@tonic-gate  *	ibt_rc_chan_modify_attr_t structure.
3060Sstevel@tonic-gate  */
3070Sstevel@tonic-gate ibt_status_t
ibt_modify_rc_channel(ibt_channel_hdl_t rc_chan,ibt_cep_modify_flags_t flags,ibt_rc_chan_modify_attr_t * attrs,ibt_queue_sizes_t * actual_sz)3080Sstevel@tonic-gate ibt_modify_rc_channel(ibt_channel_hdl_t rc_chan, ibt_cep_modify_flags_t flags,
3090Sstevel@tonic-gate     ibt_rc_chan_modify_attr_t *attrs, ibt_queue_sizes_t *actual_sz)
3100Sstevel@tonic-gate {
3110Sstevel@tonic-gate 	ibt_status_t		retval;
3120Sstevel@tonic-gate 	ibt_qp_info_t		qp_info;
3130Sstevel@tonic-gate 	int			retries = 1;
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_modify_rc_channel(%p, %x, %p, %p)",
3160Sstevel@tonic-gate 	    rc_chan, flags, attrs, actual_sz);
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 	if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
3190Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_rc_channel: "
3200Sstevel@tonic-gate 		    "type of channel (%d) is not RC", rc_chan->ch_qp.qp_type);
3210Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
3220Sstevel@tonic-gate 	}
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate retry:
3250Sstevel@tonic-gate 	bzero(&qp_info, sizeof (ibt_qp_info_t));
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate 	if (flags & IBT_CEP_SET_ADDS_VECT) {
3280Sstevel@tonic-gate 		bcopy(&attrs->rc_prim_adds_vect,
3290Sstevel@tonic-gate 		    &qp_info.qp_transport.rc.rc_path.cep_adds_vect,
3300Sstevel@tonic-gate 		    sizeof (ibt_adds_vect_t));
3310Sstevel@tonic-gate 	}
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 	qp_info.qp_trans = IBT_RC_SRV;
3340Sstevel@tonic-gate 	qp_info.qp_transport.rc.rc_path.cep_hca_port_num =
3350Sstevel@tonic-gate 	    attrs->rc_prim_port_num;
3360Sstevel@tonic-gate 	qp_info.qp_transport.rc.rc_retry_cnt = attrs->rc_path_retry_cnt;
3370Sstevel@tonic-gate 	qp_info.qp_transport.rc.rc_rnr_retry_cnt =
3380Sstevel@tonic-gate 	    attrs->rc_path_rnr_retry_cnt;
3390Sstevel@tonic-gate 	qp_info.qp_transport.rc.rc_rdma_ra_out = attrs->rc_rdma_ra_out;
3400Sstevel@tonic-gate 	qp_info.qp_transport.rc.rc_rdma_ra_in = attrs->rc_rdma_ra_in;
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 	/* Current channel state must be either SQD or RTS. */
3430Sstevel@tonic-gate 	qp_info.qp_current_state = rc_chan->ch_current_state;
3440Sstevel@tonic-gate 	qp_info.qp_state = rc_chan->ch_current_state;	/* No Change in State */
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 	qp_info.qp_flags = attrs->rc_control;
3470Sstevel@tonic-gate 	qp_info.qp_sq_sz = attrs->rc_sq_sz;
3480Sstevel@tonic-gate 	qp_info.qp_rq_sz = attrs->rc_rq_sz;
3490Sstevel@tonic-gate 	qp_info.qp_transport.rc.rc_min_rnr_nak = attrs->rc_min_rnr_nak;
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate 	if (flags & IBT_CEP_SET_ALT_PATH) {
3520Sstevel@tonic-gate 		bcopy(&attrs->rc_alt_adds_vect,
3530Sstevel@tonic-gate 		    &qp_info.qp_transport.rc.rc_alt_path.cep_adds_vect,
3540Sstevel@tonic-gate 		    sizeof (ibt_adds_vect_t));
3550Sstevel@tonic-gate 		qp_info.qp_transport.rc.rc_alt_path.cep_hca_port_num =
3560Sstevel@tonic-gate 		    attrs->rc_alt_port_num;
3570Sstevel@tonic-gate 	}
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate 	flags |= IBT_CEP_SET_STATE;
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	retval = ibt_modify_qp(rc_chan, flags, &qp_info, actual_sz);
3620Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
3630Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_rc_channel: "
3640Sstevel@tonic-gate 		    "ibt_modify_qp failed on QP %p: %d", rc_chan, retval);
3650Sstevel@tonic-gate 		/* give it one more shot if the old current state was stale */
3660Sstevel@tonic-gate 		if (qp_info.qp_current_state != rc_chan->ch_current_state &&
3670Sstevel@tonic-gate 		    --retries >= 0 &&
3680Sstevel@tonic-gate 		    (qp_info.qp_current_state == IBT_STATE_RTS ||
3690Sstevel@tonic-gate 		    qp_info.qp_current_state == IBT_STATE_SQD))
3700Sstevel@tonic-gate 			goto retry;
3710Sstevel@tonic-gate 	}
3720Sstevel@tonic-gate 
3730Sstevel@tonic-gate 	return (retval);
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate /*
3780Sstevel@tonic-gate  * UD Channel.
3790Sstevel@tonic-gate  */
3800Sstevel@tonic-gate /*
3810Sstevel@tonic-gate  * Function:
3820Sstevel@tonic-gate  *	ibt_alloc_ud_channel
3830Sstevel@tonic-gate  * Input:
3840Sstevel@tonic-gate  *	hca_hdl		HCA Handle.
3850Sstevel@tonic-gate  *	flags		Channel allocate flags.
3860Sstevel@tonic-gate  *	args		A pointer to an ibt_ud_chan_alloc_args_t struct that
3870Sstevel@tonic-gate  *			specifies required channel attributes.
3880Sstevel@tonic-gate  * Output:
3890Sstevel@tonic-gate  *	ud_chan_p	The returned UD Channel handle.
3900Sstevel@tonic-gate  *	sizes		NULL or a pointer to ibt_chan_sizes_s struct where
3910Sstevel@tonic-gate  *			new SendQ/RecvQ, and WR SGL sizes are returned.
3920Sstevel@tonic-gate  * Returns:
3930Sstevel@tonic-gate  *	IBT_SUCCESS
3940Sstevel@tonic-gate  *	IBT_INVALID_PARAM
3950Sstevel@tonic-gate  * Description:
3960Sstevel@tonic-gate  *	Allocate UD channels that satisfy the specified channel attributes.
3970Sstevel@tonic-gate  */
3980Sstevel@tonic-gate ibt_status_t
ibt_alloc_ud_channel(ibt_hca_hdl_t hca_hdl,ibt_chan_alloc_flags_t flags,ibt_ud_chan_alloc_args_t * args,ibt_channel_hdl_t * ud_chan_p,ibt_chan_sizes_t * sizes)3990Sstevel@tonic-gate ibt_alloc_ud_channel(ibt_hca_hdl_t hca_hdl, ibt_chan_alloc_flags_t flags,
4000Sstevel@tonic-gate     ibt_ud_chan_alloc_args_t *args, ibt_channel_hdl_t *ud_chan_p,
4010Sstevel@tonic-gate     ibt_chan_sizes_t *sizes)
4020Sstevel@tonic-gate {
4030Sstevel@tonic-gate 	ibt_status_t		retval;
4040Sstevel@tonic-gate 	ibt_qp_alloc_attr_t	qp_attr;
4050Sstevel@tonic-gate 	ibt_qp_info_t		qp_modify_attr;
4060Sstevel@tonic-gate 	ibt_channel_hdl_t	chanp;
407*12965SWilliam.Taylor@Oracle.COM 	ibt_chan_alloc_flags_t	variant_flags;
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_ud_channel(%p, %x, %p, %p)",
4100Sstevel@tonic-gate 	    hca_hdl, flags, args, sizes);
4110Sstevel@tonic-gate 
412*12965SWilliam.Taylor@Oracle.COM 	if (flags & IBT_ACHAN_USES_FEXCH) {
413*12965SWilliam.Taylor@Oracle.COM 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
414*12965SWilliam.Taylor@Oracle.COM 		    "FEXCH QPs are allocated by ibt_alloc_ud_channel_range()");
415*12965SWilliam.Taylor@Oracle.COM 		return (IBT_CHAN_SRV_TYPE_INVALID);
416*12965SWilliam.Taylor@Oracle.COM 	}
417*12965SWilliam.Taylor@Oracle.COM 
4180Sstevel@tonic-gate 	bzero(&qp_modify_attr, sizeof (ibt_qp_info_t));
419*12965SWilliam.Taylor@Oracle.COM 	bzero(&qp_attr, sizeof (ibt_qp_alloc_attr_t));
4200Sstevel@tonic-gate 	qp_attr.qp_alloc_flags = IBT_QP_NO_FLAGS;
421*12965SWilliam.Taylor@Oracle.COM 
422*12965SWilliam.Taylor@Oracle.COM 	/* allow at most one of these flags */
423*12965SWilliam.Taylor@Oracle.COM 	variant_flags = flags & (IBT_ACHAN_USER_MAP | IBT_ACHAN_USES_RSS |
424*12965SWilliam.Taylor@Oracle.COM 	    IBT_ACHAN_USES_RFCI | IBT_ACHAN_USES_FCMD | IBT_ACHAN_CLONE);
425*12965SWilliam.Taylor@Oracle.COM 	switch (variant_flags) {
426*12965SWilliam.Taylor@Oracle.COM 	case IBT_ACHAN_USER_MAP:
4270Sstevel@tonic-gate 		qp_attr.qp_alloc_flags |= IBT_QP_USER_MAP;
428*12965SWilliam.Taylor@Oracle.COM 		break;
429*12965SWilliam.Taylor@Oracle.COM 	case IBT_ACHAN_USES_RSS:
430*12965SWilliam.Taylor@Oracle.COM 		qp_attr.qp_alloc_flags |= IBT_QP_USES_RSS;
431*12965SWilliam.Taylor@Oracle.COM 		qp_modify_attr.qp_transport.ud.ud_rss = args->ud_rss;
432*12965SWilliam.Taylor@Oracle.COM 		break;
433*12965SWilliam.Taylor@Oracle.COM 	case IBT_ACHAN_USES_RFCI:
434*12965SWilliam.Taylor@Oracle.COM 		qp_attr.qp_alloc_flags |= IBT_QP_USES_RFCI;
435*12965SWilliam.Taylor@Oracle.COM 		qp_modify_attr.qp_transport.ud.ud_fc = qp_attr.qp_fc =
436*12965SWilliam.Taylor@Oracle.COM 		    args->ud_fc;
437*12965SWilliam.Taylor@Oracle.COM 		break;
438*12965SWilliam.Taylor@Oracle.COM 	case IBT_ACHAN_USES_FCMD:
439*12965SWilliam.Taylor@Oracle.COM 		qp_attr.qp_alloc_flags |= IBT_QP_USES_FCMD;
440*12965SWilliam.Taylor@Oracle.COM 		qp_modify_attr.qp_transport.ud.ud_fc = qp_attr.qp_fc =
441*12965SWilliam.Taylor@Oracle.COM 		    args->ud_fc;
442*12965SWilliam.Taylor@Oracle.COM 		break;
443*12965SWilliam.Taylor@Oracle.COM 	case IBT_ACHAN_CLONE:
444*12965SWilliam.Taylor@Oracle.COM 	case 0:
445*12965SWilliam.Taylor@Oracle.COM 		break;
446*12965SWilliam.Taylor@Oracle.COM 	default:
447*12965SWilliam.Taylor@Oracle.COM 		return (IBT_INVALID_PARAM);
448*12965SWilliam.Taylor@Oracle.COM 	}
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	if (flags & IBT_ACHAN_DEFER_ALLOC)
4510Sstevel@tonic-gate 		qp_attr.qp_alloc_flags |= IBT_QP_DEFER_ALLOC;
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate 	if (flags & IBT_ACHAN_USES_SRQ) {
4540Sstevel@tonic-gate 		if (args->ud_srq == NULL) {
4550Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
4560Sstevel@tonic-gate 			    "NULL SRQ Handle specified.");
4570Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
4580Sstevel@tonic-gate 		}
459*12965SWilliam.Taylor@Oracle.COM 		if (flags & IBT_ACHAN_USES_RSS) {
460*12965SWilliam.Taylor@Oracle.COM 			IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
461*12965SWilliam.Taylor@Oracle.COM 			    "SRQ not allowed with RSS.");
462*12965SWilliam.Taylor@Oracle.COM 			return (IBT_INVALID_PARAM);
463*12965SWilliam.Taylor@Oracle.COM 		}
4640Sstevel@tonic-gate 		qp_attr.qp_alloc_flags |= IBT_QP_USES_SRQ;
4650Sstevel@tonic-gate 	}
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 	/*
4680Sstevel@tonic-gate 	 * Check if this request is to clone the channel, or to allocate a
4690Sstevel@tonic-gate 	 * fresh one.
4700Sstevel@tonic-gate 	 */
4710Sstevel@tonic-gate 	if (flags & IBT_ACHAN_CLONE) {
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 		ibt_ud_chan_query_attr_t	chan_attrs;
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 		if (args->ud_clone_chan == NULL) {
4760Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
4770Sstevel@tonic-gate 			    "Clone Channel info not available.");
4780Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
4790Sstevel@tonic-gate 		} else if (args->ud_clone_chan->ch_qp.qp_hca != hca_hdl) {
4800Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
4810Sstevel@tonic-gate 			    "Clone Channel and HCA Handle mismatch");
4820Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
4830Sstevel@tonic-gate 		}
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate 		IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_ud_channel: "
4860Sstevel@tonic-gate 		    "Clone <%p> - UD Channel", args->ud_clone_chan);
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 		retval = ibt_query_ud_channel(args->ud_clone_chan, &chan_attrs);
4890Sstevel@tonic-gate 		if (retval != IBT_SUCCESS) {
4900Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
4910Sstevel@tonic-gate 			    "Failed to Query the source channel: %d", retval);
4920Sstevel@tonic-gate 			return (retval);
4930Sstevel@tonic-gate 		}
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate 		/* Setup QP alloc attributes. */
4960Sstevel@tonic-gate 		qp_attr.qp_scq_hdl = chan_attrs.ud_scq;
4970Sstevel@tonic-gate 		qp_attr.qp_rcq_hdl = chan_attrs.ud_rcq;
4980Sstevel@tonic-gate 		qp_attr.qp_pd_hdl = chan_attrs.ud_pd;
4990Sstevel@tonic-gate 		qp_attr.qp_flags = chan_attrs.ud_flags;
5000Sstevel@tonic-gate 		qp_attr.qp_srq_hdl = chan_attrs.ud_srq;
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 		bcopy(&chan_attrs.ud_chan_sizes, &qp_attr.qp_sizes,
5030Sstevel@tonic-gate 		    sizeof (ibt_chan_sizes_t));
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate 		qp_modify_attr.qp_transport.ud.ud_port =
5060Sstevel@tonic-gate 		    chan_attrs.ud_hca_port_num;
5070Sstevel@tonic-gate 		qp_modify_attr.qp_transport.ud.ud_qkey = chan_attrs.ud_qkey;
5080Sstevel@tonic-gate 		qp_modify_attr.qp_transport.ud.ud_pkey_ix =
5090Sstevel@tonic-gate 		    chan_attrs.ud_pkey_ix;
5100Sstevel@tonic-gate 	} else {
5110Sstevel@tonic-gate 		ib_pkey_t	tmp_pkey;
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate 		/* Setup QP alloc attributes. */
5140Sstevel@tonic-gate 		qp_attr.qp_scq_hdl = args->ud_scq;
5150Sstevel@tonic-gate 		qp_attr.qp_rcq_hdl = args->ud_rcq;
5160Sstevel@tonic-gate 		qp_attr.qp_pd_hdl = args->ud_pd;
5170Sstevel@tonic-gate 		qp_attr.qp_flags = args->ud_flags;
5180Sstevel@tonic-gate 		qp_attr.qp_srq_hdl = args->ud_srq;
5190Sstevel@tonic-gate 
5200Sstevel@tonic-gate 		bcopy(&args->ud_sizes, &qp_attr.qp_sizes,
5210Sstevel@tonic-gate 		    sizeof (ibt_chan_sizes_t));
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 		qp_modify_attr.qp_transport.ud.ud_port = args->ud_hca_port_num;
5240Sstevel@tonic-gate 		qp_modify_attr.qp_transport.ud.ud_qkey = args->ud_qkey;
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 		/* Validate input hca_port_num and pkey_ix values. */
5270Sstevel@tonic-gate 		if ((retval = ibt_index2pkey(hca_hdl, args->ud_hca_port_num,
5280Sstevel@tonic-gate 		    args->ud_pkey_ix, &tmp_pkey)) != IBT_SUCCESS) {
5290Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
5300Sstevel@tonic-gate 			    "ibt_index2pkey failed, status: %d", retval);
5310Sstevel@tonic-gate 			*ud_chan_p = NULL;
5320Sstevel@tonic-gate 			return (retval);
5330Sstevel@tonic-gate 		}
5340Sstevel@tonic-gate 		qp_modify_attr.qp_transport.ud.ud_pkey_ix = args->ud_pkey_ix;
5350Sstevel@tonic-gate 	}
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 	/* Allocate Channel and Initialize the channel. */
5380Sstevel@tonic-gate 	retval = ibt_alloc_qp(hca_hdl, IBT_UD_RQP, &qp_attr, sizes, NULL,
5390Sstevel@tonic-gate 	    &chanp);
5400Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
5410Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
5420Sstevel@tonic-gate 		    "Failed to allocate QP: %d", retval);
5430Sstevel@tonic-gate 		*ud_chan_p = NULL;
5440Sstevel@tonic-gate 		return (retval);
5450Sstevel@tonic-gate 	}
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 	/* Initialize UD Channel by transitioning it to RTS State. */
5480Sstevel@tonic-gate 	qp_modify_attr.qp_trans = IBT_UD_SRV;
5490Sstevel@tonic-gate 	qp_modify_attr.qp_flags = IBT_CEP_NO_FLAGS;
5500Sstevel@tonic-gate 	qp_modify_attr.qp_transport.ud.ud_sq_psn = 0;
5510Sstevel@tonic-gate 
5520Sstevel@tonic-gate 	retval = ibt_initialize_qp(chanp, &qp_modify_attr);
5530Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
5540Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
5550Sstevel@tonic-gate 		    "Failed to Initialize QP: %d", retval);
5560Sstevel@tonic-gate 
5570Sstevel@tonic-gate 		/* Free the QP as we failed to initialize it. */
5580Sstevel@tonic-gate 		(void) ibt_free_qp(chanp);
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate 		*ud_chan_p = NULL;
5610Sstevel@tonic-gate 		return (retval);
5620Sstevel@tonic-gate 	}
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate 	*ud_chan_p = chanp;
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_ud_channel(%p): - SUCCESS (%p)",
5670Sstevel@tonic-gate 	    hca_hdl, chanp);
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate 	return (IBT_SUCCESS);
5700Sstevel@tonic-gate }
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate /*
5740Sstevel@tonic-gate  * Function:
575*12965SWilliam.Taylor@Oracle.COM  *	ibt_alloc_ud_channel_range
576*12965SWilliam.Taylor@Oracle.COM  * Input:
577*12965SWilliam.Taylor@Oracle.COM  *	hca_hdl		HCA Handle.
578*12965SWilliam.Taylor@Oracle.COM  *	log2		Log (base 2) of the number of QPs to allocate.
579*12965SWilliam.Taylor@Oracle.COM  *	flags		Channel allocate flags.
580*12965SWilliam.Taylor@Oracle.COM  *	args		A pointer to an ibt_ud_chan_alloc_args_t struct that
581*12965SWilliam.Taylor@Oracle.COM  *			specifies required channel attributes.
582*12965SWilliam.Taylor@Oracle.COM  *	send_cq		A pointer to an array of CQ handles.
583*12965SWilliam.Taylor@Oracle.COM  *	recv_cq		A pointer to an array of CQ handles.
584*12965SWilliam.Taylor@Oracle.COM  * Output:
585*12965SWilliam.Taylor@Oracle.COM  *	base_qpn_p	The returned QP number of the base QP.
586*12965SWilliam.Taylor@Oracle.COM  *	ud_chan_p	The returned UD Channel handle.
587*12965SWilliam.Taylor@Oracle.COM  *	sizes		NULL or a pointer to ibt_chan_sizes_s struct where
588*12965SWilliam.Taylor@Oracle.COM  *			new SendQ/RecvQ, and WR SGL sizes are returned.
589*12965SWilliam.Taylor@Oracle.COM  * Returns:
590*12965SWilliam.Taylor@Oracle.COM  *	IBT_SUCCESS
591*12965SWilliam.Taylor@Oracle.COM  *	IBT_INVALID_PARAM
592*12965SWilliam.Taylor@Oracle.COM  * Description:
593*12965SWilliam.Taylor@Oracle.COM  *	Allocate UD channels that satisfy the specified channel attributes.
594*12965SWilliam.Taylor@Oracle.COM  */
595*12965SWilliam.Taylor@Oracle.COM ibt_status_t
ibt_alloc_ud_channel_range(ibt_hca_hdl_t hca_hdl,uint_t log2,ibt_chan_alloc_flags_t flags,ibt_ud_chan_alloc_args_t * args,ibt_cq_hdl_t * send_cq,ibt_cq_hdl_t * recv_cq,ib_qpn_t * base_qpn_p,ibt_channel_hdl_t * ud_chan_p,ibt_chan_sizes_t * sizes)596*12965SWilliam.Taylor@Oracle.COM ibt_alloc_ud_channel_range(ibt_hca_hdl_t hca_hdl, uint_t log2,
597*12965SWilliam.Taylor@Oracle.COM     ibt_chan_alloc_flags_t flags, ibt_ud_chan_alloc_args_t *args,
598*12965SWilliam.Taylor@Oracle.COM     ibt_cq_hdl_t *send_cq, ibt_cq_hdl_t *recv_cq, ib_qpn_t *base_qpn_p,
599*12965SWilliam.Taylor@Oracle.COM     ibt_channel_hdl_t *ud_chan_p, ibt_chan_sizes_t *sizes)
600*12965SWilliam.Taylor@Oracle.COM {
601*12965SWilliam.Taylor@Oracle.COM 	ibt_status_t		retval;
602*12965SWilliam.Taylor@Oracle.COM 	ibt_qp_alloc_attr_t	qp_attr;
603*12965SWilliam.Taylor@Oracle.COM 	ibt_qp_info_t		qp_modify_attr;
604*12965SWilliam.Taylor@Oracle.COM 	ibtl_channel_t		*chanp;
605*12965SWilliam.Taylor@Oracle.COM 	ibt_cq_hdl_t		ibt_cq_hdl;
606*12965SWilliam.Taylor@Oracle.COM 	ibc_cq_hdl_t		*ibc_send_cq, *ibc_recv_cq;
607*12965SWilliam.Taylor@Oracle.COM 	ibc_qp_hdl_t		*ibc_qp_hdl_p;
608*12965SWilliam.Taylor@Oracle.COM 	int			i, n = 1 << log2;
609*12965SWilliam.Taylor@Oracle.COM 	ib_pkey_t		tmp_pkey;
610*12965SWilliam.Taylor@Oracle.COM 
611*12965SWilliam.Taylor@Oracle.COM 
612*12965SWilliam.Taylor@Oracle.COM 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_ud_channel_range(%p, %x, %p, %p)",
613*12965SWilliam.Taylor@Oracle.COM 	    hca_hdl, flags, args, sizes);
614*12965SWilliam.Taylor@Oracle.COM 
615*12965SWilliam.Taylor@Oracle.COM 	bzero(&qp_modify_attr, sizeof (ibt_qp_info_t));
616*12965SWilliam.Taylor@Oracle.COM 
617*12965SWilliam.Taylor@Oracle.COM 	qp_attr.qp_alloc_flags = IBT_QP_NO_FLAGS;
618*12965SWilliam.Taylor@Oracle.COM 
619*12965SWilliam.Taylor@Oracle.COM 	if (flags & IBT_ACHAN_CLONE)
620*12965SWilliam.Taylor@Oracle.COM 		return (IBT_INVALID_PARAM);
621*12965SWilliam.Taylor@Oracle.COM 
622*12965SWilliam.Taylor@Oracle.COM 	if (flags & IBT_ACHAN_USER_MAP)
623*12965SWilliam.Taylor@Oracle.COM 		qp_attr.qp_alloc_flags |= IBT_QP_USER_MAP;
624*12965SWilliam.Taylor@Oracle.COM 
625*12965SWilliam.Taylor@Oracle.COM 	if (flags & IBT_ACHAN_DEFER_ALLOC)
626*12965SWilliam.Taylor@Oracle.COM 		qp_attr.qp_alloc_flags |= IBT_QP_DEFER_ALLOC;
627*12965SWilliam.Taylor@Oracle.COM 
628*12965SWilliam.Taylor@Oracle.COM 	if (flags & IBT_ACHAN_USES_SRQ) {
629*12965SWilliam.Taylor@Oracle.COM 		if (args->ud_srq == NULL) {
630*12965SWilliam.Taylor@Oracle.COM 			IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel: "
631*12965SWilliam.Taylor@Oracle.COM 			    "NULL SRQ Handle specified.");
632*12965SWilliam.Taylor@Oracle.COM 			return (IBT_INVALID_PARAM);
633*12965SWilliam.Taylor@Oracle.COM 		}
634*12965SWilliam.Taylor@Oracle.COM 		qp_attr.qp_alloc_flags |= IBT_QP_USES_SRQ;
635*12965SWilliam.Taylor@Oracle.COM 	}
636*12965SWilliam.Taylor@Oracle.COM 
637*12965SWilliam.Taylor@Oracle.COM 	if (flags & IBT_ACHAN_USES_FEXCH) {
638*12965SWilliam.Taylor@Oracle.COM 		qp_attr.qp_alloc_flags |= IBT_QP_USES_FEXCH;
639*12965SWilliam.Taylor@Oracle.COM 		qp_attr.qp_fc = args->ud_fc;
640*12965SWilliam.Taylor@Oracle.COM 		qp_modify_attr.qp_transport.ud.ud_fc = qp_attr.qp_fc =
641*12965SWilliam.Taylor@Oracle.COM 		    args->ud_fc;
642*12965SWilliam.Taylor@Oracle.COM 	}
643*12965SWilliam.Taylor@Oracle.COM 	if (flags & IBT_ACHAN_USES_RSS) {
644*12965SWilliam.Taylor@Oracle.COM 		if (log2 >
645*12965SWilliam.Taylor@Oracle.COM 		    hca_hdl->ha_hca_devp->hd_hca_attr->hca_rss_max_log2_table)
646*12965SWilliam.Taylor@Oracle.COM 			return (IBT_INSUFF_RESOURCE);
647*12965SWilliam.Taylor@Oracle.COM 		qp_attr.qp_alloc_flags |= IBT_QP_USES_RSS;
648*12965SWilliam.Taylor@Oracle.COM 	}
649*12965SWilliam.Taylor@Oracle.COM 
650*12965SWilliam.Taylor@Oracle.COM 	ibc_send_cq = kmem_alloc(sizeof (ibc_cq_hdl_t) << log2, KM_SLEEP);
651*12965SWilliam.Taylor@Oracle.COM 	ibc_recv_cq = kmem_alloc(sizeof (ibc_cq_hdl_t) << log2, KM_SLEEP);
652*12965SWilliam.Taylor@Oracle.COM 	ibc_qp_hdl_p = kmem_alloc(sizeof (ibc_qp_hdl_t) << log2, KM_SLEEP);
653*12965SWilliam.Taylor@Oracle.COM 
654*12965SWilliam.Taylor@Oracle.COM 	for (i = 0; i < 1 << log2; i++) {
655*12965SWilliam.Taylor@Oracle.COM 		ud_chan_p[i] = kmem_zalloc(sizeof (ibtl_channel_t), KM_SLEEP);
656*12965SWilliam.Taylor@Oracle.COM 		ibt_cq_hdl = send_cq[i];
657*12965SWilliam.Taylor@Oracle.COM 		ibc_send_cq[i] = ibt_cq_hdl ? ibt_cq_hdl->cq_ibc_cq_hdl : NULL;
658*12965SWilliam.Taylor@Oracle.COM 		ibt_cq_hdl = recv_cq[i];
659*12965SWilliam.Taylor@Oracle.COM 		ibc_recv_cq[i] = ibt_cq_hdl ? ibt_cq_hdl->cq_ibc_cq_hdl : NULL;
660*12965SWilliam.Taylor@Oracle.COM 	}
661*12965SWilliam.Taylor@Oracle.COM 
662*12965SWilliam.Taylor@Oracle.COM 	/* Setup QP alloc attributes. */
663*12965SWilliam.Taylor@Oracle.COM 	qp_attr.qp_pd_hdl = args->ud_pd;
664*12965SWilliam.Taylor@Oracle.COM 	qp_attr.qp_flags = args->ud_flags;
665*12965SWilliam.Taylor@Oracle.COM 	qp_attr.qp_srq_hdl = args->ud_srq;
666*12965SWilliam.Taylor@Oracle.COM 
667*12965SWilliam.Taylor@Oracle.COM 	bcopy(&args->ud_sizes, &qp_attr.qp_sizes,
668*12965SWilliam.Taylor@Oracle.COM 	    sizeof (ibt_chan_sizes_t));
669*12965SWilliam.Taylor@Oracle.COM 
670*12965SWilliam.Taylor@Oracle.COM 	qp_modify_attr.qp_transport.ud.ud_port = args->ud_hca_port_num;
671*12965SWilliam.Taylor@Oracle.COM 	qp_modify_attr.qp_transport.ud.ud_qkey = args->ud_qkey;
672*12965SWilliam.Taylor@Oracle.COM 
673*12965SWilliam.Taylor@Oracle.COM 	/* Validate input hca_port_num and pkey_ix values. */
674*12965SWilliam.Taylor@Oracle.COM 	if ((retval = ibt_index2pkey(hca_hdl, args->ud_hca_port_num,
675*12965SWilliam.Taylor@Oracle.COM 	    args->ud_pkey_ix, &tmp_pkey)) != IBT_SUCCESS) {
676*12965SWilliam.Taylor@Oracle.COM 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel_range:"
677*12965SWilliam.Taylor@Oracle.COM 		    " ibt_index2pkey failed, status: %d", retval);
678*12965SWilliam.Taylor@Oracle.COM 		goto fail;
679*12965SWilliam.Taylor@Oracle.COM 	}
680*12965SWilliam.Taylor@Oracle.COM 	qp_modify_attr.qp_transport.ud.ud_pkey_ix = args->ud_pkey_ix;
681*12965SWilliam.Taylor@Oracle.COM 
682*12965SWilliam.Taylor@Oracle.COM 	/* Allocate Channel and Initialize the channel. */
683*12965SWilliam.Taylor@Oracle.COM 	retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_qp_range)(
684*12965SWilliam.Taylor@Oracle.COM 	    IBTL_HCA2CIHCA(hca_hdl), log2, (ibtl_qp_hdl_t *)ud_chan_p,
685*12965SWilliam.Taylor@Oracle.COM 	    IBT_UD_RQP, &qp_attr, sizes, ibc_send_cq, ibc_recv_cq,
686*12965SWilliam.Taylor@Oracle.COM 	    base_qpn_p, ibc_qp_hdl_p);
687*12965SWilliam.Taylor@Oracle.COM 	if (retval != IBT_SUCCESS) {
688*12965SWilliam.Taylor@Oracle.COM 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel_range: "
689*12965SWilliam.Taylor@Oracle.COM 		    "Failed to allocate QPs: %d", retval);
690*12965SWilliam.Taylor@Oracle.COM 		goto fail;
691*12965SWilliam.Taylor@Oracle.COM 	}
692*12965SWilliam.Taylor@Oracle.COM 
693*12965SWilliam.Taylor@Oracle.COM 	/* Initialize UD Channel by transitioning it to RTS State. */
694*12965SWilliam.Taylor@Oracle.COM 	qp_modify_attr.qp_trans = IBT_UD_SRV;
695*12965SWilliam.Taylor@Oracle.COM 	qp_modify_attr.qp_flags = IBT_CEP_NO_FLAGS;
696*12965SWilliam.Taylor@Oracle.COM 	qp_modify_attr.qp_transport.ud.ud_sq_psn = 0;
697*12965SWilliam.Taylor@Oracle.COM 
698*12965SWilliam.Taylor@Oracle.COM 	for (i = 0; i < n; i++) {
699*12965SWilliam.Taylor@Oracle.COM 		/* Initialize the internal QP struct. */
700*12965SWilliam.Taylor@Oracle.COM 		chanp = ud_chan_p[i];
701*12965SWilliam.Taylor@Oracle.COM 		chanp->ch_qp.qp_type = IBT_UD_SRV;
702*12965SWilliam.Taylor@Oracle.COM 		chanp->ch_qp.qp_hca = hca_hdl;
703*12965SWilliam.Taylor@Oracle.COM 		chanp->ch_qp.qp_ibc_qp_hdl = ibc_qp_hdl_p[i];
704*12965SWilliam.Taylor@Oracle.COM 		chanp->ch_qp.qp_send_cq = send_cq[i];
705*12965SWilliam.Taylor@Oracle.COM 		chanp->ch_qp.qp_recv_cq = recv_cq[i];
706*12965SWilliam.Taylor@Oracle.COM 		chanp->ch_current_state = IBT_STATE_RESET;
707*12965SWilliam.Taylor@Oracle.COM 		mutex_init(&chanp->ch_cm_mutex, NULL, MUTEX_DEFAULT, NULL);
708*12965SWilliam.Taylor@Oracle.COM 		cv_init(&chanp->ch_cm_cv, NULL, CV_DEFAULT, NULL);
709*12965SWilliam.Taylor@Oracle.COM 
710*12965SWilliam.Taylor@Oracle.COM 		retval = ibt_initialize_qp(chanp, &qp_modify_attr);
711*12965SWilliam.Taylor@Oracle.COM 		if (retval != IBT_SUCCESS) {
712*12965SWilliam.Taylor@Oracle.COM 			int j;
713*12965SWilliam.Taylor@Oracle.COM 
714*12965SWilliam.Taylor@Oracle.COM 			IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel_range:"
715*12965SWilliam.Taylor@Oracle.COM 			    " Failed to Initialize QP: %d", retval);
716*12965SWilliam.Taylor@Oracle.COM 
717*12965SWilliam.Taylor@Oracle.COM 			/* Free the QP as we failed to initialize it. */
718*12965SWilliam.Taylor@Oracle.COM 			(void) ibt_free_qp(chanp);
719*12965SWilliam.Taylor@Oracle.COM 			for (j = 0; j < i; j++) {
720*12965SWilliam.Taylor@Oracle.COM 				chanp = ud_chan_p[j];
721*12965SWilliam.Taylor@Oracle.COM 				(void) ibt_free_qp(chanp);
722*12965SWilliam.Taylor@Oracle.COM 			}
723*12965SWilliam.Taylor@Oracle.COM 			goto fail;
724*12965SWilliam.Taylor@Oracle.COM 		}
725*12965SWilliam.Taylor@Oracle.COM 
726*12965SWilliam.Taylor@Oracle.COM 		/*
727*12965SWilliam.Taylor@Oracle.COM 		 * The IBTA spec does not include the signal type or PD on a QP
728*12965SWilliam.Taylor@Oracle.COM 		 * query operation. In order to implement the "CLONE" feature
729*12965SWilliam.Taylor@Oracle.COM 		 * we need to cache these values.
730*12965SWilliam.Taylor@Oracle.COM 		 */
731*12965SWilliam.Taylor@Oracle.COM 		chanp->ch_qp.qp_flags = qp_attr.qp_flags;
732*12965SWilliam.Taylor@Oracle.COM 		chanp->ch_qp.qp_pd_hdl = qp_attr.qp_pd_hdl;
733*12965SWilliam.Taylor@Oracle.COM 	}
734*12965SWilliam.Taylor@Oracle.COM 
735*12965SWilliam.Taylor@Oracle.COM 
736*12965SWilliam.Taylor@Oracle.COM 	IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel_range(%p): SUCCESS");
737*12965SWilliam.Taylor@Oracle.COM 
738*12965SWilliam.Taylor@Oracle.COM 	atomic_add_32(&hca_hdl->ha_qp_cnt, n);
739*12965SWilliam.Taylor@Oracle.COM 
740*12965SWilliam.Taylor@Oracle.COM 	retval = IBT_SUCCESS;
741*12965SWilliam.Taylor@Oracle.COM 
742*12965SWilliam.Taylor@Oracle.COM fail:
743*12965SWilliam.Taylor@Oracle.COM 	kmem_free(ibc_send_cq, sizeof (ibc_cq_hdl_t) << log2);
744*12965SWilliam.Taylor@Oracle.COM 	kmem_free(ibc_recv_cq, sizeof (ibc_cq_hdl_t) << log2);
745*12965SWilliam.Taylor@Oracle.COM 	kmem_free(ibc_qp_hdl_p, sizeof (ibc_qp_hdl_t) << log2);
746*12965SWilliam.Taylor@Oracle.COM 	if (retval != IBT_SUCCESS) {
747*12965SWilliam.Taylor@Oracle.COM 		for (i = 0; i < 1 << log2; i++) {
748*12965SWilliam.Taylor@Oracle.COM 			kmem_free(ud_chan_p[i], sizeof (ibtl_channel_t));
749*12965SWilliam.Taylor@Oracle.COM 			ud_chan_p[i] = NULL;
750*12965SWilliam.Taylor@Oracle.COM 		}
751*12965SWilliam.Taylor@Oracle.COM 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_channel_range(%p): "
752*12965SWilliam.Taylor@Oracle.COM 		    "failed: %d", retval);
753*12965SWilliam.Taylor@Oracle.COM 	}
754*12965SWilliam.Taylor@Oracle.COM 	return (retval);
755*12965SWilliam.Taylor@Oracle.COM }
756*12965SWilliam.Taylor@Oracle.COM 
757*12965SWilliam.Taylor@Oracle.COM 
758*12965SWilliam.Taylor@Oracle.COM /*
759*12965SWilliam.Taylor@Oracle.COM  * Function:
7600Sstevel@tonic-gate  *	ibt_query_ud_channel
7610Sstevel@tonic-gate  * Input:
7620Sstevel@tonic-gate  *	ud_chan		A previously allocated UD channel handle.
7630Sstevel@tonic-gate  * Output:
7640Sstevel@tonic-gate  *	chan_attrs	Channel's current attributes.
7650Sstevel@tonic-gate  * Returns:
7660Sstevel@tonic-gate  *	IBT_SUCCESS
7670Sstevel@tonic-gate  * Description:
7680Sstevel@tonic-gate  *	Query a UD channel's attributes.
7690Sstevel@tonic-gate  */
7700Sstevel@tonic-gate ibt_status_t
ibt_query_ud_channel(ibt_channel_hdl_t ud_chan,ibt_ud_chan_query_attr_t * ud_chan_attrs)7710Sstevel@tonic-gate ibt_query_ud_channel(ibt_channel_hdl_t ud_chan,
7720Sstevel@tonic-gate     ibt_ud_chan_query_attr_t *ud_chan_attrs)
7730Sstevel@tonic-gate {
7740Sstevel@tonic-gate 	ibt_status_t		retval;
7750Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_attr;
7760Sstevel@tonic-gate 
7770Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_query_ud_channel(%p, %p)",
7780Sstevel@tonic-gate 	    ud_chan, ud_chan_attrs);
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 	if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) {
7810Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_query_ud_channel: "
7820Sstevel@tonic-gate 		    "type of channel (%d) is not UD", ud_chan->ch_qp.qp_type);
7830Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
7840Sstevel@tonic-gate 	}
7850Sstevel@tonic-gate 
7860Sstevel@tonic-gate 	bzero(&qp_attr, sizeof (ibt_qp_query_attr_t));
7870Sstevel@tonic-gate 
7880Sstevel@tonic-gate 	/* Query the channel (QP) */
7890Sstevel@tonic-gate 	retval = ibt_query_qp(ud_chan, &qp_attr);
7900Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
7910Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_query_ud_channel: "
7920Sstevel@tonic-gate 		    "ibt_query_qp failed on QP %p: %d", ud_chan, retval);
7930Sstevel@tonic-gate 		return (retval);
7940Sstevel@tonic-gate 	}
7950Sstevel@tonic-gate 
7960Sstevel@tonic-gate 	ud_chan_attrs->ud_qpn = qp_attr.qp_qpn & IB_QPN_MASK;
7970Sstevel@tonic-gate 	ud_chan_attrs->ud_hca_guid = IBTL_HCA2HCAGUID(IBTL_CHAN2HCA(ud_chan));
7980Sstevel@tonic-gate 
7990Sstevel@tonic-gate 	ud_chan_attrs->ud_scq = qp_attr.qp_sq_cq;
8000Sstevel@tonic-gate 	ud_chan_attrs->ud_rcq = qp_attr.qp_rq_cq;
8010Sstevel@tonic-gate 	ud_chan_attrs->ud_pd = ud_chan->ch_qp.qp_pd_hdl;
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 	ud_chan_attrs->ud_hca_port_num =
8040Sstevel@tonic-gate 	    qp_attr.qp_info.qp_transport.ud.ud_port;
8050Sstevel@tonic-gate 
8060Sstevel@tonic-gate 	ud_chan_attrs->ud_state = qp_attr.qp_info.qp_state;
8070Sstevel@tonic-gate 	ud_chan_attrs->ud_pkey_ix = qp_attr.qp_info.qp_transport.ud.ud_pkey_ix;
8080Sstevel@tonic-gate 	ud_chan_attrs->ud_qkey = qp_attr.qp_info.qp_transport.ud.ud_qkey;
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate 	ud_chan_attrs->ud_chan_sizes.cs_sq = qp_attr.qp_info.qp_sq_sz;
8110Sstevel@tonic-gate 	ud_chan_attrs->ud_chan_sizes.cs_rq = qp_attr.qp_info.qp_rq_sz;
8120Sstevel@tonic-gate 	ud_chan_attrs->ud_chan_sizes.cs_sq_sgl = qp_attr.qp_sq_sgl;
8130Sstevel@tonic-gate 	ud_chan_attrs->ud_chan_sizes.cs_rq_sgl = qp_attr.qp_rq_sgl;
8140Sstevel@tonic-gate 	ud_chan_attrs->ud_srq = qp_attr.qp_srq;
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate 	ud_chan_attrs->ud_flags = ud_chan->ch_qp.qp_flags;
8170Sstevel@tonic-gate 
818*12965SWilliam.Taylor@Oracle.COM 	ud_chan_attrs->ud_query_fc = qp_attr.qp_query_fexch;
819*12965SWilliam.Taylor@Oracle.COM 
8200Sstevel@tonic-gate 	return (retval);
8210Sstevel@tonic-gate }
8220Sstevel@tonic-gate 
8230Sstevel@tonic-gate 
8240Sstevel@tonic-gate /*
8250Sstevel@tonic-gate  * Function:
8260Sstevel@tonic-gate  *	ibt_modify_ud_channel
8270Sstevel@tonic-gate  * Input:
8280Sstevel@tonic-gate  *	ud_chan		A previously allocated UD channel handle.
8290Sstevel@tonic-gate  *	flags		Specifies which attributes in ibt_ud_chan_modify_attr_t
8300Sstevel@tonic-gate  *			are to be modified.
8310Sstevel@tonic-gate  *	attrs		Attributes to be modified.
8320Sstevel@tonic-gate  * Output:
8330Sstevel@tonic-gate  *	actual_sz	On return contains the new send and receive queue sizes.
8340Sstevel@tonic-gate  * Returns:
8350Sstevel@tonic-gate  *	IBT_SUCCESS
8360Sstevel@tonic-gate  * Description:
8370Sstevel@tonic-gate  *	Modifies an UD channel's attributes, as specified by a
8380Sstevel@tonic-gate  *	ibt_cep_modify_flags_t parameter to those specified in the
8390Sstevel@tonic-gate  *	ibt_ud_chan_modify_attr_t structure.
8400Sstevel@tonic-gate  */
8410Sstevel@tonic-gate ibt_status_t
ibt_modify_ud_channel(ibt_channel_hdl_t ud_chan,ibt_cep_modify_flags_t flags,ibt_ud_chan_modify_attr_t * attrs,ibt_queue_sizes_t * actual_sz)8420Sstevel@tonic-gate ibt_modify_ud_channel(ibt_channel_hdl_t ud_chan, ibt_cep_modify_flags_t flags,
8430Sstevel@tonic-gate     ibt_ud_chan_modify_attr_t *attrs, ibt_queue_sizes_t *actual_sz)
8440Sstevel@tonic-gate {
8450Sstevel@tonic-gate 	ibt_status_t		retval;
8460Sstevel@tonic-gate 	ibt_qp_info_t		qp_info;
8470Sstevel@tonic-gate 	ibt_cep_modify_flags_t	good_flags;
8480Sstevel@tonic-gate 	int			retries = 1;
8490Sstevel@tonic-gate 
8500Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_modify_ud_channel(%p, %x, %p, %p)",
8510Sstevel@tonic-gate 	    ud_chan, flags, attrs, actual_sz);
8520Sstevel@tonic-gate 
8530Sstevel@tonic-gate 	if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) {
8540Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_ud_channel: "
8550Sstevel@tonic-gate 		    "type of channel (%d) is not UD", ud_chan->ch_qp.qp_type);
8560Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
8570Sstevel@tonic-gate 	}
8580Sstevel@tonic-gate 
8590Sstevel@tonic-gate 	good_flags = IBT_CEP_SET_SQ_SIZE | IBT_CEP_SET_RQ_SIZE |
8600Sstevel@tonic-gate 	    IBT_CEP_SET_QKEY;
8610Sstevel@tonic-gate 
8620Sstevel@tonic-gate 	if (flags & ~good_flags) {
8630Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_ud_channel: "
8640Sstevel@tonic-gate 		    "Invalid Modify Flags: %x", flags);
8650Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
8660Sstevel@tonic-gate 	}
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate retry:
8690Sstevel@tonic-gate 	bzero(&qp_info, sizeof (ibt_qp_info_t));
8700Sstevel@tonic-gate 
8710Sstevel@tonic-gate 	qp_info.qp_state = ud_chan->ch_current_state;	/* No Change in State */
8720Sstevel@tonic-gate 	qp_info.qp_current_state = ud_chan->ch_current_state;
8730Sstevel@tonic-gate 	qp_info.qp_flags = IBT_CEP_NO_FLAGS;
8740Sstevel@tonic-gate 
8750Sstevel@tonic-gate 	qp_info.qp_sq_sz = attrs->ud_sq_sz;
8760Sstevel@tonic-gate 	qp_info.qp_rq_sz = attrs->ud_rq_sz;
8770Sstevel@tonic-gate 	qp_info.qp_trans = IBT_UD_SRV;
8780Sstevel@tonic-gate 	qp_info.qp_transport.ud.ud_qkey = attrs->ud_qkey;
8790Sstevel@tonic-gate 
8800Sstevel@tonic-gate 	flags |= IBT_CEP_SET_STATE;
8810Sstevel@tonic-gate 
8820Sstevel@tonic-gate 	retval = ibt_modify_qp(ud_chan, flags, &qp_info, actual_sz);
8830Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
8840Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_ud_channel: "
8850Sstevel@tonic-gate 		    "ibt_modify_qp failed on QP %p: %d", ud_chan, retval);
8860Sstevel@tonic-gate 		/* give it one more shot if the old current state was stale */
8870Sstevel@tonic-gate 		if (qp_info.qp_current_state != ud_chan->ch_current_state &&
8880Sstevel@tonic-gate 		    --retries >= 0 &&
8890Sstevel@tonic-gate 		    (qp_info.qp_current_state == IBT_STATE_RTS ||
8900Sstevel@tonic-gate 		    qp_info.qp_current_state == IBT_STATE_SQD))
8910Sstevel@tonic-gate 			goto retry;
8920Sstevel@tonic-gate 	}
8930Sstevel@tonic-gate 
8940Sstevel@tonic-gate 	return (retval);
8950Sstevel@tonic-gate }
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate 
8980Sstevel@tonic-gate /*
8990Sstevel@tonic-gate  * Function:
9000Sstevel@tonic-gate  *	ibt_recover_ud_channel
9010Sstevel@tonic-gate  * Input:
9020Sstevel@tonic-gate  *	ud_chan		An UD channel handle which is in SQError state.
9030Sstevel@tonic-gate  * Output:
9040Sstevel@tonic-gate  *	none.
9050Sstevel@tonic-gate  * Returns:
9060Sstevel@tonic-gate  *	IBT_SUCCESS
9070Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID
9080Sstevel@tonic-gate  *	IBT_CHAN_SRV_TYPE_INVALID
9090Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
9100Sstevel@tonic-gate  * Description:
9110Sstevel@tonic-gate  *	Recover an UD Channel which has transitioned to SQ Error state. The
9120Sstevel@tonic-gate  *	ibt_recover_ud_channel() transitions the channel from SQ Error state
9130Sstevel@tonic-gate  *	to Ready-To-Send channel state.
9140Sstevel@tonic-gate  *
9150Sstevel@tonic-gate  *	If a work request posted to a UD channel's send queue completes with
9160Sstevel@tonic-gate  *	an error (see ibt_wc_status_t), the channel gets transitioned to SQ
9170Sstevel@tonic-gate  *	Error state. In order to reuse this channel, ibt_recover_ud_channel()
9180Sstevel@tonic-gate  *	can be used to recover the channel to a usable (Ready-to-Send) state.
9190Sstevel@tonic-gate  */
9200Sstevel@tonic-gate ibt_status_t
ibt_recover_ud_channel(ibt_channel_hdl_t ud_chan)9210Sstevel@tonic-gate ibt_recover_ud_channel(ibt_channel_hdl_t ud_chan)
9220Sstevel@tonic-gate {
9230Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
9240Sstevel@tonic-gate 	ibt_status_t		retval;
9250Sstevel@tonic-gate 
9260Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_recover_ud_channel(%p)", ud_chan);
9270Sstevel@tonic-gate 
9280Sstevel@tonic-gate 	if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) {
9290Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_recover_ud_channel: "
9300Sstevel@tonic-gate 		    "Called for non-UD channels<%d>", ud_chan->ch_qp.qp_type);
9310Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
9320Sstevel@tonic-gate 	}
9330Sstevel@tonic-gate 
9340Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
9350Sstevel@tonic-gate 
9360Sstevel@tonic-gate 	/* Set the channel state to RTS, to activate the send processing. */
9370Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_RTS;
9380Sstevel@tonic-gate 	modify_attr.qp_trans = ud_chan->ch_qp.qp_type;
9390Sstevel@tonic-gate 	modify_attr.qp_current_state = IBT_STATE_SQE;
9400Sstevel@tonic-gate 
9410Sstevel@tonic-gate 	retval = ibt_modify_qp(ud_chan, IBT_CEP_SET_STATE, &modify_attr, NULL);
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate 	if (retval != IBT_SUCCESS)
9440Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_recover_ud_channel: "
9450Sstevel@tonic-gate 		    "ibt_modify_qp failed on qp %p: status = %d",
9460Sstevel@tonic-gate 		    ud_chan, retval);
9470Sstevel@tonic-gate 
9480Sstevel@tonic-gate 	return (retval);
9490Sstevel@tonic-gate }
9500Sstevel@tonic-gate 
9510Sstevel@tonic-gate 
9520Sstevel@tonic-gate /*
9530Sstevel@tonic-gate  * Function:
9540Sstevel@tonic-gate  *	ibt_flush_channel
9550Sstevel@tonic-gate  * Input:
9560Sstevel@tonic-gate  *	chan		The opaque channel handle returned in a previous call
9570Sstevel@tonic-gate  *			to ibt_alloc_ud_channel() or ibt_alloc_rc_channel().
9580Sstevel@tonic-gate  * Output:
9590Sstevel@tonic-gate  *	none.
9600Sstevel@tonic-gate  * Returns:
9610Sstevel@tonic-gate  *	IBT_SUCCESS
9620Sstevel@tonic-gate  * Description:
9630Sstevel@tonic-gate  *	Flush the specified channel. Outstanding work requests are flushed
9640Sstevel@tonic-gate  *	so that the client can do the associated clean up. After that, the
9650Sstevel@tonic-gate  *	client will usually deregister the previously registered memory,
9660Sstevel@tonic-gate  *	then free the channel by calling ibt_free_channel().  This function
9670Sstevel@tonic-gate  *	applies to UD channels, or to RC channels that have not successfully
9680Sstevel@tonic-gate  *	been opened.
9690Sstevel@tonic-gate  */
9700Sstevel@tonic-gate ibt_status_t
ibt_flush_channel(ibt_channel_hdl_t chan)9710Sstevel@tonic-gate ibt_flush_channel(ibt_channel_hdl_t chan)
9720Sstevel@tonic-gate {
9730Sstevel@tonic-gate 	ibt_status_t retval;
9740Sstevel@tonic-gate 
9750Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_flush_channel(%p)", chan);
9760Sstevel@tonic-gate 
9770Sstevel@tonic-gate 	retval = ibt_flush_qp(chan);
9780Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
9790Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_flush_channel: "
9800Sstevel@tonic-gate 		    "ibt_flush_qp failed on QP %p: %d", chan, retval);
9810Sstevel@tonic-gate 	}
9820Sstevel@tonic-gate 
9830Sstevel@tonic-gate 	return (retval);
9840Sstevel@tonic-gate }
9850Sstevel@tonic-gate 
9860Sstevel@tonic-gate 
9870Sstevel@tonic-gate /*
9880Sstevel@tonic-gate  * Function:
9890Sstevel@tonic-gate  *	ibt_free_channel
9900Sstevel@tonic-gate  * Input:
9910Sstevel@tonic-gate  *	chan		The opaque channel handle returned in a previous
9920Sstevel@tonic-gate  *			call to ibt_alloc_{ud,rc}_channel().
9930Sstevel@tonic-gate  * Output:
9940Sstevel@tonic-gate  *	none.
9950Sstevel@tonic-gate  * Returns:
9960Sstevel@tonic-gate  *	IBT_SUCCESS
9970Sstevel@tonic-gate  * Description:
9980Sstevel@tonic-gate  *	Releases the resources associated with the specified channel.
9990Sstevel@tonic-gate  *	It is well assumed that channel has been closed before this.
10000Sstevel@tonic-gate  */
10010Sstevel@tonic-gate ibt_status_t
ibt_free_channel(ibt_channel_hdl_t chan)10020Sstevel@tonic-gate ibt_free_channel(ibt_channel_hdl_t chan)
10030Sstevel@tonic-gate {
10040Sstevel@tonic-gate 	return (ibt_free_qp(chan));
10050Sstevel@tonic-gate }
10060Sstevel@tonic-gate 
10070Sstevel@tonic-gate 
10080Sstevel@tonic-gate /*
10090Sstevel@tonic-gate  * UD Destination.
10100Sstevel@tonic-gate  */
10110Sstevel@tonic-gate /*
10120Sstevel@tonic-gate  * Function:
10130Sstevel@tonic-gate  *	ibt_alloc_ud_dest
10140Sstevel@tonic-gate  * Input:
10150Sstevel@tonic-gate  *	hca_hdl		HCA Handle.
10160Sstevel@tonic-gate  *	pd		Protection Domain
10170Sstevel@tonic-gate  * Output:
10180Sstevel@tonic-gate  *	ud_dest_p	Address to store the returned UD destination handle.
10190Sstevel@tonic-gate  * Returns:
10200Sstevel@tonic-gate  *	IBT_SUCCESS
10210Sstevel@tonic-gate  * Description:
10220Sstevel@tonic-gate  *	Allocate a UD destination handle. The returned UD destination handle
10230Sstevel@tonic-gate  *	has no useful contents, but is usable after calling ibt_modify_ud_dest,
10240Sstevel@tonic-gate  *	ibt_modify_reply_ud_dest, or ibt_open_ud_dest.
10250Sstevel@tonic-gate  */
10260Sstevel@tonic-gate ibt_status_t
ibt_alloc_ud_dest(ibt_hca_hdl_t hca_hdl,ibt_ud_dest_flags_t flags,ibt_pd_hdl_t pd,ibt_ud_dest_hdl_t * ud_dest_p)10270Sstevel@tonic-gate ibt_alloc_ud_dest(ibt_hca_hdl_t hca_hdl, ibt_ud_dest_flags_t flags,
10280Sstevel@tonic-gate     ibt_pd_hdl_t pd, ibt_ud_dest_hdl_t *ud_dest_p)
10290Sstevel@tonic-gate {
10300Sstevel@tonic-gate 	ibt_status_t	retval;
10310Sstevel@tonic-gate 	ibt_ud_dest_t	*ud_destp;
10320Sstevel@tonic-gate 	ibt_ah_hdl_t	ah;
10330Sstevel@tonic-gate 	ibt_adds_vect_t adds_vect;
10340Sstevel@tonic-gate 
10350Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_ud_dest(%p, %x, %p)",
10360Sstevel@tonic-gate 	    hca_hdl, flags, pd);
10370Sstevel@tonic-gate 
10380Sstevel@tonic-gate 	bzero(&adds_vect, sizeof (adds_vect));
10390Sstevel@tonic-gate 	adds_vect.av_port_num = 1;
10400Sstevel@tonic-gate 	adds_vect.av_srate = IBT_SRATE_1X;	/* assume the minimum */
10410Sstevel@tonic-gate 	retval = ibt_alloc_ah(hca_hdl, flags, pd, &adds_vect, &ah);
10420Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
10430Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ud_dest: "
10440Sstevel@tonic-gate 		    "Address Handle Allocation failed: %d", retval);
10450Sstevel@tonic-gate 		*ud_dest_p = NULL;
10460Sstevel@tonic-gate 		return (retval);
10470Sstevel@tonic-gate 	}
10480Sstevel@tonic-gate 	ud_destp = kmem_alloc(sizeof (*ud_destp), KM_SLEEP);
10490Sstevel@tonic-gate 	ud_destp->ud_ah = ah;
10500Sstevel@tonic-gate 	ud_destp->ud_dest_hca = hca_hdl;
10510Sstevel@tonic-gate 	ud_destp->ud_dst_qpn = 0;
10520Sstevel@tonic-gate 	ud_destp->ud_qkey = 0;
10530Sstevel@tonic-gate 	*ud_dest_p = ud_destp;
10540Sstevel@tonic-gate 	return (IBT_SUCCESS);
10550Sstevel@tonic-gate }
10560Sstevel@tonic-gate 
10570Sstevel@tonic-gate /*
10580Sstevel@tonic-gate  * Function:
10590Sstevel@tonic-gate  *	ibt_query_ud_dest
10600Sstevel@tonic-gate  * Input:
10610Sstevel@tonic-gate  *	ud_dest		A previously allocated UD destination handle.
10620Sstevel@tonic-gate  * Output:
10630Sstevel@tonic-gate  *	dest_attrs	UD destination's current attributes.
10640Sstevel@tonic-gate  * Returns:
10650Sstevel@tonic-gate  *	IBT_SUCCESS
10660Sstevel@tonic-gate  * Description:
10670Sstevel@tonic-gate  *	Query a UD destination's attributes.
10680Sstevel@tonic-gate  */
10690Sstevel@tonic-gate ibt_status_t
ibt_query_ud_dest(ibt_ud_dest_hdl_t ud_dest,ibt_ud_dest_query_attr_t * dest_attrs)10700Sstevel@tonic-gate ibt_query_ud_dest(ibt_ud_dest_hdl_t ud_dest,
10710Sstevel@tonic-gate     ibt_ud_dest_query_attr_t *dest_attrs)
10720Sstevel@tonic-gate {
10730Sstevel@tonic-gate 	ibt_status_t	retval;
10740Sstevel@tonic-gate 
10750Sstevel@tonic-gate 	ASSERT(dest_attrs != NULL);
10760Sstevel@tonic-gate 
10770Sstevel@tonic-gate 	/* Query Address Handle */
10780Sstevel@tonic-gate 	retval = ibt_query_ah(ud_dest->ud_dest_hca, ud_dest->ud_ah,
10790Sstevel@tonic-gate 	    &dest_attrs->ud_pd, &dest_attrs->ud_addr_vect);
10800Sstevel@tonic-gate 
10810Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
10820Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_query_ud_dest: "
10830Sstevel@tonic-gate 		    "Failed to Query Address Handle: %d", retval);
10840Sstevel@tonic-gate 		return (retval);
10850Sstevel@tonic-gate 	}
10860Sstevel@tonic-gate 
10870Sstevel@tonic-gate 	/* Update the return struct. */
10880Sstevel@tonic-gate 	dest_attrs->ud_hca_hdl = ud_dest->ud_dest_hca;
10890Sstevel@tonic-gate 	dest_attrs->ud_dst_qpn = ud_dest->ud_dst_qpn;
10900Sstevel@tonic-gate 	dest_attrs->ud_qkey = ud_dest->ud_qkey;
10910Sstevel@tonic-gate 
10920Sstevel@tonic-gate 	return (retval);
10930Sstevel@tonic-gate }
10940Sstevel@tonic-gate 
10950Sstevel@tonic-gate /*
10960Sstevel@tonic-gate  * Function:
10970Sstevel@tonic-gate  *	ibt_modify_ud_dest
10980Sstevel@tonic-gate  * Input:
10990Sstevel@tonic-gate  *	ud_dest		A previously allocated UD destination handle
11000Sstevel@tonic-gate  *			as returned by ibt_alloc_ud_dest().
11010Sstevel@tonic-gate  *	qkey		QKey of the destination.
11020Sstevel@tonic-gate  *	dest_qpn	QPN of the destination.
11030Sstevel@tonic-gate  *	adds_vect	NULL or Address Vector for the destination.
11040Sstevel@tonic-gate  *
11050Sstevel@tonic-gate  * Output:
11060Sstevel@tonic-gate  *	none.
11070Sstevel@tonic-gate  * Returns:
11080Sstevel@tonic-gate  *	IBT_SUCCESS
11090Sstevel@tonic-gate  * Description:
11100Sstevel@tonic-gate  *	Modify a previously allocated UD destination handle from the
11110Sstevel@tonic-gate  *	arguments supplied by the caller.
11120Sstevel@tonic-gate  */
11130Sstevel@tonic-gate ibt_status_t
ibt_modify_ud_dest(ibt_ud_dest_hdl_t ud_dest,ib_qkey_t qkey,ib_qpn_t dest_qpn,ibt_adds_vect_t * adds_vect)11140Sstevel@tonic-gate ibt_modify_ud_dest(ibt_ud_dest_hdl_t ud_dest, ib_qkey_t qkey,
11150Sstevel@tonic-gate     ib_qpn_t dest_qpn, ibt_adds_vect_t *adds_vect)
11160Sstevel@tonic-gate {
11170Sstevel@tonic-gate 	ibt_status_t	retval;
11180Sstevel@tonic-gate 
11190Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_modify_ud_dest(%p, %x, %x, %p) ",
11200Sstevel@tonic-gate 	    ud_dest, qkey, dest_qpn, adds_vect);
11210Sstevel@tonic-gate 
11220Sstevel@tonic-gate 	if ((adds_vect != NULL) &&
11230Sstevel@tonic-gate 	    (retval = ibt_modify_ah(ud_dest->ud_dest_hca, ud_dest->ud_ah,
11240Sstevel@tonic-gate 	    adds_vect)) != IBT_SUCCESS) {
11250Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_ud_dest: "
11260Sstevel@tonic-gate 		    "ibt_modify_ah() failed: status = %d", retval);
11270Sstevel@tonic-gate 		return (retval);
11280Sstevel@tonic-gate 	}
11290Sstevel@tonic-gate 	ud_dest->ud_dst_qpn = dest_qpn;
11300Sstevel@tonic-gate 	ud_dest->ud_qkey = qkey;
11310Sstevel@tonic-gate 	return (IBT_SUCCESS);
11320Sstevel@tonic-gate }
11330Sstevel@tonic-gate 
11340Sstevel@tonic-gate /*
11350Sstevel@tonic-gate  * Function:
11360Sstevel@tonic-gate  *	ibt_free_ud_dest
11370Sstevel@tonic-gate  * Input:
11380Sstevel@tonic-gate  *	ud_dest		The opaque destination handle returned in a previous
11390Sstevel@tonic-gate  *			call to ibt_alloc_ud_dest() or ibt_alloc_mcg_dest().
11400Sstevel@tonic-gate  * Output:
11410Sstevel@tonic-gate  *	none.
11420Sstevel@tonic-gate  * Returns:
11430Sstevel@tonic-gate  *	IBT_SUCCESS
11440Sstevel@tonic-gate  * Description:
11450Sstevel@tonic-gate  *	Releases the resources associated with the specified destination
11460Sstevel@tonic-gate  *	handle.
11470Sstevel@tonic-gate  */
11480Sstevel@tonic-gate ibt_status_t
ibt_free_ud_dest(ibt_ud_dest_hdl_t ud_dest)11490Sstevel@tonic-gate ibt_free_ud_dest(ibt_ud_dest_hdl_t ud_dest)
11500Sstevel@tonic-gate {
11510Sstevel@tonic-gate 	ibt_status_t	retval;
11520Sstevel@tonic-gate 
11530Sstevel@tonic-gate 	retval = ibt_free_ah(ud_dest->ud_dest_hca, ud_dest->ud_ah);
11540Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
11550Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_free_ud_dest: "
11560Sstevel@tonic-gate 		    "Address Handle free failed: %d", retval);
11570Sstevel@tonic-gate 		return (retval);
11580Sstevel@tonic-gate 	}
11590Sstevel@tonic-gate 	kmem_free(ud_dest, sizeof (*ud_dest));
11600Sstevel@tonic-gate 	return (IBT_SUCCESS);
11610Sstevel@tonic-gate }
11620Sstevel@tonic-gate 
11630Sstevel@tonic-gate static ibt_status_t
ibtl_find_sgid_ix(ib_gid_t * sgid,ibt_channel_hdl_t ud_chan,uint8_t port,uint_t * sgid_ix_p)11640Sstevel@tonic-gate ibtl_find_sgid_ix(ib_gid_t *sgid, ibt_channel_hdl_t ud_chan, uint8_t port,
11650Sstevel@tonic-gate     uint_t *sgid_ix_p)
11660Sstevel@tonic-gate {
11670Sstevel@tonic-gate 	ibtl_hca_devinfo_t *hca_devp = ud_chan->ch_qp.qp_hca->ha_hca_devp;
11680Sstevel@tonic-gate 	ib_gid_t *sgidp;
11690Sstevel@tonic-gate 	uint_t i;
11700Sstevel@tonic-gate 	uint_t sgid_tbl_sz;
11710Sstevel@tonic-gate 
11720Sstevel@tonic-gate 	if (port == 0 || port > hca_devp->hd_hca_attr->hca_nports ||
11730Sstevel@tonic-gate 	    sgid->gid_prefix == 0 || sgid->gid_guid == 0) {
11740Sstevel@tonic-gate 		*sgid_ix_p = 0;
11750Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
11760Sstevel@tonic-gate 	}
11770Sstevel@tonic-gate 	mutex_enter(&ibtl_clnt_list_mutex);
11780Sstevel@tonic-gate 	sgidp = &hca_devp->hd_portinfop[port - 1].p_sgid_tbl[0];
11790Sstevel@tonic-gate 	sgid_tbl_sz = hca_devp->hd_portinfop[port - 1].p_sgid_tbl_sz;
11800Sstevel@tonic-gate 	for (i = 0; i < sgid_tbl_sz; i++, sgidp++) {
11810Sstevel@tonic-gate 		if ((sgid->gid_guid != sgidp->gid_guid) ||
11820Sstevel@tonic-gate 		    (sgid->gid_prefix != sgidp->gid_prefix))
11830Sstevel@tonic-gate 			continue;
11840Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
11850Sstevel@tonic-gate 		*sgid_ix_p = i;
11860Sstevel@tonic-gate 		return (IBT_SUCCESS);
11870Sstevel@tonic-gate 	}
11880Sstevel@tonic-gate 	mutex_exit(&ibtl_clnt_list_mutex);
11890Sstevel@tonic-gate 	*sgid_ix_p = 0;
11900Sstevel@tonic-gate 	return (IBT_INVALID_PARAM);
11910Sstevel@tonic-gate }
11920Sstevel@tonic-gate 
11930Sstevel@tonic-gate /*
11940Sstevel@tonic-gate  * Function:
11950Sstevel@tonic-gate  *	ibt_modify_reply_ud_dest
11960Sstevel@tonic-gate  * Input:
11970Sstevel@tonic-gate  *	ud_dest		A previously allocated UD reply destination handle
11980Sstevel@tonic-gate  *			as returned by ibt_alloc_ud_dest().
11990Sstevel@tonic-gate  *	qkey		Qkey.  0 means "not specified", so use the Q_Key
12000Sstevel@tonic-gate  *			in the QP context.
12010Sstevel@tonic-gate  *	recv_buf	Pointer to the first data buffer associated with the
12020Sstevel@tonic-gate  *			receive work request.
12030Sstevel@tonic-gate  * Output:
12040Sstevel@tonic-gate  * Returns:
12050Sstevel@tonic-gate  *	IBT_SUCCESS
12060Sstevel@tonic-gate  * Description:
12070Sstevel@tonic-gate  *	Modify a previously allocated UD destination handle, so that it
12080Sstevel@tonic-gate  *	can be used to reply to the sender of the datagram contained in the
12090Sstevel@tonic-gate  *	specified work request completion.  If the qkey is not supplied (0),
12100Sstevel@tonic-gate  *	then use the qkey in the QP (we just set qkey to a privileged QKEY).
12110Sstevel@tonic-gate  */
12120Sstevel@tonic-gate ibt_status_t
ibt_modify_reply_ud_dest(ibt_channel_hdl_t ud_chan,ibt_ud_dest_hdl_t ud_dest,ib_qkey_t qkey,ibt_wc_t * wc,ib_vaddr_t recv_buf)12130Sstevel@tonic-gate ibt_modify_reply_ud_dest(ibt_channel_hdl_t ud_chan, ibt_ud_dest_hdl_t ud_dest,
12140Sstevel@tonic-gate     ib_qkey_t qkey, ibt_wc_t *wc, ib_vaddr_t recv_buf)
12150Sstevel@tonic-gate {
12160Sstevel@tonic-gate 	ibt_status_t		retval;
12170Sstevel@tonic-gate 	ibt_adds_vect_t		adds_vect;
12180Sstevel@tonic-gate 	ib_grh_t		*grh;
12190Sstevel@tonic-gate 	uint8_t			port;
12200Sstevel@tonic-gate 	uint32_t		ver_tc_flow;
12210Sstevel@tonic-gate 
12220Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_modify_reply_ud_dest(%p, %p, %x, %p, "
12230Sstevel@tonic-gate 	    "%llx)", ud_chan, ud_dest, qkey, wc, recv_buf);
12240Sstevel@tonic-gate 
12250Sstevel@tonic-gate 	if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) {
12260Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_reply_ud_dest: "
12270Sstevel@tonic-gate 		    "type of channel (%d) is not UD",
12280Sstevel@tonic-gate 		    ud_chan->ch_qp.qp_type);
12290Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
12300Sstevel@tonic-gate 	}
12310Sstevel@tonic-gate 	if (qkey == 0)
12320Sstevel@tonic-gate 		qkey = ud_chan->ch_transport.ud.ud_qkey;
12330Sstevel@tonic-gate 	port = ud_chan->ch_transport.ud.ud_port_num;
12340Sstevel@tonic-gate 
12350Sstevel@tonic-gate 	if (wc->wc_flags & IBT_WC_GRH_PRESENT) {
12360Sstevel@tonic-gate 		grh = (ib_grh_t *)(uintptr_t)recv_buf;
12370Sstevel@tonic-gate 		adds_vect.av_send_grh = B_TRUE;
12380Sstevel@tonic-gate 		adds_vect.av_dgid.gid_prefix = b2h64(grh->SGID.gid_prefix);
12390Sstevel@tonic-gate 		adds_vect.av_dgid.gid_guid = b2h64(grh->SGID.gid_guid);
12400Sstevel@tonic-gate 		adds_vect.av_sgid.gid_prefix = b2h64(grh->DGID.gid_prefix);
12410Sstevel@tonic-gate 		adds_vect.av_sgid.gid_guid = b2h64(grh->DGID.gid_guid);
12420Sstevel@tonic-gate 		(void) ibtl_find_sgid_ix(&adds_vect.av_sgid, ud_chan,
12430Sstevel@tonic-gate 		    port, &adds_vect.av_sgid_ix);
12440Sstevel@tonic-gate 		ver_tc_flow = b2h32(grh->IPVer_TC_Flow);
12450Sstevel@tonic-gate 		adds_vect.av_flow = ver_tc_flow & IB_GRH_FLOW_LABEL_MASK;
12460Sstevel@tonic-gate 		adds_vect.av_tclass = (ver_tc_flow & IB_GRH_TCLASS_MASK) >> 20;
12470Sstevel@tonic-gate 		adds_vect.av_hop = grh->HopLmt;
12480Sstevel@tonic-gate 	} else {
12490Sstevel@tonic-gate 		adds_vect.av_send_grh = B_FALSE;
12500Sstevel@tonic-gate 		adds_vect.av_dgid.gid_prefix = 0;
12510Sstevel@tonic-gate 		adds_vect.av_sgid.gid_prefix = 0;
12520Sstevel@tonic-gate 		adds_vect.av_dgid.gid_guid = 0;
12530Sstevel@tonic-gate 		adds_vect.av_sgid.gid_guid = 0;
12540Sstevel@tonic-gate 		adds_vect.av_sgid_ix = 0;
12550Sstevel@tonic-gate 		adds_vect.av_flow = 0;
12560Sstevel@tonic-gate 		adds_vect.av_tclass = 0;
12570Sstevel@tonic-gate 		adds_vect.av_hop = 0;
12580Sstevel@tonic-gate 	}
12590Sstevel@tonic-gate 
12600Sstevel@tonic-gate 	adds_vect.av_srate = IBT_SRATE_1X;	/* assume the minimum */
12610Sstevel@tonic-gate 	adds_vect.av_srvl = wc->wc_sl;
12620Sstevel@tonic-gate 	adds_vect.av_dlid = wc->wc_slid;
12630Sstevel@tonic-gate 	adds_vect.av_src_path = wc->wc_path_bits;
12640Sstevel@tonic-gate 	adds_vect.av_port_num = port;
12650Sstevel@tonic-gate 
12660Sstevel@tonic-gate 	if ((retval = ibt_modify_ah(ud_dest->ud_dest_hca, ud_dest->ud_ah,
12670Sstevel@tonic-gate 	    &adds_vect)) != IBT_SUCCESS) {
12680Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_modify_reply_ud_dest: "
12690Sstevel@tonic-gate 		    "ibt_alloc_ah() failed: status = %d", retval);
12700Sstevel@tonic-gate 		return (retval);
12710Sstevel@tonic-gate 	}
12720Sstevel@tonic-gate 	ud_dest->ud_dst_qpn = wc->wc_qpn & IB_QPN_MASK;
12730Sstevel@tonic-gate 	ud_dest->ud_qkey = qkey;
12740Sstevel@tonic-gate 
12750Sstevel@tonic-gate 	return (IBT_SUCCESS);
12760Sstevel@tonic-gate }
12770Sstevel@tonic-gate 
12780Sstevel@tonic-gate 
12790Sstevel@tonic-gate /*
12800Sstevel@tonic-gate  * Function:
12810Sstevel@tonic-gate  *	ibt_is_privileged_ud_dest
12820Sstevel@tonic-gate  * Input:
12830Sstevel@tonic-gate  *	ud_dest		A previously allocated destination handle.
12840Sstevel@tonic-gate  * Output:
12850Sstevel@tonic-gate  *	none
12860Sstevel@tonic-gate  * Returns:
12870Sstevel@tonic-gate  *	B_FALSE/B_TRUE
12880Sstevel@tonic-gate  * Description:
12890Sstevel@tonic-gate  *	Determine if a UD destination Handle is a privileged handle.
12900Sstevel@tonic-gate  */
12910Sstevel@tonic-gate boolean_t
ibt_is_privileged_ud_dest(ibt_ud_dest_hdl_t ud_dest)12920Sstevel@tonic-gate ibt_is_privileged_ud_dest(ibt_ud_dest_hdl_t ud_dest)
12930Sstevel@tonic-gate {
12940Sstevel@tonic-gate 	return ((ud_dest->ud_qkey & IB_PRIVILEGED_QKEY_BIT) ? B_TRUE : B_FALSE);
12950Sstevel@tonic-gate }
12960Sstevel@tonic-gate 
12970Sstevel@tonic-gate 
12980Sstevel@tonic-gate /*
12990Sstevel@tonic-gate  * Function:
13000Sstevel@tonic-gate  *	ibt_update_channel_qkey
13010Sstevel@tonic-gate  * Input:
13020Sstevel@tonic-gate  *	ud_chan		The UD channel handle, that is to be used to
13030Sstevel@tonic-gate  *			communicate with the specified destination.
13040Sstevel@tonic-gate  *
13050Sstevel@tonic-gate  *	ud_dest		A UD destination handle returned from
13060Sstevel@tonic-gate  *			ibt_alloc_ud_dest(9F).
13070Sstevel@tonic-gate  * Output:
13080Sstevel@tonic-gate  *	none
13090Sstevel@tonic-gate  * Returns:
13100Sstevel@tonic-gate  *	IBT_SUCCESS
13110Sstevel@tonic-gate  * Description:
13120Sstevel@tonic-gate  *   ibt_update_channel_qkey() sets the Q_Key in the specified channel context
13130Sstevel@tonic-gate  *   to the Q_Key in the specified destination handle. This function can be used
13140Sstevel@tonic-gate  *   to enable sends to a privileged destination. All posted send work requests
13150Sstevel@tonic-gate  *   that contain a privileged destination handle now use the Q_Key in the
13160Sstevel@tonic-gate  *   channel context.
13170Sstevel@tonic-gate  *
13180Sstevel@tonic-gate  *   ibt_update_channel_qkey() can also be used to enable the caller to receive
13190Sstevel@tonic-gate  *   from the specified remote destination on the specified channel.
13200Sstevel@tonic-gate  */
13210Sstevel@tonic-gate ibt_status_t
ibt_update_channel_qkey(ibt_channel_hdl_t ud_chan,ibt_ud_dest_hdl_t ud_dest)13220Sstevel@tonic-gate ibt_update_channel_qkey(ibt_channel_hdl_t ud_chan, ibt_ud_dest_hdl_t ud_dest)
13230Sstevel@tonic-gate {
13240Sstevel@tonic-gate 	ibt_status_t		retval;
13250Sstevel@tonic-gate 	ibt_qp_info_t		qp_info;
13260Sstevel@tonic-gate 
13270Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_update_channel_qkey(%p, %p)",
13280Sstevel@tonic-gate 	    ud_chan, ud_dest);
13290Sstevel@tonic-gate 
13300Sstevel@tonic-gate 	if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) {
13310Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_update_channel_qkey: "
13320Sstevel@tonic-gate 		    "type of channel (%d) is not UD",
13330Sstevel@tonic-gate 		    ud_chan->ch_qp.qp_type);
13340Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
13350Sstevel@tonic-gate 	}
13360Sstevel@tonic-gate 	bzero(&qp_info, sizeof (ibt_qp_info_t));
13370Sstevel@tonic-gate 
13380Sstevel@tonic-gate 	qp_info.qp_trans = IBT_UD_SRV;
13390Sstevel@tonic-gate 	qp_info.qp_state = ud_chan->ch_current_state;
13400Sstevel@tonic-gate 	qp_info.qp_current_state = ud_chan->ch_current_state;
13410Sstevel@tonic-gate 	qp_info.qp_transport.ud.ud_qkey = ud_dest->ud_qkey;
13420Sstevel@tonic-gate 
13430Sstevel@tonic-gate 	retval = ibt_modify_qp(ud_chan, IBT_CEP_SET_QKEY | IBT_CEP_SET_STATE,
13440Sstevel@tonic-gate 	    &qp_info, NULL);
13450Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
13460Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_update_channel_qkey: "
13470Sstevel@tonic-gate 		    "Failed to modify QP %p: status %d", ud_chan, retval);
13480Sstevel@tonic-gate 	} else {
13490Sstevel@tonic-gate 		ud_chan->ch_transport.ud.ud_qkey = ud_dest->ud_qkey;
13500Sstevel@tonic-gate 	}
13510Sstevel@tonic-gate 
13520Sstevel@tonic-gate 	return (retval);
13530Sstevel@tonic-gate }
13540Sstevel@tonic-gate 
13550Sstevel@tonic-gate 
13560Sstevel@tonic-gate /*
13570Sstevel@tonic-gate  * Function:
13580Sstevel@tonic-gate  *	ibt_set_chan_private
13590Sstevel@tonic-gate  * Input:
13600Sstevel@tonic-gate  *	chan		A previously allocated channel handle.
13610Sstevel@tonic-gate  *	clnt_private	The client private data.
13620Sstevel@tonic-gate  * Output:
13630Sstevel@tonic-gate  *	none.
13640Sstevel@tonic-gate  * Returns:
13650Sstevel@tonic-gate  *	none.
13660Sstevel@tonic-gate  * Description:
13670Sstevel@tonic-gate  *	Set the client private data.
13680Sstevel@tonic-gate  */
13690Sstevel@tonic-gate void
ibt_set_chan_private(ibt_channel_hdl_t chan,void * clnt_private)13700Sstevel@tonic-gate ibt_set_chan_private(ibt_channel_hdl_t chan, void *clnt_private)
13710Sstevel@tonic-gate {
13720Sstevel@tonic-gate 	chan->ch_clnt_private = clnt_private;
13730Sstevel@tonic-gate }
13740Sstevel@tonic-gate 
13750Sstevel@tonic-gate 
13760Sstevel@tonic-gate /*
13770Sstevel@tonic-gate  * Function:
13780Sstevel@tonic-gate  *	ibt_get_chan_private
13790Sstevel@tonic-gate  * Input:
13800Sstevel@tonic-gate  *	chan		A previously allocated channel handle.
13810Sstevel@tonic-gate  * Output:
13820Sstevel@tonic-gate  *	A pointer to the client private data.
13830Sstevel@tonic-gate  * Returns:
13840Sstevel@tonic-gate  *	none.
13850Sstevel@tonic-gate  * Description:
13860Sstevel@tonic-gate  *	Get a pointer to client private data.
13870Sstevel@tonic-gate  */
13880Sstevel@tonic-gate void *
ibt_get_chan_private(ibt_channel_hdl_t chan)13890Sstevel@tonic-gate ibt_get_chan_private(ibt_channel_hdl_t chan)
13900Sstevel@tonic-gate {
13910Sstevel@tonic-gate 	return (chan->ch_clnt_private);
13920Sstevel@tonic-gate }
13930Sstevel@tonic-gate 
13940Sstevel@tonic-gate /*
13950Sstevel@tonic-gate  * Function:
13960Sstevel@tonic-gate  *	ibt_channel_to_hca_guid
13970Sstevel@tonic-gate  * Input:
13980Sstevel@tonic-gate  *	chan		Channel Handle.
13990Sstevel@tonic-gate  * Output:
14000Sstevel@tonic-gate  *	none.
14010Sstevel@tonic-gate  * Returns:
14020Sstevel@tonic-gate  *	hca_guid	Returned HCA GUID on which the specified Channel is
14030Sstevel@tonic-gate  *			allocated. Valid if it is non-NULL on return.
14040Sstevel@tonic-gate  * Description:
14050Sstevel@tonic-gate  *	A helper function to retrieve HCA GUID for the specified Channel.
14060Sstevel@tonic-gate  */
14070Sstevel@tonic-gate ib_guid_t
ibt_channel_to_hca_guid(ibt_channel_hdl_t chan)14080Sstevel@tonic-gate ibt_channel_to_hca_guid(ibt_channel_hdl_t chan)
14090Sstevel@tonic-gate {
14100Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_channel_to_hca_guid(%p)", chan);
14110Sstevel@tonic-gate 
14120Sstevel@tonic-gate 	return (IBTL_HCA2HCAGUID(IBTL_CHAN2HCA(chan)));
14130Sstevel@tonic-gate }
14140Sstevel@tonic-gate 
14150Sstevel@tonic-gate /*
14160Sstevel@tonic-gate  * Protection Domain Verbs Functions.
14170Sstevel@tonic-gate  */
14180Sstevel@tonic-gate 
14190Sstevel@tonic-gate /*
14200Sstevel@tonic-gate  * Function:
14210Sstevel@tonic-gate  *	ibt_alloc_pd
14220Sstevel@tonic-gate  * Input:
14230Sstevel@tonic-gate  *	hca_hdl		The IBT HCA handle, the device on which we need
14240Sstevel@tonic-gate  *			to create the requested Protection Domain.
14250Sstevel@tonic-gate  *	flags		IBT_PD_NO_FLAGS, IBT_PD_USER_MAP or IBT_PD_DEFER_ALLOC
14260Sstevel@tonic-gate  * Output:
14270Sstevel@tonic-gate  *	pd		IBT Protection Domain Handle.
14280Sstevel@tonic-gate  * Returns:
14290Sstevel@tonic-gate  *	IBT_SUCCESS
14300Sstevel@tonic-gate  *	IBT_HCA_HDL_INVALID
14310Sstevel@tonic-gate  * Description:
14320Sstevel@tonic-gate  *	Allocate a Protection Domain.
14330Sstevel@tonic-gate  */
14340Sstevel@tonic-gate ibt_status_t
ibt_alloc_pd(ibt_hca_hdl_t hca_hdl,ibt_pd_flags_t flags,ibt_pd_hdl_t * pd)14350Sstevel@tonic-gate ibt_alloc_pd(ibt_hca_hdl_t hca_hdl, ibt_pd_flags_t flags, ibt_pd_hdl_t *pd)
14360Sstevel@tonic-gate {
14370Sstevel@tonic-gate 	ibt_status_t	retval;
14380Sstevel@tonic-gate 
14390Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_pd(%p, %x)", hca_hdl, flags);
14400Sstevel@tonic-gate 
14410Sstevel@tonic-gate 	/* re-direct the call to CI's call */
14420Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
14430Sstevel@tonic-gate 	retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_pd(
14440Sstevel@tonic-gate 	    IBTL_HCA2CIHCA(hca_hdl), flags, pd);
14450Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
14460Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
14470Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_pd: CI PD Alloc Err");
14480Sstevel@tonic-gate 		return (retval);
14490Sstevel@tonic-gate 	}
14500Sstevel@tonic-gate 
14510Sstevel@tonic-gate 	/* Update the PDs Resource Count per HCA Device. */
145212574SWilliam.Taylor@Oracle.COM 	atomic_inc_32(&hca_hdl->ha_pd_cnt);
14530Sstevel@tonic-gate 
14540Sstevel@tonic-gate 	return (retval);
14550Sstevel@tonic-gate }
14560Sstevel@tonic-gate 
14570Sstevel@tonic-gate /*
14580Sstevel@tonic-gate  * Function:
14590Sstevel@tonic-gate  *	ibt_free_pd
14600Sstevel@tonic-gate  * Input:
14610Sstevel@tonic-gate  *	hca_hdl		The IBT HCA handle, the device on which we need
14620Sstevel@tonic-gate  *			to free the requested Protection Domain.
14630Sstevel@tonic-gate  *	pd		IBT Protection Domain Handle.
14640Sstevel@tonic-gate  * Output:
14650Sstevel@tonic-gate  *	none.
14660Sstevel@tonic-gate  * Returns:
14670Sstevel@tonic-gate  *	IBT_SUCCESS
14680Sstevel@tonic-gate  *	IBT_HCA_HDL_INVALID
14690Sstevel@tonic-gate  *	IBT_MEM_PD_HDL_INVALID
14700Sstevel@tonic-gate  *	IBT_MEM_PD_IN_USE
14710Sstevel@tonic-gate  * Description:
14720Sstevel@tonic-gate  *	Release/de-allocate a Protection Domain.
14730Sstevel@tonic-gate  */
14740Sstevel@tonic-gate ibt_status_t
ibt_free_pd(ibt_hca_hdl_t hca_hdl,ibt_pd_hdl_t pd)14750Sstevel@tonic-gate ibt_free_pd(ibt_hca_hdl_t hca_hdl, ibt_pd_hdl_t pd)
14760Sstevel@tonic-gate {
14770Sstevel@tonic-gate 	ibt_status_t	retval;
14780Sstevel@tonic-gate 
14790Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_free_pd(%p, %p)", hca_hdl, pd);
14800Sstevel@tonic-gate 
14810Sstevel@tonic-gate 	/* re-direct the call to CI's call */
14820Sstevel@tonic-gate 	retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_free_pd(
14830Sstevel@tonic-gate 	    IBTL_HCA2CIHCA(hca_hdl), pd);
14840Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
14850Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_free_pd: CI Free PD Failed");
14860Sstevel@tonic-gate 		return (retval);
14870Sstevel@tonic-gate 	}
14880Sstevel@tonic-gate 
14890Sstevel@tonic-gate 	/* Update the PDs Resource Count per HCA Device. */
149012574SWilliam.Taylor@Oracle.COM 	atomic_dec_32(&hca_hdl->ha_pd_cnt);
14910Sstevel@tonic-gate 
14920Sstevel@tonic-gate 	return (retval);
14930Sstevel@tonic-gate }
14940Sstevel@tonic-gate 
14950Sstevel@tonic-gate 
14960Sstevel@tonic-gate /*
14970Sstevel@tonic-gate  * Address Handle Verbs Functions.
14980Sstevel@tonic-gate  */
14990Sstevel@tonic-gate 
15000Sstevel@tonic-gate /*
15010Sstevel@tonic-gate  * Function:
15020Sstevel@tonic-gate  *	ibt_alloc_ah
15030Sstevel@tonic-gate  * Input:
15040Sstevel@tonic-gate  *	hca_hdl		The IBT HCA Handle.
15050Sstevel@tonic-gate  *	pd		The IBT Protection Domain to associate with this handle.
15060Sstevel@tonic-gate  *	adds_vectp	Points to an ibt_adds_vect_t struct.
15070Sstevel@tonic-gate  * Output:
15080Sstevel@tonic-gate  *	ah		IBT Address Handle.
15090Sstevel@tonic-gate  * Returns:
15100Sstevel@tonic-gate  *	IBT_SUCCESS
15110Sstevel@tonic-gate  *	IBT_HCA_HDL_INVALID
15120Sstevel@tonic-gate  *	IBT_INSUFF_RESOURCE
15130Sstevel@tonic-gate  *	IBT_MEM_PD_HDL_INVALID
15140Sstevel@tonic-gate  * Description:
15150Sstevel@tonic-gate  *	Allocate and returns an Address Handle.
15160Sstevel@tonic-gate  */
15170Sstevel@tonic-gate ibt_status_t
ibt_alloc_ah(ibt_hca_hdl_t hca_hdl,ibt_ah_flags_t flags,ibt_pd_hdl_t pd,ibt_adds_vect_t * adds_vectp,ibt_ah_hdl_t * ah)15180Sstevel@tonic-gate ibt_alloc_ah(ibt_hca_hdl_t hca_hdl, ibt_ah_flags_t flags, ibt_pd_hdl_t pd,
15190Sstevel@tonic-gate     ibt_adds_vect_t *adds_vectp, ibt_ah_hdl_t *ah)
15200Sstevel@tonic-gate {
15210Sstevel@tonic-gate 	ibt_status_t	retval;
15220Sstevel@tonic-gate 
15230Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_alloc_ah(%p, %x, %p, %p)",
15240Sstevel@tonic-gate 	    hca_hdl, flags, pd, adds_vectp);
15250Sstevel@tonic-gate 
15260Sstevel@tonic-gate 	/* XXX - if av_send_grh, need to compute av_sgid_ix from av_sgid */
15270Sstevel@tonic-gate 
15280Sstevel@tonic-gate 	/* re-direct the call to CI's call */
15290Sstevel@tonic-gate 	retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_ah(
15300Sstevel@tonic-gate 	    IBTL_HCA2CIHCA(hca_hdl), flags, pd, adds_vectp, ah);
15310Sstevel@tonic-gate 
15320Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
15330Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_alloc_ah: "
15340Sstevel@tonic-gate 		    "ibc_alloc_ah failed: status = %d", retval);
15350Sstevel@tonic-gate 		return (retval);
15360Sstevel@tonic-gate 	}
15370Sstevel@tonic-gate 
15380Sstevel@tonic-gate 	/* Update the AHs Resource Count per HCA Device. */
153912574SWilliam.Taylor@Oracle.COM 	atomic_inc_32(&hca_hdl->ha_ah_cnt);
15400Sstevel@tonic-gate 
15410Sstevel@tonic-gate 	return (retval);
15420Sstevel@tonic-gate }
15430Sstevel@tonic-gate 
15440Sstevel@tonic-gate 
15450Sstevel@tonic-gate /*
15460Sstevel@tonic-gate  * Function:
15470Sstevel@tonic-gate  *	ibt_free_ah
15480Sstevel@tonic-gate  * Input:
15490Sstevel@tonic-gate  *	hca_hdl		The IBT HCA Handle.
15500Sstevel@tonic-gate  *	ah		IBT Address Handle.
15510Sstevel@tonic-gate  * Output:
15520Sstevel@tonic-gate  *	none.
15530Sstevel@tonic-gate  * Returns:
15540Sstevel@tonic-gate  *	IBT_SUCCESS
15550Sstevel@tonic-gate  *	IBT_HCA_HDL_INVALID
15560Sstevel@tonic-gate  *	IBT_AH_HDL_INVALID
15570Sstevel@tonic-gate  * Description:
15580Sstevel@tonic-gate  *	Release/de-allocate the specified Address Handle.
15590Sstevel@tonic-gate  */
15600Sstevel@tonic-gate ibt_status_t
ibt_free_ah(ibt_hca_hdl_t hca_hdl,ibt_ah_hdl_t ah)15610Sstevel@tonic-gate ibt_free_ah(ibt_hca_hdl_t hca_hdl, ibt_ah_hdl_t ah)
15620Sstevel@tonic-gate {
15630Sstevel@tonic-gate 	ibt_status_t	retval;
15640Sstevel@tonic-gate 
15650Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_free_ah(%p, %p)", hca_hdl, ah);
15660Sstevel@tonic-gate 
15670Sstevel@tonic-gate 	/* re-direct the call to CI's call */
15680Sstevel@tonic-gate 	retval = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_free_ah(
15690Sstevel@tonic-gate 	    IBTL_HCA2CIHCA(hca_hdl), ah);
15700Sstevel@tonic-gate 
15710Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
15720Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtl_chan, "ibt_free_ah: CI Free AH Failed");
15730Sstevel@tonic-gate 		return (retval);
15740Sstevel@tonic-gate 	}
15750Sstevel@tonic-gate 
15760Sstevel@tonic-gate 	/* Update the AHs Resource Count per HCA Device. */
157712574SWilliam.Taylor@Oracle.COM 	atomic_dec_32(&hca_hdl->ha_ah_cnt);
15780Sstevel@tonic-gate 
15790Sstevel@tonic-gate 	return (retval);
15800Sstevel@tonic-gate }
15810Sstevel@tonic-gate 
15820Sstevel@tonic-gate 
15830Sstevel@tonic-gate /*
15840Sstevel@tonic-gate  * Function:
15850Sstevel@tonic-gate  *	ibt_query_ah
15860Sstevel@tonic-gate  * Input:
15870Sstevel@tonic-gate  *	hca_hdl		The IBT HCA Handle.
15880Sstevel@tonic-gate  *	ah		IBT Address Handle.
15890Sstevel@tonic-gate  * Output:
15900Sstevel@tonic-gate  *	pd		The Protection Domain Handle with which this
15910Sstevel@tonic-gate  *			Address Handle is associated.
15920Sstevel@tonic-gate  *	adds_vectp	Points to an ibt_adds_vect_t struct.
15930Sstevel@tonic-gate  * Returns:
15940Sstevel@tonic-gate  *	IBT_SUCCESS/IBT_HCA_HDL_INVALID/IBT_AH_HDL_INVALID
15950Sstevel@tonic-gate  * Description:
15960Sstevel@tonic-gate  *	Obtain the address vector information for the specified address handle.
15970Sstevel@tonic-gate  */
15980Sstevel@tonic-gate ibt_status_t
ibt_query_ah(ibt_hca_hdl_t hca_hdl,ibt_ah_hdl_t ah,ibt_pd_hdl_t * pd,ibt_adds_vect_t * adds_vectp)15990Sstevel@tonic-gate ibt_query_ah(ibt_hca_hdl_t hca_hdl, ibt_ah_hdl_t ah, ibt_pd_hdl_t *pd,
16000Sstevel@tonic-gate     ibt_adds_vect_t *adds_vectp)
16010Sstevel@tonic-gate {
16020Sstevel@tonic-gate 	ibt_status_t	retval;
16030Sstevel@tonic-gate 
16040Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_query_ah(%p, %p)", hca_hdl, ah);
16050Sstevel@tonic-gate 
16060Sstevel@tonic-gate 	/* re-direct the call to CI's call */
16070Sstevel@tonic-gate 	retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_query_ah(
16080Sstevel@tonic-gate 	    IBTL_HCA2CIHCA(hca_hdl), ah, pd, adds_vectp));
16090Sstevel@tonic-gate 
16100Sstevel@tonic-gate 	/*
16110Sstevel@tonic-gate 	 * We need to fill in av_sgid, as the CI does only saves/restores
16120Sstevel@tonic-gate 	 * av_sgid_ix.
16130Sstevel@tonic-gate 	 */
16140Sstevel@tonic-gate 	if (retval == IBT_SUCCESS) {
16150Sstevel@tonic-gate 		ibtl_hca_devinfo_t *hca_devp = hca_hdl->ha_hca_devp;
16160Sstevel@tonic-gate 		uint8_t port = adds_vectp->av_port_num;
16170Sstevel@tonic-gate 
16180Sstevel@tonic-gate 		mutex_enter(&ibtl_clnt_list_mutex);
16190Sstevel@tonic-gate 		if (port > 0 && port <= hca_devp->hd_hca_attr->hca_nports &&
16200Sstevel@tonic-gate 		    adds_vectp->av_sgid_ix < IBTL_HDIP2SGIDTBLSZ(hca_devp)) {
16210Sstevel@tonic-gate 			ib_gid_t *sgidp;
16220Sstevel@tonic-gate 
16230Sstevel@tonic-gate 			sgidp = hca_devp->hd_portinfop[port-1].p_sgid_tbl;
16240Sstevel@tonic-gate 			adds_vectp->av_sgid = sgidp[adds_vectp->av_sgid_ix];
16250Sstevel@tonic-gate 		} else {
16260Sstevel@tonic-gate 			adds_vectp->av_sgid.gid_prefix = 0;
16270Sstevel@tonic-gate 			adds_vectp->av_sgid.gid_guid = 0;
16280Sstevel@tonic-gate 		}
16290Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
16300Sstevel@tonic-gate 	}
16310Sstevel@tonic-gate 	return (retval);
16320Sstevel@tonic-gate }
16330Sstevel@tonic-gate 
16340Sstevel@tonic-gate 
16350Sstevel@tonic-gate /*
16360Sstevel@tonic-gate  * Function:
16370Sstevel@tonic-gate  *	ibt_modify_ah
16380Sstevel@tonic-gate  * Input:
16390Sstevel@tonic-gate  *	hca_hdl		The IBT HCA Handle.
16400Sstevel@tonic-gate  *	ah		IBT Address Handle.
16410Sstevel@tonic-gate  * Output:
16420Sstevel@tonic-gate  *	adds_vectp	Points to an ibt_adds_vect_t struct. The new address
16430Sstevel@tonic-gate  *			vector information is specified is returned in this
16440Sstevel@tonic-gate  *			structure.
16450Sstevel@tonic-gate  * Returns:
16460Sstevel@tonic-gate  *	IBT_SUCCESS/IBT_HCA_HDL_INVALID/IBT_AH_HDL_INVALID
16470Sstevel@tonic-gate  * Description:
16480Sstevel@tonic-gate  *	Modify the address vector information for the specified Address Handle.
16490Sstevel@tonic-gate  */
16500Sstevel@tonic-gate ibt_status_t
ibt_modify_ah(ibt_hca_hdl_t hca_hdl,ibt_ah_hdl_t ah,ibt_adds_vect_t * adds_vectp)16510Sstevel@tonic-gate ibt_modify_ah(ibt_hca_hdl_t hca_hdl, ibt_ah_hdl_t ah,
16520Sstevel@tonic-gate     ibt_adds_vect_t *adds_vectp)
16530Sstevel@tonic-gate {
16540Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtl_chan, "ibt_modify_ah(%p, %p)", hca_hdl, ah);
16550Sstevel@tonic-gate 
16560Sstevel@tonic-gate 	/* XXX - if av_send_grh, need to compute av_sgid_ix from av_sgid */
16570Sstevel@tonic-gate 
16580Sstevel@tonic-gate 	/* re-direct the call to CI's call */
16590Sstevel@tonic-gate 	return (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_modify_ah(
16600Sstevel@tonic-gate 	    IBTL_HCA2CIHCA(hca_hdl), ah, adds_vectp));
16610Sstevel@tonic-gate }
1662