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 eib_chan_t *
eib_chan_init(void)36*13101SVenki.Rajagopalan@Sun.COM eib_chan_init(void)
37*13101SVenki.Rajagopalan@Sun.COM {
38*13101SVenki.Rajagopalan@Sun.COM eib_chan_t *chan;
39*13101SVenki.Rajagopalan@Sun.COM
40*13101SVenki.Rajagopalan@Sun.COM /*
41*13101SVenki.Rajagopalan@Sun.COM * Allocate a eib_chan_t to store stuff about admin qp and
42*13101SVenki.Rajagopalan@Sun.COM * initialize some basic stuff
43*13101SVenki.Rajagopalan@Sun.COM */
44*13101SVenki.Rajagopalan@Sun.COM chan = kmem_zalloc(sizeof (eib_chan_t), KM_SLEEP);
45*13101SVenki.Rajagopalan@Sun.COM
46*13101SVenki.Rajagopalan@Sun.COM mutex_init(&chan->ch_pkey_lock, NULL, MUTEX_DRIVER, NULL);
47*13101SVenki.Rajagopalan@Sun.COM mutex_init(&chan->ch_cep_lock, NULL, MUTEX_DRIVER, NULL);
48*13101SVenki.Rajagopalan@Sun.COM mutex_init(&chan->ch_tx_lock, NULL, MUTEX_DRIVER, NULL);
49*13101SVenki.Rajagopalan@Sun.COM mutex_init(&chan->ch_rx_lock, NULL, MUTEX_DRIVER, NULL);
50*13101SVenki.Rajagopalan@Sun.COM mutex_init(&chan->ch_vhub_lock, NULL, MUTEX_DRIVER, NULL);
51*13101SVenki.Rajagopalan@Sun.COM
52*13101SVenki.Rajagopalan@Sun.COM cv_init(&chan->ch_cep_cv, NULL, CV_DEFAULT, NULL);
53*13101SVenki.Rajagopalan@Sun.COM cv_init(&chan->ch_tx_cv, NULL, CV_DEFAULT, NULL);
54*13101SVenki.Rajagopalan@Sun.COM cv_init(&chan->ch_rx_cv, NULL, CV_DEFAULT, NULL);
55*13101SVenki.Rajagopalan@Sun.COM
56*13101SVenki.Rajagopalan@Sun.COM return (chan);
57*13101SVenki.Rajagopalan@Sun.COM }
58*13101SVenki.Rajagopalan@Sun.COM
59*13101SVenki.Rajagopalan@Sun.COM void
eib_chan_fini(eib_chan_t * chan)60*13101SVenki.Rajagopalan@Sun.COM eib_chan_fini(eib_chan_t *chan)
61*13101SVenki.Rajagopalan@Sun.COM {
62*13101SVenki.Rajagopalan@Sun.COM if (chan) {
63*13101SVenki.Rajagopalan@Sun.COM cv_destroy(&chan->ch_rx_cv);
64*13101SVenki.Rajagopalan@Sun.COM cv_destroy(&chan->ch_tx_cv);
65*13101SVenki.Rajagopalan@Sun.COM cv_destroy(&chan->ch_cep_cv);
66*13101SVenki.Rajagopalan@Sun.COM
67*13101SVenki.Rajagopalan@Sun.COM mutex_destroy(&chan->ch_vhub_lock);
68*13101SVenki.Rajagopalan@Sun.COM mutex_destroy(&chan->ch_rx_lock);
69*13101SVenki.Rajagopalan@Sun.COM mutex_destroy(&chan->ch_tx_lock);
70*13101SVenki.Rajagopalan@Sun.COM mutex_destroy(&chan->ch_cep_lock);
71*13101SVenki.Rajagopalan@Sun.COM mutex_destroy(&chan->ch_pkey_lock);
72*13101SVenki.Rajagopalan@Sun.COM
73*13101SVenki.Rajagopalan@Sun.COM kmem_free(chan, sizeof (eib_chan_t));
74*13101SVenki.Rajagopalan@Sun.COM }
75*13101SVenki.Rajagopalan@Sun.COM }
76*13101SVenki.Rajagopalan@Sun.COM
77*13101SVenki.Rajagopalan@Sun.COM int
eib_chan_post_rx(eib_t * ss,eib_chan_t * chan,uint_t * n_posted)78*13101SVenki.Rajagopalan@Sun.COM eib_chan_post_rx(eib_t *ss, eib_chan_t *chan, uint_t *n_posted)
79*13101SVenki.Rajagopalan@Sun.COM {
80*13101SVenki.Rajagopalan@Sun.COM eib_wqe_t *rwqes[EIB_RWR_CHUNK_SZ];
81*13101SVenki.Rajagopalan@Sun.COM ibt_status_t ret;
82*13101SVenki.Rajagopalan@Sun.COM uint_t n_got = 0;
83*13101SVenki.Rajagopalan@Sun.COM uint_t n_good = 0;
84*13101SVenki.Rajagopalan@Sun.COM uint_t limit = 0;
85*13101SVenki.Rajagopalan@Sun.COM uint_t room = 0;
86*13101SVenki.Rajagopalan@Sun.COM uint_t chunk_sz;
87*13101SVenki.Rajagopalan@Sun.COM int wndx;
88*13101SVenki.Rajagopalan@Sun.COM int i;
89*13101SVenki.Rajagopalan@Sun.COM
90*13101SVenki.Rajagopalan@Sun.COM /*
91*13101SVenki.Rajagopalan@Sun.COM * We don't want to post beyond the maximum rwqe size for this channel
92*13101SVenki.Rajagopalan@Sun.COM */
93*13101SVenki.Rajagopalan@Sun.COM room = chan->ch_max_rwqes - chan->ch_rx_posted;
94*13101SVenki.Rajagopalan@Sun.COM limit = (room > chan->ch_rwqe_bktsz) ? chan->ch_rwqe_bktsz : room;
95*13101SVenki.Rajagopalan@Sun.COM
96*13101SVenki.Rajagopalan@Sun.COM for (wndx = 0; wndx < limit; wndx += chunk_sz) {
97*13101SVenki.Rajagopalan@Sun.COM /*
98*13101SVenki.Rajagopalan@Sun.COM * Grab a chunk of rwqes
99*13101SVenki.Rajagopalan@Sun.COM */
100*13101SVenki.Rajagopalan@Sun.COM chunk_sz = ((limit - wndx) < EIB_RWR_CHUNK_SZ) ?
101*13101SVenki.Rajagopalan@Sun.COM (limit - wndx) : EIB_RWR_CHUNK_SZ;
102*13101SVenki.Rajagopalan@Sun.COM
103*13101SVenki.Rajagopalan@Sun.COM /*
104*13101SVenki.Rajagopalan@Sun.COM * When eib_chan_post_rx() is called to post a bunch of rwqes,
105*13101SVenki.Rajagopalan@Sun.COM * it is either during the vnic setup or when we're refilling
106*13101SVenki.Rajagopalan@Sun.COM * the data channel. Neither situation is important enough for
107*13101SVenki.Rajagopalan@Sun.COM * us to grab the wqes reserved for sending keepalives of
108*13101SVenki.Rajagopalan@Sun.COM * previously established vnics.
109*13101SVenki.Rajagopalan@Sun.COM */
110*13101SVenki.Rajagopalan@Sun.COM ret = eib_rsrc_grab_rwqes(ss, rwqes, chunk_sz, &n_got,
111*13101SVenki.Rajagopalan@Sun.COM EIB_WPRI_LO);
112*13101SVenki.Rajagopalan@Sun.COM if (ret != EIB_E_SUCCESS)
113*13101SVenki.Rajagopalan@Sun.COM break;
114*13101SVenki.Rajagopalan@Sun.COM
115*13101SVenki.Rajagopalan@Sun.COM /*
116*13101SVenki.Rajagopalan@Sun.COM * Post work requests from the rwqes we just grabbed
117*13101SVenki.Rajagopalan@Sun.COM */
118*13101SVenki.Rajagopalan@Sun.COM for (i = 0; i < n_got; i++) {
119*13101SVenki.Rajagopalan@Sun.COM eib_wqe_t *rwqe = rwqes[i];
120*13101SVenki.Rajagopalan@Sun.COM
121*13101SVenki.Rajagopalan@Sun.COM ret = eib_chan_post_recv(ss, chan, rwqe);
122*13101SVenki.Rajagopalan@Sun.COM if (ret == EIB_E_SUCCESS) {
123*13101SVenki.Rajagopalan@Sun.COM n_good++;
124*13101SVenki.Rajagopalan@Sun.COM } else if (rwqe->qe_mp) {
125*13101SVenki.Rajagopalan@Sun.COM freemsg(rwqe->qe_mp);
126*13101SVenki.Rajagopalan@Sun.COM } else {
127*13101SVenki.Rajagopalan@Sun.COM eib_rsrc_return_rwqe(ss, rwqe, NULL);
128*13101SVenki.Rajagopalan@Sun.COM }
129*13101SVenki.Rajagopalan@Sun.COM }
130*13101SVenki.Rajagopalan@Sun.COM
131*13101SVenki.Rajagopalan@Sun.COM /*
132*13101SVenki.Rajagopalan@Sun.COM * If we got less rwqes than we asked for during the grab
133*13101SVenki.Rajagopalan@Sun.COM * earlier, we'll stop asking for more and quit now.
134*13101SVenki.Rajagopalan@Sun.COM */
135*13101SVenki.Rajagopalan@Sun.COM if (n_got < chunk_sz)
136*13101SVenki.Rajagopalan@Sun.COM break;
137*13101SVenki.Rajagopalan@Sun.COM }
138*13101SVenki.Rajagopalan@Sun.COM
139*13101SVenki.Rajagopalan@Sun.COM /*
140*13101SVenki.Rajagopalan@Sun.COM * If we posted absolutely nothing, we return failure; otherwise
141*13101SVenki.Rajagopalan@Sun.COM * return success.
142*13101SVenki.Rajagopalan@Sun.COM */
143*13101SVenki.Rajagopalan@Sun.COM if (n_good == 0)
144*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_FAILURE);
145*13101SVenki.Rajagopalan@Sun.COM
146*13101SVenki.Rajagopalan@Sun.COM if (n_posted)
147*13101SVenki.Rajagopalan@Sun.COM *n_posted = n_good;
148*13101SVenki.Rajagopalan@Sun.COM
149*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_SUCCESS);
150*13101SVenki.Rajagopalan@Sun.COM }
151*13101SVenki.Rajagopalan@Sun.COM
152*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
153*13101SVenki.Rajagopalan@Sun.COM int
eib_chan_post_recv(eib_t * ss,eib_chan_t * chan,eib_wqe_t * rwqe)154*13101SVenki.Rajagopalan@Sun.COM eib_chan_post_recv(eib_t *ss, eib_chan_t *chan, eib_wqe_t *rwqe)
155*13101SVenki.Rajagopalan@Sun.COM {
156*13101SVenki.Rajagopalan@Sun.COM ibt_status_t ret;
157*13101SVenki.Rajagopalan@Sun.COM uint8_t *mp_base;
158*13101SVenki.Rajagopalan@Sun.COM size_t mp_len;
159*13101SVenki.Rajagopalan@Sun.COM
160*13101SVenki.Rajagopalan@Sun.COM rwqe->qe_sgl.ds_va = (ib_vaddr_t)(uintptr_t)rwqe->qe_cpbuf;
161*13101SVenki.Rajagopalan@Sun.COM rwqe->qe_sgl.ds_len = rwqe->qe_bufsz;
162*13101SVenki.Rajagopalan@Sun.COM
163*13101SVenki.Rajagopalan@Sun.COM /*
164*13101SVenki.Rajagopalan@Sun.COM * If this channel has receive buffer alignment restrictions, make
165*13101SVenki.Rajagopalan@Sun.COM * sure the requirements are met
166*13101SVenki.Rajagopalan@Sun.COM */
167*13101SVenki.Rajagopalan@Sun.COM if (chan->ch_ip_hdr_align) {
168*13101SVenki.Rajagopalan@Sun.COM rwqe->qe_sgl.ds_va += chan->ch_ip_hdr_align;
169*13101SVenki.Rajagopalan@Sun.COM rwqe->qe_sgl.ds_len -= chan->ch_ip_hdr_align;
170*13101SVenki.Rajagopalan@Sun.COM }
171*13101SVenki.Rajagopalan@Sun.COM
172*13101SVenki.Rajagopalan@Sun.COM /*
173*13101SVenki.Rajagopalan@Sun.COM * If the receive buffer for this channel needs to have an mblk
174*13101SVenki.Rajagopalan@Sun.COM * allocated, do it
175*13101SVenki.Rajagopalan@Sun.COM */
176*13101SVenki.Rajagopalan@Sun.COM if (chan->ch_alloc_mp) {
177*13101SVenki.Rajagopalan@Sun.COM mp_base = (uint8_t *)(uintptr_t)(rwqe->qe_sgl.ds_va);
178*13101SVenki.Rajagopalan@Sun.COM mp_len = rwqe->qe_sgl.ds_len;
179*13101SVenki.Rajagopalan@Sun.COM
180*13101SVenki.Rajagopalan@Sun.COM rwqe->qe_mp = desballoc(mp_base, mp_len, 0, &rwqe->qe_frp);
181*13101SVenki.Rajagopalan@Sun.COM if (rwqe->qe_mp == NULL) {
182*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_chan_post_recv: "
183*13101SVenki.Rajagopalan@Sun.COM "desballoc(base=0x%llx, len=0x%llx) failed",
184*13101SVenki.Rajagopalan@Sun.COM mp_base, mp_len);
185*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_FAILURE);
186*13101SVenki.Rajagopalan@Sun.COM }
187*13101SVenki.Rajagopalan@Sun.COM }
188*13101SVenki.Rajagopalan@Sun.COM
189*13101SVenki.Rajagopalan@Sun.COM /*
190*13101SVenki.Rajagopalan@Sun.COM * Check if the recv queue is already full or if we can post one more
191*13101SVenki.Rajagopalan@Sun.COM */
192*13101SVenki.Rajagopalan@Sun.COM mutex_enter(&chan->ch_rx_lock);
193*13101SVenki.Rajagopalan@Sun.COM if (chan->ch_rx_posted > (chan->ch_max_rwqes - 1)) {
194*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_chan_post_recv: "
195*13101SVenki.Rajagopalan@Sun.COM "too many rwqes posted already, posted=0x%lx, max=0x%lx",
196*13101SVenki.Rajagopalan@Sun.COM chan->ch_rx_posted, chan->ch_max_rwqes);
197*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&chan->ch_rx_lock);
198*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_FAILURE);
199*13101SVenki.Rajagopalan@Sun.COM }
200*13101SVenki.Rajagopalan@Sun.COM
201*13101SVenki.Rajagopalan@Sun.COM rwqe->qe_vnic_inst = chan->ch_vnic_inst;
202*13101SVenki.Rajagopalan@Sun.COM rwqe->qe_chan = chan;
203*13101SVenki.Rajagopalan@Sun.COM rwqe->qe_info |= EIB_WQE_FLG_POSTED_TO_HCA;
204*13101SVenki.Rajagopalan@Sun.COM
205*13101SVenki.Rajagopalan@Sun.COM ret = ibt_post_recv(chan->ch_chan, &(rwqe->qe_wr.recv), 1, NULL);
206*13101SVenki.Rajagopalan@Sun.COM if (ret != IBT_SUCCESS) {
207*13101SVenki.Rajagopalan@Sun.COM EIB_DPRINTF_ERR(ss->ei_instance, "eib_chan_post_recv: "
208*13101SVenki.Rajagopalan@Sun.COM "ibt_post_recv() failed, ret=%d", ret);
209*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&chan->ch_rx_lock);
210*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_FAILURE);
211*13101SVenki.Rajagopalan@Sun.COM }
212*13101SVenki.Rajagopalan@Sun.COM chan->ch_rx_posted++;
213*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&chan->ch_rx_lock);
214*13101SVenki.Rajagopalan@Sun.COM
215*13101SVenki.Rajagopalan@Sun.COM return (EIB_E_SUCCESS);
216*13101SVenki.Rajagopalan@Sun.COM }
217