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