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_adm_setup_cq(eib_t *);
39*13101SVenki.Rajagopalan@Sun.COM static int eib_adm_setup_ud_channel(eib_t *);
40*13101SVenki.Rajagopalan@Sun.COM static void eib_adm_comp_intr(ibt_cq_hdl_t, void *);
41*13101SVenki.Rajagopalan@Sun.COM static void eib_adm_rx_comp(eib_t *, eib_wqe_t *);
42*13101SVenki.Rajagopalan@Sun.COM static void eib_adm_tx_comp(eib_t *, eib_wqe_t *);
43*13101SVenki.Rajagopalan@Sun.COM static void eib_adm_err_comp(eib_t *, eib_wqe_t *, ibt_wc_t *);
44*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_adm_setup_cq(eib_t *);
45*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_adm_setup_ud_channel(eib_t *);
46*13101SVenki.Rajagopalan@Sun.COM
47*13101SVenki.Rajagopalan@Sun.COM int
eib_adm_setup_qp(eib_t * ss,int * err)48*13101SVenki.Rajagopalan@Sun.COM eib_adm_setup_qp(eib_t *ss, int *err)
49*13101SVenki.Rajagopalan@Sun.COM {
50*13101SVenki.Rajagopalan@Sun.COM eib_chan_t *chan;
51*13101SVenki.Rajagopalan@Sun.COM ibt_status_t ret;
52*13101SVenki.Rajagopalan@Sun.COM uint16_t pkey_ix;
53*13101SVenki.Rajagopalan@Sun.COM
54*13101SVenki.Rajagopalan@Sun.COM /*
55*13101SVenki.Rajagopalan@Sun.COM * Verify pkey
56*13101SVenki.Rajagopalan@Sun.COM */
57*13101SVenki.Rajagopalan@Sun.COM ret = ibt_pkey2index(ss->ei_hca_hdl, ss->ei_props->ep_port_num,
58*13101SVenki.Rajagopalan@Sun.COM EIB_ADMIN_PKEY, &pkey_ix);
59*13101SVenki.Rajagopalan@Sun.COM if (ret != IBT_SUCCESS) {
60*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_adm_setup_qp: "
61*13101SVenki.Rajagopalan@Sun.COM "ibt_pkey2index() failed, port_num=0x%x, "
62*13101SVenki.Rajagopalan@Sun.COM "pkey=0x%x, ret=%d", ss->ei_props->ep_port_num,
63*13101SVenki.Rajagopalan@Sun.COM EIB_ADMIN_PKEY, ret);
64*13101SVenki.Rajagopalan@Sun.COM *err = ENONET;
65*13101SVenki.Rajagopalan@Sun.COM goto adm_setup_qp_fail;
66*13101SVenki.Rajagopalan@Sun.COM }
67*13101SVenki.Rajagopalan@Sun.COM
68*13101SVenki.Rajagopalan@Sun.COM /*
69*13101SVenki.Rajagopalan@Sun.COM * Allocate a eib_chan_t to store stuff about admin qp and
70*13101SVenki.Rajagopalan@Sun.COM * initialize some basic stuff
71*13101SVenki.Rajagopalan@Sun.COM */
72*13101SVenki.Rajagopalan@Sun.COM ss->ei_admin_chan = eib_chan_init();
73*13101SVenki.Rajagopalan@Sun.COM
74*13101SVenki.Rajagopalan@Sun.COM chan = ss->ei_admin_chan;
75*13101SVenki.Rajagopalan@Sun.COM chan->ch_pkey = EIB_ADMIN_PKEY;
76*13101SVenki.Rajagopalan@Sun.COM chan->ch_pkey_ix = pkey_ix;
77*13101SVenki.Rajagopalan@Sun.COM chan->ch_vnic_inst = -1;
78*13101SVenki.Rajagopalan@Sun.COM
79*13101SVenki.Rajagopalan@Sun.COM /*
80*13101SVenki.Rajagopalan@Sun.COM * Setup a combined CQ and completion handler
81*13101SVenki.Rajagopalan@Sun.COM */
82*13101SVenki.Rajagopalan@Sun.COM if (eib_adm_setup_cq(ss) != EIB_E_SUCCESS) {
83*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_adm_setup_qp: "
84*13101SVenki.Rajagopalan@Sun.COM "eib_adm_setup_cq() failed");
85*13101SVenki.Rajagopalan@Sun.COM *err = ENOMEM;
86*13101SVenki.Rajagopalan@Sun.COM goto adm_setup_qp_fail;
87*13101SVenki.Rajagopalan@Sun.COM }
88*13101SVenki.Rajagopalan@Sun.COM
89*13101SVenki.Rajagopalan@Sun.COM /*
90*13101SVenki.Rajagopalan@Sun.COM * Setup UD channel
91*13101SVenki.Rajagopalan@Sun.COM */
92*13101SVenki.Rajagopalan@Sun.COM if (eib_adm_setup_ud_channel(ss) != EIB_E_SUCCESS) {
93*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_adm_setup_qp: "
94*13101SVenki.Rajagopalan@Sun.COM "eib_adm_setup_ud_channel() failed");
95*13101SVenki.Rajagopalan@Sun.COM *err = ENOMEM;
96*13101SVenki.Rajagopalan@Sun.COM goto adm_setup_qp_fail;
97*13101SVenki.Rajagopalan@Sun.COM }
98*13101SVenki.Rajagopalan@Sun.COM
99*13101SVenki.Rajagopalan@Sun.COM /*
100*13101SVenki.Rajagopalan@Sun.COM * Post initial set of rx buffers to the HCA
101*13101SVenki.Rajagopalan@Sun.COM */
102*13101SVenki.Rajagopalan@Sun.COM if (eib_chan_post_rx(ss, chan, NULL) != EIB_E_SUCCESS) {
103*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_adm_setup_qp: "
104*13101SVenki.Rajagopalan@Sun.COM "eib_chan_post_rx() failed");
105*13101SVenki.Rajagopalan@Sun.COM *err = ENOMEM;
106*13101SVenki.Rajagopalan@Sun.COM goto adm_setup_qp_fail;
107*13101SVenki.Rajagopalan@Sun.COM }
108*13101SVenki.Rajagopalan@Sun.COM
109*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_SUCCESS);
110*13101SVenki.Rajagopalan@Sun.COM
111*13101SVenki.Rajagopalan@Sun.COM adm_setup_qp_fail:
112*13101SVenki.Rajagopalan@Sun.COM eib_rb_adm_setup_qp(ss);
113*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_FAILURE);
114*13101SVenki.Rajagopalan@Sun.COM }
115*13101SVenki.Rajagopalan@Sun.COM
116*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
117*13101SVenki.Rajagopalan@Sun.COM uint_t
eib_adm_comp_handler(caddr_t arg1,caddr_t arg2)118*13101SVenki.Rajagopalan@Sun.COM eib_adm_comp_handler(caddr_t arg1, caddr_t arg2)
119*13101SVenki.Rajagopalan@Sun.COM {
120*13101SVenki.Rajagopalan@Sun.COM eib_t *ss = (eib_t *)(void *)arg1;
121*13101SVenki.Rajagopalan@Sun.COM eib_chan_t *chan = ss->ei_admin_chan;
122*13101SVenki.Rajagopalan@Sun.COM ibt_wc_t *wc;
123*13101SVenki.Rajagopalan@Sun.COM eib_wqe_t *wqe;
124*13101SVenki.Rajagopalan@Sun.COM ibt_status_t ret;
125*13101SVenki.Rajagopalan@Sun.COM uint_t polled;
126*13101SVenki.Rajagopalan@Sun.COM int i;
127*13101SVenki.Rajagopalan@Sun.COM
128*13101SVenki.Rajagopalan@Sun.COM /*
129*13101SVenki.Rajagopalan@Sun.COM * Re-arm the notification callback before we start polling
130*13101SVenki.Rajagopalan@Sun.COM * the completion queue. There's nothing much we can do if the
131*13101SVenki.Rajagopalan@Sun.COM * enable_cq_notify fails - we issue a warning and move on.
132*13101SVenki.Rajagopalan@Sun.COM */
133*13101SVenki.Rajagopalan@Sun.COM ret = ibt_enable_cq_notify(chan->ch_cq_hdl, IBT_NEXT_COMPLETION);
134*13101SVenki.Rajagopalan@Sun.COM if (ret != IBT_SUCCESS) {
135*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_WARN(ss->ei_instance, "eib_adm_comp_handler: "
136*13101SVenki.Rajagopalan@Sun.COM "ibt_enable_cq_notify() failed, ret=%d", ret);
137*13101SVenki.Rajagopalan@Sun.COM }
138*13101SVenki.Rajagopalan@Sun.COM
139*13101SVenki.Rajagopalan@Sun.COM /*
140*13101SVenki.Rajagopalan@Sun.COM * Handle tx and rx completions
141*13101SVenki.Rajagopalan@Sun.COM */
142*13101SVenki.Rajagopalan@Sun.COM while ((ret = ibt_poll_cq(chan->ch_cq_hdl, chan->ch_wc, chan->ch_cq_sz,
143*13101SVenki.Rajagopalan@Sun.COM &polled)) == IBT_SUCCESS) {
144*13101SVenki.Rajagopalan@Sun.COM for (wc = chan->ch_wc, i = 0; i < polled; i++, wc++) {
145*13101SVenki.Rajagopalan@Sun.COM wqe = (eib_wqe_t *)(uintptr_t)wc->wc_id;
146*13101SVenki.Rajagopalan@Sun.COM if (wc->wc_status != IBT_WC_SUCCESS) {
147*13101SVenki.Rajagopalan@Sun.COM eib_adm_err_comp(ss, wqe, wc);
148*13101SVenki.Rajagopalan@Sun.COM } else if (EIB_WQE_TYPE(wqe->qe_info) == EIB_WQE_RX) {
149*13101SVenki.Rajagopalan@Sun.COM eib_adm_rx_comp(ss, wqe);
150*13101SVenki.Rajagopalan@Sun.COM } else {
151*13101SVenki.Rajagopalan@Sun.COM eib_adm_tx_comp(ss, wqe);
152*13101SVenki.Rajagopalan@Sun.COM }
153*13101SVenki.Rajagopalan@Sun.COM }
154*13101SVenki.Rajagopalan@Sun.COM }
155*13101SVenki.Rajagopalan@Sun.COM
156*13101SVenki.Rajagopalan@Sun.COM return (DDI_INTR_CLAIMED);
157*13101SVenki.Rajagopalan@Sun.COM }
158*13101SVenki.Rajagopalan@Sun.COM
159*13101SVenki.Rajagopalan@Sun.COM void
eib_rb_adm_setup_qp(eib_t * ss)160*13101SVenki.Rajagopalan@Sun.COM eib_rb_adm_setup_qp(eib_t *ss)
161*13101SVenki.Rajagopalan@Sun.COM {
162*13101SVenki.Rajagopalan@Sun.COM eib_rb_adm_setup_ud_channel(ss);
163*13101SVenki.Rajagopalan@Sun.COM
164*13101SVenki.Rajagopalan@Sun.COM eib_rb_adm_setup_cq(ss);
165*13101SVenki.Rajagopalan@Sun.COM
166*13101SVenki.Rajagopalan@Sun.COM eib_chan_fini(ss->ei_admin_chan);
167*13101SVenki.Rajagopalan@Sun.COM ss->ei_admin_chan = NULL;
168*13101SVenki.Rajagopalan@Sun.COM }
169*13101SVenki.Rajagopalan@Sun.COM
170*13101SVenki.Rajagopalan@Sun.COM static int
eib_adm_setup_cq(eib_t * ss)171*13101SVenki.Rajagopalan@Sun.COM eib_adm_setup_cq(eib_t *ss)
172*13101SVenki.Rajagopalan@Sun.COM {
173*13101SVenki.Rajagopalan@Sun.COM eib_chan_t *chan = ss->ei_admin_chan;
174*13101SVenki.Rajagopalan@Sun.COM ibt_cq_attr_t cq_attr;
175*13101SVenki.Rajagopalan@Sun.COM ibt_status_t ret;
176*13101SVenki.Rajagopalan@Sun.COM uint_t sz;
177*13101SVenki.Rajagopalan@Sun.COM int rv;
178*13101SVenki.Rajagopalan@Sun.COM
179*13101SVenki.Rajagopalan@Sun.COM /*
180*13101SVenki.Rajagopalan@Sun.COM * Allocate the admin completion queue for sending vnic logins and
181*13101SVenki.Rajagopalan@Sun.COM * logouts and receiving vnic login acks.
182*13101SVenki.Rajagopalan@Sun.COM */
183*13101SVenki.Rajagopalan@Sun.COM cq_attr.cq_sched = NULL;
184*13101SVenki.Rajagopalan@Sun.COM cq_attr.cq_flags = IBT_CQ_NO_FLAGS;
185*13101SVenki.Rajagopalan@Sun.COM if (ss->ei_hca_attrs->hca_max_cq_sz < EIB_ADMIN_CQ_SIZE)
186*13101SVenki.Rajagopalan@Sun.COM cq_attr.cq_size = ss->ei_hca_attrs->hca_max_cq_sz;
187*13101SVenki.Rajagopalan@Sun.COM else
188*13101SVenki.Rajagopalan@Sun.COM cq_attr.cq_size = EIB_ADMIN_CQ_SIZE;
189*13101SVenki.Rajagopalan@Sun.COM
190*13101SVenki.Rajagopalan@Sun.COM ret = ibt_alloc_cq(ss->ei_hca_hdl, &cq_attr, &chan->ch_cq_hdl, &sz);
191*13101SVenki.Rajagopalan@Sun.COM if (ret != IBT_SUCCESS) {
192*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_adm_setup_cq: "
193*13101SVenki.Rajagopalan@Sun.COM "ibt_alloc_cq(cq_sz=0x%lx) failed, ret=%d",
194*13101SVenki.Rajagopalan@Sun.COM cq_attr.cq_size, ret);
195*13101SVenki.Rajagopalan@Sun.COM goto adm_setup_cq_fail;
196*13101SVenki.Rajagopalan@Sun.COM }
197*13101SVenki.Rajagopalan@Sun.COM
198*13101SVenki.Rajagopalan@Sun.COM /*
199*13101SVenki.Rajagopalan@Sun.COM * Set up other parameters for collecting completion information
200*13101SVenki.Rajagopalan@Sun.COM */
201*13101SVenki.Rajagopalan@Sun.COM chan->ch_cq_sz = sz;
202*13101SVenki.Rajagopalan@Sun.COM chan->ch_wc = kmem_zalloc(sizeof (ibt_wc_t) * sz, KM_SLEEP);
203*13101SVenki.Rajagopalan@Sun.COM
204*13101SVenki.Rajagopalan@Sun.COM /*
205*13101SVenki.Rajagopalan@Sun.COM * Allocate soft interrupt for the admin channel cq handler and
206*13101SVenki.Rajagopalan@Sun.COM * set up the handler as well.
207*13101SVenki.Rajagopalan@Sun.COM */
208*13101SVenki.Rajagopalan@Sun.COM if ((rv = ddi_intr_add_softint(ss->ei_dip, &ss->ei_admin_si_hdl,
209*13101SVenki.Rajagopalan@Sun.COM EIB_SOFTPRI_ADM, eib_adm_comp_handler, ss)) != DDI_SUCCESS) {
210*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_adm_setup_cq: "
211*13101SVenki.Rajagopalan@Sun.COM "ddi_intr_add_softint() failed for adm qp, ret=%d", rv);
212*13101SVenki.Rajagopalan@Sun.COM goto adm_setup_cq_fail;
213*13101SVenki.Rajagopalan@Sun.COM }
214*13101SVenki.Rajagopalan@Sun.COM
215*13101SVenki.Rajagopalan@Sun.COM /*
216*13101SVenki.Rajagopalan@Sun.COM * Now, set up the admin completion queue handler.
217*13101SVenki.Rajagopalan@Sun.COM */
218*13101SVenki.Rajagopalan@Sun.COM ibt_set_cq_handler(chan->ch_cq_hdl, eib_adm_comp_intr, ss);
219*13101SVenki.Rajagopalan@Sun.COM
220*13101SVenki.Rajagopalan@Sun.COM ret = ibt_enable_cq_notify(chan->ch_cq_hdl, IBT_NEXT_COMPLETION);
221*13101SVenki.Rajagopalan@Sun.COM if (ret != IBT_SUCCESS) {
222*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_adm_setup_cq: "
223*13101SVenki.Rajagopalan@Sun.COM "ibt_enable_cq_notify() failed, ret=%d", ret);
224*13101SVenki.Rajagopalan@Sun.COM goto adm_setup_cq_fail;
225*13101SVenki.Rajagopalan@Sun.COM }
226*13101SVenki.Rajagopalan@Sun.COM
227*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_SUCCESS);
228*13101SVenki.Rajagopalan@Sun.COM
229*13101SVenki.Rajagopalan@Sun.COM adm_setup_cq_fail:
230*13101SVenki.Rajagopalan@Sun.COM eib_rb_adm_setup_cq(ss);
231*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_FAILURE);
232*13101SVenki.Rajagopalan@Sun.COM }
233*13101SVenki.Rajagopalan@Sun.COM
234*13101SVenki.Rajagopalan@Sun.COM static int
eib_adm_setup_ud_channel(eib_t * ss)235*13101SVenki.Rajagopalan@Sun.COM eib_adm_setup_ud_channel(eib_t *ss)
236*13101SVenki.Rajagopalan@Sun.COM {
237*13101SVenki.Rajagopalan@Sun.COM eib_chan_t *chan = ss->ei_admin_chan;
238*13101SVenki.Rajagopalan@Sun.COM ibt_ud_chan_alloc_args_t alloc_attr;
239*13101SVenki.Rajagopalan@Sun.COM ibt_ud_chan_query_attr_t query_attr;
240*13101SVenki.Rajagopalan@Sun.COM ibt_status_t ret;
241*13101SVenki.Rajagopalan@Sun.COM
242*13101SVenki.Rajagopalan@Sun.COM bzero(&alloc_attr, sizeof (ibt_ud_chan_alloc_args_t));
243*13101SVenki.Rajagopalan@Sun.COM bzero(&query_attr, sizeof (ibt_ud_chan_query_attr_t));
244*13101SVenki.Rajagopalan@Sun.COM
245*13101SVenki.Rajagopalan@Sun.COM alloc_attr.ud_flags = IBT_ALL_SIGNALED;
246*13101SVenki.Rajagopalan@Sun.COM alloc_attr.ud_hca_port_num = ss->ei_props->ep_port_num;
247*13101SVenki.Rajagopalan@Sun.COM alloc_attr.ud_pkey_ix = chan->ch_pkey_ix;
248*13101SVenki.Rajagopalan@Sun.COM alloc_attr.ud_sizes.cs_sq = EIB_ADMIN_MAX_SWQE;
249*13101SVenki.Rajagopalan@Sun.COM alloc_attr.ud_sizes.cs_rq = EIB_ADMIN_MAX_RWQE;
250*13101SVenki.Rajagopalan@Sun.COM alloc_attr.ud_sizes.cs_sq_sgl = 1;
251*13101SVenki.Rajagopalan@Sun.COM alloc_attr.ud_sizes.cs_rq_sgl = 1;
252*13101SVenki.Rajagopalan@Sun.COM alloc_attr.ud_sizes.cs_inline = 0;
253*13101SVenki.Rajagopalan@Sun.COM
254*13101SVenki.Rajagopalan@Sun.COM alloc_attr.ud_qkey = EIB_FIP_QKEY;
255*13101SVenki.Rajagopalan@Sun.COM alloc_attr.ud_scq = chan->ch_cq_hdl;
256*13101SVenki.Rajagopalan@Sun.COM alloc_attr.ud_rcq = chan->ch_cq_hdl;
257*13101SVenki.Rajagopalan@Sun.COM alloc_attr.ud_pd = ss->ei_pd_hdl;
258*13101SVenki.Rajagopalan@Sun.COM
259*13101SVenki.Rajagopalan@Sun.COM ret = ibt_alloc_ud_channel(ss->ei_hca_hdl, IBT_ACHAN_NO_FLAGS,
260*13101SVenki.Rajagopalan@Sun.COM &alloc_attr, &chan->ch_chan, NULL);
261*13101SVenki.Rajagopalan@Sun.COM if (ret != IBT_SUCCESS) {
262*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_adm_setup_ud_channel: "
263*13101SVenki.Rajagopalan@Sun.COM "ibt_alloc_ud_channel(port=0x%x, pkey_ix=0x%x) "
264*13101SVenki.Rajagopalan@Sun.COM "failed, ret=%d", alloc_attr.ud_hca_port_num,
265*13101SVenki.Rajagopalan@Sun.COM chan->ch_pkey_ix, ret);
266*13101SVenki.Rajagopalan@Sun.COM goto adm_setup_ud_channel_fail;
267*13101SVenki.Rajagopalan@Sun.COM }
268*13101SVenki.Rajagopalan@Sun.COM
269*13101SVenki.Rajagopalan@Sun.COM ret = ibt_query_ud_channel(chan->ch_chan, &query_attr);
270*13101SVenki.Rajagopalan@Sun.COM if (ret != IBT_SUCCESS) {
271*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_adm_setup_ud_channel: "
272*13101SVenki.Rajagopalan@Sun.COM "ibt_query_ud_channel() failed, ret=%d", ret);
273*13101SVenki.Rajagopalan@Sun.COM goto adm_setup_ud_channel_fail;
274*13101SVenki.Rajagopalan@Sun.COM }
275*13101SVenki.Rajagopalan@Sun.COM
276*13101SVenki.Rajagopalan@Sun.COM chan->ch_qpn = query_attr.ud_qpn;
277*13101SVenki.Rajagopalan@Sun.COM chan->ch_max_swqes = query_attr.ud_chan_sizes.cs_sq;
278*13101SVenki.Rajagopalan@Sun.COM chan->ch_max_rwqes = query_attr.ud_chan_sizes.cs_rq;
279*13101SVenki.Rajagopalan@Sun.COM chan->ch_lwm_rwqes = chan->ch_max_rwqes >> 2;
280*13101SVenki.Rajagopalan@Sun.COM chan->ch_rwqe_bktsz = chan->ch_max_rwqes;
281*13101SVenki.Rajagopalan@Sun.COM chan->ch_ip_hdr_align = 0;
282*13101SVenki.Rajagopalan@Sun.COM chan->ch_alloc_mp = B_FALSE;
283*13101SVenki.Rajagopalan@Sun.COM chan->ch_tear_down = B_FALSE;
284*13101SVenki.Rajagopalan@Sun.COM
285*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_SUCCESS);
286*13101SVenki.Rajagopalan@Sun.COM
287*13101SVenki.Rajagopalan@Sun.COM adm_setup_ud_channel_fail:
288*13101SVenki.Rajagopalan@Sun.COM eib_rb_adm_setup_ud_channel(ss);
289*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_FAILURE);
290*13101SVenki.Rajagopalan@Sun.COM }
291*13101SVenki.Rajagopalan@Sun.COM
292*13101SVenki.Rajagopalan@Sun.COM static void
eib_adm_comp_intr(ibt_cq_hdl_t cq_hdl,void * arg)293*13101SVenki.Rajagopalan@Sun.COM eib_adm_comp_intr(ibt_cq_hdl_t cq_hdl, void *arg)
294*13101SVenki.Rajagopalan@Sun.COM {
295*13101SVenki.Rajagopalan@Sun.COM eib_t *ss = arg;
296*13101SVenki.Rajagopalan@Sun.COM eib_chan_t *chan = ss->ei_admin_chan;
297*13101SVenki.Rajagopalan@Sun.COM
298*13101SVenki.Rajagopalan@Sun.COM if (cq_hdl != chan->ch_cq_hdl) {
299*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_DEBUG(ss->ei_instance, "eib_adm_comp_intr: "
300*13101SVenki.Rajagopalan@Sun.COM "cq_hdl(0x%llx) != chan->ch_cq_hdl(0x%llx), "
301*13101SVenki.Rajagopalan@Sun.COM "ignoring completion", cq_hdl, chan->ch_cq_hdl);
302*13101SVenki.Rajagopalan@Sun.COM return;
303*13101SVenki.Rajagopalan@Sun.COM }
304*13101SVenki.Rajagopalan@Sun.COM
305*13101SVenki.Rajagopalan@Sun.COM ASSERT(ss->ei_admin_si_hdl != NULL);
306*13101SVenki.Rajagopalan@Sun.COM
307*13101SVenki.Rajagopalan@Sun.COM (void) ddi_intr_trigger_softint(ss->ei_admin_si_hdl, NULL);
308*13101SVenki.Rajagopalan@Sun.COM }
309*13101SVenki.Rajagopalan@Sun.COM
310*13101SVenki.Rajagopalan@Sun.COM static void
eib_adm_rx_comp(eib_t * ss,eib_wqe_t * wqe)311*13101SVenki.Rajagopalan@Sun.COM eib_adm_rx_comp(eib_t *ss, eib_wqe_t *wqe)
312*13101SVenki.Rajagopalan@Sun.COM {
313*13101SVenki.Rajagopalan@Sun.COM eib_chan_t *chan = ss->ei_admin_chan;
314*13101SVenki.Rajagopalan@Sun.COM eib_login_data_t ld;
315*13101SVenki.Rajagopalan@Sun.COM uint8_t *pkt = (uint8_t *)(uintptr_t)(wqe->qe_sgl.ds_va);
316*13101SVenki.Rajagopalan@Sun.COM ibt_status_t ret;
317*13101SVenki.Rajagopalan@Sun.COM
318*13101SVenki.Rajagopalan@Sun.COM /*
319*13101SVenki.Rajagopalan@Sun.COM * Skip the GRH and parse the login ack message in the packet
320*13101SVenki.Rajagopalan@Sun.COM */
321*13101SVenki.Rajagopalan@Sun.COM if (eib_fip_parse_login_ack(ss, pkt + EIB_GRH_SZ, &ld) == EIB_E_SUCCESS)
322*13101SVenki.Rajagopalan@Sun.COM eib_vnic_login_ack(ss, &ld);
323*13101SVenki.Rajagopalan@Sun.COM
324*13101SVenki.Rajagopalan@Sun.COM /*
325*13101SVenki.Rajagopalan@Sun.COM * Try to repost the rwqe. For admin channel, we can take the shortcut
326*13101SVenki.Rajagopalan@Sun.COM * and not go through eib_chan_post_recv(), since we know that the
327*13101SVenki.Rajagopalan@Sun.COM * qe_info flag, qe_chan and qe_vinst are all already set correctly; we
328*13101SVenki.Rajagopalan@Sun.COM * just took this out of the rx queue, so the ch_rx_posted will be ok
329*13101SVenki.Rajagopalan@Sun.COM * if we just posted it back. And there are no mblk allocation or
330*13101SVenki.Rajagopalan@Sun.COM * buffer alignment restrictions for this channel as well.
331*13101SVenki.Rajagopalan@Sun.COM */
332*13101SVenki.Rajagopalan@Sun.COM if (chan->ch_tear_down) {
333*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_return_rwqe(ss, wqe, chan);
334*13101SVenki.Rajagopalan@Sun.COM } else {
335*13101SVenki.Rajagopalan@Sun.COM ret = ibt_post_recv(chan->ch_chan, &(wqe->qe_wr.recv), 1, NULL);
336*13101SVenki.Rajagopalan@Sun.COM if (ret != IBT_SUCCESS) {
337*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_adm_rx_comp: "
338*13101SVenki.Rajagopalan@Sun.COM "ibt_post_recv() failed, ret=%d", ret);
339*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_return_rwqe(ss, wqe, chan);
340*13101SVenki.Rajagopalan@Sun.COM }
341*13101SVenki.Rajagopalan@Sun.COM }
342*13101SVenki.Rajagopalan@Sun.COM }
343*13101SVenki.Rajagopalan@Sun.COM
344*13101SVenki.Rajagopalan@Sun.COM static void
eib_adm_tx_comp(eib_t * ss,eib_wqe_t * wqe)345*13101SVenki.Rajagopalan@Sun.COM eib_adm_tx_comp(eib_t *ss, eib_wqe_t *wqe)
346*13101SVenki.Rajagopalan@Sun.COM {
347*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_return_swqe(ss, wqe, ss->ei_admin_chan);
348*13101SVenki.Rajagopalan@Sun.COM }
349*13101SVenki.Rajagopalan@Sun.COM
350*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
351*13101SVenki.Rajagopalan@Sun.COM static void
eib_adm_err_comp(eib_t * ss,eib_wqe_t * wqe,ibt_wc_t * wc)352*13101SVenki.Rajagopalan@Sun.COM eib_adm_err_comp(eib_t *ss, eib_wqe_t *wqe, ibt_wc_t *wc)
353*13101SVenki.Rajagopalan@Sun.COM {
354*13101SVenki.Rajagopalan@Sun.COM /*
355*13101SVenki.Rajagopalan@Sun.COM * Currently, all we do is report
356*13101SVenki.Rajagopalan@Sun.COM */
357*13101SVenki.Rajagopalan@Sun.COM switch (wc->wc_status) {
358*13101SVenki.Rajagopalan@Sun.COM case IBT_WC_WR_FLUSHED_ERR:
359*13101SVenki.Rajagopalan@Sun.COM break;
360*13101SVenki.Rajagopalan@Sun.COM
361*13101SVenki.Rajagopalan@Sun.COM case IBT_WC_LOCAL_CHAN_OP_ERR:
362*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_adm_err_comp: "
363*13101SVenki.Rajagopalan@Sun.COM "IBT_WC_LOCAL_CHAN_OP_ERR seen, wqe_info=0x%lx ",
364*13101SVenki.Rajagopalan@Sun.COM wqe->qe_info);
365*13101SVenki.Rajagopalan@Sun.COM break;
366*13101SVenki.Rajagopalan@Sun.COM
367*13101SVenki.Rajagopalan@Sun.COM case IBT_WC_LOCAL_PROTECT_ERR:
368*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_adm_err_comp: "
369*13101SVenki.Rajagopalan@Sun.COM "IBT_WC_LOCAL_PROTECT_ERR seen, wqe_info=0x%lx ",
370*13101SVenki.Rajagopalan@Sun.COM wqe->qe_info);
371*13101SVenki.Rajagopalan@Sun.COM break;
372*13101SVenki.Rajagopalan@Sun.COM }
373*13101SVenki.Rajagopalan@Sun.COM
374*13101SVenki.Rajagopalan@Sun.COM /*
375*13101SVenki.Rajagopalan@Sun.COM * When a wc indicates error, we do not attempt to repost but
376*13101SVenki.Rajagopalan@Sun.COM * simply return it to the wqe pool.
377*13101SVenki.Rajagopalan@Sun.COM */
378*13101SVenki.Rajagopalan@Sun.COM if (EIB_WQE_TYPE(wqe->qe_info) == EIB_WQE_RX)
379*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_return_rwqe(ss, wqe, ss->ei_admin_chan);
380*13101SVenki.Rajagopalan@Sun.COM else
381*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_return_swqe(ss, wqe, ss->ei_admin_chan);
382*13101SVenki.Rajagopalan@Sun.COM }
383*13101SVenki.Rajagopalan@Sun.COM
384*13101SVenki.Rajagopalan@Sun.COM static void
eib_rb_adm_setup_cq(eib_t * ss)385*13101SVenki.Rajagopalan@Sun.COM eib_rb_adm_setup_cq(eib_t *ss)
386*13101SVenki.Rajagopalan@Sun.COM {
387*13101SVenki.Rajagopalan@Sun.COM eib_chan_t *chan = ss->ei_admin_chan;
388*13101SVenki.Rajagopalan@Sun.COM ibt_status_t ret;
389*13101SVenki.Rajagopalan@Sun.COM
390*13101SVenki.Rajagopalan@Sun.COM if (chan == NULL)
391*13101SVenki.Rajagopalan@Sun.COM return;
392*13101SVenki.Rajagopalan@Sun.COM
393*13101SVenki.Rajagopalan@Sun.COM /*
394*13101SVenki.Rajagopalan@Sun.COM * Reset any completion handler we may have set up
395*13101SVenki.Rajagopalan@Sun.COM */
396*13101SVenki.Rajagopalan@Sun.COM if (chan->ch_cq_hdl)
397*13101SVenki.Rajagopalan@Sun.COM ibt_set_cq_handler(chan->ch_cq_hdl, NULL, NULL);
398*13101SVenki.Rajagopalan@Sun.COM
399*13101SVenki.Rajagopalan@Sun.COM /*
400*13101SVenki.Rajagopalan@Sun.COM * Remove any softint we may have allocated for the admin cq
401*13101SVenki.Rajagopalan@Sun.COM */
402*13101SVenki.Rajagopalan@Sun.COM if (ss->ei_admin_si_hdl) {
403*13101SVenki.Rajagopalan@Sun.COM (void) ddi_intr_remove_softint(ss->ei_admin_si_hdl);
404*13101SVenki.Rajagopalan@Sun.COM ss->ei_admin_si_hdl = NULL;
405*13101SVenki.Rajagopalan@Sun.COM }
406*13101SVenki.Rajagopalan@Sun.COM
407*13101SVenki.Rajagopalan@Sun.COM /*
408*13101SVenki.Rajagopalan@Sun.COM * Release any work completion buffers we may have allocated
409*13101SVenki.Rajagopalan@Sun.COM */
410*13101SVenki.Rajagopalan@Sun.COM if (chan->ch_wc && chan->ch_cq_sz)
411*13101SVenki.Rajagopalan@Sun.COM kmem_free(chan->ch_wc, sizeof (ibt_wc_t) * chan->ch_cq_sz);
412*13101SVenki.Rajagopalan@Sun.COM
413*13101SVenki.Rajagopalan@Sun.COM chan->ch_cq_sz = 0;
414*13101SVenki.Rajagopalan@Sun.COM chan->ch_wc = NULL;
415*13101SVenki.Rajagopalan@Sun.COM
416*13101SVenki.Rajagopalan@Sun.COM /*
417*13101SVenki.Rajagopalan@Sun.COM * Free any completion queue we may have allocated
418*13101SVenki.Rajagopalan@Sun.COM */
419*13101SVenki.Rajagopalan@Sun.COM if (chan->ch_cq_hdl) {
420*13101SVenki.Rajagopalan@Sun.COM ret = ibt_free_cq(chan->ch_cq_hdl);
421*13101SVenki.Rajagopalan@Sun.COM if (ret != IBT_SUCCESS) {
422*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_WARN(ss->ei_instance,
423*13101SVenki.Rajagopalan@Sun.COM "eib_rb_adm_setup_cq: "
424*13101SVenki.Rajagopalan@Sun.COM "ibt_free_cq() failed, ret=%d", ret);
425*13101SVenki.Rajagopalan@Sun.COM }
426*13101SVenki.Rajagopalan@Sun.COM chan->ch_cq_hdl = NULL;
427*13101SVenki.Rajagopalan@Sun.COM }
428*13101SVenki.Rajagopalan@Sun.COM }
429*13101SVenki.Rajagopalan@Sun.COM
430*13101SVenki.Rajagopalan@Sun.COM static void
eib_rb_adm_setup_ud_channel(eib_t * ss)431*13101SVenki.Rajagopalan@Sun.COM eib_rb_adm_setup_ud_channel(eib_t *ss)
432*13101SVenki.Rajagopalan@Sun.COM {
433*13101SVenki.Rajagopalan@Sun.COM eib_chan_t *chan = ss->ei_admin_chan;
434*13101SVenki.Rajagopalan@Sun.COM ibt_status_t ret;
435*13101SVenki.Rajagopalan@Sun.COM
436*13101SVenki.Rajagopalan@Sun.COM if (chan == NULL)
437*13101SVenki.Rajagopalan@Sun.COM return;
438*13101SVenki.Rajagopalan@Sun.COM
439*13101SVenki.Rajagopalan@Sun.COM if (chan->ch_chan) {
440*13101SVenki.Rajagopalan@Sun.COM /*
441*13101SVenki.Rajagopalan@Sun.COM * We're trying to tear down this UD channel. Make sure that
442*13101SVenki.Rajagopalan@Sun.COM * we don't attempt to refill (repost) at any point from now on.
443*13101SVenki.Rajagopalan@Sun.COM */
444*13101SVenki.Rajagopalan@Sun.COM chan->ch_tear_down = B_TRUE;
445*13101SVenki.Rajagopalan@Sun.COM if ((ret = ibt_flush_channel(chan->ch_chan)) != IBT_SUCCESS) {
446*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_WARN(ss->ei_instance,
447*13101SVenki.Rajagopalan@Sun.COM "eib_rb_adm_setup_ud_channel: "
448*13101SVenki.Rajagopalan@Sun.COM "ibt_flush_channel() failed, ret=%d", ret);
449*13101SVenki.Rajagopalan@Sun.COM }
450*13101SVenki.Rajagopalan@Sun.COM
451*13101SVenki.Rajagopalan@Sun.COM /*
452*13101SVenki.Rajagopalan@Sun.COM * Wait until all posted tx wqes on this channel are back with
453*13101SVenki.Rajagopalan@Sun.COM * the wqe pool.
454*13101SVenki.Rajagopalan@Sun.COM */
455*13101SVenki.Rajagopalan@Sun.COM mutex_enter(&chan->ch_tx_lock);
456*13101SVenki.Rajagopalan@Sun.COM while (chan->ch_tx_posted > 0)
457*13101SVenki.Rajagopalan@Sun.COM cv_wait(&chan->ch_tx_cv, &chan->ch_tx_lock);
458*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&chan->ch_tx_lock);
459*13101SVenki.Rajagopalan@Sun.COM
460*13101SVenki.Rajagopalan@Sun.COM /*
461*13101SVenki.Rajagopalan@Sun.COM * Wait until all posted rx wqes on this channel are back with
462*13101SVenki.Rajagopalan@Sun.COM * the wqe pool.
463*13101SVenki.Rajagopalan@Sun.COM */
464*13101SVenki.Rajagopalan@Sun.COM mutex_enter(&chan->ch_rx_lock);
465*13101SVenki.Rajagopalan@Sun.COM while (chan->ch_rx_posted > 0)
466*13101SVenki.Rajagopalan@Sun.COM cv_wait(&chan->ch_rx_cv, &chan->ch_rx_lock);
467*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&chan->ch_rx_lock);
468*13101SVenki.Rajagopalan@Sun.COM
469*13101SVenki.Rajagopalan@Sun.COM /*
470*13101SVenki.Rajagopalan@Sun.COM * Now we're ready to free this channel
471*13101SVenki.Rajagopalan@Sun.COM */
472*13101SVenki.Rajagopalan@Sun.COM if ((ret = ibt_free_channel(chan->ch_chan)) != IBT_SUCCESS) {
473*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_WARN(ss->ei_instance,
474*13101SVenki.Rajagopalan@Sun.COM "eib_rb_adm_setup_ud_channel: "
475*13101SVenki.Rajagopalan@Sun.COM "ibt_free_channel() failed, ret=%d", ret);
476*13101SVenki.Rajagopalan@Sun.COM }
477*13101SVenki.Rajagopalan@Sun.COM
478*13101SVenki.Rajagopalan@Sun.COM chan->ch_alloc_mp = B_FALSE;
479*13101SVenki.Rajagopalan@Sun.COM chan->ch_ip_hdr_align = 0;
480*13101SVenki.Rajagopalan@Sun.COM chan->ch_rwqe_bktsz = 0;
481*13101SVenki.Rajagopalan@Sun.COM chan->ch_lwm_rwqes = 0;
482*13101SVenki.Rajagopalan@Sun.COM chan->ch_max_rwqes = 0;
483*13101SVenki.Rajagopalan@Sun.COM chan->ch_max_swqes = 0;
484*13101SVenki.Rajagopalan@Sun.COM chan->ch_qpn = 0;
485*13101SVenki.Rajagopalan@Sun.COM chan->ch_chan = NULL;
486*13101SVenki.Rajagopalan@Sun.COM }
487*13101SVenki.Rajagopalan@Sun.COM }
488