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_rsrc_setup_txbufs(eib_t *, int *);
39*13101SVenki.Rajagopalan@Sun.COM static int eib_rsrc_setup_rxbufs(eib_t *, int *);
40*13101SVenki.Rajagopalan@Sun.COM static int eib_rsrc_setup_lsobufs(eib_t *, int *);
41*13101SVenki.Rajagopalan@Sun.COM static void eib_rsrc_init_wqe_pool(eib_t *, eib_wqe_pool_t **,
42*13101SVenki.Rajagopalan@Sun.COM ib_memlen_t, int);
43*13101SVenki.Rajagopalan@Sun.COM static void eib_rsrc_fini_wqe_pool(eib_t *, eib_wqe_pool_t **);
44*13101SVenki.Rajagopalan@Sun.COM static boolean_t eib_rsrc_ok_to_free_pool(eib_t *, eib_wqe_pool_t *, boolean_t);
45*13101SVenki.Rajagopalan@Sun.COM static int eib_rsrc_grab_wqes(eib_t *, eib_wqe_pool_t *, eib_wqe_t **, uint_t,
46*13101SVenki.Rajagopalan@Sun.COM uint_t *, int);
47*13101SVenki.Rajagopalan@Sun.COM static void eib_rsrc_return_wqes(eib_t *, eib_wqe_pool_t *, eib_wqe_t **,
48*13101SVenki.Rajagopalan@Sun.COM uint_t);
49*13101SVenki.Rajagopalan@Sun.COM
50*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_rsrc_setup_txbufs(eib_t *, boolean_t);
51*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_rsrc_setup_rxbufs(eib_t *, boolean_t);
52*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_rsrc_setup_lsobufs(eib_t *, boolean_t);
53*13101SVenki.Rajagopalan@Sun.COM
54*13101SVenki.Rajagopalan@Sun.COM /*
55*13101SVenki.Rajagopalan@Sun.COM * Definitions private to this file
56*13101SVenki.Rajagopalan@Sun.COM */
57*13101SVenki.Rajagopalan@Sun.COM static uint_t eib_lso_num_bufs = EIB_LSO_NUM_BUFS; /* tunable? */
58*13101SVenki.Rajagopalan@Sun.COM
59*13101SVenki.Rajagopalan@Sun.COM int
eib_rsrc_setup_bufs(eib_t * ss,int * err)60*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_setup_bufs(eib_t *ss, int *err)
61*13101SVenki.Rajagopalan@Sun.COM {
62*13101SVenki.Rajagopalan@Sun.COM if (eib_rsrc_setup_txbufs(ss, err) != EIB_E_SUCCESS)
63*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_FAILURE);
64*13101SVenki.Rajagopalan@Sun.COM
65*13101SVenki.Rajagopalan@Sun.COM if (ss->ei_caps->cp_lso_maxlen && ss->ei_caps->cp_cksum_flags &&
66*13101SVenki.Rajagopalan@Sun.COM ss->ei_caps->cp_resv_lkey_capab) {
67*13101SVenki.Rajagopalan@Sun.COM if (eib_rsrc_setup_lsobufs(ss, err) != EIB_E_SUCCESS) {
68*13101SVenki.Rajagopalan@Sun.COM eib_rb_rsrc_setup_txbufs(ss, B_FALSE);
69*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_FAILURE);
70*13101SVenki.Rajagopalan@Sun.COM }
71*13101SVenki.Rajagopalan@Sun.COM }
72*13101SVenki.Rajagopalan@Sun.COM
73*13101SVenki.Rajagopalan@Sun.COM if (eib_rsrc_setup_rxbufs(ss, err) != EIB_E_SUCCESS) {
74*13101SVenki.Rajagopalan@Sun.COM eib_rb_rsrc_setup_lsobufs(ss, B_FALSE);
75*13101SVenki.Rajagopalan@Sun.COM eib_rb_rsrc_setup_txbufs(ss, B_FALSE);
76*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_FAILURE);
77*13101SVenki.Rajagopalan@Sun.COM }
78*13101SVenki.Rajagopalan@Sun.COM
79*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_SUCCESS);
80*13101SVenki.Rajagopalan@Sun.COM }
81*13101SVenki.Rajagopalan@Sun.COM
82*13101SVenki.Rajagopalan@Sun.COM int
eib_rsrc_grab_swqes(eib_t * ss,eib_wqe_t ** wqes,uint_t n_req,uint_t * actual,int pri)83*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_grab_swqes(eib_t *ss, eib_wqe_t **wqes, uint_t n_req, uint_t *actual,
84*13101SVenki.Rajagopalan@Sun.COM int pri)
85*13101SVenki.Rajagopalan@Sun.COM {
86*13101SVenki.Rajagopalan@Sun.COM eib_wqe_t *wqe;
87*13101SVenki.Rajagopalan@Sun.COM uint32_t *encap_hdr;
88*13101SVenki.Rajagopalan@Sun.COM int ret;
89*13101SVenki.Rajagopalan@Sun.COM int i;
90*13101SVenki.Rajagopalan@Sun.COM
91*13101SVenki.Rajagopalan@Sun.COM ASSERT(ss->ei_tx != NULL);
92*13101SVenki.Rajagopalan@Sun.COM
93*13101SVenki.Rajagopalan@Sun.COM ret = eib_rsrc_grab_wqes(ss, ss->ei_tx, wqes, n_req, actual, pri);
94*13101SVenki.Rajagopalan@Sun.COM if (ret != EIB_E_SUCCESS)
95*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_FAILURE);
96*13101SVenki.Rajagopalan@Sun.COM
97*13101SVenki.Rajagopalan@Sun.COM /*
98*13101SVenki.Rajagopalan@Sun.COM * See note for eib_rsrc_grab_swqe()
99*13101SVenki.Rajagopalan@Sun.COM */
100*13101SVenki.Rajagopalan@Sun.COM for (i = 0; i < (*actual); i++) {
101*13101SVenki.Rajagopalan@Sun.COM wqe = wqes[i];
102*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.send.wr_flags = IBT_WR_NO_FLAGS;
103*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.send.wr.ud.udwr_dest = wqe->qe_dest;
104*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.send.wr_opcode = IBT_WRC_SEND;
105*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.send.wr_nds = 1;
106*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.send.wr_sgl = &wqe->qe_sgl;
107*13101SVenki.Rajagopalan@Sun.COM wqe->qe_nxt_post = NULL;
108*13101SVenki.Rajagopalan@Sun.COM wqe->qe_iov_hdl = NULL;
109*13101SVenki.Rajagopalan@Sun.COM
110*13101SVenki.Rajagopalan@Sun.COM encap_hdr = (uint32_t *)(void *)wqe->qe_payload_hdr;
111*13101SVenki.Rajagopalan@Sun.COM *encap_hdr = htonl(EIB_TX_ENCAP_HDR);
112*13101SVenki.Rajagopalan@Sun.COM }
113*13101SVenki.Rajagopalan@Sun.COM
114*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_SUCCESS);
115*13101SVenki.Rajagopalan@Sun.COM }
116*13101SVenki.Rajagopalan@Sun.COM
117*13101SVenki.Rajagopalan@Sun.COM int
eib_rsrc_grab_rwqes(eib_t * ss,eib_wqe_t ** wqes,uint_t n_req,uint_t * actual,int pri)118*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_grab_rwqes(eib_t *ss, eib_wqe_t **wqes, uint_t n_req, uint_t *actual,
119*13101SVenki.Rajagopalan@Sun.COM int pri)
120*13101SVenki.Rajagopalan@Sun.COM {
121*13101SVenki.Rajagopalan@Sun.COM ASSERT(ss->ei_rx != NULL);
122*13101SVenki.Rajagopalan@Sun.COM
123*13101SVenki.Rajagopalan@Sun.COM return (eib_rsrc_grab_wqes(ss, ss->ei_rx, wqes, n_req, actual, pri));
124*13101SVenki.Rajagopalan@Sun.COM }
125*13101SVenki.Rajagopalan@Sun.COM
126*13101SVenki.Rajagopalan@Sun.COM int
eib_rsrc_grab_lsobufs(eib_t * ss,uint_t req_sz,ibt_wr_ds_t * sgl,uint32_t * nds)127*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_grab_lsobufs(eib_t *ss, uint_t req_sz, ibt_wr_ds_t *sgl, uint32_t *nds)
128*13101SVenki.Rajagopalan@Sun.COM {
129*13101SVenki.Rajagopalan@Sun.COM eib_lsobkt_t *bkt = ss->ei_lso;
130*13101SVenki.Rajagopalan@Sun.COM eib_lsobuf_t *elem;
131*13101SVenki.Rajagopalan@Sun.COM eib_lsobuf_t *nxt;
132*13101SVenki.Rajagopalan@Sun.COM uint_t frag_sz;
133*13101SVenki.Rajagopalan@Sun.COM uint_t num_needed;
134*13101SVenki.Rajagopalan@Sun.COM int i;
135*13101SVenki.Rajagopalan@Sun.COM
136*13101SVenki.Rajagopalan@Sun.COM ASSERT(req_sz != 0);
137*13101SVenki.Rajagopalan@Sun.COM ASSERT(sgl != NULL);
138*13101SVenki.Rajagopalan@Sun.COM ASSERT(nds != NULL);
139*13101SVenki.Rajagopalan@Sun.COM
140*13101SVenki.Rajagopalan@Sun.COM /*
141*13101SVenki.Rajagopalan@Sun.COM * Determine how many bufs we'd need for the size requested
142*13101SVenki.Rajagopalan@Sun.COM */
143*13101SVenki.Rajagopalan@Sun.COM num_needed = req_sz / EIB_LSO_BUFSZ;
144*13101SVenki.Rajagopalan@Sun.COM if ((frag_sz = req_sz % EIB_LSO_BUFSZ) != 0)
145*13101SVenki.Rajagopalan@Sun.COM num_needed++;
146*13101SVenki.Rajagopalan@Sun.COM
147*13101SVenki.Rajagopalan@Sun.COM if (bkt == NULL)
148*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_FAILURE);
149*13101SVenki.Rajagopalan@Sun.COM
150*13101SVenki.Rajagopalan@Sun.COM /*
151*13101SVenki.Rajagopalan@Sun.COM * If we don't have enough lso bufs, return failure
152*13101SVenki.Rajagopalan@Sun.COM */
153*13101SVenki.Rajagopalan@Sun.COM mutex_enter(&bkt->bk_lock);
154*13101SVenki.Rajagopalan@Sun.COM if (bkt->bk_nfree < num_needed) {
155*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&bkt->bk_lock);
156*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_FAILURE);
157*13101SVenki.Rajagopalan@Sun.COM }
158*13101SVenki.Rajagopalan@Sun.COM
159*13101SVenki.Rajagopalan@Sun.COM /*
160*13101SVenki.Rajagopalan@Sun.COM * Pick the first "num_needed" bufs from the free list
161*13101SVenki.Rajagopalan@Sun.COM */
162*13101SVenki.Rajagopalan@Sun.COM elem = bkt->bk_free_head;
163*13101SVenki.Rajagopalan@Sun.COM for (i = 0; i < num_needed; i++) {
164*13101SVenki.Rajagopalan@Sun.COM ASSERT(elem->lb_isfree != 0);
165*13101SVenki.Rajagopalan@Sun.COM ASSERT(elem->lb_buf != NULL);
166*13101SVenki.Rajagopalan@Sun.COM
167*13101SVenki.Rajagopalan@Sun.COM nxt = elem->lb_next;
168*13101SVenki.Rajagopalan@Sun.COM
169*13101SVenki.Rajagopalan@Sun.COM sgl[i].ds_va = (ib_vaddr_t)(uintptr_t)elem->lb_buf;
170*13101SVenki.Rajagopalan@Sun.COM sgl[i].ds_key = bkt->bk_lkey;
171*13101SVenki.Rajagopalan@Sun.COM sgl[i].ds_len = EIB_LSO_BUFSZ;
172*13101SVenki.Rajagopalan@Sun.COM
173*13101SVenki.Rajagopalan@Sun.COM elem->lb_isfree = 0;
174*13101SVenki.Rajagopalan@Sun.COM elem->lb_next = NULL;
175*13101SVenki.Rajagopalan@Sun.COM
176*13101SVenki.Rajagopalan@Sun.COM elem = nxt;
177*13101SVenki.Rajagopalan@Sun.COM }
178*13101SVenki.Rajagopalan@Sun.COM bkt->bk_free_head = elem;
179*13101SVenki.Rajagopalan@Sun.COM
180*13101SVenki.Rajagopalan@Sun.COM /*
181*13101SVenki.Rajagopalan@Sun.COM * If the requested size is not a multiple of EIB_LSO_BUFSZ, we need
182*13101SVenki.Rajagopalan@Sun.COM * to adjust the last sgl entry's length. Since we know we need atleast
183*13101SVenki.Rajagopalan@Sun.COM * one, the i-1 use below is ok.
184*13101SVenki.Rajagopalan@Sun.COM */
185*13101SVenki.Rajagopalan@Sun.COM if (frag_sz) {
186*13101SVenki.Rajagopalan@Sun.COM sgl[i-1].ds_len = frag_sz;
187*13101SVenki.Rajagopalan@Sun.COM }
188*13101SVenki.Rajagopalan@Sun.COM
189*13101SVenki.Rajagopalan@Sun.COM /*
190*13101SVenki.Rajagopalan@Sun.COM * Update nfree count and return
191*13101SVenki.Rajagopalan@Sun.COM */
192*13101SVenki.Rajagopalan@Sun.COM bkt->bk_nfree -= num_needed;
193*13101SVenki.Rajagopalan@Sun.COM
194*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&bkt->bk_lock);
195*13101SVenki.Rajagopalan@Sun.COM
196*13101SVenki.Rajagopalan@Sun.COM *nds = num_needed;
197*13101SVenki.Rajagopalan@Sun.COM
198*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_SUCCESS);
199*13101SVenki.Rajagopalan@Sun.COM }
200*13101SVenki.Rajagopalan@Sun.COM
201*13101SVenki.Rajagopalan@Sun.COM eib_wqe_t *
eib_rsrc_grab_swqe(eib_t * ss,int pri)202*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_grab_swqe(eib_t *ss, int pri)
203*13101SVenki.Rajagopalan@Sun.COM {
204*13101SVenki.Rajagopalan@Sun.COM eib_wqe_t *wqe = NULL;
205*13101SVenki.Rajagopalan@Sun.COM uint32_t *encap_hdr;
206*13101SVenki.Rajagopalan@Sun.COM
207*13101SVenki.Rajagopalan@Sun.COM ASSERT(ss->ei_tx != NULL);
208*13101SVenki.Rajagopalan@Sun.COM (void) eib_rsrc_grab_wqes(ss, ss->ei_tx, &wqe, 1, NULL, pri);
209*13101SVenki.Rajagopalan@Sun.COM
210*13101SVenki.Rajagopalan@Sun.COM /*
211*13101SVenki.Rajagopalan@Sun.COM * Let's reset the swqe basic wr parameters to default. We need
212*13101SVenki.Rajagopalan@Sun.COM * to do this because this swqe could've previously been used
213*13101SVenki.Rajagopalan@Sun.COM * for a checksum offload (when the flags would've been set)
214*13101SVenki.Rajagopalan@Sun.COM * or for an LSO send (in which case the opcode would've been set
215*13101SVenki.Rajagopalan@Sun.COM * to a different value), or been iov mapped (in which case the
216*13101SVenki.Rajagopalan@Sun.COM * sgl/nds could've been set to different values). We'll make
217*13101SVenki.Rajagopalan@Sun.COM * it easy and initialize it here, so simple transactions can
218*13101SVenki.Rajagopalan@Sun.COM * go through without any special effort by the caller.
219*13101SVenki.Rajagopalan@Sun.COM *
220*13101SVenki.Rajagopalan@Sun.COM * Note that even though the wqe structure is common for both
221*13101SVenki.Rajagopalan@Sun.COM * send and recv, they're in two independent pools and the wqe
222*13101SVenki.Rajagopalan@Sun.COM * type remains the same throughout its lifetime. So we don't
223*13101SVenki.Rajagopalan@Sun.COM * have to worry about resetting any other field.
224*13101SVenki.Rajagopalan@Sun.COM */
225*13101SVenki.Rajagopalan@Sun.COM if (wqe) {
226*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.send.wr_flags = IBT_WR_NO_FLAGS;
227*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.send.wr.ud.udwr_dest = wqe->qe_dest;
228*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.send.wr_opcode = IBT_WRC_SEND;
229*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.send.wr_nds = 1;
230*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.send.wr_sgl = &wqe->qe_sgl;
231*13101SVenki.Rajagopalan@Sun.COM wqe->qe_nxt_post = NULL;
232*13101SVenki.Rajagopalan@Sun.COM wqe->qe_iov_hdl = NULL;
233*13101SVenki.Rajagopalan@Sun.COM
234*13101SVenki.Rajagopalan@Sun.COM encap_hdr = (uint32_t *)(void *)wqe->qe_payload_hdr;
235*13101SVenki.Rajagopalan@Sun.COM *encap_hdr = htonl(EIB_TX_ENCAP_HDR);
236*13101SVenki.Rajagopalan@Sun.COM }
237*13101SVenki.Rajagopalan@Sun.COM
238*13101SVenki.Rajagopalan@Sun.COM return (wqe);
239*13101SVenki.Rajagopalan@Sun.COM }
240*13101SVenki.Rajagopalan@Sun.COM
241*13101SVenki.Rajagopalan@Sun.COM eib_wqe_t *
eib_rsrc_grab_rwqe(eib_t * ss,int pri)242*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_grab_rwqe(eib_t *ss, int pri)
243*13101SVenki.Rajagopalan@Sun.COM {
244*13101SVenki.Rajagopalan@Sun.COM eib_wqe_t *wqe = NULL;
245*13101SVenki.Rajagopalan@Sun.COM
246*13101SVenki.Rajagopalan@Sun.COM ASSERT(ss->ei_rx != NULL);
247*13101SVenki.Rajagopalan@Sun.COM (void) eib_rsrc_grab_wqes(ss, ss->ei_rx, &wqe, 1, NULL, pri);
248*13101SVenki.Rajagopalan@Sun.COM
249*13101SVenki.Rajagopalan@Sun.COM return (wqe);
250*13101SVenki.Rajagopalan@Sun.COM }
251*13101SVenki.Rajagopalan@Sun.COM
252*13101SVenki.Rajagopalan@Sun.COM void
eib_rsrc_return_swqe(eib_t * ss,eib_wqe_t * wqe,eib_chan_t * chan)253*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_return_swqe(eib_t *ss, eib_wqe_t *wqe, eib_chan_t *chan)
254*13101SVenki.Rajagopalan@Sun.COM {
255*13101SVenki.Rajagopalan@Sun.COM ASSERT(ss->ei_tx != NULL);
256*13101SVenki.Rajagopalan@Sun.COM
257*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_return_wqes(ss, ss->ei_tx, &wqe, 1);
258*13101SVenki.Rajagopalan@Sun.COM if (chan) {
259*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_decr_posted_swqe(ss, chan);
260*13101SVenki.Rajagopalan@Sun.COM }
261*13101SVenki.Rajagopalan@Sun.COM }
262*13101SVenki.Rajagopalan@Sun.COM
263*13101SVenki.Rajagopalan@Sun.COM
264*13101SVenki.Rajagopalan@Sun.COM void
eib_rsrc_return_rwqe(eib_t * ss,eib_wqe_t * wqe,eib_chan_t * chan)265*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_return_rwqe(eib_t *ss, eib_wqe_t *wqe, eib_chan_t *chan)
266*13101SVenki.Rajagopalan@Sun.COM {
267*13101SVenki.Rajagopalan@Sun.COM ASSERT(ss->ei_rx != NULL);
268*13101SVenki.Rajagopalan@Sun.COM
269*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_return_wqes(ss, ss->ei_rx, &wqe, 1);
270*13101SVenki.Rajagopalan@Sun.COM if (chan) {
271*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_decr_posted_rwqe(ss, chan);
272*13101SVenki.Rajagopalan@Sun.COM }
273*13101SVenki.Rajagopalan@Sun.COM }
274*13101SVenki.Rajagopalan@Sun.COM
275*13101SVenki.Rajagopalan@Sun.COM void
eib_rsrc_return_lsobufs(eib_t * ss,ibt_wr_ds_t * sgl_p,uint32_t nds)276*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_return_lsobufs(eib_t *ss, ibt_wr_ds_t *sgl_p, uint32_t nds)
277*13101SVenki.Rajagopalan@Sun.COM {
278*13101SVenki.Rajagopalan@Sun.COM eib_lsobkt_t *bkt = ss->ei_lso;
279*13101SVenki.Rajagopalan@Sun.COM eib_lsobuf_t *elem;
280*13101SVenki.Rajagopalan@Sun.COM uint8_t *va;
281*13101SVenki.Rajagopalan@Sun.COM ptrdiff_t ndx;
282*13101SVenki.Rajagopalan@Sun.COM int i;
283*13101SVenki.Rajagopalan@Sun.COM
284*13101SVenki.Rajagopalan@Sun.COM /*
285*13101SVenki.Rajagopalan@Sun.COM * Nowhere to return the buffers to ??
286*13101SVenki.Rajagopalan@Sun.COM */
287*13101SVenki.Rajagopalan@Sun.COM if (bkt == NULL)
288*13101SVenki.Rajagopalan@Sun.COM return;
289*13101SVenki.Rajagopalan@Sun.COM
290*13101SVenki.Rajagopalan@Sun.COM mutex_enter(&bkt->bk_lock);
291*13101SVenki.Rajagopalan@Sun.COM
292*13101SVenki.Rajagopalan@Sun.COM for (i = 0; i < nds; i++) {
293*13101SVenki.Rajagopalan@Sun.COM va = (uint8_t *)(uintptr_t)sgl_p[i].ds_va;
294*13101SVenki.Rajagopalan@Sun.COM
295*13101SVenki.Rajagopalan@Sun.COM ASSERT(va >= bkt->bk_mem);
296*13101SVenki.Rajagopalan@Sun.COM ASSERT(va < (bkt->bk_mem + bkt->bk_nelem * EIB_LSO_BUFSZ));
297*13101SVenki.Rajagopalan@Sun.COM
298*13101SVenki.Rajagopalan@Sun.COM /*
299*13101SVenki.Rajagopalan@Sun.COM * Figure out the buflist element this sgl buffer corresponds
300*13101SVenki.Rajagopalan@Sun.COM * to and put it back at the head
301*13101SVenki.Rajagopalan@Sun.COM */
302*13101SVenki.Rajagopalan@Sun.COM ndx = ((uintptr_t)va - (uintptr_t)bkt->bk_mem) / EIB_LSO_BUFSZ;
303*13101SVenki.Rajagopalan@Sun.COM elem = bkt->bk_bufl + ndx;
304*13101SVenki.Rajagopalan@Sun.COM
305*13101SVenki.Rajagopalan@Sun.COM ASSERT(elem->lb_isfree == 0);
306*13101SVenki.Rajagopalan@Sun.COM ASSERT(elem->lb_buf == va);
307*13101SVenki.Rajagopalan@Sun.COM
308*13101SVenki.Rajagopalan@Sun.COM elem->lb_isfree = 1;
309*13101SVenki.Rajagopalan@Sun.COM elem->lb_next = bkt->bk_free_head;
310*13101SVenki.Rajagopalan@Sun.COM bkt->bk_free_head = elem;
311*13101SVenki.Rajagopalan@Sun.COM }
312*13101SVenki.Rajagopalan@Sun.COM bkt->bk_nfree += nds;
313*13101SVenki.Rajagopalan@Sun.COM
314*13101SVenki.Rajagopalan@Sun.COM /*
315*13101SVenki.Rajagopalan@Sun.COM * If the number of available lso buffers just crossed the
316*13101SVenki.Rajagopalan@Sun.COM * threshold, wakeup anyone who may be sleeping on the event.
317*13101SVenki.Rajagopalan@Sun.COM */
318*13101SVenki.Rajagopalan@Sun.COM if (((bkt->bk_nfree - nds) < EIB_LSO_FREE_BUFS_THRESH) &&
319*13101SVenki.Rajagopalan@Sun.COM (bkt->bk_nfree >= EIB_LSO_FREE_BUFS_THRESH)) {
320*13101SVenki.Rajagopalan@Sun.COM cv_broadcast(&bkt->bk_cv);
321*13101SVenki.Rajagopalan@Sun.COM }
322*13101SVenki.Rajagopalan@Sun.COM
323*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&bkt->bk_lock);
324*13101SVenki.Rajagopalan@Sun.COM }
325*13101SVenki.Rajagopalan@Sun.COM
326*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
327*13101SVenki.Rajagopalan@Sun.COM void
eib_rsrc_decr_posted_swqe(eib_t * ss,eib_chan_t * chan)328*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_decr_posted_swqe(eib_t *ss, eib_chan_t *chan)
329*13101SVenki.Rajagopalan@Sun.COM {
330*13101SVenki.Rajagopalan@Sun.COM ASSERT(chan != NULL);
331*13101SVenki.Rajagopalan@Sun.COM
332*13101SVenki.Rajagopalan@Sun.COM mutex_enter(&chan->ch_tx_lock);
333*13101SVenki.Rajagopalan@Sun.COM
334*13101SVenki.Rajagopalan@Sun.COM chan->ch_tx_posted--;
335*13101SVenki.Rajagopalan@Sun.COM if ((chan->ch_tear_down) && (chan->ch_tx_posted == 0)) {
336*13101SVenki.Rajagopalan@Sun.COM cv_signal(&chan->ch_tx_cv);
337*13101SVenki.Rajagopalan@Sun.COM }
338*13101SVenki.Rajagopalan@Sun.COM
339*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&chan->ch_tx_lock);
340*13101SVenki.Rajagopalan@Sun.COM }
341*13101SVenki.Rajagopalan@Sun.COM
342*13101SVenki.Rajagopalan@Sun.COM void
eib_rsrc_decr_posted_rwqe(eib_t * ss,eib_chan_t * chan)343*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_decr_posted_rwqe(eib_t *ss, eib_chan_t *chan)
344*13101SVenki.Rajagopalan@Sun.COM {
345*13101SVenki.Rajagopalan@Sun.COM eib_chan_t *tail;
346*13101SVenki.Rajagopalan@Sun.COM boolean_t queue_for_refill = B_FALSE;
347*13101SVenki.Rajagopalan@Sun.COM
348*13101SVenki.Rajagopalan@Sun.COM ASSERT(chan != NULL);
349*13101SVenki.Rajagopalan@Sun.COM
350*13101SVenki.Rajagopalan@Sun.COM /*
351*13101SVenki.Rajagopalan@Sun.COM * Decrement the ch_rx_posted count. If we are tearing this channel
352*13101SVenki.Rajagopalan@Sun.COM * down, signal the waiter when the count reaches 0. If we aren't
353*13101SVenki.Rajagopalan@Sun.COM * tearing the channel down, see if the count has gone below the low
354*13101SVenki.Rajagopalan@Sun.COM * water mark. If it has, and if this channel isn't already being
355*13101SVenki.Rajagopalan@Sun.COM * refilled, queue the channel up with the service thread for a
356*13101SVenki.Rajagopalan@Sun.COM * rwqe refill.
357*13101SVenki.Rajagopalan@Sun.COM */
358*13101SVenki.Rajagopalan@Sun.COM mutex_enter(&chan->ch_rx_lock);
359*13101SVenki.Rajagopalan@Sun.COM chan->ch_rx_posted--;
360*13101SVenki.Rajagopalan@Sun.COM if (chan->ch_tear_down) {
361*13101SVenki.Rajagopalan@Sun.COM if (chan->ch_rx_posted == 0)
362*13101SVenki.Rajagopalan@Sun.COM cv_signal(&chan->ch_rx_cv);
363*13101SVenki.Rajagopalan@Sun.COM } else if (chan->ch_rx_posted < chan->ch_lwm_rwqes) {
364*13101SVenki.Rajagopalan@Sun.COM if (chan->ch_rx_refilling == B_FALSE) {
365*13101SVenki.Rajagopalan@Sun.COM chan->ch_rx_refilling = B_TRUE;
366*13101SVenki.Rajagopalan@Sun.COM queue_for_refill = B_TRUE;
367*13101SVenki.Rajagopalan@Sun.COM }
368*13101SVenki.Rajagopalan@Sun.COM }
369*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&chan->ch_rx_lock);
370*13101SVenki.Rajagopalan@Sun.COM
371*13101SVenki.Rajagopalan@Sun.COM if (queue_for_refill) {
372*13101SVenki.Rajagopalan@Sun.COM mutex_enter(&ss->ei_rxpost_lock);
373*13101SVenki.Rajagopalan@Sun.COM
374*13101SVenki.Rajagopalan@Sun.COM chan->ch_rxpost_next = NULL;
375*13101SVenki.Rajagopalan@Sun.COM for (tail = ss->ei_rxpost; tail; tail = tail->ch_rxpost_next) {
376*13101SVenki.Rajagopalan@Sun.COM if (tail->ch_rxpost_next == NULL)
377*13101SVenki.Rajagopalan@Sun.COM break;
378*13101SVenki.Rajagopalan@Sun.COM }
379*13101SVenki.Rajagopalan@Sun.COM if (tail) {
380*13101SVenki.Rajagopalan@Sun.COM tail->ch_rxpost_next = chan;
381*13101SVenki.Rajagopalan@Sun.COM } else {
382*13101SVenki.Rajagopalan@Sun.COM ss->ei_rxpost = chan;
383*13101SVenki.Rajagopalan@Sun.COM }
384*13101SVenki.Rajagopalan@Sun.COM
385*13101SVenki.Rajagopalan@Sun.COM cv_signal(&ss->ei_rxpost_cv);
386*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&ss->ei_rxpost_lock);
387*13101SVenki.Rajagopalan@Sun.COM }
388*13101SVenki.Rajagopalan@Sun.COM }
389*13101SVenki.Rajagopalan@Sun.COM
390*13101SVenki.Rajagopalan@Sun.COM void
eib_rsrc_txwqes_needed(eib_t * ss)391*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_txwqes_needed(eib_t *ss)
392*13101SVenki.Rajagopalan@Sun.COM {
393*13101SVenki.Rajagopalan@Sun.COM eib_wqe_pool_t *wp = ss->ei_tx;
394*13101SVenki.Rajagopalan@Sun.COM
395*13101SVenki.Rajagopalan@Sun.COM EIB_INCR_COUNTER(&ss->ei_stats->st_noxmitbuf);
396*13101SVenki.Rajagopalan@Sun.COM
397*13101SVenki.Rajagopalan@Sun.COM mutex_enter(&wp->wp_lock);
398*13101SVenki.Rajagopalan@Sun.COM if ((wp->wp_status & EIB_TXWQE_SHORT) == 0) {
399*13101SVenki.Rajagopalan@Sun.COM wp->wp_status |= EIB_TXWQE_SHORT;
400*13101SVenki.Rajagopalan@Sun.COM cv_broadcast(&wp->wp_cv);
401*13101SVenki.Rajagopalan@Sun.COM }
402*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&wp->wp_lock);
403*13101SVenki.Rajagopalan@Sun.COM }
404*13101SVenki.Rajagopalan@Sun.COM
405*13101SVenki.Rajagopalan@Sun.COM void
eib_rsrc_lsobufs_needed(eib_t * ss)406*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_lsobufs_needed(eib_t *ss)
407*13101SVenki.Rajagopalan@Sun.COM {
408*13101SVenki.Rajagopalan@Sun.COM eib_lsobkt_t *bkt = ss->ei_lso;
409*13101SVenki.Rajagopalan@Sun.COM
410*13101SVenki.Rajagopalan@Sun.COM EIB_INCR_COUNTER(&ss->ei_stats->st_noxmitbuf);
411*13101SVenki.Rajagopalan@Sun.COM
412*13101SVenki.Rajagopalan@Sun.COM if (bkt == NULL) {
413*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_WARN(ss->ei_instance,
414*13101SVenki.Rajagopalan@Sun.COM "eib_rsrc_lsobufs_needed: "
415*13101SVenki.Rajagopalan@Sun.COM "lso bufs seem to be needed even though "
416*13101SVenki.Rajagopalan@Sun.COM "LSO support was not advertised");
417*13101SVenki.Rajagopalan@Sun.COM return;
418*13101SVenki.Rajagopalan@Sun.COM }
419*13101SVenki.Rajagopalan@Sun.COM
420*13101SVenki.Rajagopalan@Sun.COM mutex_enter(&bkt->bk_lock);
421*13101SVenki.Rajagopalan@Sun.COM if ((bkt->bk_status & EIB_LBUF_SHORT) == 0) {
422*13101SVenki.Rajagopalan@Sun.COM bkt->bk_status |= EIB_LBUF_SHORT;
423*13101SVenki.Rajagopalan@Sun.COM cv_broadcast(&bkt->bk_cv);
424*13101SVenki.Rajagopalan@Sun.COM }
425*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&bkt->bk_lock);
426*13101SVenki.Rajagopalan@Sun.COM }
427*13101SVenki.Rajagopalan@Sun.COM
428*13101SVenki.Rajagopalan@Sun.COM boolean_t
eib_rsrc_rxpool_low(eib_wqe_t * wqe)429*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_rxpool_low(eib_wqe_t *wqe)
430*13101SVenki.Rajagopalan@Sun.COM {
431*13101SVenki.Rajagopalan@Sun.COM eib_wqe_pool_t *wp = wqe->qe_pool;
432*13101SVenki.Rajagopalan@Sun.COM boolean_t ret = B_FALSE;
433*13101SVenki.Rajagopalan@Sun.COM
434*13101SVenki.Rajagopalan@Sun.COM /*
435*13101SVenki.Rajagopalan@Sun.COM * Set the EIB_RXWQE_SHORT flag when the number of free wqes
436*13101SVenki.Rajagopalan@Sun.COM * in the rx pool falls below the low threshold for rwqes and
437*13101SVenki.Rajagopalan@Sun.COM * clear it only when the number of free wqes gets back above
438*13101SVenki.Rajagopalan@Sun.COM * the high water mark.
439*13101SVenki.Rajagopalan@Sun.COM */
440*13101SVenki.Rajagopalan@Sun.COM mutex_enter(&wp->wp_lock);
441*13101SVenki.Rajagopalan@Sun.COM
442*13101SVenki.Rajagopalan@Sun.COM if (wp->wp_nfree <= EIB_NFREE_RWQES_LOW) {
443*13101SVenki.Rajagopalan@Sun.COM wp->wp_status |= (EIB_RXWQE_SHORT);
444*13101SVenki.Rajagopalan@Sun.COM } else if (wp->wp_nfree >= EIB_NFREE_RWQES_HWM) {
445*13101SVenki.Rajagopalan@Sun.COM wp->wp_status &= (~EIB_RXWQE_SHORT);
446*13101SVenki.Rajagopalan@Sun.COM }
447*13101SVenki.Rajagopalan@Sun.COM
448*13101SVenki.Rajagopalan@Sun.COM if ((wp->wp_status & EIB_RXWQE_SHORT) == EIB_RXWQE_SHORT)
449*13101SVenki.Rajagopalan@Sun.COM ret = B_TRUE;
450*13101SVenki.Rajagopalan@Sun.COM
451*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&wp->wp_lock);
452*13101SVenki.Rajagopalan@Sun.COM
453*13101SVenki.Rajagopalan@Sun.COM return (ret);
454*13101SVenki.Rajagopalan@Sun.COM }
455*13101SVenki.Rajagopalan@Sun.COM
456*13101SVenki.Rajagopalan@Sun.COM void
eib_rb_rsrc_setup_bufs(eib_t * ss,boolean_t force)457*13101SVenki.Rajagopalan@Sun.COM eib_rb_rsrc_setup_bufs(eib_t *ss, boolean_t force)
458*13101SVenki.Rajagopalan@Sun.COM {
459*13101SVenki.Rajagopalan@Sun.COM eib_rb_rsrc_setup_rxbufs(ss, force);
460*13101SVenki.Rajagopalan@Sun.COM eib_rb_rsrc_setup_lsobufs(ss, force);
461*13101SVenki.Rajagopalan@Sun.COM eib_rb_rsrc_setup_txbufs(ss, force);
462*13101SVenki.Rajagopalan@Sun.COM }
463*13101SVenki.Rajagopalan@Sun.COM
464*13101SVenki.Rajagopalan@Sun.COM static int
eib_rsrc_setup_txbufs(eib_t * ss,int * err)465*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_setup_txbufs(eib_t *ss, int *err)
466*13101SVenki.Rajagopalan@Sun.COM {
467*13101SVenki.Rajagopalan@Sun.COM eib_wqe_pool_t *tx;
468*13101SVenki.Rajagopalan@Sun.COM eib_wqe_t *wqe;
469*13101SVenki.Rajagopalan@Sun.COM ibt_ud_dest_hdl_t dest;
470*13101SVenki.Rajagopalan@Sun.COM ibt_mr_attr_t attr;
471*13101SVenki.Rajagopalan@Sun.COM ibt_mr_desc_t desc;
472*13101SVenki.Rajagopalan@Sun.COM ibt_status_t ret;
473*13101SVenki.Rajagopalan@Sun.COM kthread_t *kt;
474*13101SVenki.Rajagopalan@Sun.COM uint32_t *encap_hdr;
475*13101SVenki.Rajagopalan@Sun.COM uint8_t *buf;
476*13101SVenki.Rajagopalan@Sun.COM uint_t mtu = ss->ei_props->ep_mtu;
477*13101SVenki.Rajagopalan@Sun.COM uint_t tx_bufsz;
478*13101SVenki.Rajagopalan@Sun.COM uint_t blk;
479*13101SVenki.Rajagopalan@Sun.COM uint_t ndx;
480*13101SVenki.Rajagopalan@Sun.COM uint_t i;
481*13101SVenki.Rajagopalan@Sun.COM int lso_enabled;
482*13101SVenki.Rajagopalan@Sun.COM
483*13101SVenki.Rajagopalan@Sun.COM /*
484*13101SVenki.Rajagopalan@Sun.COM * Try to allocate and initialize the tx wqe pool
485*13101SVenki.Rajagopalan@Sun.COM */
486*13101SVenki.Rajagopalan@Sun.COM if (ss->ei_tx != NULL)
487*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_SUCCESS);
488*13101SVenki.Rajagopalan@Sun.COM
489*13101SVenki.Rajagopalan@Sun.COM /*
490*13101SVenki.Rajagopalan@Sun.COM * If we keep the tx buffers as mtu-sized, then potentially every
491*13101SVenki.Rajagopalan@Sun.COM * LSO request that cannot be satisfactorily mapped, will use up
492*13101SVenki.Rajagopalan@Sun.COM * the 8K large (default size) lso buffers. This may be inadvisable
493*13101SVenki.Rajagopalan@Sun.COM * given that lso buffers are a scarce resource. Instead, we'll
494*13101SVenki.Rajagopalan@Sun.COM * slightly raise the size of the copy buffers in the send wqes
495*13101SVenki.Rajagopalan@Sun.COM * (say to EIB_TX_COPY_THRESH) so that requests that cannot be
496*13101SVenki.Rajagopalan@Sun.COM * mapped could still avoid using the 8K LSO buffers if they're
497*13101SVenki.Rajagopalan@Sun.COM * less than the copy threshold size.
498*13101SVenki.Rajagopalan@Sun.COM */
499*13101SVenki.Rajagopalan@Sun.COM lso_enabled = ss->ei_caps->cp_lso_maxlen &&
500*13101SVenki.Rajagopalan@Sun.COM ss->ei_caps->cp_cksum_flags && ss->ei_caps->cp_resv_lkey_capab;
501*13101SVenki.Rajagopalan@Sun.COM tx_bufsz = ((lso_enabled) && (EIB_TX_COPY_THRESH > mtu)) ?
502*13101SVenki.Rajagopalan@Sun.COM EIB_TX_COPY_THRESH : mtu;
503*13101SVenki.Rajagopalan@Sun.COM
504*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_init_wqe_pool(ss, &ss->ei_tx, tx_bufsz, EIB_WP_TYPE_TX);
505*13101SVenki.Rajagopalan@Sun.COM tx = ss->ei_tx;
506*13101SVenki.Rajagopalan@Sun.COM
507*13101SVenki.Rajagopalan@Sun.COM /*
508*13101SVenki.Rajagopalan@Sun.COM * Register the TX memory region with IBTF for use
509*13101SVenki.Rajagopalan@Sun.COM */
510*13101SVenki.Rajagopalan@Sun.COM attr.mr_vaddr = tx->wp_vaddr;
511*13101SVenki.Rajagopalan@Sun.COM attr.mr_len = tx->wp_memsz;
512*13101SVenki.Rajagopalan@Sun.COM attr.mr_as = NULL;
513*13101SVenki.Rajagopalan@Sun.COM attr.mr_flags = IBT_MR_SLEEP;
514*13101SVenki.Rajagopalan@Sun.COM
515*13101SVenki.Rajagopalan@Sun.COM ret = ibt_register_mr(ss->ei_hca_hdl, ss->ei_pd_hdl, &attr,
516*13101SVenki.Rajagopalan@Sun.COM &tx->wp_mr, &desc);
517*13101SVenki.Rajagopalan@Sun.COM if (ret != IBT_SUCCESS) {
518*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_rsrc_setup_txbufs: "
519*13101SVenki.Rajagopalan@Sun.COM "ibt_register_mr() failed for tx "
520*13101SVenki.Rajagopalan@Sun.COM "region (0x%llx, 0x%llx) with ret=%d",
521*13101SVenki.Rajagopalan@Sun.COM attr.mr_vaddr, attr.mr_len, ret);
522*13101SVenki.Rajagopalan@Sun.COM
523*13101SVenki.Rajagopalan@Sun.COM *err = EINVAL;
524*13101SVenki.Rajagopalan@Sun.COM goto rsrc_setup_txbufs_fail;
525*13101SVenki.Rajagopalan@Sun.COM }
526*13101SVenki.Rajagopalan@Sun.COM tx->wp_lkey = desc.md_lkey;
527*13101SVenki.Rajagopalan@Sun.COM
528*13101SVenki.Rajagopalan@Sun.COM /*
529*13101SVenki.Rajagopalan@Sun.COM * Now setup the tx wqes
530*13101SVenki.Rajagopalan@Sun.COM */
531*13101SVenki.Rajagopalan@Sun.COM buf = (uint8_t *)(uintptr_t)(tx->wp_vaddr);
532*13101SVenki.Rajagopalan@Sun.COM for (i = 0, blk = 0; blk < EIB_BLKS_PER_POOL; blk++) {
533*13101SVenki.Rajagopalan@Sun.COM for (ndx = 0; ndx < EIB_WQES_PER_BLK; ndx++, i++) {
534*13101SVenki.Rajagopalan@Sun.COM wqe = &tx->wp_wqe[i];
535*13101SVenki.Rajagopalan@Sun.COM /*
536*13101SVenki.Rajagopalan@Sun.COM * Allocate a UD destination handle
537*13101SVenki.Rajagopalan@Sun.COM */
538*13101SVenki.Rajagopalan@Sun.COM ret = ibt_alloc_ud_dest(ss->ei_hca_hdl,
539*13101SVenki.Rajagopalan@Sun.COM IBT_UD_DEST_NO_FLAGS, ss->ei_pd_hdl, &dest);
540*13101SVenki.Rajagopalan@Sun.COM if (ret != IBT_SUCCESS) {
541*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance,
542*13101SVenki.Rajagopalan@Sun.COM "eib_rsrc_setup_txbufs: "
543*13101SVenki.Rajagopalan@Sun.COM "ibt_alloc_ud_dest(hca_hdl=0x%llx) "
544*13101SVenki.Rajagopalan@Sun.COM "failed, ret=%d", ss->ei_hca_hdl, ret);
545*13101SVenki.Rajagopalan@Sun.COM
546*13101SVenki.Rajagopalan@Sun.COM *err = ENOMEM;
547*13101SVenki.Rajagopalan@Sun.COM goto rsrc_setup_txbufs_fail;
548*13101SVenki.Rajagopalan@Sun.COM }
549*13101SVenki.Rajagopalan@Sun.COM
550*13101SVenki.Rajagopalan@Sun.COM /*
551*13101SVenki.Rajagopalan@Sun.COM * These parameters should remain fixed throughout the
552*13101SVenki.Rajagopalan@Sun.COM * lifetime of this wqe.
553*13101SVenki.Rajagopalan@Sun.COM */
554*13101SVenki.Rajagopalan@Sun.COM wqe->qe_pool = tx;
555*13101SVenki.Rajagopalan@Sun.COM wqe->qe_cpbuf = buf;
556*13101SVenki.Rajagopalan@Sun.COM wqe->qe_bufsz = tx_bufsz;
557*13101SVenki.Rajagopalan@Sun.COM
558*13101SVenki.Rajagopalan@Sun.COM /*
559*13101SVenki.Rajagopalan@Sun.COM * The qe_dest and qe_payload_hdr are specific to tx
560*13101SVenki.Rajagopalan@Sun.COM * only, but remain unchanged throughout the lifetime
561*13101SVenki.Rajagopalan@Sun.COM * of the wqe.
562*13101SVenki.Rajagopalan@Sun.COM *
563*13101SVenki.Rajagopalan@Sun.COM * The payload header is normally used when we have an
564*13101SVenki.Rajagopalan@Sun.COM * LSO packet to send. Since the EoIB encapsulation
565*13101SVenki.Rajagopalan@Sun.COM * header won't be part of the message we get from the
566*13101SVenki.Rajagopalan@Sun.COM * network layer, we'll need to copy the lso header into
567*13101SVenki.Rajagopalan@Sun.COM * a new buffer every time before we hand over the LSO
568*13101SVenki.Rajagopalan@Sun.COM * send request to the hca driver.
569*13101SVenki.Rajagopalan@Sun.COM */
570*13101SVenki.Rajagopalan@Sun.COM wqe->qe_dest = dest;
571*13101SVenki.Rajagopalan@Sun.COM wqe->qe_payload_hdr =
572*13101SVenki.Rajagopalan@Sun.COM kmem_zalloc(EIB_MAX_PAYLOAD_HDR_SZ, KM_SLEEP);
573*13101SVenki.Rajagopalan@Sun.COM
574*13101SVenki.Rajagopalan@Sun.COM /*
575*13101SVenki.Rajagopalan@Sun.COM * The encapsulation header is at the start of the
576*13101SVenki.Rajagopalan@Sun.COM * payload header and is initialized to the default
577*13101SVenki.Rajagopalan@Sun.COM * encapsulation header we use (no multiple segments,
578*13101SVenki.Rajagopalan@Sun.COM * no FCS). This part of the header is not expected
579*13101SVenki.Rajagopalan@Sun.COM * to change.
580*13101SVenki.Rajagopalan@Sun.COM */
581*13101SVenki.Rajagopalan@Sun.COM encap_hdr = (uint32_t *)(void *)wqe->qe_payload_hdr;
582*13101SVenki.Rajagopalan@Sun.COM *encap_hdr = htonl(EIB_TX_ENCAP_HDR);
583*13101SVenki.Rajagopalan@Sun.COM
584*13101SVenki.Rajagopalan@Sun.COM /*
585*13101SVenki.Rajagopalan@Sun.COM * The parameter set below are used in tx and rx paths.
586*13101SVenki.Rajagopalan@Sun.COM * These parameters (except ds_key) are reset to these
587*13101SVenki.Rajagopalan@Sun.COM * default values in eib_rsrc_return_wqes().
588*13101SVenki.Rajagopalan@Sun.COM */
589*13101SVenki.Rajagopalan@Sun.COM wqe->qe_sgl.ds_key = tx->wp_lkey;
590*13101SVenki.Rajagopalan@Sun.COM wqe->qe_sgl.ds_va = (ib_vaddr_t)(uintptr_t)buf;
591*13101SVenki.Rajagopalan@Sun.COM wqe->qe_sgl.ds_len = wqe->qe_bufsz;
592*13101SVenki.Rajagopalan@Sun.COM wqe->qe_mp = NULL;
593*13101SVenki.Rajagopalan@Sun.COM wqe->qe_info =
594*13101SVenki.Rajagopalan@Sun.COM ((blk & EIB_WQEBLK_MASK) << EIB_WQEBLK_SHIFT) |
595*13101SVenki.Rajagopalan@Sun.COM ((ndx & EIB_WQENDX_MASK) << EIB_WQENDX_SHIFT) |
596*13101SVenki.Rajagopalan@Sun.COM ((uint_t)EIB_WQE_TX << EIB_WQETYP_SHIFT);
597*13101SVenki.Rajagopalan@Sun.COM
598*13101SVenki.Rajagopalan@Sun.COM /*
599*13101SVenki.Rajagopalan@Sun.COM * These tx-specific parameters (except wr_id and
600*13101SVenki.Rajagopalan@Sun.COM * wr_trans) are reset in eib_rsrc_grab_swqes() to make
601*13101SVenki.Rajagopalan@Sun.COM * sure any freshly acquired swqe from the pool has
602*13101SVenki.Rajagopalan@Sun.COM * these default settings for the caller.
603*13101SVenki.Rajagopalan@Sun.COM */
604*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.send.wr_id = (ibt_wrid_t)(uintptr_t)wqe;
605*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.send.wr_trans = IBT_UD_SRV;
606*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.send.wr_flags = IBT_WR_NO_FLAGS;
607*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.send.wr.ud.udwr_dest = wqe->qe_dest;
608*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.send.wr_opcode = IBT_WRC_SEND;
609*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.send.wr_nds = 1;
610*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.send.wr_sgl = &wqe->qe_sgl;
611*13101SVenki.Rajagopalan@Sun.COM wqe->qe_nxt_post = NULL;
612*13101SVenki.Rajagopalan@Sun.COM wqe->qe_iov_hdl = NULL;
613*13101SVenki.Rajagopalan@Sun.COM
614*13101SVenki.Rajagopalan@Sun.COM buf += wqe->qe_bufsz;
615*13101SVenki.Rajagopalan@Sun.COM }
616*13101SVenki.Rajagopalan@Sun.COM }
617*13101SVenki.Rajagopalan@Sun.COM
618*13101SVenki.Rajagopalan@Sun.COM /*
619*13101SVenki.Rajagopalan@Sun.COM * Before returning, create a kernel thread to monitor the status
620*13101SVenki.Rajagopalan@Sun.COM * of wqes in the tx wqe pool. Note that this thread cannot be
621*13101SVenki.Rajagopalan@Sun.COM * created from eib_state_init() during attach(), since the thread
622*13101SVenki.Rajagopalan@Sun.COM * expects the wqe pool to be allocated and ready when it starts,
623*13101SVenki.Rajagopalan@Sun.COM * and the tx bufs initialization only happens during eib_m_start().
624*13101SVenki.Rajagopalan@Sun.COM */
625*13101SVenki.Rajagopalan@Sun.COM kt = thread_create(NULL, 0, eib_monitor_tx_wqes, ss, 0,
626*13101SVenki.Rajagopalan@Sun.COM &p0, TS_RUN, minclsyspri);
627*13101SVenki.Rajagopalan@Sun.COM ss->ei_txwqe_monitor = kt->t_did;
628*13101SVenki.Rajagopalan@Sun.COM
629*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_SUCCESS);
630*13101SVenki.Rajagopalan@Sun.COM
631*13101SVenki.Rajagopalan@Sun.COM rsrc_setup_txbufs_fail:
632*13101SVenki.Rajagopalan@Sun.COM eib_rb_rsrc_setup_txbufs(ss, B_FALSE);
633*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_FAILURE);
634*13101SVenki.Rajagopalan@Sun.COM }
635*13101SVenki.Rajagopalan@Sun.COM
636*13101SVenki.Rajagopalan@Sun.COM static int
eib_rsrc_setup_rxbufs(eib_t * ss,int * err)637*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_setup_rxbufs(eib_t *ss, int *err)
638*13101SVenki.Rajagopalan@Sun.COM {
639*13101SVenki.Rajagopalan@Sun.COM eib_wqe_pool_t *rx;
640*13101SVenki.Rajagopalan@Sun.COM eib_wqe_t *wqe;
641*13101SVenki.Rajagopalan@Sun.COM ibt_mr_attr_t attr;
642*13101SVenki.Rajagopalan@Sun.COM ibt_mr_desc_t desc;
643*13101SVenki.Rajagopalan@Sun.COM ibt_status_t ret;
644*13101SVenki.Rajagopalan@Sun.COM uint8_t *buf;
645*13101SVenki.Rajagopalan@Sun.COM uint_t mtu = ss->ei_props->ep_mtu;
646*13101SVenki.Rajagopalan@Sun.COM uint_t blk;
647*13101SVenki.Rajagopalan@Sun.COM uint_t ndx;
648*13101SVenki.Rajagopalan@Sun.COM uint_t i;
649*13101SVenki.Rajagopalan@Sun.COM
650*13101SVenki.Rajagopalan@Sun.COM /*
651*13101SVenki.Rajagopalan@Sun.COM * Try to allocate and initialize the wqe pool. When this is called
652*13101SVenki.Rajagopalan@Sun.COM * during a plumb via the mac m_start callback, we need to make
653*13101SVenki.Rajagopalan@Sun.COM * sure there is a need to allocate a wqe pool afresh. If during a
654*13101SVenki.Rajagopalan@Sun.COM * previous unplumb we didn't free the wqe pool because the nw layer
655*13101SVenki.Rajagopalan@Sun.COM * was holding on to some rx buffers, we don't need to allocate new
656*13101SVenki.Rajagopalan@Sun.COM * pool and set up the buffers again; we'll just start re-using the
657*13101SVenki.Rajagopalan@Sun.COM * previous one.
658*13101SVenki.Rajagopalan@Sun.COM */
659*13101SVenki.Rajagopalan@Sun.COM if (ss->ei_rx != NULL)
660*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_SUCCESS);
661*13101SVenki.Rajagopalan@Sun.COM
662*13101SVenki.Rajagopalan@Sun.COM /*
663*13101SVenki.Rajagopalan@Sun.COM * The receive buffer has to work for all channels, specifically the
664*13101SVenki.Rajagopalan@Sun.COM * data qp of the vnics. This means that the buffer must be large
665*13101SVenki.Rajagopalan@Sun.COM * enough to hold MTU sized IB payload (including the EoIB and ethernet
666*13101SVenki.Rajagopalan@Sun.COM * headers) plus the GRH. In addition, because the ethernet header is
667*13101SVenki.Rajagopalan@Sun.COM * either 14 or 18 bytes (tagless or vlan tagged), we should have the
668*13101SVenki.Rajagopalan@Sun.COM * buffer filled in such a way that the IP header starts at atleast a
669*13101SVenki.Rajagopalan@Sun.COM * 4-byte aligned address. In order to do this, we need to have some
670*13101SVenki.Rajagopalan@Sun.COM * additional room.
671*13101SVenki.Rajagopalan@Sun.COM */
672*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_init_wqe_pool(ss, &ss->ei_rx,
673*13101SVenki.Rajagopalan@Sun.COM mtu + EIB_GRH_SZ + EIB_IPHDR_ALIGN_ROOM, EIB_WP_TYPE_RX);
674*13101SVenki.Rajagopalan@Sun.COM rx = ss->ei_rx;
675*13101SVenki.Rajagopalan@Sun.COM
676*13101SVenki.Rajagopalan@Sun.COM /*
677*13101SVenki.Rajagopalan@Sun.COM * Register the RX memory region with IBTF for use
678*13101SVenki.Rajagopalan@Sun.COM */
679*13101SVenki.Rajagopalan@Sun.COM attr.mr_vaddr = rx->wp_vaddr;
680*13101SVenki.Rajagopalan@Sun.COM attr.mr_len = rx->wp_memsz;
681*13101SVenki.Rajagopalan@Sun.COM attr.mr_as = NULL;
682*13101SVenki.Rajagopalan@Sun.COM attr.mr_flags = IBT_MR_SLEEP | IBT_MR_ENABLE_LOCAL_WRITE;
683*13101SVenki.Rajagopalan@Sun.COM
684*13101SVenki.Rajagopalan@Sun.COM ret = ibt_register_mr(ss->ei_hca_hdl, ss->ei_pd_hdl, &attr,
685*13101SVenki.Rajagopalan@Sun.COM &rx->wp_mr, &desc);
686*13101SVenki.Rajagopalan@Sun.COM if (ret != IBT_SUCCESS) {
687*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_rsrc_setup_rxbufs: "
688*13101SVenki.Rajagopalan@Sun.COM "ibt_register_mr() failed for rx "
689*13101SVenki.Rajagopalan@Sun.COM "region (0x%llx, 0x%llx) with ret=%d",
690*13101SVenki.Rajagopalan@Sun.COM attr.mr_vaddr, attr.mr_len, ret);
691*13101SVenki.Rajagopalan@Sun.COM
692*13101SVenki.Rajagopalan@Sun.COM *err = EINVAL;
693*13101SVenki.Rajagopalan@Sun.COM goto rsrc_setup_rxbufs_fail;
694*13101SVenki.Rajagopalan@Sun.COM }
695*13101SVenki.Rajagopalan@Sun.COM rx->wp_lkey = desc.md_lkey;
696*13101SVenki.Rajagopalan@Sun.COM
697*13101SVenki.Rajagopalan@Sun.COM /*
698*13101SVenki.Rajagopalan@Sun.COM * Now setup the rx wqes
699*13101SVenki.Rajagopalan@Sun.COM */
700*13101SVenki.Rajagopalan@Sun.COM buf = (uint8_t *)(uintptr_t)(rx->wp_vaddr);
701*13101SVenki.Rajagopalan@Sun.COM for (i = 0, blk = 0; blk < EIB_BLKS_PER_POOL; blk++) {
702*13101SVenki.Rajagopalan@Sun.COM for (ndx = 0; ndx < EIB_WQES_PER_BLK; ndx++, i++) {
703*13101SVenki.Rajagopalan@Sun.COM wqe = &rx->wp_wqe[i];
704*13101SVenki.Rajagopalan@Sun.COM
705*13101SVenki.Rajagopalan@Sun.COM /*
706*13101SVenki.Rajagopalan@Sun.COM * These parameters should remain fixed throughout the
707*13101SVenki.Rajagopalan@Sun.COM * lifetime of this recv wqe. The qe_frp will only be
708*13101SVenki.Rajagopalan@Sun.COM * used by the data channel of vnics and will remain
709*13101SVenki.Rajagopalan@Sun.COM * unused by other channels.
710*13101SVenki.Rajagopalan@Sun.COM */
711*13101SVenki.Rajagopalan@Sun.COM wqe->qe_pool = rx;
712*13101SVenki.Rajagopalan@Sun.COM wqe->qe_cpbuf = buf;
713*13101SVenki.Rajagopalan@Sun.COM wqe->qe_bufsz = mtu + EIB_GRH_SZ + EIB_IPHDR_ALIGN_ROOM;
714*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.recv.wr_id = (ibt_wrid_t)(uintptr_t)wqe;
715*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.recv.wr_nds = 1;
716*13101SVenki.Rajagopalan@Sun.COM wqe->qe_wr.recv.wr_sgl = &wqe->qe_sgl;
717*13101SVenki.Rajagopalan@Sun.COM wqe->qe_frp.free_func = eib_data_rx_recycle;
718*13101SVenki.Rajagopalan@Sun.COM wqe->qe_frp.free_arg = (caddr_t)wqe;
719*13101SVenki.Rajagopalan@Sun.COM
720*13101SVenki.Rajagopalan@Sun.COM /*
721*13101SVenki.Rajagopalan@Sun.COM * The parameter set below are used in tx and rx paths.
722*13101SVenki.Rajagopalan@Sun.COM * These parameters (except ds_key) are reset to these
723*13101SVenki.Rajagopalan@Sun.COM * default values in eib_rsrc_return_wqes().
724*13101SVenki.Rajagopalan@Sun.COM */
725*13101SVenki.Rajagopalan@Sun.COM wqe->qe_sgl.ds_key = rx->wp_lkey;
726*13101SVenki.Rajagopalan@Sun.COM wqe->qe_sgl.ds_va = (ib_vaddr_t)(uintptr_t)buf;
727*13101SVenki.Rajagopalan@Sun.COM wqe->qe_sgl.ds_len = wqe->qe_bufsz;
728*13101SVenki.Rajagopalan@Sun.COM wqe->qe_mp = NULL;
729*13101SVenki.Rajagopalan@Sun.COM wqe->qe_info =
730*13101SVenki.Rajagopalan@Sun.COM ((blk & EIB_WQEBLK_MASK) << EIB_WQEBLK_SHIFT) |
731*13101SVenki.Rajagopalan@Sun.COM ((ndx & EIB_WQENDX_MASK) << EIB_WQENDX_SHIFT) |
732*13101SVenki.Rajagopalan@Sun.COM ((uint_t)EIB_WQE_RX << EIB_WQETYP_SHIFT);
733*13101SVenki.Rajagopalan@Sun.COM
734*13101SVenki.Rajagopalan@Sun.COM /*
735*13101SVenki.Rajagopalan@Sun.COM * These rx-specific parameters are also reset to
736*13101SVenki.Rajagopalan@Sun.COM * these default values in eib_rsrc_return_wqes().
737*13101SVenki.Rajagopalan@Sun.COM */
738*13101SVenki.Rajagopalan@Sun.COM wqe->qe_chan = NULL;
739*13101SVenki.Rajagopalan@Sun.COM wqe->qe_vnic_inst = -1;
740*13101SVenki.Rajagopalan@Sun.COM
741*13101SVenki.Rajagopalan@Sun.COM buf += (mtu + EIB_GRH_SZ + EIB_IPHDR_ALIGN_ROOM);
742*13101SVenki.Rajagopalan@Sun.COM }
743*13101SVenki.Rajagopalan@Sun.COM }
744*13101SVenki.Rajagopalan@Sun.COM
745*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_SUCCESS);
746*13101SVenki.Rajagopalan@Sun.COM
747*13101SVenki.Rajagopalan@Sun.COM rsrc_setup_rxbufs_fail:
748*13101SVenki.Rajagopalan@Sun.COM eib_rb_rsrc_setup_rxbufs(ss, B_FALSE);
749*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_FAILURE);
750*13101SVenki.Rajagopalan@Sun.COM }
751*13101SVenki.Rajagopalan@Sun.COM
752*13101SVenki.Rajagopalan@Sun.COM static int
eib_rsrc_setup_lsobufs(eib_t * ss,int * err)753*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_setup_lsobufs(eib_t *ss, int *err)
754*13101SVenki.Rajagopalan@Sun.COM {
755*13101SVenki.Rajagopalan@Sun.COM eib_lsobkt_t *bkt;
756*13101SVenki.Rajagopalan@Sun.COM eib_lsobuf_t *elem;
757*13101SVenki.Rajagopalan@Sun.COM eib_lsobuf_t *tail;
758*13101SVenki.Rajagopalan@Sun.COM ibt_mr_attr_t attr;
759*13101SVenki.Rajagopalan@Sun.COM ibt_mr_desc_t desc;
760*13101SVenki.Rajagopalan@Sun.COM kthread_t *kt;
761*13101SVenki.Rajagopalan@Sun.COM
762*13101SVenki.Rajagopalan@Sun.COM uint8_t *lsomem;
763*13101SVenki.Rajagopalan@Sun.COM uint8_t *memp;
764*13101SVenki.Rajagopalan@Sun.COM ibt_status_t ret;
765*13101SVenki.Rajagopalan@Sun.COM int i;
766*13101SVenki.Rajagopalan@Sun.COM
767*13101SVenki.Rajagopalan@Sun.COM /*
768*13101SVenki.Rajagopalan@Sun.COM * Allocate the lso bucket and space for buffers
769*13101SVenki.Rajagopalan@Sun.COM */
770*13101SVenki.Rajagopalan@Sun.COM bkt = kmem_zalloc(sizeof (eib_lsobkt_t), KM_SLEEP);
771*13101SVenki.Rajagopalan@Sun.COM lsomem = kmem_zalloc(eib_lso_num_bufs * EIB_LSO_BUFSZ, KM_SLEEP);
772*13101SVenki.Rajagopalan@Sun.COM
773*13101SVenki.Rajagopalan@Sun.COM /*
774*13101SVenki.Rajagopalan@Sun.COM * Register lso memory and save the lkey
775*13101SVenki.Rajagopalan@Sun.COM */
776*13101SVenki.Rajagopalan@Sun.COM attr.mr_vaddr = (uint64_t)(uintptr_t)lsomem;
777*13101SVenki.Rajagopalan@Sun.COM attr.mr_len = eib_lso_num_bufs * EIB_LSO_BUFSZ;
778*13101SVenki.Rajagopalan@Sun.COM attr.mr_as = NULL;
779*13101SVenki.Rajagopalan@Sun.COM attr.mr_flags = IBT_MR_SLEEP;
780*13101SVenki.Rajagopalan@Sun.COM
781*13101SVenki.Rajagopalan@Sun.COM ret = ibt_register_mr(ss->ei_hca_hdl, ss->ei_pd_hdl, &attr,
782*13101SVenki.Rajagopalan@Sun.COM &bkt->bk_mr_hdl, &desc);
783*13101SVenki.Rajagopalan@Sun.COM if (ret != IBT_SUCCESS) {
784*13101SVenki.Rajagopalan@Sun.COM *err = EINVAL;
785*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_rsrc_setup_lsobufs: "
786*13101SVenki.Rajagopalan@Sun.COM "ibt_register_mr() failed for LSO "
787*13101SVenki.Rajagopalan@Sun.COM "region (0x%llx, 0x%llx) with ret=%d",
788*13101SVenki.Rajagopalan@Sun.COM attr.mr_vaddr, attr.mr_len, ret);
789*13101SVenki.Rajagopalan@Sun.COM
790*13101SVenki.Rajagopalan@Sun.COM kmem_free(lsomem, eib_lso_num_bufs * EIB_LSO_BUFSZ);
791*13101SVenki.Rajagopalan@Sun.COM kmem_free(bkt, sizeof (eib_lsobkt_t));
792*13101SVenki.Rajagopalan@Sun.COM
793*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_FAILURE);
794*13101SVenki.Rajagopalan@Sun.COM }
795*13101SVenki.Rajagopalan@Sun.COM bkt->bk_lkey = desc.md_lkey;
796*13101SVenki.Rajagopalan@Sun.COM
797*13101SVenki.Rajagopalan@Sun.COM /*
798*13101SVenki.Rajagopalan@Sun.COM * Now allocate the buflist. Note that the elements in the buflist and
799*13101SVenki.Rajagopalan@Sun.COM * the buffers in the lso memory have a permanent 1-1 relation, so we
800*13101SVenki.Rajagopalan@Sun.COM * can always derive the address of a buflist entry from the address of
801*13101SVenki.Rajagopalan@Sun.COM * an lso buffer.
802*13101SVenki.Rajagopalan@Sun.COM */
803*13101SVenki.Rajagopalan@Sun.COM bkt->bk_bufl = kmem_zalloc(eib_lso_num_bufs * sizeof (eib_lsobuf_t),
804*13101SVenki.Rajagopalan@Sun.COM KM_SLEEP);
805*13101SVenki.Rajagopalan@Sun.COM
806*13101SVenki.Rajagopalan@Sun.COM /*
807*13101SVenki.Rajagopalan@Sun.COM * Set up the lso buf chain
808*13101SVenki.Rajagopalan@Sun.COM */
809*13101SVenki.Rajagopalan@Sun.COM memp = lsomem;
810*13101SVenki.Rajagopalan@Sun.COM elem = bkt->bk_bufl;
811*13101SVenki.Rajagopalan@Sun.COM for (i = 0; i < eib_lso_num_bufs; i++) {
812*13101SVenki.Rajagopalan@Sun.COM elem->lb_isfree = 1;
813*13101SVenki.Rajagopalan@Sun.COM elem->lb_buf = memp;
814*13101SVenki.Rajagopalan@Sun.COM elem->lb_next = elem + 1;
815*13101SVenki.Rajagopalan@Sun.COM
816*13101SVenki.Rajagopalan@Sun.COM tail = elem;
817*13101SVenki.Rajagopalan@Sun.COM
818*13101SVenki.Rajagopalan@Sun.COM memp += EIB_LSO_BUFSZ;
819*13101SVenki.Rajagopalan@Sun.COM elem++;
820*13101SVenki.Rajagopalan@Sun.COM }
821*13101SVenki.Rajagopalan@Sun.COM tail->lb_next = NULL;
822*13101SVenki.Rajagopalan@Sun.COM
823*13101SVenki.Rajagopalan@Sun.COM /*
824*13101SVenki.Rajagopalan@Sun.COM * Set up the LSO buffer information in eib state
825*13101SVenki.Rajagopalan@Sun.COM */
826*13101SVenki.Rajagopalan@Sun.COM bkt->bk_free_head = bkt->bk_bufl;
827*13101SVenki.Rajagopalan@Sun.COM bkt->bk_mem = lsomem;
828*13101SVenki.Rajagopalan@Sun.COM bkt->bk_nelem = eib_lso_num_bufs;
829*13101SVenki.Rajagopalan@Sun.COM bkt->bk_nfree = bkt->bk_nelem;
830*13101SVenki.Rajagopalan@Sun.COM
831*13101SVenki.Rajagopalan@Sun.COM mutex_init(&bkt->bk_lock, NULL, MUTEX_DRIVER, NULL);
832*13101SVenki.Rajagopalan@Sun.COM cv_init(&bkt->bk_cv, NULL, CV_DEFAULT, NULL);
833*13101SVenki.Rajagopalan@Sun.COM
834*13101SVenki.Rajagopalan@Sun.COM ss->ei_lso = bkt;
835*13101SVenki.Rajagopalan@Sun.COM
836*13101SVenki.Rajagopalan@Sun.COM /*
837*13101SVenki.Rajagopalan@Sun.COM * Before returning, create a kernel thread to monitor the status
838*13101SVenki.Rajagopalan@Sun.COM * of lso bufs
839*13101SVenki.Rajagopalan@Sun.COM */
840*13101SVenki.Rajagopalan@Sun.COM kt = thread_create(NULL, 0, eib_monitor_lso_bufs, ss, 0,
841*13101SVenki.Rajagopalan@Sun.COM &p0, TS_RUN, minclsyspri);
842*13101SVenki.Rajagopalan@Sun.COM ss->ei_lsobufs_monitor = kt->t_did;
843*13101SVenki.Rajagopalan@Sun.COM
844*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_SUCCESS);
845*13101SVenki.Rajagopalan@Sun.COM }
846*13101SVenki.Rajagopalan@Sun.COM
847*13101SVenki.Rajagopalan@Sun.COM static void
eib_rsrc_init_wqe_pool(eib_t * ss,eib_wqe_pool_t ** wpp,ib_memlen_t bufsz,int wp_type)848*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_init_wqe_pool(eib_t *ss, eib_wqe_pool_t **wpp, ib_memlen_t bufsz,
849*13101SVenki.Rajagopalan@Sun.COM int wp_type)
850*13101SVenki.Rajagopalan@Sun.COM {
851*13101SVenki.Rajagopalan@Sun.COM eib_wqe_pool_t *wp;
852*13101SVenki.Rajagopalan@Sun.COM uint_t wp_wqesz;
853*13101SVenki.Rajagopalan@Sun.COM int i;
854*13101SVenki.Rajagopalan@Sun.COM
855*13101SVenki.Rajagopalan@Sun.COM ASSERT(wpp != NULL);
856*13101SVenki.Rajagopalan@Sun.COM ASSERT(*wpp == NULL);
857*13101SVenki.Rajagopalan@Sun.COM
858*13101SVenki.Rajagopalan@Sun.COM /*
859*13101SVenki.Rajagopalan@Sun.COM * Allocate the wqe pool, wqes and bufs
860*13101SVenki.Rajagopalan@Sun.COM */
861*13101SVenki.Rajagopalan@Sun.COM wp = kmem_zalloc(sizeof (eib_wqe_pool_t), KM_SLEEP);
862*13101SVenki.Rajagopalan@Sun.COM wp_wqesz = EIB_WQES_PER_POOL * sizeof (eib_wqe_t);
863*13101SVenki.Rajagopalan@Sun.COM wp->wp_wqe = (eib_wqe_t *)kmem_zalloc(wp_wqesz, KM_SLEEP);
864*13101SVenki.Rajagopalan@Sun.COM wp->wp_memsz = EIB_WQES_PER_POOL * bufsz;
865*13101SVenki.Rajagopalan@Sun.COM wp->wp_vaddr = (ib_vaddr_t)(uintptr_t)kmem_zalloc(wp->wp_memsz,
866*13101SVenki.Rajagopalan@Sun.COM KM_SLEEP);
867*13101SVenki.Rajagopalan@Sun.COM wp->wp_ss = ss;
868*13101SVenki.Rajagopalan@Sun.COM wp->wp_type = wp_type;
869*13101SVenki.Rajagopalan@Sun.COM wp->wp_nfree_lwm = (wp_type == EIB_WP_TYPE_TX) ?
870*13101SVenki.Rajagopalan@Sun.COM EIB_NFREE_SWQES_LWM : EIB_NFREE_RWQES_LWM;
871*13101SVenki.Rajagopalan@Sun.COM
872*13101SVenki.Rajagopalan@Sun.COM /*
873*13101SVenki.Rajagopalan@Sun.COM * Initialize the lock and bitmaps: everything is available at first,
874*13101SVenki.Rajagopalan@Sun.COM * but note that if the number of blocks per pool is less than 64, we
875*13101SVenki.Rajagopalan@Sun.COM * need to initialize those extra bits as "unavailable" - these will
876*13101SVenki.Rajagopalan@Sun.COM * remain unavailable throughout.
877*13101SVenki.Rajagopalan@Sun.COM */
878*13101SVenki.Rajagopalan@Sun.COM mutex_init(&wp->wp_lock, NULL, MUTEX_DRIVER, NULL);
879*13101SVenki.Rajagopalan@Sun.COM cv_init(&wp->wp_cv, NULL, CV_DEFAULT, NULL);
880*13101SVenki.Rajagopalan@Sun.COM
881*13101SVenki.Rajagopalan@Sun.COM wp->wp_nfree = EIB_WQES_PER_POOL;
882*13101SVenki.Rajagopalan@Sun.COM wp->wp_free_blks = (EIB_BLKS_PER_POOL >= 64) ? (~0) :
883*13101SVenki.Rajagopalan@Sun.COM (((uint64_t)1 << EIB_BLKS_PER_POOL) - 1);
884*13101SVenki.Rajagopalan@Sun.COM for (i = 0; i < EIB_BLKS_PER_POOL; i++)
885*13101SVenki.Rajagopalan@Sun.COM wp->wp_free_wqes[i] = ~0;
886*13101SVenki.Rajagopalan@Sun.COM
887*13101SVenki.Rajagopalan@Sun.COM *wpp = wp;
888*13101SVenki.Rajagopalan@Sun.COM }
889*13101SVenki.Rajagopalan@Sun.COM
890*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
891*13101SVenki.Rajagopalan@Sun.COM static void
eib_rsrc_fini_wqe_pool(eib_t * ss,eib_wqe_pool_t ** wpp)892*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_fini_wqe_pool(eib_t *ss, eib_wqe_pool_t **wpp)
893*13101SVenki.Rajagopalan@Sun.COM {
894*13101SVenki.Rajagopalan@Sun.COM eib_wqe_pool_t *wp;
895*13101SVenki.Rajagopalan@Sun.COM
896*13101SVenki.Rajagopalan@Sun.COM ASSERT(wpp != NULL);
897*13101SVenki.Rajagopalan@Sun.COM
898*13101SVenki.Rajagopalan@Sun.COM wp = *wpp;
899*13101SVenki.Rajagopalan@Sun.COM ASSERT(*wpp != NULL);
900*13101SVenki.Rajagopalan@Sun.COM
901*13101SVenki.Rajagopalan@Sun.COM cv_destroy(&wp->wp_cv);
902*13101SVenki.Rajagopalan@Sun.COM mutex_destroy(&wp->wp_lock);
903*13101SVenki.Rajagopalan@Sun.COM
904*13101SVenki.Rajagopalan@Sun.COM kmem_free((void *)(uintptr_t)(wp->wp_vaddr), wp->wp_memsz);
905*13101SVenki.Rajagopalan@Sun.COM kmem_free(wp->wp_wqe, EIB_WQES_PER_POOL * sizeof (eib_wqe_t));
906*13101SVenki.Rajagopalan@Sun.COM kmem_free(wp, sizeof (eib_wqe_pool_t));
907*13101SVenki.Rajagopalan@Sun.COM
908*13101SVenki.Rajagopalan@Sun.COM *wpp = NULL;
909*13101SVenki.Rajagopalan@Sun.COM }
910*13101SVenki.Rajagopalan@Sun.COM
911*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
912*13101SVenki.Rajagopalan@Sun.COM static boolean_t
eib_rsrc_ok_to_free_pool(eib_t * ss,eib_wqe_pool_t * wp,boolean_t force)913*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_ok_to_free_pool(eib_t *ss, eib_wqe_pool_t *wp, boolean_t force)
914*13101SVenki.Rajagopalan@Sun.COM {
915*13101SVenki.Rajagopalan@Sun.COM uint64_t free_blks;
916*13101SVenki.Rajagopalan@Sun.COM int i;
917*13101SVenki.Rajagopalan@Sun.COM
918*13101SVenki.Rajagopalan@Sun.COM /*
919*13101SVenki.Rajagopalan@Sun.COM * See if we can release all memory allocated for buffers, wqes and
920*13101SVenki.Rajagopalan@Sun.COM * the pool. Note that in the case of data channel rx buffers, some
921*13101SVenki.Rajagopalan@Sun.COM * of the buffers may not be free if the nw layer is holding on to
922*13101SVenki.Rajagopalan@Sun.COM * them still. If this is the case, we cannot free the wqe pool now
923*13101SVenki.Rajagopalan@Sun.COM * or a subsequent access by the nw layer to the buffers will cause
924*13101SVenki.Rajagopalan@Sun.COM * a panic.
925*13101SVenki.Rajagopalan@Sun.COM */
926*13101SVenki.Rajagopalan@Sun.COM ASSERT(wp != NULL);
927*13101SVenki.Rajagopalan@Sun.COM
928*13101SVenki.Rajagopalan@Sun.COM /*
929*13101SVenki.Rajagopalan@Sun.COM * If force-free flag is set, we can always release the memory.
930*13101SVenki.Rajagopalan@Sun.COM * Note that this flag is unused currently, and should be removed.
931*13101SVenki.Rajagopalan@Sun.COM */
932*13101SVenki.Rajagopalan@Sun.COM if (force == B_TRUE)
933*13101SVenki.Rajagopalan@Sun.COM return (B_TRUE);
934*13101SVenki.Rajagopalan@Sun.COM
935*13101SVenki.Rajagopalan@Sun.COM mutex_enter(&wp->wp_lock);
936*13101SVenki.Rajagopalan@Sun.COM
937*13101SVenki.Rajagopalan@Sun.COM /*
938*13101SVenki.Rajagopalan@Sun.COM * If a whole block remains allocated, obviously we cannot free
939*13101SVenki.Rajagopalan@Sun.COM * the pool
940*13101SVenki.Rajagopalan@Sun.COM */
941*13101SVenki.Rajagopalan@Sun.COM free_blks = (EIB_BLKS_PER_POOL >= 64) ? (~0) :
942*13101SVenki.Rajagopalan@Sun.COM (((uint64_t)1 << EIB_BLKS_PER_POOL) - 1);
943*13101SVenki.Rajagopalan@Sun.COM if (wp->wp_free_blks != free_blks) {
944*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&wp->wp_lock);
945*13101SVenki.Rajagopalan@Sun.COM return (B_FALSE);
946*13101SVenki.Rajagopalan@Sun.COM }
947*13101SVenki.Rajagopalan@Sun.COM
948*13101SVenki.Rajagopalan@Sun.COM /*
949*13101SVenki.Rajagopalan@Sun.COM * If even a single wqe within any one block remains in-use, we
950*13101SVenki.Rajagopalan@Sun.COM * cannot free the pool
951*13101SVenki.Rajagopalan@Sun.COM */
952*13101SVenki.Rajagopalan@Sun.COM for (i = 0; i < EIB_BLKS_PER_POOL; i++) {
953*13101SVenki.Rajagopalan@Sun.COM if (wp->wp_free_wqes[i] != (~0)) {
954*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&wp->wp_lock);
955*13101SVenki.Rajagopalan@Sun.COM return (B_FALSE);
956*13101SVenki.Rajagopalan@Sun.COM }
957*13101SVenki.Rajagopalan@Sun.COM }
958*13101SVenki.Rajagopalan@Sun.COM
959*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&wp->wp_lock);
960*13101SVenki.Rajagopalan@Sun.COM
961*13101SVenki.Rajagopalan@Sun.COM return (B_TRUE);
962*13101SVenki.Rajagopalan@Sun.COM }
963*13101SVenki.Rajagopalan@Sun.COM
964*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
965*13101SVenki.Rajagopalan@Sun.COM static int
eib_rsrc_grab_wqes(eib_t * ss,eib_wqe_pool_t * wp,eib_wqe_t ** wqes,uint_t n_req,uint_t * actual,int pri)966*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_grab_wqes(eib_t *ss, eib_wqe_pool_t *wp, eib_wqe_t **wqes,
967*13101SVenki.Rajagopalan@Sun.COM uint_t n_req, uint_t *actual, int pri)
968*13101SVenki.Rajagopalan@Sun.COM {
969*13101SVenki.Rajagopalan@Sun.COM uint_t n_allocd = 0;
970*13101SVenki.Rajagopalan@Sun.COM int blk;
971*13101SVenki.Rajagopalan@Sun.COM int ndx;
972*13101SVenki.Rajagopalan@Sun.COM int wqe_ndx;
973*13101SVenki.Rajagopalan@Sun.COM
974*13101SVenki.Rajagopalan@Sun.COM ASSERT(wp != NULL);
975*13101SVenki.Rajagopalan@Sun.COM ASSERT(wqes != NULL);
976*13101SVenki.Rajagopalan@Sun.COM
977*13101SVenki.Rajagopalan@Sun.COM mutex_enter(&wp->wp_lock);
978*13101SVenki.Rajagopalan@Sun.COM
979*13101SVenki.Rajagopalan@Sun.COM /*
980*13101SVenki.Rajagopalan@Sun.COM * If this is a low priority request, adjust the number requested
981*13101SVenki.Rajagopalan@Sun.COM * so we don't allocate beyond the low-water-mark
982*13101SVenki.Rajagopalan@Sun.COM */
983*13101SVenki.Rajagopalan@Sun.COM if (pri == EIB_WPRI_LO) {
984*13101SVenki.Rajagopalan@Sun.COM if (wp->wp_nfree <= wp->wp_nfree_lwm)
985*13101SVenki.Rajagopalan@Sun.COM n_req = 0;
986*13101SVenki.Rajagopalan@Sun.COM else if ((wp->wp_nfree - n_req) < wp->wp_nfree_lwm)
987*13101SVenki.Rajagopalan@Sun.COM n_req = wp->wp_nfree - wp->wp_nfree_lwm;
988*13101SVenki.Rajagopalan@Sun.COM }
989*13101SVenki.Rajagopalan@Sun.COM
990*13101SVenki.Rajagopalan@Sun.COM for (n_allocd = 0; n_allocd < n_req; n_allocd++) {
991*13101SVenki.Rajagopalan@Sun.COM /*
992*13101SVenki.Rajagopalan@Sun.COM * If the entire pool is unavailable, quit
993*13101SVenki.Rajagopalan@Sun.COM */
994*13101SVenki.Rajagopalan@Sun.COM if (wp->wp_free_blks == 0)
995*13101SVenki.Rajagopalan@Sun.COM break;
996*13101SVenki.Rajagopalan@Sun.COM
997*13101SVenki.Rajagopalan@Sun.COM /*
998*13101SVenki.Rajagopalan@Sun.COM * Find the first wqe that's available
999*13101SVenki.Rajagopalan@Sun.COM */
1000*13101SVenki.Rajagopalan@Sun.COM blk = EIB_FIND_LSB_SET(wp->wp_free_blks);
1001*13101SVenki.Rajagopalan@Sun.COM ASSERT(blk != -1);
1002*13101SVenki.Rajagopalan@Sun.COM ndx = EIB_FIND_LSB_SET(wp->wp_free_wqes[blk]);
1003*13101SVenki.Rajagopalan@Sun.COM ASSERT(ndx != -1);
1004*13101SVenki.Rajagopalan@Sun.COM
1005*13101SVenki.Rajagopalan@Sun.COM /*
1006*13101SVenki.Rajagopalan@Sun.COM * Mark the wqe as allocated
1007*13101SVenki.Rajagopalan@Sun.COM */
1008*13101SVenki.Rajagopalan@Sun.COM wp->wp_free_wqes[blk] &= (~((uint64_t)1 << ndx));
1009*13101SVenki.Rajagopalan@Sun.COM
1010*13101SVenki.Rajagopalan@Sun.COM /*
1011*13101SVenki.Rajagopalan@Sun.COM * If this was the last free wqe in this block, mark
1012*13101SVenki.Rajagopalan@Sun.COM * the block itself as unavailable
1013*13101SVenki.Rajagopalan@Sun.COM */
1014*13101SVenki.Rajagopalan@Sun.COM if (wp->wp_free_wqes[blk] == 0)
1015*13101SVenki.Rajagopalan@Sun.COM wp->wp_free_blks &= (~((uint64_t)1 << blk));
1016*13101SVenki.Rajagopalan@Sun.COM
1017*13101SVenki.Rajagopalan@Sun.COM /*
1018*13101SVenki.Rajagopalan@Sun.COM * Return this wqe to the caller
1019*13101SVenki.Rajagopalan@Sun.COM */
1020*13101SVenki.Rajagopalan@Sun.COM wqe_ndx = blk * EIB_WQES_PER_BLK + ndx;
1021*13101SVenki.Rajagopalan@Sun.COM wqes[n_allocd] = &(wp->wp_wqe[wqe_ndx]);
1022*13101SVenki.Rajagopalan@Sun.COM }
1023*13101SVenki.Rajagopalan@Sun.COM
1024*13101SVenki.Rajagopalan@Sun.COM wp->wp_nfree -= n_allocd;
1025*13101SVenki.Rajagopalan@Sun.COM
1026*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&wp->wp_lock);
1027*13101SVenki.Rajagopalan@Sun.COM
1028*13101SVenki.Rajagopalan@Sun.COM if (n_allocd == 0)
1029*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_FAILURE);
1030*13101SVenki.Rajagopalan@Sun.COM
1031*13101SVenki.Rajagopalan@Sun.COM if (actual) {
1032*13101SVenki.Rajagopalan@Sun.COM *actual = n_allocd;
1033*13101SVenki.Rajagopalan@Sun.COM }
1034*13101SVenki.Rajagopalan@Sun.COM
1035*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_SUCCESS);
1036*13101SVenki.Rajagopalan@Sun.COM }
1037*13101SVenki.Rajagopalan@Sun.COM
1038*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
1039*13101SVenki.Rajagopalan@Sun.COM static void
eib_rsrc_return_wqes(eib_t * ss,eib_wqe_pool_t * wp,eib_wqe_t ** wqes,uint_t n_wqes)1040*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_return_wqes(eib_t *ss, eib_wqe_pool_t *wp, eib_wqe_t **wqes,
1041*13101SVenki.Rajagopalan@Sun.COM uint_t n_wqes)
1042*13101SVenki.Rajagopalan@Sun.COM {
1043*13101SVenki.Rajagopalan@Sun.COM eib_wqe_t *wqe;
1044*13101SVenki.Rajagopalan@Sun.COM uint_t n_freed = 0;
1045*13101SVenki.Rajagopalan@Sun.COM uint_t blk;
1046*13101SVenki.Rajagopalan@Sun.COM uint_t ndx;
1047*13101SVenki.Rajagopalan@Sun.COM
1048*13101SVenki.Rajagopalan@Sun.COM ASSERT(wp != NULL);
1049*13101SVenki.Rajagopalan@Sun.COM ASSERT(wqes != NULL);
1050*13101SVenki.Rajagopalan@Sun.COM
1051*13101SVenki.Rajagopalan@Sun.COM mutex_enter(&wp->wp_lock);
1052*13101SVenki.Rajagopalan@Sun.COM for (n_freed = 0; n_freed < n_wqes; n_freed++) {
1053*13101SVenki.Rajagopalan@Sun.COM wqe = wqes[n_freed];
1054*13101SVenki.Rajagopalan@Sun.COM
1055*13101SVenki.Rajagopalan@Sun.COM /*
1056*13101SVenki.Rajagopalan@Sun.COM * This wqe is being returned back to the pool, so clear
1057*13101SVenki.Rajagopalan@Sun.COM * any wqe flags and reset buffer address and size in the
1058*13101SVenki.Rajagopalan@Sun.COM * single segment sgl back to what they were initially.
1059*13101SVenki.Rajagopalan@Sun.COM * Also erase any mblk pointer and callback function ptrs.
1060*13101SVenki.Rajagopalan@Sun.COM */
1061*13101SVenki.Rajagopalan@Sun.COM wqe->qe_sgl.ds_va = (ib_vaddr_t)(uintptr_t)wqe->qe_cpbuf;
1062*13101SVenki.Rajagopalan@Sun.COM wqe->qe_sgl.ds_len = wqe->qe_bufsz;
1063*13101SVenki.Rajagopalan@Sun.COM wqe->qe_mp = NULL;
1064*13101SVenki.Rajagopalan@Sun.COM wqe->qe_chan = NULL;
1065*13101SVenki.Rajagopalan@Sun.COM wqe->qe_vnic_inst = -1;
1066*13101SVenki.Rajagopalan@Sun.COM wqe->qe_info &= (~EIB_WQEFLGS_MASK);
1067*13101SVenki.Rajagopalan@Sun.COM
1068*13101SVenki.Rajagopalan@Sun.COM /*
1069*13101SVenki.Rajagopalan@Sun.COM * Mark the wqe free in its block
1070*13101SVenki.Rajagopalan@Sun.COM */
1071*13101SVenki.Rajagopalan@Sun.COM blk = EIB_WQE_BLK(wqe->qe_info);
1072*13101SVenki.Rajagopalan@Sun.COM ndx = EIB_WQE_NDX(wqe->qe_info);
1073*13101SVenki.Rajagopalan@Sun.COM
1074*13101SVenki.Rajagopalan@Sun.COM wp->wp_free_wqes[blk] |= ((uint64_t)1 << ndx);
1075*13101SVenki.Rajagopalan@Sun.COM
1076*13101SVenki.Rajagopalan@Sun.COM /*
1077*13101SVenki.Rajagopalan@Sun.COM * This block now has atleast one wqe free, so mark
1078*13101SVenki.Rajagopalan@Sun.COM * the block itself as available and move on to the
1079*13101SVenki.Rajagopalan@Sun.COM * next wqe to free
1080*13101SVenki.Rajagopalan@Sun.COM */
1081*13101SVenki.Rajagopalan@Sun.COM wp->wp_free_blks |= ((uint64_t)1 << blk);
1082*13101SVenki.Rajagopalan@Sun.COM }
1083*13101SVenki.Rajagopalan@Sun.COM
1084*13101SVenki.Rajagopalan@Sun.COM wp->wp_nfree += n_freed;
1085*13101SVenki.Rajagopalan@Sun.COM
1086*13101SVenki.Rajagopalan@Sun.COM /*
1087*13101SVenki.Rajagopalan@Sun.COM * If the number of available wqes in the pool has just crossed
1088*13101SVenki.Rajagopalan@Sun.COM * the high-water-mark, wakeup anyone who may be sleeping on it.
1089*13101SVenki.Rajagopalan@Sun.COM */
1090*13101SVenki.Rajagopalan@Sun.COM if ((wp->wp_type == EIB_WP_TYPE_TX) &&
1091*13101SVenki.Rajagopalan@Sun.COM ((wp->wp_nfree - n_freed) < EIB_NFREE_SWQES_HWM) &&
1092*13101SVenki.Rajagopalan@Sun.COM (wp->wp_nfree >= EIB_NFREE_SWQES_HWM)) {
1093*13101SVenki.Rajagopalan@Sun.COM cv_broadcast(&wp->wp_cv);
1094*13101SVenki.Rajagopalan@Sun.COM }
1095*13101SVenki.Rajagopalan@Sun.COM
1096*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&wp->wp_lock);
1097*13101SVenki.Rajagopalan@Sun.COM }
1098*13101SVenki.Rajagopalan@Sun.COM
1099*13101SVenki.Rajagopalan@Sun.COM static void
eib_rb_rsrc_setup_txbufs(eib_t * ss,boolean_t force)1100*13101SVenki.Rajagopalan@Sun.COM eib_rb_rsrc_setup_txbufs(eib_t *ss, boolean_t force)
1101*13101SVenki.Rajagopalan@Sun.COM {
1102*13101SVenki.Rajagopalan@Sun.COM eib_wqe_pool_t *wp = ss->ei_tx;
1103*13101SVenki.Rajagopalan@Sun.COM eib_wqe_t *wqe;
1104*13101SVenki.Rajagopalan@Sun.COM ibt_ud_dest_hdl_t dest;
1105*13101SVenki.Rajagopalan@Sun.COM ibt_status_t ret;
1106*13101SVenki.Rajagopalan@Sun.COM uint8_t *plhdr;
1107*13101SVenki.Rajagopalan@Sun.COM int i;
1108*13101SVenki.Rajagopalan@Sun.COM
1109*13101SVenki.Rajagopalan@Sun.COM if (wp == NULL)
1110*13101SVenki.Rajagopalan@Sun.COM return;
1111*13101SVenki.Rajagopalan@Sun.COM
1112*13101SVenki.Rajagopalan@Sun.COM /*
1113*13101SVenki.Rajagopalan@Sun.COM * Check if it's ok to free the tx wqe pool (i.e. all buffers have
1114*13101SVenki.Rajagopalan@Sun.COM * been reclaimed) and if so, stop the txwqe monitor thread (and wait
1115*13101SVenki.Rajagopalan@Sun.COM * for it to die), release the UD destination handles, deregister
1116*13101SVenki.Rajagopalan@Sun.COM * memory and fini the wqe pool.
1117*13101SVenki.Rajagopalan@Sun.COM */
1118*13101SVenki.Rajagopalan@Sun.COM if (eib_rsrc_ok_to_free_pool(ss, wp, force)) {
1119*13101SVenki.Rajagopalan@Sun.COM eib_stop_monitor_tx_wqes(ss);
1120*13101SVenki.Rajagopalan@Sun.COM
1121*13101SVenki.Rajagopalan@Sun.COM for (i = 0; i < EIB_WQES_PER_POOL; i++) {
1122*13101SVenki.Rajagopalan@Sun.COM wqe = &wp->wp_wqe[i];
1123*13101SVenki.Rajagopalan@Sun.COM if ((plhdr = wqe->qe_payload_hdr) != NULL) {
1124*13101SVenki.Rajagopalan@Sun.COM kmem_free(plhdr, EIB_MAX_PAYLOAD_HDR_SZ);
1125*13101SVenki.Rajagopalan@Sun.COM }
1126*13101SVenki.Rajagopalan@Sun.COM if ((dest = wqe->qe_dest) != NULL) {
1127*13101SVenki.Rajagopalan@Sun.COM ret = ibt_free_ud_dest(dest);
1128*13101SVenki.Rajagopalan@Sun.COM if (ret != IBT_SUCCESS) {
1129*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_WARN(ss->ei_instance,
1130*13101SVenki.Rajagopalan@Sun.COM "eib_rb_rsrc_setup_txbufs: "
1131*13101SVenki.Rajagopalan@Sun.COM "ibt_free_ud_dest() failed, ret=%d",
1132*13101SVenki.Rajagopalan@Sun.COM ret);
1133*13101SVenki.Rajagopalan@Sun.COM }
1134*13101SVenki.Rajagopalan@Sun.COM }
1135*13101SVenki.Rajagopalan@Sun.COM }
1136*13101SVenki.Rajagopalan@Sun.COM if (wp->wp_mr) {
1137*13101SVenki.Rajagopalan@Sun.COM if ((ret = ibt_deregister_mr(ss->ei_hca_hdl,
1138*13101SVenki.Rajagopalan@Sun.COM wp->wp_mr)) != IBT_SUCCESS) {
1139*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_WARN(ss->ei_instance,
1140*13101SVenki.Rajagopalan@Sun.COM "eib_rb_rsrc_setup_txbufs: "
1141*13101SVenki.Rajagopalan@Sun.COM "ibt_deregister_mr() failed, ret=%d", ret);
1142*13101SVenki.Rajagopalan@Sun.COM }
1143*13101SVenki.Rajagopalan@Sun.COM wp->wp_mr = NULL;
1144*13101SVenki.Rajagopalan@Sun.COM }
1145*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_fini_wqe_pool(ss, &ss->ei_tx);
1146*13101SVenki.Rajagopalan@Sun.COM }
1147*13101SVenki.Rajagopalan@Sun.COM }
1148*13101SVenki.Rajagopalan@Sun.COM
1149*13101SVenki.Rajagopalan@Sun.COM void
eib_rb_rsrc_setup_rxbufs(eib_t * ss,boolean_t force)1150*13101SVenki.Rajagopalan@Sun.COM eib_rb_rsrc_setup_rxbufs(eib_t *ss, boolean_t force)
1151*13101SVenki.Rajagopalan@Sun.COM {
1152*13101SVenki.Rajagopalan@Sun.COM eib_wqe_pool_t *rx = ss->ei_rx;
1153*13101SVenki.Rajagopalan@Sun.COM ibt_status_t ret;
1154*13101SVenki.Rajagopalan@Sun.COM
1155*13101SVenki.Rajagopalan@Sun.COM if (rx == NULL)
1156*13101SVenki.Rajagopalan@Sun.COM return;
1157*13101SVenki.Rajagopalan@Sun.COM
1158*13101SVenki.Rajagopalan@Sun.COM /*
1159*13101SVenki.Rajagopalan@Sun.COM * Check if it's ok to free the rx wqe pool (i.e. all buffers have
1160*13101SVenki.Rajagopalan@Sun.COM * been reclaimed) and if so, deregister memory and fini the wqe pool.
1161*13101SVenki.Rajagopalan@Sun.COM */
1162*13101SVenki.Rajagopalan@Sun.COM if (eib_rsrc_ok_to_free_pool(ss, rx, force)) {
1163*13101SVenki.Rajagopalan@Sun.COM if (rx->wp_mr) {
1164*13101SVenki.Rajagopalan@Sun.COM if ((ret = ibt_deregister_mr(ss->ei_hca_hdl,
1165*13101SVenki.Rajagopalan@Sun.COM rx->wp_mr)) != IBT_SUCCESS) {
1166*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_WARN(ss->ei_instance,
1167*13101SVenki.Rajagopalan@Sun.COM "eib_rb_rsrc_setup_rxbufs: "
1168*13101SVenki.Rajagopalan@Sun.COM "ibt_deregister_mr() failed, ret=%d", ret);
1169*13101SVenki.Rajagopalan@Sun.COM }
1170*13101SVenki.Rajagopalan@Sun.COM rx->wp_mr = NULL;
1171*13101SVenki.Rajagopalan@Sun.COM }
1172*13101SVenki.Rajagopalan@Sun.COM
1173*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_fini_wqe_pool(ss, &ss->ei_rx);
1174*13101SVenki.Rajagopalan@Sun.COM }
1175*13101SVenki.Rajagopalan@Sun.COM }
1176*13101SVenki.Rajagopalan@Sun.COM
1177*13101SVenki.Rajagopalan@Sun.COM static void
eib_rb_rsrc_setup_lsobufs(eib_t * ss,boolean_t force)1178*13101SVenki.Rajagopalan@Sun.COM eib_rb_rsrc_setup_lsobufs(eib_t *ss, boolean_t force)
1179*13101SVenki.Rajagopalan@Sun.COM {
1180*13101SVenki.Rajagopalan@Sun.COM eib_lsobkt_t *bkt;
1181*13101SVenki.Rajagopalan@Sun.COM ibt_status_t ret;
1182*13101SVenki.Rajagopalan@Sun.COM
1183*13101SVenki.Rajagopalan@Sun.COM /*
1184*13101SVenki.Rajagopalan@Sun.COM * Remove the lso bucket from the state
1185*13101SVenki.Rajagopalan@Sun.COM */
1186*13101SVenki.Rajagopalan@Sun.COM if ((bkt = ss->ei_lso) == NULL)
1187*13101SVenki.Rajagopalan@Sun.COM return;
1188*13101SVenki.Rajagopalan@Sun.COM
1189*13101SVenki.Rajagopalan@Sun.COM /*
1190*13101SVenki.Rajagopalan@Sun.COM * Try to stop the lso bufs monitor thread. If we fail, we simply
1191*13101SVenki.Rajagopalan@Sun.COM * return. We'll have another shot at it later from detach() with
1192*13101SVenki.Rajagopalan@Sun.COM * the force flag set.
1193*13101SVenki.Rajagopalan@Sun.COM */
1194*13101SVenki.Rajagopalan@Sun.COM if (eib_stop_monitor_lso_bufs(ss, force) != EIB_E_SUCCESS)
1195*13101SVenki.Rajagopalan@Sun.COM return;
1196*13101SVenki.Rajagopalan@Sun.COM
1197*13101SVenki.Rajagopalan@Sun.COM /*
1198*13101SVenki.Rajagopalan@Sun.COM * Free the buflist
1199*13101SVenki.Rajagopalan@Sun.COM */
1200*13101SVenki.Rajagopalan@Sun.COM if (bkt->bk_bufl) {
1201*13101SVenki.Rajagopalan@Sun.COM kmem_free(bkt->bk_bufl, bkt->bk_nelem * sizeof (eib_lsobuf_t));
1202*13101SVenki.Rajagopalan@Sun.COM bkt->bk_bufl = NULL;
1203*13101SVenki.Rajagopalan@Sun.COM }
1204*13101SVenki.Rajagopalan@Sun.COM
1205*13101SVenki.Rajagopalan@Sun.COM /*
1206*13101SVenki.Rajagopalan@Sun.COM * Deregister LSO memory and free it
1207*13101SVenki.Rajagopalan@Sun.COM */
1208*13101SVenki.Rajagopalan@Sun.COM if (bkt->bk_mr_hdl) {
1209*13101SVenki.Rajagopalan@Sun.COM if ((ret = ibt_deregister_mr(ss->ei_hca_hdl,
1210*13101SVenki.Rajagopalan@Sun.COM bkt->bk_mr_hdl)) != IBT_SUCCESS) {
1211*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_WARN(ss->ei_instance,
1212*13101SVenki.Rajagopalan@Sun.COM "eib_rb_rsrc_setup_lsobufs: "
1213*13101SVenki.Rajagopalan@Sun.COM "ibt_deregister_mr() failed, ret=%d", ret);
1214*13101SVenki.Rajagopalan@Sun.COM }
1215*13101SVenki.Rajagopalan@Sun.COM bkt->bk_mr_hdl = NULL;
1216*13101SVenki.Rajagopalan@Sun.COM }
1217*13101SVenki.Rajagopalan@Sun.COM if (bkt->bk_mem) {
1218*13101SVenki.Rajagopalan@Sun.COM kmem_free(bkt->bk_mem, bkt->bk_nelem * EIB_LSO_BUFSZ);
1219*13101SVenki.Rajagopalan@Sun.COM bkt->bk_mem = NULL;
1220*13101SVenki.Rajagopalan@Sun.COM }
1221*13101SVenki.Rajagopalan@Sun.COM
1222*13101SVenki.Rajagopalan@Sun.COM /*
1223*13101SVenki.Rajagopalan@Sun.COM * Destroy the mutex and condvar
1224*13101SVenki.Rajagopalan@Sun.COM */
1225*13101SVenki.Rajagopalan@Sun.COM cv_destroy(&bkt->bk_cv);
1226*13101SVenki.Rajagopalan@Sun.COM mutex_destroy(&bkt->bk_lock);
1227*13101SVenki.Rajagopalan@Sun.COM
1228*13101SVenki.Rajagopalan@Sun.COM /*
1229*13101SVenki.Rajagopalan@Sun.COM * Finally, free the lso bucket itself
1230*13101SVenki.Rajagopalan@Sun.COM */
1231*13101SVenki.Rajagopalan@Sun.COM kmem_free(bkt, sizeof (eib_lsobkt_t));
1232*13101SVenki.Rajagopalan@Sun.COM ss->ei_lso = NULL;
1233*13101SVenki.Rajagopalan@Sun.COM }
1234