xref: /onnv-gate/usr/src/uts/common/io/ib/clients/eoib/eib_ctl.c (revision 13101:da7b13ec3a28)
1*13101SVenki.Rajagopalan@Sun.COM /*
2*13101SVenki.Rajagopalan@Sun.COM  * CDDL HEADER START
3*13101SVenki.Rajagopalan@Sun.COM  *
4*13101SVenki.Rajagopalan@Sun.COM  * The contents of this file are subject to the terms of the
5*13101SVenki.Rajagopalan@Sun.COM  * Common Development and Distribution License (the "License").
6*13101SVenki.Rajagopalan@Sun.COM  * You may not use this file except in compliance with the License.
7*13101SVenki.Rajagopalan@Sun.COM  *
8*13101SVenki.Rajagopalan@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*13101SVenki.Rajagopalan@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*13101SVenki.Rajagopalan@Sun.COM  * See the License for the specific language governing permissions
11*13101SVenki.Rajagopalan@Sun.COM  * and limitations under the License.
12*13101SVenki.Rajagopalan@Sun.COM  *
13*13101SVenki.Rajagopalan@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*13101SVenki.Rajagopalan@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*13101SVenki.Rajagopalan@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*13101SVenki.Rajagopalan@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*13101SVenki.Rajagopalan@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*13101SVenki.Rajagopalan@Sun.COM  *
19*13101SVenki.Rajagopalan@Sun.COM  * CDDL HEADER END
20*13101SVenki.Rajagopalan@Sun.COM  */
21*13101SVenki.Rajagopalan@Sun.COM 
22*13101SVenki.Rajagopalan@Sun.COM /*
23*13101SVenki.Rajagopalan@Sun.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*13101SVenki.Rajagopalan@Sun.COM  */
25*13101SVenki.Rajagopalan@Sun.COM 
26*13101SVenki.Rajagopalan@Sun.COM #include <sys/types.h>
27*13101SVenki.Rajagopalan@Sun.COM #include <sys/kmem.h>
28*13101SVenki.Rajagopalan@Sun.COM #include <sys/conf.h>
29*13101SVenki.Rajagopalan@Sun.COM #include <sys/ddi.h>
30*13101SVenki.Rajagopalan@Sun.COM #include <sys/sunddi.h>
31*13101SVenki.Rajagopalan@Sun.COM #include <sys/ksynch.h>
32*13101SVenki.Rajagopalan@Sun.COM 
33*13101SVenki.Rajagopalan@Sun.COM #include <sys/ib/clients/eoib/eib_impl.h>
34*13101SVenki.Rajagopalan@Sun.COM 
35*13101SVenki.Rajagopalan@Sun.COM /*
36*13101SVenki.Rajagopalan@Sun.COM  * Declarations private to this file
37*13101SVenki.Rajagopalan@Sun.COM  */
38*13101SVenki.Rajagopalan@Sun.COM static int eib_ctl_setup_cq(eib_t *, eib_vnic_t *);
39*13101SVenki.Rajagopalan@Sun.COM static int eib_ctl_setup_ud_channel(eib_t *, eib_vnic_t *);
40*13101SVenki.Rajagopalan@Sun.COM static void eib_ctl_comp_intr(ibt_cq_hdl_t, void *);
41*13101SVenki.Rajagopalan@Sun.COM static void eib_ctl_rx_comp(eib_vnic_t *, eib_wqe_t *);
42*13101SVenki.Rajagopalan@Sun.COM static void eib_ctl_tx_comp(eib_vnic_t *, eib_wqe_t *);
43*13101SVenki.Rajagopalan@Sun.COM static void eib_ctl_err_comp(eib_vnic_t *, eib_wqe_t *, ibt_wc_t *);
44*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_ctl_setup_cq(eib_t *, eib_vnic_t *);
45*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_ctl_setup_ud_channel(eib_t *, eib_vnic_t *);
46*13101SVenki.Rajagopalan@Sun.COM 
47*13101SVenki.Rajagopalan@Sun.COM int
eib_ctl_create_qp(eib_t * ss,eib_vnic_t * vnic,int * err)48*13101SVenki.Rajagopalan@Sun.COM eib_ctl_create_qp(eib_t *ss, eib_vnic_t *vnic, int *err)
49*13101SVenki.Rajagopalan@Sun.COM {
50*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = NULL;
51*13101SVenki.Rajagopalan@Sun.COM 
52*13101SVenki.Rajagopalan@Sun.COM 	/*
53*13101SVenki.Rajagopalan@Sun.COM 	 * Allocate a eib_chan_t to store stuff about this vnic's ctl qp
54*13101SVenki.Rajagopalan@Sun.COM 	 * and initialize it with default admin qp pkey parameters. We'll
55*13101SVenki.Rajagopalan@Sun.COM 	 * re-associate this with the pkey we receive from the gw once we
56*13101SVenki.Rajagopalan@Sun.COM 	 * receive the login ack.
57*13101SVenki.Rajagopalan@Sun.COM 	 */
58*13101SVenki.Rajagopalan@Sun.COM 	vnic->vn_ctl_chan = eib_chan_init();
59*13101SVenki.Rajagopalan@Sun.COM 
60*13101SVenki.Rajagopalan@Sun.COM 	chan = vnic->vn_ctl_chan;
61*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_pkey = ss->ei_admin_chan->ch_pkey;
62*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_pkey_ix = ss->ei_admin_chan->ch_pkey_ix;
63*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_vnic_inst = vnic->vn_instance;
64*13101SVenki.Rajagopalan@Sun.COM 
65*13101SVenki.Rajagopalan@Sun.COM 	/*
66*13101SVenki.Rajagopalan@Sun.COM 	 * Setup a combined CQ and completion handler
67*13101SVenki.Rajagopalan@Sun.COM 	 */
68*13101SVenki.Rajagopalan@Sun.COM 	if (eib_ctl_setup_cq(ss, vnic) != EIB_E_SUCCESS) {
69*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance, "eib_ctl_create_qp: "
70*13101SVenki.Rajagopalan@Sun.COM 		    "eib_ctl_setup_cq() failed");
71*13101SVenki.Rajagopalan@Sun.COM 		*err = ENOMEM;
72*13101SVenki.Rajagopalan@Sun.COM 		goto ctl_create_qp_fail;
73*13101SVenki.Rajagopalan@Sun.COM 	}
74*13101SVenki.Rajagopalan@Sun.COM 
75*13101SVenki.Rajagopalan@Sun.COM 	/*
76*13101SVenki.Rajagopalan@Sun.COM 	 * Setup UD channel
77*13101SVenki.Rajagopalan@Sun.COM 	 */
78*13101SVenki.Rajagopalan@Sun.COM 	if (eib_ctl_setup_ud_channel(ss, vnic) != EIB_E_SUCCESS) {
79*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance, "eib_ctl_create_qp: "
80*13101SVenki.Rajagopalan@Sun.COM 		    "eib_ctl_setup_ud_channel() failed");
81*13101SVenki.Rajagopalan@Sun.COM 		*err = ENOMEM;
82*13101SVenki.Rajagopalan@Sun.COM 		goto ctl_create_qp_fail;
83*13101SVenki.Rajagopalan@Sun.COM 	}
84*13101SVenki.Rajagopalan@Sun.COM 
85*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
86*13101SVenki.Rajagopalan@Sun.COM 
87*13101SVenki.Rajagopalan@Sun.COM ctl_create_qp_fail:
88*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_ctl_create_qp(ss, vnic);
89*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_FAILURE);
90*13101SVenki.Rajagopalan@Sun.COM }
91*13101SVenki.Rajagopalan@Sun.COM 
92*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
93*13101SVenki.Rajagopalan@Sun.COM uint_t
eib_ctl_comp_handler(caddr_t arg1,caddr_t arg2)94*13101SVenki.Rajagopalan@Sun.COM eib_ctl_comp_handler(caddr_t arg1, caddr_t arg2)
95*13101SVenki.Rajagopalan@Sun.COM {
96*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_t *vnic = (eib_vnic_t *)(void *)arg1;
97*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = vnic->vn_ctl_chan;
98*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = vnic->vn_ss;
99*13101SVenki.Rajagopalan@Sun.COM 	ibt_wc_t *wc;
100*13101SVenki.Rajagopalan@Sun.COM 	eib_wqe_t *wqe;
101*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
102*13101SVenki.Rajagopalan@Sun.COM 	uint_t polled;
103*13101SVenki.Rajagopalan@Sun.COM 	int i;
104*13101SVenki.Rajagopalan@Sun.COM 
105*13101SVenki.Rajagopalan@Sun.COM 	/*
106*13101SVenki.Rajagopalan@Sun.COM 	 * Re-arm the notification callback before we start polling
107*13101SVenki.Rajagopalan@Sun.COM 	 * the completion queue.  There's nothing much we can do if the
108*13101SVenki.Rajagopalan@Sun.COM 	 * enable_cq_notify fails - we issue a warning and move on.
109*13101SVenki.Rajagopalan@Sun.COM 	 */
110*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_enable_cq_notify(chan->ch_cq_hdl, IBT_NEXT_COMPLETION);
111*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
112*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_ctl_comp_handler: "
113*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_enable_cq_notify() failed, ret=%d", ret);
114*13101SVenki.Rajagopalan@Sun.COM 	}
115*13101SVenki.Rajagopalan@Sun.COM 
116*13101SVenki.Rajagopalan@Sun.COM 	/*
117*13101SVenki.Rajagopalan@Sun.COM 	 * Handle tx and rx completions
118*13101SVenki.Rajagopalan@Sun.COM 	 */
119*13101SVenki.Rajagopalan@Sun.COM 	while ((ret = ibt_poll_cq(chan->ch_cq_hdl, chan->ch_wc, chan->ch_cq_sz,
120*13101SVenki.Rajagopalan@Sun.COM 	    &polled)) == IBT_SUCCESS) {
121*13101SVenki.Rajagopalan@Sun.COM 		for (wc = chan->ch_wc, i = 0; i < polled; i++, wc++) {
122*13101SVenki.Rajagopalan@Sun.COM 			wqe = (eib_wqe_t *)(uintptr_t)wc->wc_id;
123*13101SVenki.Rajagopalan@Sun.COM 			if (wc->wc_status != IBT_WC_SUCCESS) {
124*13101SVenki.Rajagopalan@Sun.COM 				eib_ctl_err_comp(vnic, wqe, wc);
125*13101SVenki.Rajagopalan@Sun.COM 			} else if (EIB_WQE_TYPE(wqe->qe_info) == EIB_WQE_RX) {
126*13101SVenki.Rajagopalan@Sun.COM 				eib_ctl_rx_comp(vnic, wqe);
127*13101SVenki.Rajagopalan@Sun.COM 			} else {
128*13101SVenki.Rajagopalan@Sun.COM 				eib_ctl_tx_comp(vnic, wqe);
129*13101SVenki.Rajagopalan@Sun.COM 			}
130*13101SVenki.Rajagopalan@Sun.COM 		}
131*13101SVenki.Rajagopalan@Sun.COM 	}
132*13101SVenki.Rajagopalan@Sun.COM 
133*13101SVenki.Rajagopalan@Sun.COM 	return (DDI_INTR_CLAIMED);
134*13101SVenki.Rajagopalan@Sun.COM }
135*13101SVenki.Rajagopalan@Sun.COM 
136*13101SVenki.Rajagopalan@Sun.COM void
eib_rb_ctl_create_qp(eib_t * ss,eib_vnic_t * vnic)137*13101SVenki.Rajagopalan@Sun.COM eib_rb_ctl_create_qp(eib_t *ss, eib_vnic_t *vnic)
138*13101SVenki.Rajagopalan@Sun.COM {
139*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_ctl_setup_ud_channel(ss, vnic);
140*13101SVenki.Rajagopalan@Sun.COM 
141*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_ctl_setup_cq(ss, vnic);
142*13101SVenki.Rajagopalan@Sun.COM 
143*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_fini(vnic->vn_ctl_chan);
144*13101SVenki.Rajagopalan@Sun.COM 	vnic->vn_ctl_chan = NULL;
145*13101SVenki.Rajagopalan@Sun.COM }
146*13101SVenki.Rajagopalan@Sun.COM 
147*13101SVenki.Rajagopalan@Sun.COM static int
eib_ctl_setup_cq(eib_t * ss,eib_vnic_t * vnic)148*13101SVenki.Rajagopalan@Sun.COM eib_ctl_setup_cq(eib_t *ss, eib_vnic_t *vnic)
149*13101SVenki.Rajagopalan@Sun.COM {
150*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = vnic->vn_ctl_chan;
151*13101SVenki.Rajagopalan@Sun.COM 	ibt_cq_attr_t cq_attr;
152*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
153*13101SVenki.Rajagopalan@Sun.COM 	uint_t sz;
154*13101SVenki.Rajagopalan@Sun.COM 	int rv;
155*13101SVenki.Rajagopalan@Sun.COM 
156*13101SVenki.Rajagopalan@Sun.COM 	/*
157*13101SVenki.Rajagopalan@Sun.COM 	 * Allocate a completion queue for sending vhub table request
158*13101SVenki.Rajagopalan@Sun.COM 	 * and vhub-update/vnic-alive messages and responses from the
159*13101SVenki.Rajagopalan@Sun.COM 	 * gateway
160*13101SVenki.Rajagopalan@Sun.COM 	 */
161*13101SVenki.Rajagopalan@Sun.COM 	cq_attr.cq_sched = NULL;
162*13101SVenki.Rajagopalan@Sun.COM 	cq_attr.cq_flags = IBT_CQ_NO_FLAGS;
163*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_hca_attrs->hca_max_cq_sz < EIB_CTL_CQ_SIZE)
164*13101SVenki.Rajagopalan@Sun.COM 		cq_attr.cq_size = ss->ei_hca_attrs->hca_max_cq_sz;
165*13101SVenki.Rajagopalan@Sun.COM 	else
166*13101SVenki.Rajagopalan@Sun.COM 		cq_attr.cq_size = EIB_CTL_CQ_SIZE;
167*13101SVenki.Rajagopalan@Sun.COM 
168*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_alloc_cq(ss->ei_hca_hdl, &cq_attr, &chan->ch_cq_hdl, &sz);
169*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
170*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance, "eib_ctl_setup_cq: "
171*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_alloc_cq(cq_sz=0x%lx) failed, ret=%d",
172*13101SVenki.Rajagopalan@Sun.COM 		    cq_attr.cq_size, ret);
173*13101SVenki.Rajagopalan@Sun.COM 		goto ctl_setup_cq_fail;
174*13101SVenki.Rajagopalan@Sun.COM 	}
175*13101SVenki.Rajagopalan@Sun.COM 
176*13101SVenki.Rajagopalan@Sun.COM 	/*
177*13101SVenki.Rajagopalan@Sun.COM 	 * Set up other parameters for collecting completion information
178*13101SVenki.Rajagopalan@Sun.COM 	 */
179*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_cq_sz = sz;
180*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_wc = kmem_zalloc(sizeof (ibt_wc_t) * sz, KM_SLEEP);
181*13101SVenki.Rajagopalan@Sun.COM 
182*13101SVenki.Rajagopalan@Sun.COM 	/*
183*13101SVenki.Rajagopalan@Sun.COM 	 * Allocate soft interrupt for this vnic's control channel cq
184*13101SVenki.Rajagopalan@Sun.COM 	 * handler and set up the IBTL cq handler.
185*13101SVenki.Rajagopalan@Sun.COM 	 */
186*13101SVenki.Rajagopalan@Sun.COM 	if ((rv = ddi_intr_add_softint(ss->ei_dip, &vnic->vn_ctl_si_hdl,
187*13101SVenki.Rajagopalan@Sun.COM 	    EIB_SOFTPRI_CTL, eib_ctl_comp_handler, vnic)) != DDI_SUCCESS) {
188*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance, "eib_ctl_setup_cq: "
189*13101SVenki.Rajagopalan@Sun.COM 		    "ddi_intr_add_softint() failed for vnic %d ctl qp, ret=%d",
190*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_instance, rv);
191*13101SVenki.Rajagopalan@Sun.COM 		goto ctl_setup_cq_fail;
192*13101SVenki.Rajagopalan@Sun.COM 	}
193*13101SVenki.Rajagopalan@Sun.COM 
194*13101SVenki.Rajagopalan@Sun.COM 	/*
195*13101SVenki.Rajagopalan@Sun.COM 	 * Now, set up this vnic's control channel completion queue handler
196*13101SVenki.Rajagopalan@Sun.COM 	 */
197*13101SVenki.Rajagopalan@Sun.COM 	ibt_set_cq_handler(chan->ch_cq_hdl, eib_ctl_comp_intr, vnic);
198*13101SVenki.Rajagopalan@Sun.COM 
199*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_enable_cq_notify(chan->ch_cq_hdl, IBT_NEXT_COMPLETION);
200*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
201*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance, "eib_ctl_setup_cq: "
202*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_enable_cq_notify() failed, ret=%d", ret);
203*13101SVenki.Rajagopalan@Sun.COM 		goto ctl_setup_cq_fail;
204*13101SVenki.Rajagopalan@Sun.COM 	}
205*13101SVenki.Rajagopalan@Sun.COM 
206*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
207*13101SVenki.Rajagopalan@Sun.COM 
208*13101SVenki.Rajagopalan@Sun.COM ctl_setup_cq_fail:
209*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_ctl_setup_cq(ss, vnic);
210*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_FAILURE);
211*13101SVenki.Rajagopalan@Sun.COM }
212*13101SVenki.Rajagopalan@Sun.COM 
213*13101SVenki.Rajagopalan@Sun.COM static int
eib_ctl_setup_ud_channel(eib_t * ss,eib_vnic_t * vnic)214*13101SVenki.Rajagopalan@Sun.COM eib_ctl_setup_ud_channel(eib_t *ss, eib_vnic_t *vnic)
215*13101SVenki.Rajagopalan@Sun.COM {
216*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = vnic->vn_ctl_chan;
217*13101SVenki.Rajagopalan@Sun.COM 	ibt_ud_chan_alloc_args_t alloc_attr;
218*13101SVenki.Rajagopalan@Sun.COM 	ibt_ud_chan_query_attr_t query_attr;
219*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
220*13101SVenki.Rajagopalan@Sun.COM 
221*13101SVenki.Rajagopalan@Sun.COM 	bzero(&alloc_attr, sizeof (ibt_ud_chan_alloc_args_t));
222*13101SVenki.Rajagopalan@Sun.COM 	bzero(&query_attr, sizeof (ibt_ud_chan_query_attr_t));
223*13101SVenki.Rajagopalan@Sun.COM 
224*13101SVenki.Rajagopalan@Sun.COM 	alloc_attr.ud_flags = IBT_ALL_SIGNALED;
225*13101SVenki.Rajagopalan@Sun.COM 	alloc_attr.ud_hca_port_num = ss->ei_props->ep_port_num;
226*13101SVenki.Rajagopalan@Sun.COM 	alloc_attr.ud_pkey_ix = chan->ch_pkey_ix;
227*13101SVenki.Rajagopalan@Sun.COM 	alloc_attr.ud_sizes.cs_sq = EIB_CTL_MAX_SWQE;
228*13101SVenki.Rajagopalan@Sun.COM 	alloc_attr.ud_sizes.cs_rq = EIB_CTL_MAX_RWQE;
229*13101SVenki.Rajagopalan@Sun.COM 	alloc_attr.ud_sizes.cs_sq_sgl = 1;
230*13101SVenki.Rajagopalan@Sun.COM 	alloc_attr.ud_sizes.cs_rq_sgl = 1;
231*13101SVenki.Rajagopalan@Sun.COM 	alloc_attr.ud_sizes.cs_inline = 0;
232*13101SVenki.Rajagopalan@Sun.COM 
233*13101SVenki.Rajagopalan@Sun.COM 	alloc_attr.ud_qkey = EIB_FIP_QKEY;
234*13101SVenki.Rajagopalan@Sun.COM 	alloc_attr.ud_scq = chan->ch_cq_hdl;
235*13101SVenki.Rajagopalan@Sun.COM 	alloc_attr.ud_rcq = chan->ch_cq_hdl;
236*13101SVenki.Rajagopalan@Sun.COM 	alloc_attr.ud_pd = ss->ei_pd_hdl;
237*13101SVenki.Rajagopalan@Sun.COM 
238*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_alloc_ud_channel(ss->ei_hca_hdl, IBT_ACHAN_NO_FLAGS,
239*13101SVenki.Rajagopalan@Sun.COM 	    &alloc_attr, &chan->ch_chan, NULL);
240*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
241*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance, "eib_ctl_setup_ud_channel: "
242*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_alloc_ud_channel(port=0x%x, pkey_ix=0x%x) "
243*13101SVenki.Rajagopalan@Sun.COM 		    "failed, ret=%d", alloc_attr.ud_hca_port_num,
244*13101SVenki.Rajagopalan@Sun.COM 		    chan->ch_pkey_ix, ret);
245*13101SVenki.Rajagopalan@Sun.COM 		goto ctl_setup_ud_channel_fail;
246*13101SVenki.Rajagopalan@Sun.COM 	}
247*13101SVenki.Rajagopalan@Sun.COM 
248*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_query_ud_channel(chan->ch_chan, &query_attr);
249*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
250*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance, "eib_ctl_setup_ud_channel: "
251*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_query_ud_channel() failed, ret=%d", ret);
252*13101SVenki.Rajagopalan@Sun.COM 		goto ctl_setup_ud_channel_fail;
253*13101SVenki.Rajagopalan@Sun.COM 	}
254*13101SVenki.Rajagopalan@Sun.COM 
255*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_qpn = query_attr.ud_qpn;
256*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_max_swqes = query_attr.ud_chan_sizes.cs_sq;
257*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_max_rwqes = query_attr.ud_chan_sizes.cs_rq;
258*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_lwm_rwqes = chan->ch_max_rwqes >> 2;
259*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_rwqe_bktsz = chan->ch_max_rwqes;
260*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_ip_hdr_align = 0;
261*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_alloc_mp = B_FALSE;
262*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_tear_down = B_FALSE;
263*13101SVenki.Rajagopalan@Sun.COM 
264*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
265*13101SVenki.Rajagopalan@Sun.COM 
266*13101SVenki.Rajagopalan@Sun.COM ctl_setup_ud_channel_fail:
267*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_ctl_setup_ud_channel(ss, vnic);
268*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_FAILURE);
269*13101SVenki.Rajagopalan@Sun.COM }
270*13101SVenki.Rajagopalan@Sun.COM 
271*13101SVenki.Rajagopalan@Sun.COM static void
eib_ctl_comp_intr(ibt_cq_hdl_t cq_hdl,void * arg)272*13101SVenki.Rajagopalan@Sun.COM eib_ctl_comp_intr(ibt_cq_hdl_t cq_hdl, void *arg)
273*13101SVenki.Rajagopalan@Sun.COM {
274*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_t *vnic = arg;
275*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = vnic->vn_ss;
276*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = vnic->vn_ctl_chan;
277*13101SVenki.Rajagopalan@Sun.COM 
278*13101SVenki.Rajagopalan@Sun.COM 	if (cq_hdl != chan->ch_cq_hdl) {
279*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance, "eib_ctl_comp_intr: "
280*13101SVenki.Rajagopalan@Sun.COM 		    "cq_hdl(0x%llx) != chan->ch_cq_hdl(0x%llx), "
281*13101SVenki.Rajagopalan@Sun.COM 		    "ignoring completion", cq_hdl, chan->ch_cq_hdl);
282*13101SVenki.Rajagopalan@Sun.COM 		return;
283*13101SVenki.Rajagopalan@Sun.COM 	}
284*13101SVenki.Rajagopalan@Sun.COM 
285*13101SVenki.Rajagopalan@Sun.COM 	ASSERT(vnic->vn_ctl_si_hdl != NULL);
286*13101SVenki.Rajagopalan@Sun.COM 
287*13101SVenki.Rajagopalan@Sun.COM 	(void) ddi_intr_trigger_softint(vnic->vn_ctl_si_hdl, NULL);
288*13101SVenki.Rajagopalan@Sun.COM }
289*13101SVenki.Rajagopalan@Sun.COM 
290*13101SVenki.Rajagopalan@Sun.COM static void
eib_ctl_rx_comp(eib_vnic_t * vnic,eib_wqe_t * wqe)291*13101SVenki.Rajagopalan@Sun.COM eib_ctl_rx_comp(eib_vnic_t *vnic, eib_wqe_t *wqe)
292*13101SVenki.Rajagopalan@Sun.COM {
293*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = vnic->vn_ss;
294*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = vnic->vn_ctl_chan;
295*13101SVenki.Rajagopalan@Sun.COM 	uint8_t *pkt = (uint8_t *)(uintptr_t)(wqe->qe_sgl.ds_va);
296*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
297*13101SVenki.Rajagopalan@Sun.COM 
298*13101SVenki.Rajagopalan@Sun.COM 	/*
299*13101SVenki.Rajagopalan@Sun.COM 	 * Skip the GRH and parse the message in the packet
300*13101SVenki.Rajagopalan@Sun.COM 	 */
301*13101SVenki.Rajagopalan@Sun.COM 	(void) eib_fip_parse_ctl_pkt(pkt + EIB_GRH_SZ, vnic);
302*13101SVenki.Rajagopalan@Sun.COM 
303*13101SVenki.Rajagopalan@Sun.COM 	/*
304*13101SVenki.Rajagopalan@Sun.COM 	 * Try to repost the rwqe.  For control channels, we take the shortcut
305*13101SVenki.Rajagopalan@Sun.COM 	 * and not go through eib_chan_post_recv(), since we know that the
306*13101SVenki.Rajagopalan@Sun.COM 	 * qe_info flag, qe_chan and qe_vinst are all already set correctly; we
307*13101SVenki.Rajagopalan@Sun.COM 	 * just took this out of the rx queue, so the ch_rx_posted will be ok
308*13101SVenki.Rajagopalan@Sun.COM 	 * if we just posted it back. And there are no mblk allocation or
309*13101SVenki.Rajagopalan@Sun.COM 	 * buffer alignment restrictions for this channel as well.
310*13101SVenki.Rajagopalan@Sun.COM 	 */
311*13101SVenki.Rajagopalan@Sun.COM 	if (chan->ch_tear_down) {
312*13101SVenki.Rajagopalan@Sun.COM 		eib_rsrc_return_rwqe(ss, wqe, chan);
313*13101SVenki.Rajagopalan@Sun.COM 	} else {
314*13101SVenki.Rajagopalan@Sun.COM 		ret = ibt_post_recv(chan->ch_chan, &(wqe->qe_wr.recv), 1, NULL);
315*13101SVenki.Rajagopalan@Sun.COM 		if (ret != IBT_SUCCESS) {
316*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_ERR(ss->ei_instance, "eib_ctl_rx_comp: "
317*13101SVenki.Rajagopalan@Sun.COM 			    "ibt_post_recv() failed, ret=%d", ret);
318*13101SVenki.Rajagopalan@Sun.COM 			eib_rsrc_return_rwqe(ss, wqe, chan);
319*13101SVenki.Rajagopalan@Sun.COM 		}
320*13101SVenki.Rajagopalan@Sun.COM 	}
321*13101SVenki.Rajagopalan@Sun.COM }
322*13101SVenki.Rajagopalan@Sun.COM 
323*13101SVenki.Rajagopalan@Sun.COM static void
eib_ctl_tx_comp(eib_vnic_t * vnic,eib_wqe_t * wqe)324*13101SVenki.Rajagopalan@Sun.COM eib_ctl_tx_comp(eib_vnic_t *vnic, eib_wqe_t *wqe)
325*13101SVenki.Rajagopalan@Sun.COM {
326*13101SVenki.Rajagopalan@Sun.COM 	eib_rsrc_return_swqe(vnic->vn_ss, wqe, vnic->vn_ctl_chan);
327*13101SVenki.Rajagopalan@Sun.COM }
328*13101SVenki.Rajagopalan@Sun.COM 
329*13101SVenki.Rajagopalan@Sun.COM static void
eib_ctl_err_comp(eib_vnic_t * vnic,eib_wqe_t * wqe,ibt_wc_t * wc)330*13101SVenki.Rajagopalan@Sun.COM eib_ctl_err_comp(eib_vnic_t *vnic, eib_wqe_t *wqe, ibt_wc_t *wc)
331*13101SVenki.Rajagopalan@Sun.COM {
332*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = vnic->vn_ss;
333*13101SVenki.Rajagopalan@Sun.COM 
334*13101SVenki.Rajagopalan@Sun.COM 	/*
335*13101SVenki.Rajagopalan@Sun.COM 	 * Currently, all we do is report
336*13101SVenki.Rajagopalan@Sun.COM 	 */
337*13101SVenki.Rajagopalan@Sun.COM 	switch (wc->wc_status) {
338*13101SVenki.Rajagopalan@Sun.COM 	case IBT_WC_WR_FLUSHED_ERR:
339*13101SVenki.Rajagopalan@Sun.COM 		break;
340*13101SVenki.Rajagopalan@Sun.COM 
341*13101SVenki.Rajagopalan@Sun.COM 	case IBT_WC_LOCAL_CHAN_OP_ERR:
342*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance, "eib_ctl_err_comp: "
343*13101SVenki.Rajagopalan@Sun.COM 		    "IBT_WC_LOCAL_CHAN_OP_ERR seen, wqe_info=0x%lx ",
344*13101SVenki.Rajagopalan@Sun.COM 		    wqe->qe_info);
345*13101SVenki.Rajagopalan@Sun.COM 		break;
346*13101SVenki.Rajagopalan@Sun.COM 
347*13101SVenki.Rajagopalan@Sun.COM 	case IBT_WC_LOCAL_PROTECT_ERR:
348*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance, "eib_ctl_err_comp: "
349*13101SVenki.Rajagopalan@Sun.COM 		    "IBT_WC_LOCAL_PROTECT_ERR seen, wqe_info=0x%lx ",
350*13101SVenki.Rajagopalan@Sun.COM 		    wqe->qe_info);
351*13101SVenki.Rajagopalan@Sun.COM 		break;
352*13101SVenki.Rajagopalan@Sun.COM 	}
353*13101SVenki.Rajagopalan@Sun.COM 
354*13101SVenki.Rajagopalan@Sun.COM 	/*
355*13101SVenki.Rajagopalan@Sun.COM 	 * When a wc indicates error, we do not attempt to repost but
356*13101SVenki.Rajagopalan@Sun.COM 	 * simply return it to the wqe pool.
357*13101SVenki.Rajagopalan@Sun.COM 	 */
358*13101SVenki.Rajagopalan@Sun.COM 	if (EIB_WQE_TYPE(wqe->qe_info) == EIB_WQE_RX)
359*13101SVenki.Rajagopalan@Sun.COM 		eib_rsrc_return_rwqe(ss, wqe, vnic->vn_ctl_chan);
360*13101SVenki.Rajagopalan@Sun.COM 	else
361*13101SVenki.Rajagopalan@Sun.COM 		eib_rsrc_return_swqe(ss, wqe, vnic->vn_ctl_chan);
362*13101SVenki.Rajagopalan@Sun.COM }
363*13101SVenki.Rajagopalan@Sun.COM 
364*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
365*13101SVenki.Rajagopalan@Sun.COM static void
eib_rb_ctl_setup_cq(eib_t * ss,eib_vnic_t * vnic)366*13101SVenki.Rajagopalan@Sun.COM eib_rb_ctl_setup_cq(eib_t *ss, eib_vnic_t *vnic)
367*13101SVenki.Rajagopalan@Sun.COM {
368*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = vnic->vn_ctl_chan;
369*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
370*13101SVenki.Rajagopalan@Sun.COM 
371*13101SVenki.Rajagopalan@Sun.COM 	if (chan == NULL)
372*13101SVenki.Rajagopalan@Sun.COM 		return;
373*13101SVenki.Rajagopalan@Sun.COM 
374*13101SVenki.Rajagopalan@Sun.COM 	/*
375*13101SVenki.Rajagopalan@Sun.COM 	 * Reset any completion handler we may have set up
376*13101SVenki.Rajagopalan@Sun.COM 	 */
377*13101SVenki.Rajagopalan@Sun.COM 	if (chan->ch_cq_hdl)
378*13101SVenki.Rajagopalan@Sun.COM 		ibt_set_cq_handler(chan->ch_cq_hdl, NULL, NULL);
379*13101SVenki.Rajagopalan@Sun.COM 
380*13101SVenki.Rajagopalan@Sun.COM 	/*
381*13101SVenki.Rajagopalan@Sun.COM 	 * Remove any softint we may have allocated for this cq
382*13101SVenki.Rajagopalan@Sun.COM 	 */
383*13101SVenki.Rajagopalan@Sun.COM 	if (vnic->vn_ctl_si_hdl) {
384*13101SVenki.Rajagopalan@Sun.COM 		(void) ddi_intr_remove_softint(vnic->vn_ctl_si_hdl);
385*13101SVenki.Rajagopalan@Sun.COM 		vnic->vn_ctl_si_hdl = NULL;
386*13101SVenki.Rajagopalan@Sun.COM 	}
387*13101SVenki.Rajagopalan@Sun.COM 
388*13101SVenki.Rajagopalan@Sun.COM 	/*
389*13101SVenki.Rajagopalan@Sun.COM 	 * Release any work completion buffers we may have allocated
390*13101SVenki.Rajagopalan@Sun.COM 	 */
391*13101SVenki.Rajagopalan@Sun.COM 	if (chan->ch_wc && chan->ch_cq_sz)
392*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(chan->ch_wc, sizeof (ibt_wc_t) * chan->ch_cq_sz);
393*13101SVenki.Rajagopalan@Sun.COM 
394*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_cq_sz = 0;
395*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_wc = NULL;
396*13101SVenki.Rajagopalan@Sun.COM 
397*13101SVenki.Rajagopalan@Sun.COM 	/*
398*13101SVenki.Rajagopalan@Sun.COM 	 * Free any completion queue we may have allocated
399*13101SVenki.Rajagopalan@Sun.COM 	 */
400*13101SVenki.Rajagopalan@Sun.COM 	if (chan->ch_cq_hdl) {
401*13101SVenki.Rajagopalan@Sun.COM 		ret = ibt_free_cq(chan->ch_cq_hdl);
402*13101SVenki.Rajagopalan@Sun.COM 		if (ret != IBT_SUCCESS) {
403*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
404*13101SVenki.Rajagopalan@Sun.COM 			    "eib_rb_ctl_setup_cq: "
405*13101SVenki.Rajagopalan@Sun.COM 			    "ibt_free_cq() failed, ret=%d", ret);
406*13101SVenki.Rajagopalan@Sun.COM 		}
407*13101SVenki.Rajagopalan@Sun.COM 		chan->ch_cq_hdl = NULL;
408*13101SVenki.Rajagopalan@Sun.COM 	}
409*13101SVenki.Rajagopalan@Sun.COM }
410*13101SVenki.Rajagopalan@Sun.COM 
411*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
412*13101SVenki.Rajagopalan@Sun.COM static void
eib_rb_ctl_setup_ud_channel(eib_t * ss,eib_vnic_t * vnic)413*13101SVenki.Rajagopalan@Sun.COM eib_rb_ctl_setup_ud_channel(eib_t *ss, eib_vnic_t *vnic)
414*13101SVenki.Rajagopalan@Sun.COM {
415*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = vnic->vn_ctl_chan;
416*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
417*13101SVenki.Rajagopalan@Sun.COM 
418*13101SVenki.Rajagopalan@Sun.COM 	if (chan == NULL)
419*13101SVenki.Rajagopalan@Sun.COM 		return;
420*13101SVenki.Rajagopalan@Sun.COM 
421*13101SVenki.Rajagopalan@Sun.COM 	if (chan->ch_chan) {
422*13101SVenki.Rajagopalan@Sun.COM 		/*
423*13101SVenki.Rajagopalan@Sun.COM 		 * We're trying to tear down this UD channel. Make sure that
424*13101SVenki.Rajagopalan@Sun.COM 		 * we don't attempt to refill (repost) at any point from now on.
425*13101SVenki.Rajagopalan@Sun.COM 		 */
426*13101SVenki.Rajagopalan@Sun.COM 		chan->ch_tear_down = B_TRUE;
427*13101SVenki.Rajagopalan@Sun.COM 		if ((ret = ibt_flush_channel(chan->ch_chan)) != IBT_SUCCESS) {
428*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
429*13101SVenki.Rajagopalan@Sun.COM 			    "eib_rb_ctl_setup_ud_channel: "
430*13101SVenki.Rajagopalan@Sun.COM 			    "ibt_flush_channel() failed, ret=%d", ret);
431*13101SVenki.Rajagopalan@Sun.COM 		}
432*13101SVenki.Rajagopalan@Sun.COM 
433*13101SVenki.Rajagopalan@Sun.COM 		/*
434*13101SVenki.Rajagopalan@Sun.COM 		 * Wait until all posted tx wqes on this channel are back with
435*13101SVenki.Rajagopalan@Sun.COM 		 * the wqe pool.
436*13101SVenki.Rajagopalan@Sun.COM 		 */
437*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&chan->ch_tx_lock);
438*13101SVenki.Rajagopalan@Sun.COM 		while (chan->ch_tx_posted > 0)
439*13101SVenki.Rajagopalan@Sun.COM 			cv_wait(&chan->ch_tx_cv, &chan->ch_tx_lock);
440*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&chan->ch_tx_lock);
441*13101SVenki.Rajagopalan@Sun.COM 
442*13101SVenki.Rajagopalan@Sun.COM 		/*
443*13101SVenki.Rajagopalan@Sun.COM 		 * Wait until all posted rx wqes on this channel are back with
444*13101SVenki.Rajagopalan@Sun.COM 		 * the wqe pool.
445*13101SVenki.Rajagopalan@Sun.COM 		 */
446*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&chan->ch_rx_lock);
447*13101SVenki.Rajagopalan@Sun.COM 		while (chan->ch_rx_posted > 0)
448*13101SVenki.Rajagopalan@Sun.COM 			cv_wait(&chan->ch_rx_cv, &chan->ch_rx_lock);
449*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&chan->ch_rx_lock);
450*13101SVenki.Rajagopalan@Sun.COM 
451*13101SVenki.Rajagopalan@Sun.COM 		/*
452*13101SVenki.Rajagopalan@Sun.COM 		 * Now we're ready to free this channel
453*13101SVenki.Rajagopalan@Sun.COM 		 */
454*13101SVenki.Rajagopalan@Sun.COM 		if ((ret = ibt_free_channel(chan->ch_chan)) != IBT_SUCCESS) {
455*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
456*13101SVenki.Rajagopalan@Sun.COM 			    "eib_rb_ctl_setup_ud_channel: "
457*13101SVenki.Rajagopalan@Sun.COM 			    "ibt_free_channel() failed, ret=%d", ret);
458*13101SVenki.Rajagopalan@Sun.COM 		}
459*13101SVenki.Rajagopalan@Sun.COM 
460*13101SVenki.Rajagopalan@Sun.COM 		chan->ch_alloc_mp = B_FALSE;
461*13101SVenki.Rajagopalan@Sun.COM 		chan->ch_ip_hdr_align = 0;
462*13101SVenki.Rajagopalan@Sun.COM 		chan->ch_rwqe_bktsz = 0;
463*13101SVenki.Rajagopalan@Sun.COM 		chan->ch_lwm_rwqes = 0;
464*13101SVenki.Rajagopalan@Sun.COM 		chan->ch_max_rwqes = 0;
465*13101SVenki.Rajagopalan@Sun.COM 		chan->ch_max_swqes = 0;
466*13101SVenki.Rajagopalan@Sun.COM 		chan->ch_qpn = 0;
467*13101SVenki.Rajagopalan@Sun.COM 		chan->ch_chan = NULL;
468*13101SVenki.Rajagopalan@Sun.COM 	}
469*13101SVenki.Rajagopalan@Sun.COM }
470