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