1*12011SSriharsha.Basavapatna@Sun.COM /*
2*12011SSriharsha.Basavapatna@Sun.COM * CDDL HEADER START
3*12011SSriharsha.Basavapatna@Sun.COM *
4*12011SSriharsha.Basavapatna@Sun.COM * The contents of this file are subject to the terms of the
5*12011SSriharsha.Basavapatna@Sun.COM * Common Development and Distribution License (the "License").
6*12011SSriharsha.Basavapatna@Sun.COM * You may not use this file except in compliance with the License.
7*12011SSriharsha.Basavapatna@Sun.COM *
8*12011SSriharsha.Basavapatna@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*12011SSriharsha.Basavapatna@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*12011SSriharsha.Basavapatna@Sun.COM * See the License for the specific language governing permissions
11*12011SSriharsha.Basavapatna@Sun.COM * and limitations under the License.
12*12011SSriharsha.Basavapatna@Sun.COM *
13*12011SSriharsha.Basavapatna@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*12011SSriharsha.Basavapatna@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*12011SSriharsha.Basavapatna@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*12011SSriharsha.Basavapatna@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*12011SSriharsha.Basavapatna@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*12011SSriharsha.Basavapatna@Sun.COM *
19*12011SSriharsha.Basavapatna@Sun.COM * CDDL HEADER END
20*12011SSriharsha.Basavapatna@Sun.COM */
21*12011SSriharsha.Basavapatna@Sun.COM
22*12011SSriharsha.Basavapatna@Sun.COM /*
23*12011SSriharsha.Basavapatna@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24*12011SSriharsha.Basavapatna@Sun.COM * Use is subject to license terms.
25*12011SSriharsha.Basavapatna@Sun.COM */
26*12011SSriharsha.Basavapatna@Sun.COM #include <sys/types.h>
27*12011SSriharsha.Basavapatna@Sun.COM #include <sys/errno.h>
28*12011SSriharsha.Basavapatna@Sun.COM #include <sys/sysmacros.h>
29*12011SSriharsha.Basavapatna@Sun.COM #include <sys/param.h>
30*12011SSriharsha.Basavapatna@Sun.COM #include <sys/machsystm.h>
31*12011SSriharsha.Basavapatna@Sun.COM #include <sys/stream.h>
32*12011SSriharsha.Basavapatna@Sun.COM #include <sys/strsubr.h>
33*12011SSriharsha.Basavapatna@Sun.COM #include <sys/kmem.h>
34*12011SSriharsha.Basavapatna@Sun.COM #include <sys/strsun.h>
35*12011SSriharsha.Basavapatna@Sun.COM #include <sys/callb.h>
36*12011SSriharsha.Basavapatna@Sun.COM #include <sys/sdt.h>
37*12011SSriharsha.Basavapatna@Sun.COM #include <sys/ethernet.h>
38*12011SSriharsha.Basavapatna@Sun.COM #include <sys/mach_descrip.h>
39*12011SSriharsha.Basavapatna@Sun.COM #include <sys/mdeg.h>
40*12011SSriharsha.Basavapatna@Sun.COM #include <sys/vnet.h>
41*12011SSriharsha.Basavapatna@Sun.COM #include <sys/vio_mailbox.h>
42*12011SSriharsha.Basavapatna@Sun.COM #include <sys/vio_common.h>
43*12011SSriharsha.Basavapatna@Sun.COM #include <sys/vnet_common.h>
44*12011SSriharsha.Basavapatna@Sun.COM #include <sys/vnet_mailbox.h>
45*12011SSriharsha.Basavapatna@Sun.COM #include <sys/vio_util.h>
46*12011SSriharsha.Basavapatna@Sun.COM #include <sys/vnet_gen.h>
47*12011SSriharsha.Basavapatna@Sun.COM
48*12011SSriharsha.Basavapatna@Sun.COM /*
49*12011SSriharsha.Basavapatna@Sun.COM * This file contains the implementation of TxDring data transfer mode of VIO
50*12011SSriharsha.Basavapatna@Sun.COM * Protocol in vnet. The functions in this file are invoked from vnet_gen.c
51*12011SSriharsha.Basavapatna@Sun.COM * after TxDring mode is negotiated with the peer during attribute phase of
52*12011SSriharsha.Basavapatna@Sun.COM * handshake. This file contains functions that setup the transmit and receive
53*12011SSriharsha.Basavapatna@Sun.COM * descriptor rings, and associated resources in TxDring mode. It also contains
54*12011SSriharsha.Basavapatna@Sun.COM * the transmit and receive data processing functions that are invoked in
55*12011SSriharsha.Basavapatna@Sun.COM * TxDring mode.
56*12011SSriharsha.Basavapatna@Sun.COM */
57*12011SSriharsha.Basavapatna@Sun.COM
58*12011SSriharsha.Basavapatna@Sun.COM /* Functions exported to vnet_gen.c */
59*12011SSriharsha.Basavapatna@Sun.COM int vgen_create_tx_dring(vgen_ldc_t *ldcp);
60*12011SSriharsha.Basavapatna@Sun.COM void vgen_destroy_tx_dring(vgen_ldc_t *ldcp);
61*12011SSriharsha.Basavapatna@Sun.COM int vgen_map_rx_dring(vgen_ldc_t *ldcp, void *pkt);
62*12011SSriharsha.Basavapatna@Sun.COM void vgen_unmap_rx_dring(vgen_ldc_t *ldcp);
63*12011SSriharsha.Basavapatna@Sun.COM int vgen_dringsend(void *arg, mblk_t *mp);
64*12011SSriharsha.Basavapatna@Sun.COM void vgen_ldc_msg_worker(void *arg);
65*12011SSriharsha.Basavapatna@Sun.COM void vgen_stop_msg_thread(vgen_ldc_t *ldcp);
66*12011SSriharsha.Basavapatna@Sun.COM int vgen_handle_dringdata(void *arg1, void *arg2);
67*12011SSriharsha.Basavapatna@Sun.COM mblk_t *vgen_poll_rcv(vgen_ldc_t *ldcp, int bytes_to_pickup);
68*12011SSriharsha.Basavapatna@Sun.COM int vgen_check_datamsg_seq(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
69*12011SSriharsha.Basavapatna@Sun.COM int vgen_sendmsg(vgen_ldc_t *ldcp, caddr_t msg, size_t msglen,
70*12011SSriharsha.Basavapatna@Sun.COM boolean_t caller_holds_lock);
71*12011SSriharsha.Basavapatna@Sun.COM
72*12011SSriharsha.Basavapatna@Sun.COM /* Internal functions */
73*12011SSriharsha.Basavapatna@Sun.COM static int vgen_init_multipools(vgen_ldc_t *ldcp);
74*12011SSriharsha.Basavapatna@Sun.COM static int vgen_handle_dringdata_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
75*12011SSriharsha.Basavapatna@Sun.COM static int vgen_process_dringdata(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
76*12011SSriharsha.Basavapatna@Sun.COM static int vgen_handle_dringdata_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
77*12011SSriharsha.Basavapatna@Sun.COM static int vgen_handle_dringdata_nack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
78*12011SSriharsha.Basavapatna@Sun.COM static void vgen_rx(vgen_ldc_t *ldcp, mblk_t *bp, mblk_t *bpt);
79*12011SSriharsha.Basavapatna@Sun.COM static int vgen_send_dringdata(vgen_ldc_t *ldcp, uint32_t start, int32_t end);
80*12011SSriharsha.Basavapatna@Sun.COM static int vgen_send_dringack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp,
81*12011SSriharsha.Basavapatna@Sun.COM uint32_t start, int32_t end, uint8_t pstate);
82*12011SSriharsha.Basavapatna@Sun.COM static void vgen_reclaim(vgen_ldc_t *ldcp);
83*12011SSriharsha.Basavapatna@Sun.COM static void vgen_reclaim_dring(vgen_ldc_t *ldcp);
84*12011SSriharsha.Basavapatna@Sun.COM
85*12011SSriharsha.Basavapatna@Sun.COM /* Functions imported from vnet_gen.c */
86*12011SSriharsha.Basavapatna@Sun.COM extern int vgen_handle_evt_read(vgen_ldc_t *ldcp, vgen_caller_t caller);
87*12011SSriharsha.Basavapatna@Sun.COM extern int vgen_handle_evt_reset(vgen_ldc_t *ldcp, vgen_caller_t caller);
88*12011SSriharsha.Basavapatna@Sun.COM extern void vgen_handle_pkt_data(void *arg1, void *arg2, uint32_t msglen);
89*12011SSriharsha.Basavapatna@Sun.COM extern void vgen_destroy_rxpools(void *arg);
90*12011SSriharsha.Basavapatna@Sun.COM
91*12011SSriharsha.Basavapatna@Sun.COM /* Tunables */
92*12011SSriharsha.Basavapatna@Sun.COM extern int vgen_rxpool_cleanup_delay;
93*12011SSriharsha.Basavapatna@Sun.COM extern boolean_t vnet_jumbo_rxpools;
94*12011SSriharsha.Basavapatna@Sun.COM extern uint32_t vnet_num_descriptors;
95*12011SSriharsha.Basavapatna@Sun.COM extern uint32_t vgen_chain_len;
96*12011SSriharsha.Basavapatna@Sun.COM extern uint32_t vgen_ldcwr_retries;
97*12011SSriharsha.Basavapatna@Sun.COM extern uint32_t vgen_recv_delay;
98*12011SSriharsha.Basavapatna@Sun.COM extern uint32_t vgen_recv_retries;
99*12011SSriharsha.Basavapatna@Sun.COM extern uint32_t vgen_rbufsz1;
100*12011SSriharsha.Basavapatna@Sun.COM extern uint32_t vgen_rbufsz2;
101*12011SSriharsha.Basavapatna@Sun.COM extern uint32_t vgen_rbufsz3;
102*12011SSriharsha.Basavapatna@Sun.COM extern uint32_t vgen_rbufsz4;
103*12011SSriharsha.Basavapatna@Sun.COM extern uint32_t vgen_nrbufs1;
104*12011SSriharsha.Basavapatna@Sun.COM extern uint32_t vgen_nrbufs2;
105*12011SSriharsha.Basavapatna@Sun.COM extern uint32_t vgen_nrbufs3;
106*12011SSriharsha.Basavapatna@Sun.COM extern uint32_t vgen_nrbufs4;
107*12011SSriharsha.Basavapatna@Sun.COM
108*12011SSriharsha.Basavapatna@Sun.COM #ifdef DEBUG
109*12011SSriharsha.Basavapatna@Sun.COM
110*12011SSriharsha.Basavapatna@Sun.COM #define DEBUG_PRINTF vgen_debug_printf
111*12011SSriharsha.Basavapatna@Sun.COM
112*12011SSriharsha.Basavapatna@Sun.COM extern int vnet_dbglevel;
113*12011SSriharsha.Basavapatna@Sun.COM extern int vgen_inject_err_flag;
114*12011SSriharsha.Basavapatna@Sun.COM
115*12011SSriharsha.Basavapatna@Sun.COM extern void vgen_debug_printf(const char *fname, vgen_t *vgenp,
116*12011SSriharsha.Basavapatna@Sun.COM vgen_ldc_t *ldcp, const char *fmt, ...);
117*12011SSriharsha.Basavapatna@Sun.COM extern boolean_t vgen_inject_error(vgen_ldc_t *ldcp, int error);
118*12011SSriharsha.Basavapatna@Sun.COM
119*12011SSriharsha.Basavapatna@Sun.COM #endif
120*12011SSriharsha.Basavapatna@Sun.COM
121*12011SSriharsha.Basavapatna@Sun.COM /*
122*12011SSriharsha.Basavapatna@Sun.COM * Allocate transmit resources for the channel. The resources consist of a
123*12011SSriharsha.Basavapatna@Sun.COM * transmit descriptor ring and an associated transmit buffer area.
124*12011SSriharsha.Basavapatna@Sun.COM */
125*12011SSriharsha.Basavapatna@Sun.COM int
vgen_create_tx_dring(vgen_ldc_t * ldcp)126*12011SSriharsha.Basavapatna@Sun.COM vgen_create_tx_dring(vgen_ldc_t *ldcp)
127*12011SSriharsha.Basavapatna@Sun.COM {
128*12011SSriharsha.Basavapatna@Sun.COM int i;
129*12011SSriharsha.Basavapatna@Sun.COM int rv;
130*12011SSriharsha.Basavapatna@Sun.COM ldc_mem_info_t minfo;
131*12011SSriharsha.Basavapatna@Sun.COM uint32_t txdsize;
132*12011SSriharsha.Basavapatna@Sun.COM uint32_t tbufsize;
133*12011SSriharsha.Basavapatna@Sun.COM vgen_private_desc_t *tbufp;
134*12011SSriharsha.Basavapatna@Sun.COM vnet_public_desc_t *txdp;
135*12011SSriharsha.Basavapatna@Sun.COM vio_dring_entry_hdr_t *hdrp;
136*12011SSriharsha.Basavapatna@Sun.COM caddr_t datap = NULL;
137*12011SSriharsha.Basavapatna@Sun.COM int ci;
138*12011SSriharsha.Basavapatna@Sun.COM uint32_t ncookies;
139*12011SSriharsha.Basavapatna@Sun.COM size_t data_sz;
140*12011SSriharsha.Basavapatna@Sun.COM vgen_t *vgenp = LDC_TO_VGEN(ldcp);
141*12011SSriharsha.Basavapatna@Sun.COM
142*12011SSriharsha.Basavapatna@Sun.COM ldcp->num_txds = vnet_num_descriptors;
143*12011SSriharsha.Basavapatna@Sun.COM txdsize = sizeof (vnet_public_desc_t);
144*12011SSriharsha.Basavapatna@Sun.COM tbufsize = sizeof (vgen_private_desc_t);
145*12011SSriharsha.Basavapatna@Sun.COM
146*12011SSriharsha.Basavapatna@Sun.COM /* allocate transmit buffer ring */
147*12011SSriharsha.Basavapatna@Sun.COM tbufp = kmem_zalloc(ldcp->num_txds * tbufsize, KM_NOSLEEP);
148*12011SSriharsha.Basavapatna@Sun.COM if (tbufp == NULL) {
149*12011SSriharsha.Basavapatna@Sun.COM return (DDI_FAILURE);
150*12011SSriharsha.Basavapatna@Sun.COM }
151*12011SSriharsha.Basavapatna@Sun.COM ldcp->tbufp = tbufp;
152*12011SSriharsha.Basavapatna@Sun.COM ldcp->tbufendp = &((ldcp->tbufp)[ldcp->num_txds]);
153*12011SSriharsha.Basavapatna@Sun.COM
154*12011SSriharsha.Basavapatna@Sun.COM /* create transmit descriptor ring */
155*12011SSriharsha.Basavapatna@Sun.COM rv = ldc_mem_dring_create(ldcp->num_txds, txdsize,
156*12011SSriharsha.Basavapatna@Sun.COM &ldcp->tx_dring_handle);
157*12011SSriharsha.Basavapatna@Sun.COM if (rv != 0) {
158*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "ldc_mem_dring_create() failed\n");
159*12011SSriharsha.Basavapatna@Sun.COM goto fail;
160*12011SSriharsha.Basavapatna@Sun.COM }
161*12011SSriharsha.Basavapatna@Sun.COM
162*12011SSriharsha.Basavapatna@Sun.COM /* get the addr of descriptor ring */
163*12011SSriharsha.Basavapatna@Sun.COM rv = ldc_mem_dring_info(ldcp->tx_dring_handle, &minfo);
164*12011SSriharsha.Basavapatna@Sun.COM if (rv != 0) {
165*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "ldc_mem_dring_info() failed\n");
166*12011SSriharsha.Basavapatna@Sun.COM goto fail;
167*12011SSriharsha.Basavapatna@Sun.COM }
168*12011SSriharsha.Basavapatna@Sun.COM ldcp->txdp = (vnet_public_desc_t *)(minfo.vaddr);
169*12011SSriharsha.Basavapatna@Sun.COM
170*12011SSriharsha.Basavapatna@Sun.COM /*
171*12011SSriharsha.Basavapatna@Sun.COM * In order to ensure that the number of ldc cookies per descriptor is
172*12011SSriharsha.Basavapatna@Sun.COM * limited to be within the default MAX_COOKIES (2), we take the steps
173*12011SSriharsha.Basavapatna@Sun.COM * outlined below:
174*12011SSriharsha.Basavapatna@Sun.COM *
175*12011SSriharsha.Basavapatna@Sun.COM * Align the entire data buffer area to 8K and carve out per descriptor
176*12011SSriharsha.Basavapatna@Sun.COM * data buffers starting from this 8K aligned base address.
177*12011SSriharsha.Basavapatna@Sun.COM *
178*12011SSriharsha.Basavapatna@Sun.COM * We round up the mtu specified to be a multiple of 2K or 4K.
179*12011SSriharsha.Basavapatna@Sun.COM * For sizes up to 12K we round up the size to the next 2K.
180*12011SSriharsha.Basavapatna@Sun.COM * For sizes > 12K we round up to the next 4K (otherwise sizes such as
181*12011SSriharsha.Basavapatna@Sun.COM * 14K could end up needing 3 cookies, with the buffer spread across
182*12011SSriharsha.Basavapatna@Sun.COM * 3 8K pages: 8K+6K, 2K+8K+2K, 6K+8K, ...).
183*12011SSriharsha.Basavapatna@Sun.COM */
184*12011SSriharsha.Basavapatna@Sun.COM data_sz = vgenp->max_frame_size + VNET_IPALIGN + VNET_LDCALIGN;
185*12011SSriharsha.Basavapatna@Sun.COM if (data_sz <= VNET_12K) {
186*12011SSriharsha.Basavapatna@Sun.COM data_sz = VNET_ROUNDUP_2K(data_sz);
187*12011SSriharsha.Basavapatna@Sun.COM } else {
188*12011SSriharsha.Basavapatna@Sun.COM data_sz = VNET_ROUNDUP_4K(data_sz);
189*12011SSriharsha.Basavapatna@Sun.COM }
190*12011SSriharsha.Basavapatna@Sun.COM
191*12011SSriharsha.Basavapatna@Sun.COM /* allocate extra 8K bytes for alignment */
192*12011SSriharsha.Basavapatna@Sun.COM ldcp->tx_data_sz = (data_sz * ldcp->num_txds) + VNET_8K;
193*12011SSriharsha.Basavapatna@Sun.COM datap = kmem_zalloc(ldcp->tx_data_sz, KM_SLEEP);
194*12011SSriharsha.Basavapatna@Sun.COM ldcp->tx_datap = datap;
195*12011SSriharsha.Basavapatna@Sun.COM
196*12011SSriharsha.Basavapatna@Sun.COM
197*12011SSriharsha.Basavapatna@Sun.COM /* align the starting address of the data area to 8K */
198*12011SSriharsha.Basavapatna@Sun.COM datap = (caddr_t)VNET_ROUNDUP_8K((uintptr_t)datap);
199*12011SSriharsha.Basavapatna@Sun.COM
200*12011SSriharsha.Basavapatna@Sun.COM /*
201*12011SSriharsha.Basavapatna@Sun.COM * for each private descriptor, allocate a ldc mem_handle which is
202*12011SSriharsha.Basavapatna@Sun.COM * required to map the data during transmit, set the flags
203*12011SSriharsha.Basavapatna@Sun.COM * to free (available for use by transmit routine).
204*12011SSriharsha.Basavapatna@Sun.COM */
205*12011SSriharsha.Basavapatna@Sun.COM
206*12011SSriharsha.Basavapatna@Sun.COM for (i = 0; i < ldcp->num_txds; i++) {
207*12011SSriharsha.Basavapatna@Sun.COM
208*12011SSriharsha.Basavapatna@Sun.COM tbufp = &(ldcp->tbufp[i]);
209*12011SSriharsha.Basavapatna@Sun.COM rv = ldc_mem_alloc_handle(ldcp->ldc_handle,
210*12011SSriharsha.Basavapatna@Sun.COM &(tbufp->memhandle));
211*12011SSriharsha.Basavapatna@Sun.COM if (rv) {
212*12011SSriharsha.Basavapatna@Sun.COM tbufp->memhandle = 0;
213*12011SSriharsha.Basavapatna@Sun.COM goto fail;
214*12011SSriharsha.Basavapatna@Sun.COM }
215*12011SSriharsha.Basavapatna@Sun.COM
216*12011SSriharsha.Basavapatna@Sun.COM /*
217*12011SSriharsha.Basavapatna@Sun.COM * bind ldc memhandle to the corresponding transmit buffer.
218*12011SSriharsha.Basavapatna@Sun.COM */
219*12011SSriharsha.Basavapatna@Sun.COM ci = ncookies = 0;
220*12011SSriharsha.Basavapatna@Sun.COM rv = ldc_mem_bind_handle(tbufp->memhandle,
221*12011SSriharsha.Basavapatna@Sun.COM (caddr_t)datap, data_sz, LDC_SHADOW_MAP,
222*12011SSriharsha.Basavapatna@Sun.COM LDC_MEM_R, &(tbufp->memcookie[ci]), &ncookies);
223*12011SSriharsha.Basavapatna@Sun.COM if (rv != 0) {
224*12011SSriharsha.Basavapatna@Sun.COM goto fail;
225*12011SSriharsha.Basavapatna@Sun.COM }
226*12011SSriharsha.Basavapatna@Sun.COM
227*12011SSriharsha.Basavapatna@Sun.COM /*
228*12011SSriharsha.Basavapatna@Sun.COM * successful in binding the handle to tx data buffer.
229*12011SSriharsha.Basavapatna@Sun.COM * set datap in the private descr to this buffer.
230*12011SSriharsha.Basavapatna@Sun.COM */
231*12011SSriharsha.Basavapatna@Sun.COM tbufp->datap = datap;
232*12011SSriharsha.Basavapatna@Sun.COM
233*12011SSriharsha.Basavapatna@Sun.COM if ((ncookies == 0) ||
234*12011SSriharsha.Basavapatna@Sun.COM (ncookies > MAX_COOKIES)) {
235*12011SSriharsha.Basavapatna@Sun.COM goto fail;
236*12011SSriharsha.Basavapatna@Sun.COM }
237*12011SSriharsha.Basavapatna@Sun.COM
238*12011SSriharsha.Basavapatna@Sun.COM for (ci = 1; ci < ncookies; ci++) {
239*12011SSriharsha.Basavapatna@Sun.COM rv = ldc_mem_nextcookie(tbufp->memhandle,
240*12011SSriharsha.Basavapatna@Sun.COM &(tbufp->memcookie[ci]));
241*12011SSriharsha.Basavapatna@Sun.COM if (rv != 0) {
242*12011SSriharsha.Basavapatna@Sun.COM goto fail;
243*12011SSriharsha.Basavapatna@Sun.COM }
244*12011SSriharsha.Basavapatna@Sun.COM }
245*12011SSriharsha.Basavapatna@Sun.COM
246*12011SSriharsha.Basavapatna@Sun.COM tbufp->ncookies = ncookies;
247*12011SSriharsha.Basavapatna@Sun.COM datap += data_sz;
248*12011SSriharsha.Basavapatna@Sun.COM
249*12011SSriharsha.Basavapatna@Sun.COM tbufp->flags = VGEN_PRIV_DESC_FREE;
250*12011SSriharsha.Basavapatna@Sun.COM txdp = &(ldcp->txdp[i]);
251*12011SSriharsha.Basavapatna@Sun.COM hdrp = &txdp->hdr;
252*12011SSriharsha.Basavapatna@Sun.COM hdrp->dstate = VIO_DESC_FREE;
253*12011SSriharsha.Basavapatna@Sun.COM hdrp->ack = B_FALSE;
254*12011SSriharsha.Basavapatna@Sun.COM tbufp->descp = txdp;
255*12011SSriharsha.Basavapatna@Sun.COM
256*12011SSriharsha.Basavapatna@Sun.COM }
257*12011SSriharsha.Basavapatna@Sun.COM
258*12011SSriharsha.Basavapatna@Sun.COM /*
259*12011SSriharsha.Basavapatna@Sun.COM * The descriptors and the associated buffers are all ready;
260*12011SSriharsha.Basavapatna@Sun.COM * now bind descriptor ring to the channel.
261*12011SSriharsha.Basavapatna@Sun.COM */
262*12011SSriharsha.Basavapatna@Sun.COM rv = ldc_mem_dring_bind(ldcp->ldc_handle, ldcp->tx_dring_handle,
263*12011SSriharsha.Basavapatna@Sun.COM LDC_DIRECT_MAP | LDC_SHADOW_MAP, LDC_MEM_RW,
264*12011SSriharsha.Basavapatna@Sun.COM &ldcp->tx_dring_cookie, &ncookies);
265*12011SSriharsha.Basavapatna@Sun.COM if (rv != 0) {
266*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "ldc_mem_dring_bind failed "
267*12011SSriharsha.Basavapatna@Sun.COM "rv(%x)\n", rv);
268*12011SSriharsha.Basavapatna@Sun.COM goto fail;
269*12011SSriharsha.Basavapatna@Sun.COM }
270*12011SSriharsha.Basavapatna@Sun.COM ASSERT(ncookies == 1);
271*12011SSriharsha.Basavapatna@Sun.COM ldcp->tx_dring_ncookies = ncookies;
272*12011SSriharsha.Basavapatna@Sun.COM
273*12011SSriharsha.Basavapatna@Sun.COM /* reset tbuf walking pointers */
274*12011SSriharsha.Basavapatna@Sun.COM ldcp->next_tbufp = ldcp->tbufp;
275*12011SSriharsha.Basavapatna@Sun.COM ldcp->cur_tbufp = ldcp->tbufp;
276*12011SSriharsha.Basavapatna@Sun.COM
277*12011SSriharsha.Basavapatna@Sun.COM /* initialize tx seqnum and index */
278*12011SSriharsha.Basavapatna@Sun.COM ldcp->next_txseq = VNET_ISS;
279*12011SSriharsha.Basavapatna@Sun.COM ldcp->next_txi = 0;
280*12011SSriharsha.Basavapatna@Sun.COM
281*12011SSriharsha.Basavapatna@Sun.COM ldcp->resched_peer = B_TRUE;
282*12011SSriharsha.Basavapatna@Sun.COM ldcp->resched_peer_txi = 0;
283*12011SSriharsha.Basavapatna@Sun.COM
284*12011SSriharsha.Basavapatna@Sun.COM return (VGEN_SUCCESS);
285*12011SSriharsha.Basavapatna@Sun.COM
286*12011SSriharsha.Basavapatna@Sun.COM fail:
287*12011SSriharsha.Basavapatna@Sun.COM vgen_destroy_tx_dring(ldcp);
288*12011SSriharsha.Basavapatna@Sun.COM return (VGEN_FAILURE);
289*12011SSriharsha.Basavapatna@Sun.COM }
290*12011SSriharsha.Basavapatna@Sun.COM
291*12011SSriharsha.Basavapatna@Sun.COM /*
292*12011SSriharsha.Basavapatna@Sun.COM * Free transmit resources for the channel.
293*12011SSriharsha.Basavapatna@Sun.COM */
294*12011SSriharsha.Basavapatna@Sun.COM void
vgen_destroy_tx_dring(vgen_ldc_t * ldcp)295*12011SSriharsha.Basavapatna@Sun.COM vgen_destroy_tx_dring(vgen_ldc_t *ldcp)
296*12011SSriharsha.Basavapatna@Sun.COM {
297*12011SSriharsha.Basavapatna@Sun.COM int i;
298*12011SSriharsha.Basavapatna@Sun.COM int tbufsize = sizeof (vgen_private_desc_t);
299*12011SSriharsha.Basavapatna@Sun.COM vgen_private_desc_t *tbufp = ldcp->tbufp;
300*12011SSriharsha.Basavapatna@Sun.COM
301*12011SSriharsha.Basavapatna@Sun.COM /* We first unbind the descriptor ring */
302*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->tx_dring_ncookies != 0) {
303*12011SSriharsha.Basavapatna@Sun.COM (void) ldc_mem_dring_unbind(ldcp->tx_dring_handle);
304*12011SSriharsha.Basavapatna@Sun.COM ldcp->tx_dring_ncookies = 0;
305*12011SSriharsha.Basavapatna@Sun.COM }
306*12011SSriharsha.Basavapatna@Sun.COM
307*12011SSriharsha.Basavapatna@Sun.COM /* Unbind transmit buffers */
308*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->tbufp != NULL) {
309*12011SSriharsha.Basavapatna@Sun.COM /* for each tbuf (priv_desc), free ldc mem_handle */
310*12011SSriharsha.Basavapatna@Sun.COM for (i = 0; i < ldcp->num_txds; i++) {
311*12011SSriharsha.Basavapatna@Sun.COM
312*12011SSriharsha.Basavapatna@Sun.COM tbufp = &(ldcp->tbufp[i]);
313*12011SSriharsha.Basavapatna@Sun.COM
314*12011SSriharsha.Basavapatna@Sun.COM if (tbufp->datap) { /* if bound to a ldc memhandle */
315*12011SSriharsha.Basavapatna@Sun.COM (void) ldc_mem_unbind_handle(tbufp->memhandle);
316*12011SSriharsha.Basavapatna@Sun.COM tbufp->datap = NULL;
317*12011SSriharsha.Basavapatna@Sun.COM }
318*12011SSriharsha.Basavapatna@Sun.COM if (tbufp->memhandle) {
319*12011SSriharsha.Basavapatna@Sun.COM (void) ldc_mem_free_handle(tbufp->memhandle);
320*12011SSriharsha.Basavapatna@Sun.COM tbufp->memhandle = 0;
321*12011SSriharsha.Basavapatna@Sun.COM }
322*12011SSriharsha.Basavapatna@Sun.COM }
323*12011SSriharsha.Basavapatna@Sun.COM }
324*12011SSriharsha.Basavapatna@Sun.COM
325*12011SSriharsha.Basavapatna@Sun.COM /* Free tx data buffer area */
326*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->tx_datap != NULL) {
327*12011SSriharsha.Basavapatna@Sun.COM kmem_free(ldcp->tx_datap, ldcp->tx_data_sz);
328*12011SSriharsha.Basavapatna@Sun.COM ldcp->tx_datap = NULL;
329*12011SSriharsha.Basavapatna@Sun.COM ldcp->tx_data_sz = 0;
330*12011SSriharsha.Basavapatna@Sun.COM }
331*12011SSriharsha.Basavapatna@Sun.COM
332*12011SSriharsha.Basavapatna@Sun.COM /* Free transmit descriptor ring */
333*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->tx_dring_handle != 0) {
334*12011SSriharsha.Basavapatna@Sun.COM (void) ldc_mem_dring_destroy(ldcp->tx_dring_handle);
335*12011SSriharsha.Basavapatna@Sun.COM ldcp->tx_dring_handle = 0;
336*12011SSriharsha.Basavapatna@Sun.COM ldcp->txdp = NULL;
337*12011SSriharsha.Basavapatna@Sun.COM }
338*12011SSriharsha.Basavapatna@Sun.COM
339*12011SSriharsha.Basavapatna@Sun.COM /* Free transmit buffer ring */
340*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->tbufp != NULL) {
341*12011SSriharsha.Basavapatna@Sun.COM kmem_free(ldcp->tbufp, ldcp->num_txds * tbufsize);
342*12011SSriharsha.Basavapatna@Sun.COM ldcp->tbufp = ldcp->tbufendp = NULL;
343*12011SSriharsha.Basavapatna@Sun.COM }
344*12011SSriharsha.Basavapatna@Sun.COM }
345*12011SSriharsha.Basavapatna@Sun.COM
346*12011SSriharsha.Basavapatna@Sun.COM /*
347*12011SSriharsha.Basavapatna@Sun.COM * Map the transmit descriptor ring exported
348*12011SSriharsha.Basavapatna@Sun.COM * by the peer, as our receive descriptor ring.
349*12011SSriharsha.Basavapatna@Sun.COM */
350*12011SSriharsha.Basavapatna@Sun.COM int
vgen_map_rx_dring(vgen_ldc_t * ldcp,void * pkt)351*12011SSriharsha.Basavapatna@Sun.COM vgen_map_rx_dring(vgen_ldc_t *ldcp, void *pkt)
352*12011SSriharsha.Basavapatna@Sun.COM {
353*12011SSriharsha.Basavapatna@Sun.COM int rv;
354*12011SSriharsha.Basavapatna@Sun.COM ldc_mem_info_t minfo;
355*12011SSriharsha.Basavapatna@Sun.COM ldc_mem_cookie_t dcookie;
356*12011SSriharsha.Basavapatna@Sun.COM uint32_t ncookies;
357*12011SSriharsha.Basavapatna@Sun.COM uint32_t num_desc;
358*12011SSriharsha.Basavapatna@Sun.COM uint32_t desc_size;
359*12011SSriharsha.Basavapatna@Sun.COM vio_dring_reg_msg_t *msg = pkt;
360*12011SSriharsha.Basavapatna@Sun.COM vgen_t *vgenp = LDC_TO_VGEN(ldcp);
361*12011SSriharsha.Basavapatna@Sun.COM
362*12011SSriharsha.Basavapatna@Sun.COM ncookies = msg->ncookies;
363*12011SSriharsha.Basavapatna@Sun.COM num_desc = msg->num_descriptors;
364*12011SSriharsha.Basavapatna@Sun.COM desc_size = msg->descriptor_size;
365*12011SSriharsha.Basavapatna@Sun.COM bcopy(&msg->cookie[0], &dcookie, sizeof (ldc_mem_cookie_t));
366*12011SSriharsha.Basavapatna@Sun.COM
367*12011SSriharsha.Basavapatna@Sun.COM /*
368*12011SSriharsha.Basavapatna@Sun.COM * Sanity check.
369*12011SSriharsha.Basavapatna@Sun.COM */
370*12011SSriharsha.Basavapatna@Sun.COM if (num_desc < VGEN_NUM_DESCRIPTORS_MIN ||
371*12011SSriharsha.Basavapatna@Sun.COM desc_size < sizeof (vnet_public_desc_t)) {
372*12011SSriharsha.Basavapatna@Sun.COM goto fail;
373*12011SSriharsha.Basavapatna@Sun.COM }
374*12011SSriharsha.Basavapatna@Sun.COM
375*12011SSriharsha.Basavapatna@Sun.COM /* Map the remote dring */
376*12011SSriharsha.Basavapatna@Sun.COM rv = ldc_mem_dring_map(ldcp->ldc_handle, &dcookie, ncookies, num_desc,
377*12011SSriharsha.Basavapatna@Sun.COM desc_size, LDC_DIRECT_MAP, &(ldcp->rx_dring_handle));
378*12011SSriharsha.Basavapatna@Sun.COM if (rv != 0) {
379*12011SSriharsha.Basavapatna@Sun.COM goto fail;
380*12011SSriharsha.Basavapatna@Sun.COM }
381*12011SSriharsha.Basavapatna@Sun.COM
382*12011SSriharsha.Basavapatna@Sun.COM /*
383*12011SSriharsha.Basavapatna@Sun.COM * Sucessfully mapped, now try to get info about the mapped dring
384*12011SSriharsha.Basavapatna@Sun.COM */
385*12011SSriharsha.Basavapatna@Sun.COM rv = ldc_mem_dring_info(ldcp->rx_dring_handle, &minfo);
386*12011SSriharsha.Basavapatna@Sun.COM if (rv != 0) {
387*12011SSriharsha.Basavapatna@Sun.COM goto fail;
388*12011SSriharsha.Basavapatna@Sun.COM }
389*12011SSriharsha.Basavapatna@Sun.COM
390*12011SSriharsha.Basavapatna@Sun.COM /*
391*12011SSriharsha.Basavapatna@Sun.COM * Save ring address, number of descriptors.
392*12011SSriharsha.Basavapatna@Sun.COM */
393*12011SSriharsha.Basavapatna@Sun.COM ldcp->mrxdp = (vnet_public_desc_t *)(minfo.vaddr);
394*12011SSriharsha.Basavapatna@Sun.COM bcopy(&dcookie, &(ldcp->rx_dring_cookie), sizeof (dcookie));
395*12011SSriharsha.Basavapatna@Sun.COM ldcp->rx_dring_ncookies = ncookies;
396*12011SSriharsha.Basavapatna@Sun.COM ldcp->num_rxds = num_desc;
397*12011SSriharsha.Basavapatna@Sun.COM
398*12011SSriharsha.Basavapatna@Sun.COM /* Initialize rx dring indexes and seqnum */
399*12011SSriharsha.Basavapatna@Sun.COM ldcp->next_rxi = 0;
400*12011SSriharsha.Basavapatna@Sun.COM ldcp->next_rxseq = VNET_ISS;
401*12011SSriharsha.Basavapatna@Sun.COM ldcp->dring_mtype = minfo.mtype;
402*12011SSriharsha.Basavapatna@Sun.COM
403*12011SSriharsha.Basavapatna@Sun.COM /* Save peer's dring_info values */
404*12011SSriharsha.Basavapatna@Sun.COM bcopy(&dcookie, &(ldcp->peer_hparams.dring_cookie),
405*12011SSriharsha.Basavapatna@Sun.COM sizeof (ldc_mem_cookie_t));
406*12011SSriharsha.Basavapatna@Sun.COM ldcp->peer_hparams.num_desc = num_desc;
407*12011SSriharsha.Basavapatna@Sun.COM ldcp->peer_hparams.desc_size = desc_size;
408*12011SSriharsha.Basavapatna@Sun.COM ldcp->peer_hparams.dring_ncookies = ncookies;
409*12011SSriharsha.Basavapatna@Sun.COM
410*12011SSriharsha.Basavapatna@Sun.COM /* Set dring_ident for the peer */
411*12011SSriharsha.Basavapatna@Sun.COM ldcp->peer_hparams.dring_ident = (uint64_t)ldcp->txdp;
412*12011SSriharsha.Basavapatna@Sun.COM
413*12011SSriharsha.Basavapatna@Sun.COM /* Return the dring_ident in ack msg */
414*12011SSriharsha.Basavapatna@Sun.COM msg->dring_ident = (uint64_t)ldcp->txdp;
415*12011SSriharsha.Basavapatna@Sun.COM
416*12011SSriharsha.Basavapatna@Sun.COM /* alloc rx mblk pools */
417*12011SSriharsha.Basavapatna@Sun.COM rv = vgen_init_multipools(ldcp);
418*12011SSriharsha.Basavapatna@Sun.COM if (rv != 0) {
419*12011SSriharsha.Basavapatna@Sun.COM /*
420*12011SSriharsha.Basavapatna@Sun.COM * We do not return failure if receive mblk pools can't
421*12011SSriharsha.Basavapatna@Sun.COM * be allocated; instead allocb(9F) will be used to
422*12011SSriharsha.Basavapatna@Sun.COM * dynamically allocate buffers during receive.
423*12011SSriharsha.Basavapatna@Sun.COM */
424*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp,
425*12011SSriharsha.Basavapatna@Sun.COM "vnet%d: failed to allocate rx mblk "
426*12011SSriharsha.Basavapatna@Sun.COM "pools for channel(0x%lx)\n",
427*12011SSriharsha.Basavapatna@Sun.COM vgenp->instance, ldcp->ldc_id);
428*12011SSriharsha.Basavapatna@Sun.COM }
429*12011SSriharsha.Basavapatna@Sun.COM
430*12011SSriharsha.Basavapatna@Sun.COM return (VGEN_SUCCESS);
431*12011SSriharsha.Basavapatna@Sun.COM
432*12011SSriharsha.Basavapatna@Sun.COM fail:
433*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->rx_dring_handle != 0) {
434*12011SSriharsha.Basavapatna@Sun.COM (void) ldc_mem_dring_unmap(ldcp->rx_dring_handle);
435*12011SSriharsha.Basavapatna@Sun.COM ldcp->rx_dring_handle = 0;
436*12011SSriharsha.Basavapatna@Sun.COM }
437*12011SSriharsha.Basavapatna@Sun.COM return (VGEN_FAILURE);
438*12011SSriharsha.Basavapatna@Sun.COM }
439*12011SSriharsha.Basavapatna@Sun.COM
440*12011SSriharsha.Basavapatna@Sun.COM /*
441*12011SSriharsha.Basavapatna@Sun.COM * Unmap the receive descriptor ring.
442*12011SSriharsha.Basavapatna@Sun.COM */
443*12011SSriharsha.Basavapatna@Sun.COM void
vgen_unmap_rx_dring(vgen_ldc_t * ldcp)444*12011SSriharsha.Basavapatna@Sun.COM vgen_unmap_rx_dring(vgen_ldc_t *ldcp)
445*12011SSriharsha.Basavapatna@Sun.COM {
446*12011SSriharsha.Basavapatna@Sun.COM vgen_t *vgenp = LDC_TO_VGEN(ldcp);
447*12011SSriharsha.Basavapatna@Sun.COM vio_mblk_pool_t *vmp = NULL;
448*12011SSriharsha.Basavapatna@Sun.COM
449*12011SSriharsha.Basavapatna@Sun.COM /* Destroy receive mblk pools */
450*12011SSriharsha.Basavapatna@Sun.COM vio_destroy_multipools(&ldcp->vmp, &vmp);
451*12011SSriharsha.Basavapatna@Sun.COM if (vmp != NULL) {
452*12011SSriharsha.Basavapatna@Sun.COM /*
453*12011SSriharsha.Basavapatna@Sun.COM * If we can't destroy the rx pool for this channel,
454*12011SSriharsha.Basavapatna@Sun.COM * dispatch a task to retry and clean up. Note that we
455*12011SSriharsha.Basavapatna@Sun.COM * don't need to wait for the task to complete. If the
456*12011SSriharsha.Basavapatna@Sun.COM * vnet device itself gets detached, it will wait for
457*12011SSriharsha.Basavapatna@Sun.COM * the task to complete implicitly in
458*12011SSriharsha.Basavapatna@Sun.COM * ddi_taskq_destroy().
459*12011SSriharsha.Basavapatna@Sun.COM */
460*12011SSriharsha.Basavapatna@Sun.COM (void) ddi_taskq_dispatch(vgenp->rxp_taskq,
461*12011SSriharsha.Basavapatna@Sun.COM vgen_destroy_rxpools, vmp, DDI_SLEEP);
462*12011SSriharsha.Basavapatna@Sun.COM }
463*12011SSriharsha.Basavapatna@Sun.COM
464*12011SSriharsha.Basavapatna@Sun.COM /* Unmap peer's dring */
465*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->rx_dring_handle != 0) {
466*12011SSriharsha.Basavapatna@Sun.COM (void) ldc_mem_dring_unmap(ldcp->rx_dring_handle);
467*12011SSriharsha.Basavapatna@Sun.COM ldcp->rx_dring_handle = 0;
468*12011SSriharsha.Basavapatna@Sun.COM }
469*12011SSriharsha.Basavapatna@Sun.COM
470*12011SSriharsha.Basavapatna@Sun.COM /* clobber rx ring members */
471*12011SSriharsha.Basavapatna@Sun.COM bzero(&ldcp->rx_dring_cookie, sizeof (ldcp->rx_dring_cookie));
472*12011SSriharsha.Basavapatna@Sun.COM ldcp->mrxdp = NULL;
473*12011SSriharsha.Basavapatna@Sun.COM ldcp->next_rxi = 0;
474*12011SSriharsha.Basavapatna@Sun.COM ldcp->num_rxds = 0;
475*12011SSriharsha.Basavapatna@Sun.COM ldcp->next_rxseq = VNET_ISS;
476*12011SSriharsha.Basavapatna@Sun.COM }
477*12011SSriharsha.Basavapatna@Sun.COM
478*12011SSriharsha.Basavapatna@Sun.COM /* Allocate receive resources */
479*12011SSriharsha.Basavapatna@Sun.COM static int
vgen_init_multipools(vgen_ldc_t * ldcp)480*12011SSriharsha.Basavapatna@Sun.COM vgen_init_multipools(vgen_ldc_t *ldcp)
481*12011SSriharsha.Basavapatna@Sun.COM {
482*12011SSriharsha.Basavapatna@Sun.COM size_t data_sz;
483*12011SSriharsha.Basavapatna@Sun.COM vgen_t *vgenp = LDC_TO_VGEN(ldcp);
484*12011SSriharsha.Basavapatna@Sun.COM int status;
485*12011SSriharsha.Basavapatna@Sun.COM uint32_t sz1 = 0;
486*12011SSriharsha.Basavapatna@Sun.COM uint32_t sz2 = 0;
487*12011SSriharsha.Basavapatna@Sun.COM uint32_t sz3 = 0;
488*12011SSriharsha.Basavapatna@Sun.COM uint32_t sz4 = 0;
489*12011SSriharsha.Basavapatna@Sun.COM
490*12011SSriharsha.Basavapatna@Sun.COM /*
491*12011SSriharsha.Basavapatna@Sun.COM * We round up the mtu specified to be a multiple of 2K.
492*12011SSriharsha.Basavapatna@Sun.COM * We then create rx pools based on the rounded up size.
493*12011SSriharsha.Basavapatna@Sun.COM */
494*12011SSriharsha.Basavapatna@Sun.COM data_sz = vgenp->max_frame_size + VNET_IPALIGN + VNET_LDCALIGN;
495*12011SSriharsha.Basavapatna@Sun.COM data_sz = VNET_ROUNDUP_2K(data_sz);
496*12011SSriharsha.Basavapatna@Sun.COM
497*12011SSriharsha.Basavapatna@Sun.COM /*
498*12011SSriharsha.Basavapatna@Sun.COM * If pool sizes are specified, use them. Note that the presence of
499*12011SSriharsha.Basavapatna@Sun.COM * the first tunable will be used as a hint.
500*12011SSriharsha.Basavapatna@Sun.COM */
501*12011SSriharsha.Basavapatna@Sun.COM if (vgen_rbufsz1 != 0) {
502*12011SSriharsha.Basavapatna@Sun.COM
503*12011SSriharsha.Basavapatna@Sun.COM sz1 = vgen_rbufsz1;
504*12011SSriharsha.Basavapatna@Sun.COM sz2 = vgen_rbufsz2;
505*12011SSriharsha.Basavapatna@Sun.COM sz3 = vgen_rbufsz3;
506*12011SSriharsha.Basavapatna@Sun.COM sz4 = vgen_rbufsz4;
507*12011SSriharsha.Basavapatna@Sun.COM
508*12011SSriharsha.Basavapatna@Sun.COM if (sz4 == 0) { /* need 3 pools */
509*12011SSriharsha.Basavapatna@Sun.COM
510*12011SSriharsha.Basavapatna@Sun.COM ldcp->max_rxpool_size = sz3;
511*12011SSriharsha.Basavapatna@Sun.COM status = vio_init_multipools(&ldcp->vmp,
512*12011SSriharsha.Basavapatna@Sun.COM VGEN_NUM_VMPOOLS, sz1, sz2, sz3, vgen_nrbufs1,
513*12011SSriharsha.Basavapatna@Sun.COM vgen_nrbufs2, vgen_nrbufs3);
514*12011SSriharsha.Basavapatna@Sun.COM
515*12011SSriharsha.Basavapatna@Sun.COM } else {
516*12011SSriharsha.Basavapatna@Sun.COM
517*12011SSriharsha.Basavapatna@Sun.COM ldcp->max_rxpool_size = sz4;
518*12011SSriharsha.Basavapatna@Sun.COM status = vio_init_multipools(&ldcp->vmp,
519*12011SSriharsha.Basavapatna@Sun.COM VGEN_NUM_VMPOOLS + 1, sz1, sz2, sz3, sz4,
520*12011SSriharsha.Basavapatna@Sun.COM vgen_nrbufs1, vgen_nrbufs2, vgen_nrbufs3,
521*12011SSriharsha.Basavapatna@Sun.COM vgen_nrbufs4);
522*12011SSriharsha.Basavapatna@Sun.COM }
523*12011SSriharsha.Basavapatna@Sun.COM return (status);
524*12011SSriharsha.Basavapatna@Sun.COM }
525*12011SSriharsha.Basavapatna@Sun.COM
526*12011SSriharsha.Basavapatna@Sun.COM /*
527*12011SSriharsha.Basavapatna@Sun.COM * Pool sizes are not specified. We select the pool sizes based on the
528*12011SSriharsha.Basavapatna@Sun.COM * mtu if vnet_jumbo_rxpools is enabled.
529*12011SSriharsha.Basavapatna@Sun.COM */
530*12011SSriharsha.Basavapatna@Sun.COM if (vnet_jumbo_rxpools == B_FALSE || data_sz == VNET_2K) {
531*12011SSriharsha.Basavapatna@Sun.COM /*
532*12011SSriharsha.Basavapatna@Sun.COM * Receive buffer pool allocation based on mtu is disabled.
533*12011SSriharsha.Basavapatna@Sun.COM * Use the default mechanism of standard size pool allocation.
534*12011SSriharsha.Basavapatna@Sun.COM */
535*12011SSriharsha.Basavapatna@Sun.COM sz1 = VGEN_DBLK_SZ_128;
536*12011SSriharsha.Basavapatna@Sun.COM sz2 = VGEN_DBLK_SZ_256;
537*12011SSriharsha.Basavapatna@Sun.COM sz3 = VGEN_DBLK_SZ_2048;
538*12011SSriharsha.Basavapatna@Sun.COM ldcp->max_rxpool_size = sz3;
539*12011SSriharsha.Basavapatna@Sun.COM
540*12011SSriharsha.Basavapatna@Sun.COM status = vio_init_multipools(&ldcp->vmp, VGEN_NUM_VMPOOLS,
541*12011SSriharsha.Basavapatna@Sun.COM sz1, sz2, sz3,
542*12011SSriharsha.Basavapatna@Sun.COM vgen_nrbufs1, vgen_nrbufs2, vgen_nrbufs3);
543*12011SSriharsha.Basavapatna@Sun.COM
544*12011SSriharsha.Basavapatna@Sun.COM return (status);
545*12011SSriharsha.Basavapatna@Sun.COM }
546*12011SSriharsha.Basavapatna@Sun.COM
547*12011SSriharsha.Basavapatna@Sun.COM switch (data_sz) {
548*12011SSriharsha.Basavapatna@Sun.COM
549*12011SSriharsha.Basavapatna@Sun.COM case VNET_4K:
550*12011SSriharsha.Basavapatna@Sun.COM
551*12011SSriharsha.Basavapatna@Sun.COM sz1 = VGEN_DBLK_SZ_128;
552*12011SSriharsha.Basavapatna@Sun.COM sz2 = VGEN_DBLK_SZ_256;
553*12011SSriharsha.Basavapatna@Sun.COM sz3 = VGEN_DBLK_SZ_2048;
554*12011SSriharsha.Basavapatna@Sun.COM sz4 = sz3 << 1; /* 4K */
555*12011SSriharsha.Basavapatna@Sun.COM ldcp->max_rxpool_size = sz4;
556*12011SSriharsha.Basavapatna@Sun.COM
557*12011SSriharsha.Basavapatna@Sun.COM status = vio_init_multipools(&ldcp->vmp, VGEN_NUM_VMPOOLS + 1,
558*12011SSriharsha.Basavapatna@Sun.COM sz1, sz2, sz3, sz4,
559*12011SSriharsha.Basavapatna@Sun.COM vgen_nrbufs1, vgen_nrbufs2, vgen_nrbufs3, vgen_nrbufs4);
560*12011SSriharsha.Basavapatna@Sun.COM break;
561*12011SSriharsha.Basavapatna@Sun.COM
562*12011SSriharsha.Basavapatna@Sun.COM default: /* data_sz: 4K+ to 16K */
563*12011SSriharsha.Basavapatna@Sun.COM
564*12011SSriharsha.Basavapatna@Sun.COM sz1 = VGEN_DBLK_SZ_256;
565*12011SSriharsha.Basavapatna@Sun.COM sz2 = VGEN_DBLK_SZ_2048;
566*12011SSriharsha.Basavapatna@Sun.COM sz3 = data_sz >> 1; /* Jumbo-size/2 */
567*12011SSriharsha.Basavapatna@Sun.COM sz4 = data_sz; /* Jumbo-size */
568*12011SSriharsha.Basavapatna@Sun.COM ldcp->max_rxpool_size = sz4;
569*12011SSriharsha.Basavapatna@Sun.COM
570*12011SSriharsha.Basavapatna@Sun.COM status = vio_init_multipools(&ldcp->vmp, VGEN_NUM_VMPOOLS + 1,
571*12011SSriharsha.Basavapatna@Sun.COM sz1, sz2, sz3, sz4,
572*12011SSriharsha.Basavapatna@Sun.COM vgen_nrbufs1, vgen_nrbufs2, vgen_nrbufs3, vgen_nrbufs4);
573*12011SSriharsha.Basavapatna@Sun.COM break;
574*12011SSriharsha.Basavapatna@Sun.COM
575*12011SSriharsha.Basavapatna@Sun.COM }
576*12011SSriharsha.Basavapatna@Sun.COM
577*12011SSriharsha.Basavapatna@Sun.COM return (status);
578*12011SSriharsha.Basavapatna@Sun.COM }
579*12011SSriharsha.Basavapatna@Sun.COM
580*12011SSriharsha.Basavapatna@Sun.COM /*
581*12011SSriharsha.Basavapatna@Sun.COM * This function transmits normal data frames (non-priority) over the channel.
582*12011SSriharsha.Basavapatna@Sun.COM * It queues the frame into the transmit descriptor ring and sends a
583*12011SSriharsha.Basavapatna@Sun.COM * VIO_DRING_DATA message if needed, to wake up the peer to (re)start
584*12011SSriharsha.Basavapatna@Sun.COM * processing.
585*12011SSriharsha.Basavapatna@Sun.COM */
586*12011SSriharsha.Basavapatna@Sun.COM int
vgen_dringsend(void * arg,mblk_t * mp)587*12011SSriharsha.Basavapatna@Sun.COM vgen_dringsend(void *arg, mblk_t *mp)
588*12011SSriharsha.Basavapatna@Sun.COM {
589*12011SSriharsha.Basavapatna@Sun.COM vgen_ldc_t *ldcp = (vgen_ldc_t *)arg;
590*12011SSriharsha.Basavapatna@Sun.COM vgen_private_desc_t *tbufp;
591*12011SSriharsha.Basavapatna@Sun.COM vgen_private_desc_t *rtbufp;
592*12011SSriharsha.Basavapatna@Sun.COM vnet_public_desc_t *rtxdp;
593*12011SSriharsha.Basavapatna@Sun.COM vgen_private_desc_t *ntbufp;
594*12011SSriharsha.Basavapatna@Sun.COM vnet_public_desc_t *txdp;
595*12011SSriharsha.Basavapatna@Sun.COM vio_dring_entry_hdr_t *hdrp;
596*12011SSriharsha.Basavapatna@Sun.COM vgen_stats_t *statsp;
597*12011SSriharsha.Basavapatna@Sun.COM struct ether_header *ehp;
598*12011SSriharsha.Basavapatna@Sun.COM boolean_t is_bcast = B_FALSE;
599*12011SSriharsha.Basavapatna@Sun.COM boolean_t is_mcast = B_FALSE;
600*12011SSriharsha.Basavapatna@Sun.COM size_t mblksz;
601*12011SSriharsha.Basavapatna@Sun.COM caddr_t dst;
602*12011SSriharsha.Basavapatna@Sun.COM mblk_t *bp;
603*12011SSriharsha.Basavapatna@Sun.COM size_t size;
604*12011SSriharsha.Basavapatna@Sun.COM int rv = 0;
605*12011SSriharsha.Basavapatna@Sun.COM vgen_t *vgenp = LDC_TO_VGEN(ldcp);
606*12011SSriharsha.Basavapatna@Sun.COM vgen_hparams_t *lp = &ldcp->local_hparams;
607*12011SSriharsha.Basavapatna@Sun.COM
608*12011SSriharsha.Basavapatna@Sun.COM statsp = &ldcp->stats;
609*12011SSriharsha.Basavapatna@Sun.COM size = msgsize(mp);
610*12011SSriharsha.Basavapatna@Sun.COM
611*12011SSriharsha.Basavapatna@Sun.COM DBG1(vgenp, ldcp, "enter\n");
612*12011SSriharsha.Basavapatna@Sun.COM
613*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->ldc_status != LDC_UP) {
614*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "status(%d), dropping packet\n",
615*12011SSriharsha.Basavapatna@Sun.COM ldcp->ldc_status);
616*12011SSriharsha.Basavapatna@Sun.COM goto dringsend_exit;
617*12011SSriharsha.Basavapatna@Sun.COM }
618*12011SSriharsha.Basavapatna@Sun.COM
619*12011SSriharsha.Basavapatna@Sun.COM /* drop the packet if ldc is not up or handshake is not done */
620*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->hphase != VH_DONE) {
621*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "hphase(%x), dropping packet\n",
622*12011SSriharsha.Basavapatna@Sun.COM ldcp->hphase);
623*12011SSriharsha.Basavapatna@Sun.COM goto dringsend_exit;
624*12011SSriharsha.Basavapatna@Sun.COM }
625*12011SSriharsha.Basavapatna@Sun.COM
626*12011SSriharsha.Basavapatna@Sun.COM if (size > (size_t)lp->mtu) {
627*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "invalid size(%d)\n", size);
628*12011SSriharsha.Basavapatna@Sun.COM goto dringsend_exit;
629*12011SSriharsha.Basavapatna@Sun.COM }
630*12011SSriharsha.Basavapatna@Sun.COM if (size < ETHERMIN)
631*12011SSriharsha.Basavapatna@Sun.COM size = ETHERMIN;
632*12011SSriharsha.Basavapatna@Sun.COM
633*12011SSriharsha.Basavapatna@Sun.COM ehp = (struct ether_header *)mp->b_rptr;
634*12011SSriharsha.Basavapatna@Sun.COM is_bcast = IS_BROADCAST(ehp);
635*12011SSriharsha.Basavapatna@Sun.COM is_mcast = IS_MULTICAST(ehp);
636*12011SSriharsha.Basavapatna@Sun.COM
637*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->txlock);
638*12011SSriharsha.Basavapatna@Sun.COM /*
639*12011SSriharsha.Basavapatna@Sun.COM * allocate a descriptor
640*12011SSriharsha.Basavapatna@Sun.COM */
641*12011SSriharsha.Basavapatna@Sun.COM tbufp = ldcp->next_tbufp;
642*12011SSriharsha.Basavapatna@Sun.COM ntbufp = NEXTTBUF(ldcp, tbufp);
643*12011SSriharsha.Basavapatna@Sun.COM if (ntbufp == ldcp->cur_tbufp) { /* out of tbufs/txds */
644*12011SSriharsha.Basavapatna@Sun.COM
645*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->tclock);
646*12011SSriharsha.Basavapatna@Sun.COM /* Try reclaiming now */
647*12011SSriharsha.Basavapatna@Sun.COM vgen_reclaim_dring(ldcp);
648*12011SSriharsha.Basavapatna@Sun.COM ldcp->reclaim_lbolt = ddi_get_lbolt();
649*12011SSriharsha.Basavapatna@Sun.COM
650*12011SSriharsha.Basavapatna@Sun.COM if (ntbufp == ldcp->cur_tbufp) {
651*12011SSriharsha.Basavapatna@Sun.COM /* Now we are really out of tbuf/txds */
652*12011SSriharsha.Basavapatna@Sun.COM ldcp->tx_blocked_lbolt = ddi_get_lbolt();
653*12011SSriharsha.Basavapatna@Sun.COM ldcp->tx_blocked = B_TRUE;
654*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->tclock);
655*12011SSriharsha.Basavapatna@Sun.COM
656*12011SSriharsha.Basavapatna@Sun.COM statsp->tx_no_desc++;
657*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->txlock);
658*12011SSriharsha.Basavapatna@Sun.COM
659*12011SSriharsha.Basavapatna@Sun.COM return (VGEN_TX_NORESOURCES);
660*12011SSriharsha.Basavapatna@Sun.COM }
661*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->tclock);
662*12011SSriharsha.Basavapatna@Sun.COM }
663*12011SSriharsha.Basavapatna@Sun.COM /* update next available tbuf in the ring and update tx index */
664*12011SSriharsha.Basavapatna@Sun.COM ldcp->next_tbufp = ntbufp;
665*12011SSriharsha.Basavapatna@Sun.COM INCR_TXI(ldcp->next_txi, ldcp);
666*12011SSriharsha.Basavapatna@Sun.COM
667*12011SSriharsha.Basavapatna@Sun.COM /* Mark the buffer busy before releasing the lock */
668*12011SSriharsha.Basavapatna@Sun.COM tbufp->flags = VGEN_PRIV_DESC_BUSY;
669*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->txlock);
670*12011SSriharsha.Basavapatna@Sun.COM
671*12011SSriharsha.Basavapatna@Sun.COM /* copy data into pre-allocated transmit buffer */
672*12011SSriharsha.Basavapatna@Sun.COM dst = tbufp->datap + VNET_IPALIGN;
673*12011SSriharsha.Basavapatna@Sun.COM for (bp = mp; bp != NULL; bp = bp->b_cont) {
674*12011SSriharsha.Basavapatna@Sun.COM mblksz = MBLKL(bp);
675*12011SSriharsha.Basavapatna@Sun.COM bcopy(bp->b_rptr, dst, mblksz);
676*12011SSriharsha.Basavapatna@Sun.COM dst += mblksz;
677*12011SSriharsha.Basavapatna@Sun.COM }
678*12011SSriharsha.Basavapatna@Sun.COM
679*12011SSriharsha.Basavapatna@Sun.COM tbufp->datalen = size;
680*12011SSriharsha.Basavapatna@Sun.COM
681*12011SSriharsha.Basavapatna@Sun.COM /* initialize the corresponding public descriptor (txd) */
682*12011SSriharsha.Basavapatna@Sun.COM txdp = tbufp->descp;
683*12011SSriharsha.Basavapatna@Sun.COM hdrp = &txdp->hdr;
684*12011SSriharsha.Basavapatna@Sun.COM txdp->nbytes = size;
685*12011SSriharsha.Basavapatna@Sun.COM txdp->ncookies = tbufp->ncookies;
686*12011SSriharsha.Basavapatna@Sun.COM bcopy((tbufp->memcookie), (txdp->memcookie),
687*12011SSriharsha.Basavapatna@Sun.COM tbufp->ncookies * sizeof (ldc_mem_cookie_t));
688*12011SSriharsha.Basavapatna@Sun.COM
689*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->wrlock);
690*12011SSriharsha.Basavapatna@Sun.COM /*
691*12011SSriharsha.Basavapatna@Sun.COM * If the flags not set to BUSY, it implies that the clobber
692*12011SSriharsha.Basavapatna@Sun.COM * was done while we were copying the data. In such case,
693*12011SSriharsha.Basavapatna@Sun.COM * discard the packet and return.
694*12011SSriharsha.Basavapatna@Sun.COM */
695*12011SSriharsha.Basavapatna@Sun.COM if (tbufp->flags != VGEN_PRIV_DESC_BUSY) {
696*12011SSriharsha.Basavapatna@Sun.COM statsp->oerrors++;
697*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->wrlock);
698*12011SSriharsha.Basavapatna@Sun.COM goto dringsend_exit;
699*12011SSriharsha.Basavapatna@Sun.COM }
700*12011SSriharsha.Basavapatna@Sun.COM hdrp->dstate = VIO_DESC_READY;
701*12011SSriharsha.Basavapatna@Sun.COM
702*12011SSriharsha.Basavapatna@Sun.COM /* update stats */
703*12011SSriharsha.Basavapatna@Sun.COM statsp->opackets++;
704*12011SSriharsha.Basavapatna@Sun.COM statsp->obytes += size;
705*12011SSriharsha.Basavapatna@Sun.COM if (is_bcast)
706*12011SSriharsha.Basavapatna@Sun.COM statsp->brdcstxmt++;
707*12011SSriharsha.Basavapatna@Sun.COM else if (is_mcast)
708*12011SSriharsha.Basavapatna@Sun.COM statsp->multixmt++;
709*12011SSriharsha.Basavapatna@Sun.COM
710*12011SSriharsha.Basavapatna@Sun.COM /* send dring datamsg to the peer */
711*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->resched_peer) {
712*12011SSriharsha.Basavapatna@Sun.COM
713*12011SSriharsha.Basavapatna@Sun.COM rtbufp = &ldcp->tbufp[ldcp->resched_peer_txi];
714*12011SSriharsha.Basavapatna@Sun.COM rtxdp = rtbufp->descp;
715*12011SSriharsha.Basavapatna@Sun.COM
716*12011SSriharsha.Basavapatna@Sun.COM if (rtxdp->hdr.dstate == VIO_DESC_READY) {
717*12011SSriharsha.Basavapatna@Sun.COM rv = vgen_send_dringdata(ldcp,
718*12011SSriharsha.Basavapatna@Sun.COM (uint32_t)ldcp->resched_peer_txi, -1);
719*12011SSriharsha.Basavapatna@Sun.COM if (rv != 0) {
720*12011SSriharsha.Basavapatna@Sun.COM /* error: drop the packet */
721*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp,
722*12011SSriharsha.Basavapatna@Sun.COM "failed sending dringdata msg "
723*12011SSriharsha.Basavapatna@Sun.COM "rv(%d) len(%d)\n", rv, size);
724*12011SSriharsha.Basavapatna@Sun.COM statsp->oerrors++;
725*12011SSriharsha.Basavapatna@Sun.COM } else {
726*12011SSriharsha.Basavapatna@Sun.COM ldcp->resched_peer = B_FALSE;
727*12011SSriharsha.Basavapatna@Sun.COM }
728*12011SSriharsha.Basavapatna@Sun.COM
729*12011SSriharsha.Basavapatna@Sun.COM }
730*12011SSriharsha.Basavapatna@Sun.COM
731*12011SSriharsha.Basavapatna@Sun.COM }
732*12011SSriharsha.Basavapatna@Sun.COM
733*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->wrlock);
734*12011SSriharsha.Basavapatna@Sun.COM
735*12011SSriharsha.Basavapatna@Sun.COM dringsend_exit:
736*12011SSriharsha.Basavapatna@Sun.COM if (rv == ECONNRESET) {
737*12011SSriharsha.Basavapatna@Sun.COM (void) vgen_handle_evt_reset(ldcp, VGEN_OTHER);
738*12011SSriharsha.Basavapatna@Sun.COM }
739*12011SSriharsha.Basavapatna@Sun.COM freemsg(mp);
740*12011SSriharsha.Basavapatna@Sun.COM DBG1(vgenp, ldcp, "exit\n");
741*12011SSriharsha.Basavapatna@Sun.COM return (VGEN_TX_SUCCESS);
742*12011SSriharsha.Basavapatna@Sun.COM }
743*12011SSriharsha.Basavapatna@Sun.COM
744*12011SSriharsha.Basavapatna@Sun.COM mblk_t *
vgen_poll_rcv(vgen_ldc_t * ldcp,int bytes_to_pickup)745*12011SSriharsha.Basavapatna@Sun.COM vgen_poll_rcv(vgen_ldc_t *ldcp, int bytes_to_pickup)
746*12011SSriharsha.Basavapatna@Sun.COM {
747*12011SSriharsha.Basavapatna@Sun.COM mblk_t *bp = NULL;
748*12011SSriharsha.Basavapatna@Sun.COM mblk_t *bpt = NULL;
749*12011SSriharsha.Basavapatna@Sun.COM mblk_t *mp = NULL;
750*12011SSriharsha.Basavapatna@Sun.COM size_t mblk_sz = 0;
751*12011SSriharsha.Basavapatna@Sun.COM size_t sz = 0;
752*12011SSriharsha.Basavapatna@Sun.COM uint_t count = 0;
753*12011SSriharsha.Basavapatna@Sun.COM
754*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->pollq_lock);
755*12011SSriharsha.Basavapatna@Sun.COM
756*12011SSriharsha.Basavapatna@Sun.COM bp = ldcp->pollq_headp;
757*12011SSriharsha.Basavapatna@Sun.COM while (bp != NULL) {
758*12011SSriharsha.Basavapatna@Sun.COM /* get the size of this packet */
759*12011SSriharsha.Basavapatna@Sun.COM mblk_sz = msgdsize(bp);
760*12011SSriharsha.Basavapatna@Sun.COM
761*12011SSriharsha.Basavapatna@Sun.COM /* if adding this pkt, exceeds the size limit, we are done. */
762*12011SSriharsha.Basavapatna@Sun.COM if (sz + mblk_sz > bytes_to_pickup) {
763*12011SSriharsha.Basavapatna@Sun.COM break;
764*12011SSriharsha.Basavapatna@Sun.COM }
765*12011SSriharsha.Basavapatna@Sun.COM
766*12011SSriharsha.Basavapatna@Sun.COM /* we have room for this packet */
767*12011SSriharsha.Basavapatna@Sun.COM sz += mblk_sz;
768*12011SSriharsha.Basavapatna@Sun.COM
769*12011SSriharsha.Basavapatna@Sun.COM /* increment the # of packets being sent up */
770*12011SSriharsha.Basavapatna@Sun.COM count++;
771*12011SSriharsha.Basavapatna@Sun.COM
772*12011SSriharsha.Basavapatna@Sun.COM /* track the last processed pkt */
773*12011SSriharsha.Basavapatna@Sun.COM bpt = bp;
774*12011SSriharsha.Basavapatna@Sun.COM
775*12011SSriharsha.Basavapatna@Sun.COM /* get the next pkt */
776*12011SSriharsha.Basavapatna@Sun.COM bp = bp->b_next;
777*12011SSriharsha.Basavapatna@Sun.COM }
778*12011SSriharsha.Basavapatna@Sun.COM
779*12011SSriharsha.Basavapatna@Sun.COM if (count != 0) {
780*12011SSriharsha.Basavapatna@Sun.COM /*
781*12011SSriharsha.Basavapatna@Sun.COM * picked up some packets; save the head of pkts to be sent up.
782*12011SSriharsha.Basavapatna@Sun.COM */
783*12011SSriharsha.Basavapatna@Sun.COM mp = ldcp->pollq_headp;
784*12011SSriharsha.Basavapatna@Sun.COM
785*12011SSriharsha.Basavapatna@Sun.COM /* move the pollq_headp to skip over the pkts being sent up */
786*12011SSriharsha.Basavapatna@Sun.COM ldcp->pollq_headp = bp;
787*12011SSriharsha.Basavapatna@Sun.COM
788*12011SSriharsha.Basavapatna@Sun.COM /* picked up all pending pkts in the queue; reset tail also */
789*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->pollq_headp == NULL) {
790*12011SSriharsha.Basavapatna@Sun.COM ldcp->pollq_tailp = NULL;
791*12011SSriharsha.Basavapatna@Sun.COM }
792*12011SSriharsha.Basavapatna@Sun.COM
793*12011SSriharsha.Basavapatna@Sun.COM /* terminate the tail of pkts to be sent up */
794*12011SSriharsha.Basavapatna@Sun.COM bpt->b_next = NULL;
795*12011SSriharsha.Basavapatna@Sun.COM }
796*12011SSriharsha.Basavapatna@Sun.COM
797*12011SSriharsha.Basavapatna@Sun.COM /*
798*12011SSriharsha.Basavapatna@Sun.COM * We prepend any high priority packets to the chain of packets; note
799*12011SSriharsha.Basavapatna@Sun.COM * that if we are already at the bytes_to_pickup limit, we might
800*12011SSriharsha.Basavapatna@Sun.COM * slightly exceed that in such cases. That should be ok, as these pkts
801*12011SSriharsha.Basavapatna@Sun.COM * are expected to be small in size and arrive at an interval in the
802*12011SSriharsha.Basavapatna@Sun.COM * the order of a few seconds.
803*12011SSriharsha.Basavapatna@Sun.COM */
804*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->rx_pktdata == vgen_handle_pkt_data &&
805*12011SSriharsha.Basavapatna@Sun.COM ldcp->rx_pri_head != NULL) {
806*12011SSriharsha.Basavapatna@Sun.COM ldcp->rx_pri_tail->b_next = mp;
807*12011SSriharsha.Basavapatna@Sun.COM mp = ldcp->rx_pri_head;
808*12011SSriharsha.Basavapatna@Sun.COM ldcp->rx_pri_head = ldcp->rx_pri_tail = NULL;
809*12011SSriharsha.Basavapatna@Sun.COM }
810*12011SSriharsha.Basavapatna@Sun.COM
811*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->pollq_lock);
812*12011SSriharsha.Basavapatna@Sun.COM
813*12011SSriharsha.Basavapatna@Sun.COM return (mp);
814*12011SSriharsha.Basavapatna@Sun.COM }
815*12011SSriharsha.Basavapatna@Sun.COM
816*12011SSriharsha.Basavapatna@Sun.COM /*
817*12011SSriharsha.Basavapatna@Sun.COM * Process dring data messages (info/ack/nack)
818*12011SSriharsha.Basavapatna@Sun.COM */
819*12011SSriharsha.Basavapatna@Sun.COM int
vgen_handle_dringdata(void * arg1,void * arg2)820*12011SSriharsha.Basavapatna@Sun.COM vgen_handle_dringdata(void *arg1, void *arg2)
821*12011SSriharsha.Basavapatna@Sun.COM {
822*12011SSriharsha.Basavapatna@Sun.COM vgen_ldc_t *ldcp = (vgen_ldc_t *)arg1;
823*12011SSriharsha.Basavapatna@Sun.COM vio_msg_tag_t *tagp = (vio_msg_tag_t *)arg2;
824*12011SSriharsha.Basavapatna@Sun.COM vgen_t *vgenp = LDC_TO_VGEN(ldcp);
825*12011SSriharsha.Basavapatna@Sun.COM int rv = 0;
826*12011SSriharsha.Basavapatna@Sun.COM
827*12011SSriharsha.Basavapatna@Sun.COM DBG1(vgenp, ldcp, "enter\n");
828*12011SSriharsha.Basavapatna@Sun.COM switch (tagp->vio_subtype) {
829*12011SSriharsha.Basavapatna@Sun.COM
830*12011SSriharsha.Basavapatna@Sun.COM case VIO_SUBTYPE_INFO:
831*12011SSriharsha.Basavapatna@Sun.COM /*
832*12011SSriharsha.Basavapatna@Sun.COM * To reduce the locking contention, release the
833*12011SSriharsha.Basavapatna@Sun.COM * cblock here and re-acquire it once we are done
834*12011SSriharsha.Basavapatna@Sun.COM * receiving packets.
835*12011SSriharsha.Basavapatna@Sun.COM */
836*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->cblock);
837*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->rxlock);
838*12011SSriharsha.Basavapatna@Sun.COM rv = vgen_handle_dringdata_info(ldcp, tagp);
839*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->rxlock);
840*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->cblock);
841*12011SSriharsha.Basavapatna@Sun.COM break;
842*12011SSriharsha.Basavapatna@Sun.COM
843*12011SSriharsha.Basavapatna@Sun.COM case VIO_SUBTYPE_ACK:
844*12011SSriharsha.Basavapatna@Sun.COM rv = vgen_handle_dringdata_ack(ldcp, tagp);
845*12011SSriharsha.Basavapatna@Sun.COM break;
846*12011SSriharsha.Basavapatna@Sun.COM
847*12011SSriharsha.Basavapatna@Sun.COM case VIO_SUBTYPE_NACK:
848*12011SSriharsha.Basavapatna@Sun.COM rv = vgen_handle_dringdata_nack(ldcp, tagp);
849*12011SSriharsha.Basavapatna@Sun.COM break;
850*12011SSriharsha.Basavapatna@Sun.COM }
851*12011SSriharsha.Basavapatna@Sun.COM DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
852*12011SSriharsha.Basavapatna@Sun.COM return (rv);
853*12011SSriharsha.Basavapatna@Sun.COM }
854*12011SSriharsha.Basavapatna@Sun.COM
855*12011SSriharsha.Basavapatna@Sun.COM static int
vgen_handle_dringdata_info(vgen_ldc_t * ldcp,vio_msg_tag_t * tagp)856*12011SSriharsha.Basavapatna@Sun.COM vgen_handle_dringdata_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
857*12011SSriharsha.Basavapatna@Sun.COM {
858*12011SSriharsha.Basavapatna@Sun.COM uint32_t start;
859*12011SSriharsha.Basavapatna@Sun.COM int32_t end;
860*12011SSriharsha.Basavapatna@Sun.COM int rv = 0;
861*12011SSriharsha.Basavapatna@Sun.COM vio_dring_msg_t *dringmsg = (vio_dring_msg_t *)tagp;
862*12011SSriharsha.Basavapatna@Sun.COM vgen_t *vgenp = LDC_TO_VGEN(ldcp);
863*12011SSriharsha.Basavapatna@Sun.COM vgen_stats_t *statsp = &ldcp->stats;
864*12011SSriharsha.Basavapatna@Sun.COM #ifdef VGEN_HANDLE_LOST_PKTS
865*12011SSriharsha.Basavapatna@Sun.COM uint32_t rxi;
866*12011SSriharsha.Basavapatna@Sun.COM int n;
867*12011SSriharsha.Basavapatna@Sun.COM #endif
868*12011SSriharsha.Basavapatna@Sun.COM
869*12011SSriharsha.Basavapatna@Sun.COM DBG1(vgenp, ldcp, "enter\n");
870*12011SSriharsha.Basavapatna@Sun.COM
871*12011SSriharsha.Basavapatna@Sun.COM start = dringmsg->start_idx;
872*12011SSriharsha.Basavapatna@Sun.COM end = dringmsg->end_idx;
873*12011SSriharsha.Basavapatna@Sun.COM /*
874*12011SSriharsha.Basavapatna@Sun.COM * received a data msg, which contains the start and end
875*12011SSriharsha.Basavapatna@Sun.COM * indices of the descriptors within the rx ring holding data,
876*12011SSriharsha.Basavapatna@Sun.COM * the seq_num of data packet corresponding to the start index,
877*12011SSriharsha.Basavapatna@Sun.COM * and the dring_ident.
878*12011SSriharsha.Basavapatna@Sun.COM * We can now read the contents of each of these descriptors
879*12011SSriharsha.Basavapatna@Sun.COM * and gather data from it.
880*12011SSriharsha.Basavapatna@Sun.COM */
881*12011SSriharsha.Basavapatna@Sun.COM DBG1(vgenp, ldcp, "INFO: start(%d), end(%d)\n",
882*12011SSriharsha.Basavapatna@Sun.COM start, end);
883*12011SSriharsha.Basavapatna@Sun.COM
884*12011SSriharsha.Basavapatna@Sun.COM /* validate rx start and end indexes */
885*12011SSriharsha.Basavapatna@Sun.COM if (!(CHECK_RXI(start, ldcp)) || ((end != -1) &&
886*12011SSriharsha.Basavapatna@Sun.COM !(CHECK_RXI(end, ldcp)))) {
887*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "Invalid Rx start(%d) or end(%d)\n",
888*12011SSriharsha.Basavapatna@Sun.COM start, end);
889*12011SSriharsha.Basavapatna@Sun.COM /* drop the message if invalid index */
890*12011SSriharsha.Basavapatna@Sun.COM return (rv);
891*12011SSriharsha.Basavapatna@Sun.COM }
892*12011SSriharsha.Basavapatna@Sun.COM
893*12011SSriharsha.Basavapatna@Sun.COM /* validate dring_ident */
894*12011SSriharsha.Basavapatna@Sun.COM if (dringmsg->dring_ident != ldcp->peer_hparams.dring_ident) {
895*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "Invalid dring ident 0x%x\n",
896*12011SSriharsha.Basavapatna@Sun.COM dringmsg->dring_ident);
897*12011SSriharsha.Basavapatna@Sun.COM /* invalid dring_ident, drop the msg */
898*12011SSriharsha.Basavapatna@Sun.COM return (rv);
899*12011SSriharsha.Basavapatna@Sun.COM }
900*12011SSriharsha.Basavapatna@Sun.COM #ifdef DEBUG
901*12011SSriharsha.Basavapatna@Sun.COM if (vgen_inject_error(ldcp, VGEN_ERR_RXLOST)) {
902*12011SSriharsha.Basavapatna@Sun.COM /* drop this msg to simulate lost pkts for debugging */
903*12011SSriharsha.Basavapatna@Sun.COM vgen_inject_err_flag &= ~(VGEN_ERR_RXLOST);
904*12011SSriharsha.Basavapatna@Sun.COM return (rv);
905*12011SSriharsha.Basavapatna@Sun.COM }
906*12011SSriharsha.Basavapatna@Sun.COM #endif
907*12011SSriharsha.Basavapatna@Sun.COM
908*12011SSriharsha.Basavapatna@Sun.COM statsp->dring_data_msgs_rcvd++;
909*12011SSriharsha.Basavapatna@Sun.COM
910*12011SSriharsha.Basavapatna@Sun.COM #ifdef VGEN_HANDLE_LOST_PKTS
911*12011SSriharsha.Basavapatna@Sun.COM
912*12011SSriharsha.Basavapatna@Sun.COM /* receive start index doesn't match expected index */
913*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->next_rxi != start) {
914*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "next_rxi(%d) != start(%d)\n",
915*12011SSriharsha.Basavapatna@Sun.COM ldcp->next_rxi, start);
916*12011SSriharsha.Basavapatna@Sun.COM
917*12011SSriharsha.Basavapatna@Sun.COM /* calculate the number of pkts lost */
918*12011SSriharsha.Basavapatna@Sun.COM if (start >= ldcp->next_rxi) {
919*12011SSriharsha.Basavapatna@Sun.COM n = start - ldcp->next_rxi;
920*12011SSriharsha.Basavapatna@Sun.COM } else {
921*12011SSriharsha.Basavapatna@Sun.COM n = ldcp->num_rxds - (ldcp->next_rxi - start);
922*12011SSriharsha.Basavapatna@Sun.COM }
923*12011SSriharsha.Basavapatna@Sun.COM
924*12011SSriharsha.Basavapatna@Sun.COM statsp->rx_lost_pkts += n;
925*12011SSriharsha.Basavapatna@Sun.COM tagp->vio_subtype = VIO_SUBTYPE_NACK;
926*12011SSriharsha.Basavapatna@Sun.COM tagp->vio_sid = ldcp->local_sid;
927*12011SSriharsha.Basavapatna@Sun.COM /* indicate the range of lost descriptors */
928*12011SSriharsha.Basavapatna@Sun.COM dringmsg->start_idx = ldcp->next_rxi;
929*12011SSriharsha.Basavapatna@Sun.COM rxi = start;
930*12011SSriharsha.Basavapatna@Sun.COM DECR_RXI(rxi, ldcp);
931*12011SSriharsha.Basavapatna@Sun.COM dringmsg->end_idx = rxi;
932*12011SSriharsha.Basavapatna@Sun.COM /* dring ident is left unchanged */
933*12011SSriharsha.Basavapatna@Sun.COM rv = vgen_sendmsg(ldcp, (caddr_t)tagp,
934*12011SSriharsha.Basavapatna@Sun.COM sizeof (*dringmsg), B_FALSE);
935*12011SSriharsha.Basavapatna@Sun.COM if (rv != VGEN_SUCCESS) {
936*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp,
937*12011SSriharsha.Basavapatna@Sun.COM "vgen_sendmsg failed, stype:NACK\n");
938*12011SSriharsha.Basavapatna@Sun.COM return (rv);
939*12011SSriharsha.Basavapatna@Sun.COM }
940*12011SSriharsha.Basavapatna@Sun.COM /*
941*12011SSriharsha.Basavapatna@Sun.COM * treat this range of descrs/pkts as dropped
942*12011SSriharsha.Basavapatna@Sun.COM * and set the new expected value of next_rxi
943*12011SSriharsha.Basavapatna@Sun.COM * and continue(below) to process from the new
944*12011SSriharsha.Basavapatna@Sun.COM * start index.
945*12011SSriharsha.Basavapatna@Sun.COM */
946*12011SSriharsha.Basavapatna@Sun.COM ldcp->next_rxi = start;
947*12011SSriharsha.Basavapatna@Sun.COM }
948*12011SSriharsha.Basavapatna@Sun.COM
949*12011SSriharsha.Basavapatna@Sun.COM #endif /* VGEN_HANDLE_LOST_PKTS */
950*12011SSriharsha.Basavapatna@Sun.COM
951*12011SSriharsha.Basavapatna@Sun.COM /* Now receive messages */
952*12011SSriharsha.Basavapatna@Sun.COM rv = vgen_process_dringdata(ldcp, tagp);
953*12011SSriharsha.Basavapatna@Sun.COM
954*12011SSriharsha.Basavapatna@Sun.COM DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
955*12011SSriharsha.Basavapatna@Sun.COM return (rv);
956*12011SSriharsha.Basavapatna@Sun.COM }
957*12011SSriharsha.Basavapatna@Sun.COM
958*12011SSriharsha.Basavapatna@Sun.COM static int
vgen_process_dringdata(vgen_ldc_t * ldcp,vio_msg_tag_t * tagp)959*12011SSriharsha.Basavapatna@Sun.COM vgen_process_dringdata(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
960*12011SSriharsha.Basavapatna@Sun.COM {
961*12011SSriharsha.Basavapatna@Sun.COM boolean_t set_ack_start = B_FALSE;
962*12011SSriharsha.Basavapatna@Sun.COM uint32_t start;
963*12011SSriharsha.Basavapatna@Sun.COM uint32_t ack_end;
964*12011SSriharsha.Basavapatna@Sun.COM uint32_t next_rxi;
965*12011SSriharsha.Basavapatna@Sun.COM uint32_t rxi;
966*12011SSriharsha.Basavapatna@Sun.COM int count = 0;
967*12011SSriharsha.Basavapatna@Sun.COM int rv = 0;
968*12011SSriharsha.Basavapatna@Sun.COM uint32_t retries = 0;
969*12011SSriharsha.Basavapatna@Sun.COM vgen_stats_t *statsp;
970*12011SSriharsha.Basavapatna@Sun.COM vnet_public_desc_t rxd;
971*12011SSriharsha.Basavapatna@Sun.COM vio_dring_entry_hdr_t *hdrp;
972*12011SSriharsha.Basavapatna@Sun.COM mblk_t *bp = NULL;
973*12011SSriharsha.Basavapatna@Sun.COM mblk_t *bpt = NULL;
974*12011SSriharsha.Basavapatna@Sun.COM uint32_t ack_start;
975*12011SSriharsha.Basavapatna@Sun.COM boolean_t rxd_err = B_FALSE;
976*12011SSriharsha.Basavapatna@Sun.COM mblk_t *mp = NULL;
977*12011SSriharsha.Basavapatna@Sun.COM vio_mblk_t *vmp = NULL;
978*12011SSriharsha.Basavapatna@Sun.COM size_t nbytes;
979*12011SSriharsha.Basavapatna@Sun.COM boolean_t ack_needed = B_FALSE;
980*12011SSriharsha.Basavapatna@Sun.COM size_t nread;
981*12011SSriharsha.Basavapatna@Sun.COM uint64_t off = 0;
982*12011SSriharsha.Basavapatna@Sun.COM struct ether_header *ehp;
983*12011SSriharsha.Basavapatna@Sun.COM vio_dring_msg_t *dringmsg = (vio_dring_msg_t *)tagp;
984*12011SSriharsha.Basavapatna@Sun.COM vgen_t *vgenp = LDC_TO_VGEN(ldcp);
985*12011SSriharsha.Basavapatna@Sun.COM vgen_hparams_t *lp = &ldcp->local_hparams;
986*12011SSriharsha.Basavapatna@Sun.COM
987*12011SSriharsha.Basavapatna@Sun.COM DBG1(vgenp, ldcp, "enter\n");
988*12011SSriharsha.Basavapatna@Sun.COM
989*12011SSriharsha.Basavapatna@Sun.COM statsp = &ldcp->stats;
990*12011SSriharsha.Basavapatna@Sun.COM start = dringmsg->start_idx;
991*12011SSriharsha.Basavapatna@Sun.COM
992*12011SSriharsha.Basavapatna@Sun.COM /*
993*12011SSriharsha.Basavapatna@Sun.COM * start processing the descriptors from the specified
994*12011SSriharsha.Basavapatna@Sun.COM * start index, up to the index a descriptor is not ready
995*12011SSriharsha.Basavapatna@Sun.COM * to be processed or we process the entire descriptor ring
996*12011SSriharsha.Basavapatna@Sun.COM * and wrap around upto the start index.
997*12011SSriharsha.Basavapatna@Sun.COM */
998*12011SSriharsha.Basavapatna@Sun.COM
999*12011SSriharsha.Basavapatna@Sun.COM /* need to set the start index of descriptors to be ack'd */
1000*12011SSriharsha.Basavapatna@Sun.COM set_ack_start = B_TRUE;
1001*12011SSriharsha.Basavapatna@Sun.COM
1002*12011SSriharsha.Basavapatna@Sun.COM /* index upto which we have ack'd */
1003*12011SSriharsha.Basavapatna@Sun.COM ack_end = start;
1004*12011SSriharsha.Basavapatna@Sun.COM DECR_RXI(ack_end, ldcp);
1005*12011SSriharsha.Basavapatna@Sun.COM
1006*12011SSriharsha.Basavapatna@Sun.COM next_rxi = rxi = start;
1007*12011SSriharsha.Basavapatna@Sun.COM do {
1008*12011SSriharsha.Basavapatna@Sun.COM vgen_recv_retry:
1009*12011SSriharsha.Basavapatna@Sun.COM rv = vnet_dring_entry_copy(&(ldcp->mrxdp[rxi]), &rxd,
1010*12011SSriharsha.Basavapatna@Sun.COM ldcp->dring_mtype, ldcp->rx_dring_handle, rxi, rxi);
1011*12011SSriharsha.Basavapatna@Sun.COM if (rv != 0) {
1012*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "ldc_mem_dring_acquire() failed"
1013*12011SSriharsha.Basavapatna@Sun.COM " rv(%d)\n", rv);
1014*12011SSriharsha.Basavapatna@Sun.COM statsp->ierrors++;
1015*12011SSriharsha.Basavapatna@Sun.COM return (rv);
1016*12011SSriharsha.Basavapatna@Sun.COM }
1017*12011SSriharsha.Basavapatna@Sun.COM
1018*12011SSriharsha.Basavapatna@Sun.COM hdrp = &rxd.hdr;
1019*12011SSriharsha.Basavapatna@Sun.COM
1020*12011SSriharsha.Basavapatna@Sun.COM if (hdrp->dstate != VIO_DESC_READY) {
1021*12011SSriharsha.Basavapatna@Sun.COM /*
1022*12011SSriharsha.Basavapatna@Sun.COM * Before waiting and retry here, send up
1023*12011SSriharsha.Basavapatna@Sun.COM * the packets that are received already
1024*12011SSriharsha.Basavapatna@Sun.COM */
1025*12011SSriharsha.Basavapatna@Sun.COM if (bp != NULL) {
1026*12011SSriharsha.Basavapatna@Sun.COM DTRACE_PROBE1(vgen_rcv_msgs, int, count);
1027*12011SSriharsha.Basavapatna@Sun.COM vgen_rx(ldcp, bp, bpt);
1028*12011SSriharsha.Basavapatna@Sun.COM count = 0;
1029*12011SSriharsha.Basavapatna@Sun.COM bp = bpt = NULL;
1030*12011SSriharsha.Basavapatna@Sun.COM }
1031*12011SSriharsha.Basavapatna@Sun.COM /*
1032*12011SSriharsha.Basavapatna@Sun.COM * descriptor is not ready.
1033*12011SSriharsha.Basavapatna@Sun.COM * retry descriptor acquire, stop processing
1034*12011SSriharsha.Basavapatna@Sun.COM * after max # retries.
1035*12011SSriharsha.Basavapatna@Sun.COM */
1036*12011SSriharsha.Basavapatna@Sun.COM if (retries == vgen_recv_retries)
1037*12011SSriharsha.Basavapatna@Sun.COM break;
1038*12011SSriharsha.Basavapatna@Sun.COM retries++;
1039*12011SSriharsha.Basavapatna@Sun.COM drv_usecwait(vgen_recv_delay);
1040*12011SSriharsha.Basavapatna@Sun.COM goto vgen_recv_retry;
1041*12011SSriharsha.Basavapatna@Sun.COM }
1042*12011SSriharsha.Basavapatna@Sun.COM retries = 0;
1043*12011SSriharsha.Basavapatna@Sun.COM
1044*12011SSriharsha.Basavapatna@Sun.COM if (set_ack_start) {
1045*12011SSriharsha.Basavapatna@Sun.COM /*
1046*12011SSriharsha.Basavapatna@Sun.COM * initialize the start index of the range
1047*12011SSriharsha.Basavapatna@Sun.COM * of descriptors to be ack'd.
1048*12011SSriharsha.Basavapatna@Sun.COM */
1049*12011SSriharsha.Basavapatna@Sun.COM ack_start = rxi;
1050*12011SSriharsha.Basavapatna@Sun.COM set_ack_start = B_FALSE;
1051*12011SSriharsha.Basavapatna@Sun.COM }
1052*12011SSriharsha.Basavapatna@Sun.COM
1053*12011SSriharsha.Basavapatna@Sun.COM if ((rxd.nbytes < ETHERMIN) ||
1054*12011SSriharsha.Basavapatna@Sun.COM (rxd.nbytes > lp->mtu) ||
1055*12011SSriharsha.Basavapatna@Sun.COM (rxd.ncookies == 0) ||
1056*12011SSriharsha.Basavapatna@Sun.COM (rxd.ncookies > MAX_COOKIES)) {
1057*12011SSriharsha.Basavapatna@Sun.COM rxd_err = B_TRUE;
1058*12011SSriharsha.Basavapatna@Sun.COM } else {
1059*12011SSriharsha.Basavapatna@Sun.COM /*
1060*12011SSriharsha.Basavapatna@Sun.COM * Try to allocate an mblk from the free pool
1061*12011SSriharsha.Basavapatna@Sun.COM * of recv mblks for the channel.
1062*12011SSriharsha.Basavapatna@Sun.COM * If this fails, use allocb().
1063*12011SSriharsha.Basavapatna@Sun.COM */
1064*12011SSriharsha.Basavapatna@Sun.COM nbytes = (VNET_IPALIGN + rxd.nbytes + 7) & ~7;
1065*12011SSriharsha.Basavapatna@Sun.COM if (nbytes > ldcp->max_rxpool_size) {
1066*12011SSriharsha.Basavapatna@Sun.COM mp = allocb(VNET_IPALIGN + rxd.nbytes + 8,
1067*12011SSriharsha.Basavapatna@Sun.COM BPRI_MED);
1068*12011SSriharsha.Basavapatna@Sun.COM vmp = NULL;
1069*12011SSriharsha.Basavapatna@Sun.COM } else {
1070*12011SSriharsha.Basavapatna@Sun.COM vmp = vio_multipool_allocb(&ldcp->vmp, nbytes);
1071*12011SSriharsha.Basavapatna@Sun.COM if (vmp == NULL) {
1072*12011SSriharsha.Basavapatna@Sun.COM statsp->rx_vio_allocb_fail++;
1073*12011SSriharsha.Basavapatna@Sun.COM /*
1074*12011SSriharsha.Basavapatna@Sun.COM * Data buffer returned by allocb(9F)
1075*12011SSriharsha.Basavapatna@Sun.COM * is 8byte aligned. We allocate extra
1076*12011SSriharsha.Basavapatna@Sun.COM * 8 bytes to ensure size is multiple
1077*12011SSriharsha.Basavapatna@Sun.COM * of 8 bytes for ldc_mem_copy().
1078*12011SSriharsha.Basavapatna@Sun.COM */
1079*12011SSriharsha.Basavapatna@Sun.COM mp = allocb(VNET_IPALIGN +
1080*12011SSriharsha.Basavapatna@Sun.COM rxd.nbytes + 8, BPRI_MED);
1081*12011SSriharsha.Basavapatna@Sun.COM } else {
1082*12011SSriharsha.Basavapatna@Sun.COM mp = vmp->mp;
1083*12011SSriharsha.Basavapatna@Sun.COM }
1084*12011SSriharsha.Basavapatna@Sun.COM }
1085*12011SSriharsha.Basavapatna@Sun.COM }
1086*12011SSriharsha.Basavapatna@Sun.COM if ((rxd_err) || (mp == NULL)) {
1087*12011SSriharsha.Basavapatna@Sun.COM /*
1088*12011SSriharsha.Basavapatna@Sun.COM * rxd_err or allocb() failure,
1089*12011SSriharsha.Basavapatna@Sun.COM * drop this packet, get next.
1090*12011SSriharsha.Basavapatna@Sun.COM */
1091*12011SSriharsha.Basavapatna@Sun.COM if (rxd_err) {
1092*12011SSriharsha.Basavapatna@Sun.COM statsp->ierrors++;
1093*12011SSriharsha.Basavapatna@Sun.COM rxd_err = B_FALSE;
1094*12011SSriharsha.Basavapatna@Sun.COM } else {
1095*12011SSriharsha.Basavapatna@Sun.COM statsp->rx_allocb_fail++;
1096*12011SSriharsha.Basavapatna@Sun.COM }
1097*12011SSriharsha.Basavapatna@Sun.COM
1098*12011SSriharsha.Basavapatna@Sun.COM ack_needed = hdrp->ack;
1099*12011SSriharsha.Basavapatna@Sun.COM
1100*12011SSriharsha.Basavapatna@Sun.COM /* set descriptor done bit */
1101*12011SSriharsha.Basavapatna@Sun.COM rv = vnet_dring_entry_set_dstate(&(ldcp->mrxdp[rxi]),
1102*12011SSriharsha.Basavapatna@Sun.COM ldcp->dring_mtype, ldcp->rx_dring_handle, rxi, rxi,
1103*12011SSriharsha.Basavapatna@Sun.COM VIO_DESC_DONE);
1104*12011SSriharsha.Basavapatna@Sun.COM if (rv != 0) {
1105*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp,
1106*12011SSriharsha.Basavapatna@Sun.COM "vnet_dring_entry_set_dstate err rv(%d)\n",
1107*12011SSriharsha.Basavapatna@Sun.COM rv);
1108*12011SSriharsha.Basavapatna@Sun.COM return (rv);
1109*12011SSriharsha.Basavapatna@Sun.COM }
1110*12011SSriharsha.Basavapatna@Sun.COM
1111*12011SSriharsha.Basavapatna@Sun.COM if (ack_needed) {
1112*12011SSriharsha.Basavapatna@Sun.COM ack_needed = B_FALSE;
1113*12011SSriharsha.Basavapatna@Sun.COM /*
1114*12011SSriharsha.Basavapatna@Sun.COM * sender needs ack for this packet,
1115*12011SSriharsha.Basavapatna@Sun.COM * ack pkts upto this index.
1116*12011SSriharsha.Basavapatna@Sun.COM */
1117*12011SSriharsha.Basavapatna@Sun.COM ack_end = rxi;
1118*12011SSriharsha.Basavapatna@Sun.COM
1119*12011SSriharsha.Basavapatna@Sun.COM rv = vgen_send_dringack(ldcp, tagp,
1120*12011SSriharsha.Basavapatna@Sun.COM ack_start, ack_end,
1121*12011SSriharsha.Basavapatna@Sun.COM VIO_DP_ACTIVE);
1122*12011SSriharsha.Basavapatna@Sun.COM if (rv != VGEN_SUCCESS) {
1123*12011SSriharsha.Basavapatna@Sun.COM goto error_ret;
1124*12011SSriharsha.Basavapatna@Sun.COM }
1125*12011SSriharsha.Basavapatna@Sun.COM
1126*12011SSriharsha.Basavapatna@Sun.COM /* need to set new ack start index */
1127*12011SSriharsha.Basavapatna@Sun.COM set_ack_start = B_TRUE;
1128*12011SSriharsha.Basavapatna@Sun.COM }
1129*12011SSriharsha.Basavapatna@Sun.COM goto vgen_next_rxi;
1130*12011SSriharsha.Basavapatna@Sun.COM }
1131*12011SSriharsha.Basavapatna@Sun.COM
1132*12011SSriharsha.Basavapatna@Sun.COM nread = nbytes;
1133*12011SSriharsha.Basavapatna@Sun.COM rv = ldc_mem_copy(ldcp->ldc_handle,
1134*12011SSriharsha.Basavapatna@Sun.COM (caddr_t)mp->b_rptr, off, &nread,
1135*12011SSriharsha.Basavapatna@Sun.COM rxd.memcookie, rxd.ncookies, LDC_COPY_IN);
1136*12011SSriharsha.Basavapatna@Sun.COM
1137*12011SSriharsha.Basavapatna@Sun.COM /* if ldc_mem_copy() failed */
1138*12011SSriharsha.Basavapatna@Sun.COM if (rv) {
1139*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "ldc_mem_copy err rv(%d)\n", rv);
1140*12011SSriharsha.Basavapatna@Sun.COM statsp->ierrors++;
1141*12011SSriharsha.Basavapatna@Sun.COM freemsg(mp);
1142*12011SSriharsha.Basavapatna@Sun.COM goto error_ret;
1143*12011SSriharsha.Basavapatna@Sun.COM }
1144*12011SSriharsha.Basavapatna@Sun.COM
1145*12011SSriharsha.Basavapatna@Sun.COM ack_needed = hdrp->ack;
1146*12011SSriharsha.Basavapatna@Sun.COM
1147*12011SSriharsha.Basavapatna@Sun.COM rv = vnet_dring_entry_set_dstate(&(ldcp->mrxdp[rxi]),
1148*12011SSriharsha.Basavapatna@Sun.COM ldcp->dring_mtype, ldcp->rx_dring_handle, rxi, rxi,
1149*12011SSriharsha.Basavapatna@Sun.COM VIO_DESC_DONE);
1150*12011SSriharsha.Basavapatna@Sun.COM if (rv != 0) {
1151*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp,
1152*12011SSriharsha.Basavapatna@Sun.COM "vnet_dring_entry_set_dstate err rv(%d)\n", rv);
1153*12011SSriharsha.Basavapatna@Sun.COM freemsg(mp);
1154*12011SSriharsha.Basavapatna@Sun.COM goto error_ret;
1155*12011SSriharsha.Basavapatna@Sun.COM }
1156*12011SSriharsha.Basavapatna@Sun.COM
1157*12011SSriharsha.Basavapatna@Sun.COM mp->b_rptr += VNET_IPALIGN;
1158*12011SSriharsha.Basavapatna@Sun.COM
1159*12011SSriharsha.Basavapatna@Sun.COM if (ack_needed) {
1160*12011SSriharsha.Basavapatna@Sun.COM ack_needed = B_FALSE;
1161*12011SSriharsha.Basavapatna@Sun.COM /*
1162*12011SSriharsha.Basavapatna@Sun.COM * sender needs ack for this packet,
1163*12011SSriharsha.Basavapatna@Sun.COM * ack pkts upto this index.
1164*12011SSriharsha.Basavapatna@Sun.COM */
1165*12011SSriharsha.Basavapatna@Sun.COM ack_end = rxi;
1166*12011SSriharsha.Basavapatna@Sun.COM
1167*12011SSriharsha.Basavapatna@Sun.COM rv = vgen_send_dringack(ldcp, tagp,
1168*12011SSriharsha.Basavapatna@Sun.COM ack_start, ack_end, VIO_DP_ACTIVE);
1169*12011SSriharsha.Basavapatna@Sun.COM if (rv != VGEN_SUCCESS) {
1170*12011SSriharsha.Basavapatna@Sun.COM freemsg(mp);
1171*12011SSriharsha.Basavapatna@Sun.COM goto error_ret;
1172*12011SSriharsha.Basavapatna@Sun.COM }
1173*12011SSriharsha.Basavapatna@Sun.COM
1174*12011SSriharsha.Basavapatna@Sun.COM /* need to set new ack start index */
1175*12011SSriharsha.Basavapatna@Sun.COM set_ack_start = B_TRUE;
1176*12011SSriharsha.Basavapatna@Sun.COM }
1177*12011SSriharsha.Basavapatna@Sun.COM
1178*12011SSriharsha.Basavapatna@Sun.COM if (nread != nbytes) {
1179*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp,
1180*12011SSriharsha.Basavapatna@Sun.COM "ldc_mem_copy nread(%lx), nbytes(%lx)\n",
1181*12011SSriharsha.Basavapatna@Sun.COM nread, nbytes);
1182*12011SSriharsha.Basavapatna@Sun.COM statsp->ierrors++;
1183*12011SSriharsha.Basavapatna@Sun.COM freemsg(mp);
1184*12011SSriharsha.Basavapatna@Sun.COM goto vgen_next_rxi;
1185*12011SSriharsha.Basavapatna@Sun.COM }
1186*12011SSriharsha.Basavapatna@Sun.COM
1187*12011SSriharsha.Basavapatna@Sun.COM /* point to the actual end of data */
1188*12011SSriharsha.Basavapatna@Sun.COM mp->b_wptr = mp->b_rptr + rxd.nbytes;
1189*12011SSriharsha.Basavapatna@Sun.COM
1190*12011SSriharsha.Basavapatna@Sun.COM if (vmp != NULL) {
1191*12011SSriharsha.Basavapatna@Sun.COM vmp->state = VIO_MBLK_HAS_DATA;
1192*12011SSriharsha.Basavapatna@Sun.COM }
1193*12011SSriharsha.Basavapatna@Sun.COM
1194*12011SSriharsha.Basavapatna@Sun.COM /* update stats */
1195*12011SSriharsha.Basavapatna@Sun.COM statsp->ipackets++;
1196*12011SSriharsha.Basavapatna@Sun.COM statsp->rbytes += rxd.nbytes;
1197*12011SSriharsha.Basavapatna@Sun.COM ehp = (struct ether_header *)mp->b_rptr;
1198*12011SSriharsha.Basavapatna@Sun.COM if (IS_BROADCAST(ehp))
1199*12011SSriharsha.Basavapatna@Sun.COM statsp->brdcstrcv++;
1200*12011SSriharsha.Basavapatna@Sun.COM else if (IS_MULTICAST(ehp))
1201*12011SSriharsha.Basavapatna@Sun.COM statsp->multircv++;
1202*12011SSriharsha.Basavapatna@Sun.COM
1203*12011SSriharsha.Basavapatna@Sun.COM /* build a chain of received packets */
1204*12011SSriharsha.Basavapatna@Sun.COM if (bp == NULL) {
1205*12011SSriharsha.Basavapatna@Sun.COM /* first pkt */
1206*12011SSriharsha.Basavapatna@Sun.COM bp = mp;
1207*12011SSriharsha.Basavapatna@Sun.COM bpt = bp;
1208*12011SSriharsha.Basavapatna@Sun.COM bpt->b_next = NULL;
1209*12011SSriharsha.Basavapatna@Sun.COM } else {
1210*12011SSriharsha.Basavapatna@Sun.COM mp->b_next = NULL;
1211*12011SSriharsha.Basavapatna@Sun.COM bpt->b_next = mp;
1212*12011SSriharsha.Basavapatna@Sun.COM bpt = mp;
1213*12011SSriharsha.Basavapatna@Sun.COM }
1214*12011SSriharsha.Basavapatna@Sun.COM
1215*12011SSriharsha.Basavapatna@Sun.COM if (count++ > vgen_chain_len) {
1216*12011SSriharsha.Basavapatna@Sun.COM DTRACE_PROBE1(vgen_rcv_msgs, int, count);
1217*12011SSriharsha.Basavapatna@Sun.COM vgen_rx(ldcp, bp, bpt);
1218*12011SSriharsha.Basavapatna@Sun.COM count = 0;
1219*12011SSriharsha.Basavapatna@Sun.COM bp = bpt = NULL;
1220*12011SSriharsha.Basavapatna@Sun.COM }
1221*12011SSriharsha.Basavapatna@Sun.COM
1222*12011SSriharsha.Basavapatna@Sun.COM vgen_next_rxi:
1223*12011SSriharsha.Basavapatna@Sun.COM /* update end index of range of descrs to be ack'd */
1224*12011SSriharsha.Basavapatna@Sun.COM ack_end = rxi;
1225*12011SSriharsha.Basavapatna@Sun.COM
1226*12011SSriharsha.Basavapatna@Sun.COM /* update the next index to be processed */
1227*12011SSriharsha.Basavapatna@Sun.COM INCR_RXI(next_rxi, ldcp);
1228*12011SSriharsha.Basavapatna@Sun.COM if (next_rxi == start) {
1229*12011SSriharsha.Basavapatna@Sun.COM /*
1230*12011SSriharsha.Basavapatna@Sun.COM * processed the entire descriptor ring upto
1231*12011SSriharsha.Basavapatna@Sun.COM * the index at which we started.
1232*12011SSriharsha.Basavapatna@Sun.COM */
1233*12011SSriharsha.Basavapatna@Sun.COM break;
1234*12011SSriharsha.Basavapatna@Sun.COM }
1235*12011SSriharsha.Basavapatna@Sun.COM
1236*12011SSriharsha.Basavapatna@Sun.COM rxi = next_rxi;
1237*12011SSriharsha.Basavapatna@Sun.COM
1238*12011SSriharsha.Basavapatna@Sun.COM _NOTE(CONSTCOND)
1239*12011SSriharsha.Basavapatna@Sun.COM } while (1);
1240*12011SSriharsha.Basavapatna@Sun.COM
1241*12011SSriharsha.Basavapatna@Sun.COM /*
1242*12011SSriharsha.Basavapatna@Sun.COM * send an ack message to peer indicating that we have stopped
1243*12011SSriharsha.Basavapatna@Sun.COM * processing descriptors.
1244*12011SSriharsha.Basavapatna@Sun.COM */
1245*12011SSriharsha.Basavapatna@Sun.COM if (set_ack_start) {
1246*12011SSriharsha.Basavapatna@Sun.COM /*
1247*12011SSriharsha.Basavapatna@Sun.COM * We have ack'd upto some index and we have not
1248*12011SSriharsha.Basavapatna@Sun.COM * processed any descriptors beyond that index.
1249*12011SSriharsha.Basavapatna@Sun.COM * Use the last ack'd index as both the start and
1250*12011SSriharsha.Basavapatna@Sun.COM * end of range of descrs being ack'd.
1251*12011SSriharsha.Basavapatna@Sun.COM * Note: This results in acking the last index twice
1252*12011SSriharsha.Basavapatna@Sun.COM * and should be harmless.
1253*12011SSriharsha.Basavapatna@Sun.COM */
1254*12011SSriharsha.Basavapatna@Sun.COM ack_start = ack_end;
1255*12011SSriharsha.Basavapatna@Sun.COM }
1256*12011SSriharsha.Basavapatna@Sun.COM
1257*12011SSriharsha.Basavapatna@Sun.COM rv = vgen_send_dringack(ldcp, tagp, ack_start, ack_end,
1258*12011SSriharsha.Basavapatna@Sun.COM VIO_DP_STOPPED);
1259*12011SSriharsha.Basavapatna@Sun.COM if (rv != VGEN_SUCCESS) {
1260*12011SSriharsha.Basavapatna@Sun.COM goto error_ret;
1261*12011SSriharsha.Basavapatna@Sun.COM }
1262*12011SSriharsha.Basavapatna@Sun.COM
1263*12011SSriharsha.Basavapatna@Sun.COM /* save new recv index of next dring msg */
1264*12011SSriharsha.Basavapatna@Sun.COM ldcp->next_rxi = next_rxi;
1265*12011SSriharsha.Basavapatna@Sun.COM
1266*12011SSriharsha.Basavapatna@Sun.COM error_ret:
1267*12011SSriharsha.Basavapatna@Sun.COM /* send up packets received so far */
1268*12011SSriharsha.Basavapatna@Sun.COM if (bp != NULL) {
1269*12011SSriharsha.Basavapatna@Sun.COM DTRACE_PROBE1(vgen_rcv_msgs, int, count);
1270*12011SSriharsha.Basavapatna@Sun.COM vgen_rx(ldcp, bp, bpt);
1271*12011SSriharsha.Basavapatna@Sun.COM bp = bpt = NULL;
1272*12011SSriharsha.Basavapatna@Sun.COM }
1273*12011SSriharsha.Basavapatna@Sun.COM DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
1274*12011SSriharsha.Basavapatna@Sun.COM return (rv);
1275*12011SSriharsha.Basavapatna@Sun.COM
1276*12011SSriharsha.Basavapatna@Sun.COM }
1277*12011SSriharsha.Basavapatna@Sun.COM
1278*12011SSriharsha.Basavapatna@Sun.COM static int
vgen_handle_dringdata_ack(vgen_ldc_t * ldcp,vio_msg_tag_t * tagp)1279*12011SSriharsha.Basavapatna@Sun.COM vgen_handle_dringdata_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
1280*12011SSriharsha.Basavapatna@Sun.COM {
1281*12011SSriharsha.Basavapatna@Sun.COM int rv = 0;
1282*12011SSriharsha.Basavapatna@Sun.COM uint32_t start;
1283*12011SSriharsha.Basavapatna@Sun.COM int32_t end;
1284*12011SSriharsha.Basavapatna@Sun.COM uint32_t txi;
1285*12011SSriharsha.Basavapatna@Sun.COM boolean_t ready_txd = B_FALSE;
1286*12011SSriharsha.Basavapatna@Sun.COM vgen_stats_t *statsp;
1287*12011SSriharsha.Basavapatna@Sun.COM vgen_private_desc_t *tbufp;
1288*12011SSriharsha.Basavapatna@Sun.COM vnet_public_desc_t *txdp;
1289*12011SSriharsha.Basavapatna@Sun.COM vio_dring_entry_hdr_t *hdrp;
1290*12011SSriharsha.Basavapatna@Sun.COM vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1291*12011SSriharsha.Basavapatna@Sun.COM vio_dring_msg_t *dringmsg = (vio_dring_msg_t *)tagp;
1292*12011SSriharsha.Basavapatna@Sun.COM
1293*12011SSriharsha.Basavapatna@Sun.COM DBG1(vgenp, ldcp, "enter\n");
1294*12011SSriharsha.Basavapatna@Sun.COM start = dringmsg->start_idx;
1295*12011SSriharsha.Basavapatna@Sun.COM end = dringmsg->end_idx;
1296*12011SSriharsha.Basavapatna@Sun.COM statsp = &ldcp->stats;
1297*12011SSriharsha.Basavapatna@Sun.COM
1298*12011SSriharsha.Basavapatna@Sun.COM /*
1299*12011SSriharsha.Basavapatna@Sun.COM * received an ack corresponding to a specific descriptor for
1300*12011SSriharsha.Basavapatna@Sun.COM * which we had set the ACK bit in the descriptor (during
1301*12011SSriharsha.Basavapatna@Sun.COM * transmit). This enables us to reclaim descriptors.
1302*12011SSriharsha.Basavapatna@Sun.COM */
1303*12011SSriharsha.Basavapatna@Sun.COM
1304*12011SSriharsha.Basavapatna@Sun.COM DBG2(vgenp, ldcp, "ACK: start(%d), end(%d)\n", start, end);
1305*12011SSriharsha.Basavapatna@Sun.COM
1306*12011SSriharsha.Basavapatna@Sun.COM /* validate start and end indexes in the tx ack msg */
1307*12011SSriharsha.Basavapatna@Sun.COM if (!(CHECK_TXI(start, ldcp)) || !(CHECK_TXI(end, ldcp))) {
1308*12011SSriharsha.Basavapatna@Sun.COM /* drop the message if invalid index */
1309*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "Invalid Tx ack start(%d) or end(%d)\n",
1310*12011SSriharsha.Basavapatna@Sun.COM start, end);
1311*12011SSriharsha.Basavapatna@Sun.COM return (rv);
1312*12011SSriharsha.Basavapatna@Sun.COM }
1313*12011SSriharsha.Basavapatna@Sun.COM /* validate dring_ident */
1314*12011SSriharsha.Basavapatna@Sun.COM if (dringmsg->dring_ident != ldcp->local_hparams.dring_ident) {
1315*12011SSriharsha.Basavapatna@Sun.COM /* invalid dring_ident, drop the msg */
1316*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "Invalid dring ident 0x%x\n",
1317*12011SSriharsha.Basavapatna@Sun.COM dringmsg->dring_ident);
1318*12011SSriharsha.Basavapatna@Sun.COM return (rv);
1319*12011SSriharsha.Basavapatna@Sun.COM }
1320*12011SSriharsha.Basavapatna@Sun.COM statsp->dring_data_acks_rcvd++;
1321*12011SSriharsha.Basavapatna@Sun.COM
1322*12011SSriharsha.Basavapatna@Sun.COM /* reclaim descriptors that are done */
1323*12011SSriharsha.Basavapatna@Sun.COM vgen_reclaim(ldcp);
1324*12011SSriharsha.Basavapatna@Sun.COM
1325*12011SSriharsha.Basavapatna@Sun.COM if (dringmsg->dring_process_state != VIO_DP_STOPPED) {
1326*12011SSriharsha.Basavapatna@Sun.COM /*
1327*12011SSriharsha.Basavapatna@Sun.COM * receiver continued processing descriptors after
1328*12011SSriharsha.Basavapatna@Sun.COM * sending us the ack.
1329*12011SSriharsha.Basavapatna@Sun.COM */
1330*12011SSriharsha.Basavapatna@Sun.COM return (rv);
1331*12011SSriharsha.Basavapatna@Sun.COM }
1332*12011SSriharsha.Basavapatna@Sun.COM
1333*12011SSriharsha.Basavapatna@Sun.COM statsp->dring_stopped_acks_rcvd++;
1334*12011SSriharsha.Basavapatna@Sun.COM
1335*12011SSriharsha.Basavapatna@Sun.COM /* receiver stopped processing descriptors */
1336*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->wrlock);
1337*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->tclock);
1338*12011SSriharsha.Basavapatna@Sun.COM
1339*12011SSriharsha.Basavapatna@Sun.COM /*
1340*12011SSriharsha.Basavapatna@Sun.COM * determine if there are any pending tx descriptors
1341*12011SSriharsha.Basavapatna@Sun.COM * ready to be processed by the receiver(peer) and if so,
1342*12011SSriharsha.Basavapatna@Sun.COM * send a message to the peer to restart receiving.
1343*12011SSriharsha.Basavapatna@Sun.COM */
1344*12011SSriharsha.Basavapatna@Sun.COM ready_txd = B_FALSE;
1345*12011SSriharsha.Basavapatna@Sun.COM
1346*12011SSriharsha.Basavapatna@Sun.COM /*
1347*12011SSriharsha.Basavapatna@Sun.COM * using the end index of the descriptor range for which
1348*12011SSriharsha.Basavapatna@Sun.COM * we received the ack, check if the next descriptor is
1349*12011SSriharsha.Basavapatna@Sun.COM * ready.
1350*12011SSriharsha.Basavapatna@Sun.COM */
1351*12011SSriharsha.Basavapatna@Sun.COM txi = end;
1352*12011SSriharsha.Basavapatna@Sun.COM INCR_TXI(txi, ldcp);
1353*12011SSriharsha.Basavapatna@Sun.COM tbufp = &ldcp->tbufp[txi];
1354*12011SSriharsha.Basavapatna@Sun.COM txdp = tbufp->descp;
1355*12011SSriharsha.Basavapatna@Sun.COM hdrp = &txdp->hdr;
1356*12011SSriharsha.Basavapatna@Sun.COM if (hdrp->dstate == VIO_DESC_READY) {
1357*12011SSriharsha.Basavapatna@Sun.COM ready_txd = B_TRUE;
1358*12011SSriharsha.Basavapatna@Sun.COM } else {
1359*12011SSriharsha.Basavapatna@Sun.COM /*
1360*12011SSriharsha.Basavapatna@Sun.COM * descr next to the end of ack'd descr range is not
1361*12011SSriharsha.Basavapatna@Sun.COM * ready.
1362*12011SSriharsha.Basavapatna@Sun.COM * starting from the current reclaim index, check
1363*12011SSriharsha.Basavapatna@Sun.COM * if any descriptor is ready.
1364*12011SSriharsha.Basavapatna@Sun.COM */
1365*12011SSriharsha.Basavapatna@Sun.COM
1366*12011SSriharsha.Basavapatna@Sun.COM txi = ldcp->cur_tbufp - ldcp->tbufp;
1367*12011SSriharsha.Basavapatna@Sun.COM tbufp = &ldcp->tbufp[txi];
1368*12011SSriharsha.Basavapatna@Sun.COM
1369*12011SSriharsha.Basavapatna@Sun.COM txdp = tbufp->descp;
1370*12011SSriharsha.Basavapatna@Sun.COM hdrp = &txdp->hdr;
1371*12011SSriharsha.Basavapatna@Sun.COM if (hdrp->dstate == VIO_DESC_READY) {
1372*12011SSriharsha.Basavapatna@Sun.COM ready_txd = B_TRUE;
1373*12011SSriharsha.Basavapatna@Sun.COM }
1374*12011SSriharsha.Basavapatna@Sun.COM
1375*12011SSriharsha.Basavapatna@Sun.COM }
1376*12011SSriharsha.Basavapatna@Sun.COM
1377*12011SSriharsha.Basavapatna@Sun.COM if (ready_txd) {
1378*12011SSriharsha.Basavapatna@Sun.COM /*
1379*12011SSriharsha.Basavapatna@Sun.COM * we have tx descriptor(s) ready to be
1380*12011SSriharsha.Basavapatna@Sun.COM * processed by the receiver.
1381*12011SSriharsha.Basavapatna@Sun.COM * send a message to the peer with the start index
1382*12011SSriharsha.Basavapatna@Sun.COM * of ready descriptors.
1383*12011SSriharsha.Basavapatna@Sun.COM */
1384*12011SSriharsha.Basavapatna@Sun.COM rv = vgen_send_dringdata(ldcp, txi, -1);
1385*12011SSriharsha.Basavapatna@Sun.COM if (rv != VGEN_SUCCESS) {
1386*12011SSriharsha.Basavapatna@Sun.COM ldcp->resched_peer = B_TRUE;
1387*12011SSriharsha.Basavapatna@Sun.COM ldcp->resched_peer_txi = txi;
1388*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->tclock);
1389*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->wrlock);
1390*12011SSriharsha.Basavapatna@Sun.COM return (rv);
1391*12011SSriharsha.Basavapatna@Sun.COM }
1392*12011SSriharsha.Basavapatna@Sun.COM } else {
1393*12011SSriharsha.Basavapatna@Sun.COM /*
1394*12011SSriharsha.Basavapatna@Sun.COM * no ready tx descriptors. set the flag to send a
1395*12011SSriharsha.Basavapatna@Sun.COM * message to peer when tx descriptors are ready in
1396*12011SSriharsha.Basavapatna@Sun.COM * transmit routine.
1397*12011SSriharsha.Basavapatna@Sun.COM */
1398*12011SSriharsha.Basavapatna@Sun.COM ldcp->resched_peer = B_TRUE;
1399*12011SSriharsha.Basavapatna@Sun.COM ldcp->resched_peer_txi = ldcp->cur_tbufp - ldcp->tbufp;
1400*12011SSriharsha.Basavapatna@Sun.COM }
1401*12011SSriharsha.Basavapatna@Sun.COM
1402*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->tclock);
1403*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->wrlock);
1404*12011SSriharsha.Basavapatna@Sun.COM DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
1405*12011SSriharsha.Basavapatna@Sun.COM return (rv);
1406*12011SSriharsha.Basavapatna@Sun.COM }
1407*12011SSriharsha.Basavapatna@Sun.COM
1408*12011SSriharsha.Basavapatna@Sun.COM static int
vgen_handle_dringdata_nack(vgen_ldc_t * ldcp,vio_msg_tag_t * tagp)1409*12011SSriharsha.Basavapatna@Sun.COM vgen_handle_dringdata_nack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
1410*12011SSriharsha.Basavapatna@Sun.COM {
1411*12011SSriharsha.Basavapatna@Sun.COM int rv = 0;
1412*12011SSriharsha.Basavapatna@Sun.COM uint32_t start;
1413*12011SSriharsha.Basavapatna@Sun.COM int32_t end;
1414*12011SSriharsha.Basavapatna@Sun.COM uint32_t txi;
1415*12011SSriharsha.Basavapatna@Sun.COM vnet_public_desc_t *txdp;
1416*12011SSriharsha.Basavapatna@Sun.COM vio_dring_entry_hdr_t *hdrp;
1417*12011SSriharsha.Basavapatna@Sun.COM vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1418*12011SSriharsha.Basavapatna@Sun.COM vio_dring_msg_t *dringmsg = (vio_dring_msg_t *)tagp;
1419*12011SSriharsha.Basavapatna@Sun.COM
1420*12011SSriharsha.Basavapatna@Sun.COM DBG1(vgenp, ldcp, "enter\n");
1421*12011SSriharsha.Basavapatna@Sun.COM start = dringmsg->start_idx;
1422*12011SSriharsha.Basavapatna@Sun.COM end = dringmsg->end_idx;
1423*12011SSriharsha.Basavapatna@Sun.COM
1424*12011SSriharsha.Basavapatna@Sun.COM /*
1425*12011SSriharsha.Basavapatna@Sun.COM * peer sent a NACK msg to indicate lost packets.
1426*12011SSriharsha.Basavapatna@Sun.COM * The start and end correspond to the range of descriptors
1427*12011SSriharsha.Basavapatna@Sun.COM * for which the peer didn't receive a dring data msg and so
1428*12011SSriharsha.Basavapatna@Sun.COM * didn't receive the corresponding data.
1429*12011SSriharsha.Basavapatna@Sun.COM */
1430*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "NACK: start(%d), end(%d)\n", start, end);
1431*12011SSriharsha.Basavapatna@Sun.COM
1432*12011SSriharsha.Basavapatna@Sun.COM /* validate start and end indexes in the tx nack msg */
1433*12011SSriharsha.Basavapatna@Sun.COM if (!(CHECK_TXI(start, ldcp)) || !(CHECK_TXI(end, ldcp))) {
1434*12011SSriharsha.Basavapatna@Sun.COM /* drop the message if invalid index */
1435*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "Invalid Tx nack start(%d) or end(%d)\n",
1436*12011SSriharsha.Basavapatna@Sun.COM start, end);
1437*12011SSriharsha.Basavapatna@Sun.COM return (rv);
1438*12011SSriharsha.Basavapatna@Sun.COM }
1439*12011SSriharsha.Basavapatna@Sun.COM /* validate dring_ident */
1440*12011SSriharsha.Basavapatna@Sun.COM if (dringmsg->dring_ident != ldcp->local_hparams.dring_ident) {
1441*12011SSriharsha.Basavapatna@Sun.COM /* invalid dring_ident, drop the msg */
1442*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "Invalid dring ident 0x%x\n",
1443*12011SSriharsha.Basavapatna@Sun.COM dringmsg->dring_ident);
1444*12011SSriharsha.Basavapatna@Sun.COM return (rv);
1445*12011SSriharsha.Basavapatna@Sun.COM }
1446*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->txlock);
1447*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->tclock);
1448*12011SSriharsha.Basavapatna@Sun.COM
1449*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->next_tbufp == ldcp->cur_tbufp) {
1450*12011SSriharsha.Basavapatna@Sun.COM /* no busy descriptors, bogus nack ? */
1451*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->tclock);
1452*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->txlock);
1453*12011SSriharsha.Basavapatna@Sun.COM return (rv);
1454*12011SSriharsha.Basavapatna@Sun.COM }
1455*12011SSriharsha.Basavapatna@Sun.COM
1456*12011SSriharsha.Basavapatna@Sun.COM /* we just mark the descrs as done so they can be reclaimed */
1457*12011SSriharsha.Basavapatna@Sun.COM for (txi = start; txi <= end; ) {
1458*12011SSriharsha.Basavapatna@Sun.COM txdp = &(ldcp->txdp[txi]);
1459*12011SSriharsha.Basavapatna@Sun.COM hdrp = &txdp->hdr;
1460*12011SSriharsha.Basavapatna@Sun.COM if (hdrp->dstate == VIO_DESC_READY)
1461*12011SSriharsha.Basavapatna@Sun.COM hdrp->dstate = VIO_DESC_DONE;
1462*12011SSriharsha.Basavapatna@Sun.COM INCR_TXI(txi, ldcp);
1463*12011SSriharsha.Basavapatna@Sun.COM }
1464*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->tclock);
1465*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->txlock);
1466*12011SSriharsha.Basavapatna@Sun.COM DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
1467*12011SSriharsha.Basavapatna@Sun.COM return (rv);
1468*12011SSriharsha.Basavapatna@Sun.COM }
1469*12011SSriharsha.Basavapatna@Sun.COM
1470*12011SSriharsha.Basavapatna@Sun.COM /*
1471*12011SSriharsha.Basavapatna@Sun.COM * Send received packets up the stack.
1472*12011SSriharsha.Basavapatna@Sun.COM */
1473*12011SSriharsha.Basavapatna@Sun.COM static void
vgen_rx(vgen_ldc_t * ldcp,mblk_t * bp,mblk_t * bpt)1474*12011SSriharsha.Basavapatna@Sun.COM vgen_rx(vgen_ldc_t *ldcp, mblk_t *bp, mblk_t *bpt)
1475*12011SSriharsha.Basavapatna@Sun.COM {
1476*12011SSriharsha.Basavapatna@Sun.COM vio_net_rx_cb_t vrx_cb = ldcp->portp->vcb.vio_net_rx_cb;
1477*12011SSriharsha.Basavapatna@Sun.COM vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1478*12011SSriharsha.Basavapatna@Sun.COM
1479*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->msg_thread != NULL) {
1480*12011SSriharsha.Basavapatna@Sun.COM ASSERT(MUTEX_HELD(&ldcp->rxlock));
1481*12011SSriharsha.Basavapatna@Sun.COM } else {
1482*12011SSriharsha.Basavapatna@Sun.COM ASSERT(MUTEX_HELD(&ldcp->cblock));
1483*12011SSriharsha.Basavapatna@Sun.COM }
1484*12011SSriharsha.Basavapatna@Sun.COM
1485*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->pollq_lock);
1486*12011SSriharsha.Basavapatna@Sun.COM
1487*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->polling_on == B_TRUE) {
1488*12011SSriharsha.Basavapatna@Sun.COM /*
1489*12011SSriharsha.Basavapatna@Sun.COM * If we are in polling mode, simply queue
1490*12011SSriharsha.Basavapatna@Sun.COM * the packets onto the poll queue and return.
1491*12011SSriharsha.Basavapatna@Sun.COM */
1492*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->pollq_headp == NULL) {
1493*12011SSriharsha.Basavapatna@Sun.COM ldcp->pollq_headp = bp;
1494*12011SSriharsha.Basavapatna@Sun.COM ldcp->pollq_tailp = bpt;
1495*12011SSriharsha.Basavapatna@Sun.COM } else {
1496*12011SSriharsha.Basavapatna@Sun.COM ldcp->pollq_tailp->b_next = bp;
1497*12011SSriharsha.Basavapatna@Sun.COM ldcp->pollq_tailp = bpt;
1498*12011SSriharsha.Basavapatna@Sun.COM }
1499*12011SSriharsha.Basavapatna@Sun.COM
1500*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->pollq_lock);
1501*12011SSriharsha.Basavapatna@Sun.COM return;
1502*12011SSriharsha.Basavapatna@Sun.COM }
1503*12011SSriharsha.Basavapatna@Sun.COM
1504*12011SSriharsha.Basavapatna@Sun.COM /*
1505*12011SSriharsha.Basavapatna@Sun.COM * Prepend any pending mblks in the poll queue, now that we
1506*12011SSriharsha.Basavapatna@Sun.COM * are in interrupt mode, before sending up the chain of pkts.
1507*12011SSriharsha.Basavapatna@Sun.COM */
1508*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->pollq_headp != NULL) {
1509*12011SSriharsha.Basavapatna@Sun.COM DBG2(vgenp, ldcp, "vgen_rx(%lx), pending pollq_headp\n",
1510*12011SSriharsha.Basavapatna@Sun.COM (uintptr_t)ldcp);
1511*12011SSriharsha.Basavapatna@Sun.COM ldcp->pollq_tailp->b_next = bp;
1512*12011SSriharsha.Basavapatna@Sun.COM bp = ldcp->pollq_headp;
1513*12011SSriharsha.Basavapatna@Sun.COM ldcp->pollq_headp = ldcp->pollq_tailp = NULL;
1514*12011SSriharsha.Basavapatna@Sun.COM }
1515*12011SSriharsha.Basavapatna@Sun.COM
1516*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->pollq_lock);
1517*12011SSriharsha.Basavapatna@Sun.COM
1518*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->msg_thread != NULL) {
1519*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->rxlock);
1520*12011SSriharsha.Basavapatna@Sun.COM } else {
1521*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->cblock);
1522*12011SSriharsha.Basavapatna@Sun.COM }
1523*12011SSriharsha.Basavapatna@Sun.COM
1524*12011SSriharsha.Basavapatna@Sun.COM /* Send up the packets */
1525*12011SSriharsha.Basavapatna@Sun.COM vrx_cb(ldcp->portp->vhp, bp);
1526*12011SSriharsha.Basavapatna@Sun.COM
1527*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->msg_thread != NULL) {
1528*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->rxlock);
1529*12011SSriharsha.Basavapatna@Sun.COM } else {
1530*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->cblock);
1531*12011SSriharsha.Basavapatna@Sun.COM }
1532*12011SSriharsha.Basavapatna@Sun.COM }
1533*12011SSriharsha.Basavapatna@Sun.COM
1534*12011SSriharsha.Basavapatna@Sun.COM static void
vgen_reclaim(vgen_ldc_t * ldcp)1535*12011SSriharsha.Basavapatna@Sun.COM vgen_reclaim(vgen_ldc_t *ldcp)
1536*12011SSriharsha.Basavapatna@Sun.COM {
1537*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->tclock);
1538*12011SSriharsha.Basavapatna@Sun.COM vgen_reclaim_dring(ldcp);
1539*12011SSriharsha.Basavapatna@Sun.COM ldcp->reclaim_lbolt = ddi_get_lbolt();
1540*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->tclock);
1541*12011SSriharsha.Basavapatna@Sun.COM }
1542*12011SSriharsha.Basavapatna@Sun.COM
1543*12011SSriharsha.Basavapatna@Sun.COM /*
1544*12011SSriharsha.Basavapatna@Sun.COM * transmit reclaim function. starting from the current reclaim index
1545*12011SSriharsha.Basavapatna@Sun.COM * look for descriptors marked DONE and reclaim the descriptor.
1546*12011SSriharsha.Basavapatna@Sun.COM */
1547*12011SSriharsha.Basavapatna@Sun.COM static void
vgen_reclaim_dring(vgen_ldc_t * ldcp)1548*12011SSriharsha.Basavapatna@Sun.COM vgen_reclaim_dring(vgen_ldc_t *ldcp)
1549*12011SSriharsha.Basavapatna@Sun.COM {
1550*12011SSriharsha.Basavapatna@Sun.COM int count = 0;
1551*12011SSriharsha.Basavapatna@Sun.COM vnet_public_desc_t *txdp;
1552*12011SSriharsha.Basavapatna@Sun.COM vgen_private_desc_t *tbufp;
1553*12011SSriharsha.Basavapatna@Sun.COM vio_dring_entry_hdr_t *hdrp;
1554*12011SSriharsha.Basavapatna@Sun.COM
1555*12011SSriharsha.Basavapatna@Sun.COM tbufp = ldcp->cur_tbufp;
1556*12011SSriharsha.Basavapatna@Sun.COM txdp = tbufp->descp;
1557*12011SSriharsha.Basavapatna@Sun.COM hdrp = &txdp->hdr;
1558*12011SSriharsha.Basavapatna@Sun.COM
1559*12011SSriharsha.Basavapatna@Sun.COM while ((hdrp->dstate == VIO_DESC_DONE) &&
1560*12011SSriharsha.Basavapatna@Sun.COM (tbufp != ldcp->next_tbufp)) {
1561*12011SSriharsha.Basavapatna@Sun.COM tbufp->flags = VGEN_PRIV_DESC_FREE;
1562*12011SSriharsha.Basavapatna@Sun.COM hdrp->dstate = VIO_DESC_FREE;
1563*12011SSriharsha.Basavapatna@Sun.COM hdrp->ack = B_FALSE;
1564*12011SSriharsha.Basavapatna@Sun.COM
1565*12011SSriharsha.Basavapatna@Sun.COM tbufp = NEXTTBUF(ldcp, tbufp);
1566*12011SSriharsha.Basavapatna@Sun.COM txdp = tbufp->descp;
1567*12011SSriharsha.Basavapatna@Sun.COM hdrp = &txdp->hdr;
1568*12011SSriharsha.Basavapatna@Sun.COM count++;
1569*12011SSriharsha.Basavapatna@Sun.COM }
1570*12011SSriharsha.Basavapatna@Sun.COM
1571*12011SSriharsha.Basavapatna@Sun.COM ldcp->cur_tbufp = tbufp;
1572*12011SSriharsha.Basavapatna@Sun.COM
1573*12011SSriharsha.Basavapatna@Sun.COM /*
1574*12011SSriharsha.Basavapatna@Sun.COM * Check if mac layer should be notified to restart transmissions
1575*12011SSriharsha.Basavapatna@Sun.COM */
1576*12011SSriharsha.Basavapatna@Sun.COM if ((ldcp->tx_blocked) && (count > 0)) {
1577*12011SSriharsha.Basavapatna@Sun.COM vio_net_tx_update_t vtx_update =
1578*12011SSriharsha.Basavapatna@Sun.COM ldcp->portp->vcb.vio_net_tx_update;
1579*12011SSriharsha.Basavapatna@Sun.COM
1580*12011SSriharsha.Basavapatna@Sun.COM ldcp->tx_blocked = B_FALSE;
1581*12011SSriharsha.Basavapatna@Sun.COM vtx_update(ldcp->portp->vhp);
1582*12011SSriharsha.Basavapatna@Sun.COM }
1583*12011SSriharsha.Basavapatna@Sun.COM }
1584*12011SSriharsha.Basavapatna@Sun.COM
1585*12011SSriharsha.Basavapatna@Sun.COM /*
1586*12011SSriharsha.Basavapatna@Sun.COM * Send descriptor ring data message to the peer over ldc.
1587*12011SSriharsha.Basavapatna@Sun.COM */
1588*12011SSriharsha.Basavapatna@Sun.COM static int
vgen_send_dringdata(vgen_ldc_t * ldcp,uint32_t start,int32_t end)1589*12011SSriharsha.Basavapatna@Sun.COM vgen_send_dringdata(vgen_ldc_t *ldcp, uint32_t start, int32_t end)
1590*12011SSriharsha.Basavapatna@Sun.COM {
1591*12011SSriharsha.Basavapatna@Sun.COM vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1592*12011SSriharsha.Basavapatna@Sun.COM vio_dring_msg_t dringmsg, *msgp = &dringmsg;
1593*12011SSriharsha.Basavapatna@Sun.COM vio_msg_tag_t *tagp = &msgp->tag;
1594*12011SSriharsha.Basavapatna@Sun.COM vgen_stats_t *statsp = &ldcp->stats;
1595*12011SSriharsha.Basavapatna@Sun.COM int rv;
1596*12011SSriharsha.Basavapatna@Sun.COM
1597*12011SSriharsha.Basavapatna@Sun.COM #ifdef DEBUG
1598*12011SSriharsha.Basavapatna@Sun.COM if (vgen_inject_error(ldcp, VGEN_ERR_TXTIMEOUT)) {
1599*12011SSriharsha.Basavapatna@Sun.COM return (VGEN_SUCCESS);
1600*12011SSriharsha.Basavapatna@Sun.COM }
1601*12011SSriharsha.Basavapatna@Sun.COM #endif
1602*12011SSriharsha.Basavapatna@Sun.COM bzero(msgp, sizeof (*msgp));
1603*12011SSriharsha.Basavapatna@Sun.COM
1604*12011SSriharsha.Basavapatna@Sun.COM tagp->vio_msgtype = VIO_TYPE_DATA;
1605*12011SSriharsha.Basavapatna@Sun.COM tagp->vio_subtype = VIO_SUBTYPE_INFO;
1606*12011SSriharsha.Basavapatna@Sun.COM tagp->vio_subtype_env = VIO_DRING_DATA;
1607*12011SSriharsha.Basavapatna@Sun.COM tagp->vio_sid = ldcp->local_sid;
1608*12011SSriharsha.Basavapatna@Sun.COM
1609*12011SSriharsha.Basavapatna@Sun.COM msgp->dring_ident = ldcp->local_hparams.dring_ident;
1610*12011SSriharsha.Basavapatna@Sun.COM msgp->start_idx = start;
1611*12011SSriharsha.Basavapatna@Sun.COM msgp->end_idx = end;
1612*12011SSriharsha.Basavapatna@Sun.COM
1613*12011SSriharsha.Basavapatna@Sun.COM rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (dringmsg), B_TRUE);
1614*12011SSriharsha.Basavapatna@Sun.COM if (rv != VGEN_SUCCESS) {
1615*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "vgen_sendmsg failed\n");
1616*12011SSriharsha.Basavapatna@Sun.COM return (rv);
1617*12011SSriharsha.Basavapatna@Sun.COM }
1618*12011SSriharsha.Basavapatna@Sun.COM
1619*12011SSriharsha.Basavapatna@Sun.COM statsp->dring_data_msgs_sent++;
1620*12011SSriharsha.Basavapatna@Sun.COM
1621*12011SSriharsha.Basavapatna@Sun.COM DBG2(vgenp, ldcp, "DRING_DATA_SENT \n");
1622*12011SSriharsha.Basavapatna@Sun.COM
1623*12011SSriharsha.Basavapatna@Sun.COM return (VGEN_SUCCESS);
1624*12011SSriharsha.Basavapatna@Sun.COM }
1625*12011SSriharsha.Basavapatna@Sun.COM
1626*12011SSriharsha.Basavapatna@Sun.COM /*
1627*12011SSriharsha.Basavapatna@Sun.COM * Send dring data ack message.
1628*12011SSriharsha.Basavapatna@Sun.COM */
1629*12011SSriharsha.Basavapatna@Sun.COM static int
vgen_send_dringack(vgen_ldc_t * ldcp,vio_msg_tag_t * tagp,uint32_t start,int32_t end,uint8_t pstate)1630*12011SSriharsha.Basavapatna@Sun.COM vgen_send_dringack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp, uint32_t start,
1631*12011SSriharsha.Basavapatna@Sun.COM int32_t end, uint8_t pstate)
1632*12011SSriharsha.Basavapatna@Sun.COM {
1633*12011SSriharsha.Basavapatna@Sun.COM int rv = 0;
1634*12011SSriharsha.Basavapatna@Sun.COM vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1635*12011SSriharsha.Basavapatna@Sun.COM vio_dring_msg_t *msgp = (vio_dring_msg_t *)tagp;
1636*12011SSriharsha.Basavapatna@Sun.COM vgen_stats_t *statsp = &ldcp->stats;
1637*12011SSriharsha.Basavapatna@Sun.COM
1638*12011SSriharsha.Basavapatna@Sun.COM tagp->vio_msgtype = VIO_TYPE_DATA;
1639*12011SSriharsha.Basavapatna@Sun.COM tagp->vio_subtype = VIO_SUBTYPE_ACK;
1640*12011SSriharsha.Basavapatna@Sun.COM tagp->vio_subtype_env = VIO_DRING_DATA;
1641*12011SSriharsha.Basavapatna@Sun.COM tagp->vio_sid = ldcp->local_sid;
1642*12011SSriharsha.Basavapatna@Sun.COM msgp->start_idx = start;
1643*12011SSriharsha.Basavapatna@Sun.COM msgp->end_idx = end;
1644*12011SSriharsha.Basavapatna@Sun.COM msgp->dring_process_state = pstate;
1645*12011SSriharsha.Basavapatna@Sun.COM
1646*12011SSriharsha.Basavapatna@Sun.COM rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*msgp), B_FALSE);
1647*12011SSriharsha.Basavapatna@Sun.COM if (rv != VGEN_SUCCESS) {
1648*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "vgen_sendmsg() failed\n");
1649*12011SSriharsha.Basavapatna@Sun.COM }
1650*12011SSriharsha.Basavapatna@Sun.COM
1651*12011SSriharsha.Basavapatna@Sun.COM statsp->dring_data_acks_sent++;
1652*12011SSriharsha.Basavapatna@Sun.COM if (pstate == VIO_DP_STOPPED) {
1653*12011SSriharsha.Basavapatna@Sun.COM statsp->dring_stopped_acks_sent++;
1654*12011SSriharsha.Basavapatna@Sun.COM }
1655*12011SSriharsha.Basavapatna@Sun.COM
1656*12011SSriharsha.Basavapatna@Sun.COM return (rv);
1657*12011SSriharsha.Basavapatna@Sun.COM }
1658*12011SSriharsha.Basavapatna@Sun.COM
1659*12011SSriharsha.Basavapatna@Sun.COM /*
1660*12011SSriharsha.Basavapatna@Sun.COM * Wrapper routine to send the given message over ldc using ldc_write().
1661*12011SSriharsha.Basavapatna@Sun.COM */
1662*12011SSriharsha.Basavapatna@Sun.COM int
vgen_sendmsg(vgen_ldc_t * ldcp,caddr_t msg,size_t msglen,boolean_t caller_holds_lock)1663*12011SSriharsha.Basavapatna@Sun.COM vgen_sendmsg(vgen_ldc_t *ldcp, caddr_t msg, size_t msglen,
1664*12011SSriharsha.Basavapatna@Sun.COM boolean_t caller_holds_lock)
1665*12011SSriharsha.Basavapatna@Sun.COM {
1666*12011SSriharsha.Basavapatna@Sun.COM int rv;
1667*12011SSriharsha.Basavapatna@Sun.COM size_t len;
1668*12011SSriharsha.Basavapatna@Sun.COM uint32_t retries = 0;
1669*12011SSriharsha.Basavapatna@Sun.COM vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1670*12011SSriharsha.Basavapatna@Sun.COM vio_msg_tag_t *tagp = (vio_msg_tag_t *)msg;
1671*12011SSriharsha.Basavapatna@Sun.COM vio_dring_msg_t *dmsg;
1672*12011SSriharsha.Basavapatna@Sun.COM vio_raw_data_msg_t *rmsg;
1673*12011SSriharsha.Basavapatna@Sun.COM boolean_t data_msg = B_FALSE;
1674*12011SSriharsha.Basavapatna@Sun.COM
1675*12011SSriharsha.Basavapatna@Sun.COM len = msglen;
1676*12011SSriharsha.Basavapatna@Sun.COM if ((len == 0) || (msg == NULL))
1677*12011SSriharsha.Basavapatna@Sun.COM return (VGEN_FAILURE);
1678*12011SSriharsha.Basavapatna@Sun.COM
1679*12011SSriharsha.Basavapatna@Sun.COM if (!caller_holds_lock) {
1680*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->wrlock);
1681*12011SSriharsha.Basavapatna@Sun.COM }
1682*12011SSriharsha.Basavapatna@Sun.COM
1683*12011SSriharsha.Basavapatna@Sun.COM if (tagp->vio_subtype == VIO_SUBTYPE_INFO) {
1684*12011SSriharsha.Basavapatna@Sun.COM if (tagp->vio_subtype_env == VIO_DRING_DATA) {
1685*12011SSriharsha.Basavapatna@Sun.COM dmsg = (vio_dring_msg_t *)tagp;
1686*12011SSriharsha.Basavapatna@Sun.COM dmsg->seq_num = ldcp->next_txseq;
1687*12011SSriharsha.Basavapatna@Sun.COM data_msg = B_TRUE;
1688*12011SSriharsha.Basavapatna@Sun.COM } else if (tagp->vio_subtype_env == VIO_PKT_DATA) {
1689*12011SSriharsha.Basavapatna@Sun.COM rmsg = (vio_raw_data_msg_t *)tagp;
1690*12011SSriharsha.Basavapatna@Sun.COM rmsg->seq_num = ldcp->next_txseq;
1691*12011SSriharsha.Basavapatna@Sun.COM data_msg = B_TRUE;
1692*12011SSriharsha.Basavapatna@Sun.COM }
1693*12011SSriharsha.Basavapatna@Sun.COM }
1694*12011SSriharsha.Basavapatna@Sun.COM
1695*12011SSriharsha.Basavapatna@Sun.COM do {
1696*12011SSriharsha.Basavapatna@Sun.COM len = msglen;
1697*12011SSriharsha.Basavapatna@Sun.COM rv = ldc_write(ldcp->ldc_handle, (caddr_t)msg, &len);
1698*12011SSriharsha.Basavapatna@Sun.COM if (retries++ >= vgen_ldcwr_retries)
1699*12011SSriharsha.Basavapatna@Sun.COM break;
1700*12011SSriharsha.Basavapatna@Sun.COM } while (rv == EWOULDBLOCK);
1701*12011SSriharsha.Basavapatna@Sun.COM
1702*12011SSriharsha.Basavapatna@Sun.COM if (rv == 0 && data_msg == B_TRUE) {
1703*12011SSriharsha.Basavapatna@Sun.COM ldcp->next_txseq++;
1704*12011SSriharsha.Basavapatna@Sun.COM }
1705*12011SSriharsha.Basavapatna@Sun.COM
1706*12011SSriharsha.Basavapatna@Sun.COM if (!caller_holds_lock) {
1707*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->wrlock);
1708*12011SSriharsha.Basavapatna@Sun.COM }
1709*12011SSriharsha.Basavapatna@Sun.COM
1710*12011SSriharsha.Basavapatna@Sun.COM if (rv != 0) {
1711*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "ldc_write failed: rv(%d)\n",
1712*12011SSriharsha.Basavapatna@Sun.COM rv, msglen);
1713*12011SSriharsha.Basavapatna@Sun.COM return (rv);
1714*12011SSriharsha.Basavapatna@Sun.COM }
1715*12011SSriharsha.Basavapatna@Sun.COM
1716*12011SSriharsha.Basavapatna@Sun.COM if (len != msglen) {
1717*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp, "ldc_write failed: rv(%d) msglen (%d)\n",
1718*12011SSriharsha.Basavapatna@Sun.COM rv, msglen);
1719*12011SSriharsha.Basavapatna@Sun.COM return (VGEN_FAILURE);
1720*12011SSriharsha.Basavapatna@Sun.COM }
1721*12011SSriharsha.Basavapatna@Sun.COM
1722*12011SSriharsha.Basavapatna@Sun.COM return (VGEN_SUCCESS);
1723*12011SSriharsha.Basavapatna@Sun.COM }
1724*12011SSriharsha.Basavapatna@Sun.COM
1725*12011SSriharsha.Basavapatna@Sun.COM int
vgen_check_datamsg_seq(vgen_ldc_t * ldcp,vio_msg_tag_t * tagp)1726*12011SSriharsha.Basavapatna@Sun.COM vgen_check_datamsg_seq(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
1727*12011SSriharsha.Basavapatna@Sun.COM {
1728*12011SSriharsha.Basavapatna@Sun.COM vio_raw_data_msg_t *rmsg;
1729*12011SSriharsha.Basavapatna@Sun.COM vio_dring_msg_t *dmsg;
1730*12011SSriharsha.Basavapatna@Sun.COM uint64_t seq_num;
1731*12011SSriharsha.Basavapatna@Sun.COM vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1732*12011SSriharsha.Basavapatna@Sun.COM
1733*12011SSriharsha.Basavapatna@Sun.COM if (tagp->vio_subtype_env == VIO_DRING_DATA) {
1734*12011SSriharsha.Basavapatna@Sun.COM dmsg = (vio_dring_msg_t *)tagp;
1735*12011SSriharsha.Basavapatna@Sun.COM seq_num = dmsg->seq_num;
1736*12011SSriharsha.Basavapatna@Sun.COM } else if (tagp->vio_subtype_env == VIO_PKT_DATA) {
1737*12011SSriharsha.Basavapatna@Sun.COM rmsg = (vio_raw_data_msg_t *)tagp;
1738*12011SSriharsha.Basavapatna@Sun.COM seq_num = rmsg->seq_num;
1739*12011SSriharsha.Basavapatna@Sun.COM } else {
1740*12011SSriharsha.Basavapatna@Sun.COM return (EINVAL);
1741*12011SSriharsha.Basavapatna@Sun.COM }
1742*12011SSriharsha.Basavapatna@Sun.COM
1743*12011SSriharsha.Basavapatna@Sun.COM if (seq_num != ldcp->next_rxseq) {
1744*12011SSriharsha.Basavapatna@Sun.COM
1745*12011SSriharsha.Basavapatna@Sun.COM /* seqnums don't match */
1746*12011SSriharsha.Basavapatna@Sun.COM DWARN(vgenp, ldcp,
1747*12011SSriharsha.Basavapatna@Sun.COM "next_rxseq(0x%lx) != seq_num(0x%lx)\n",
1748*12011SSriharsha.Basavapatna@Sun.COM ldcp->next_rxseq, seq_num);
1749*12011SSriharsha.Basavapatna@Sun.COM return (EINVAL);
1750*12011SSriharsha.Basavapatna@Sun.COM
1751*12011SSriharsha.Basavapatna@Sun.COM }
1752*12011SSriharsha.Basavapatna@Sun.COM
1753*12011SSriharsha.Basavapatna@Sun.COM ldcp->next_rxseq++;
1754*12011SSriharsha.Basavapatna@Sun.COM
1755*12011SSriharsha.Basavapatna@Sun.COM return (0);
1756*12011SSriharsha.Basavapatna@Sun.COM }
1757*12011SSriharsha.Basavapatna@Sun.COM
1758*12011SSriharsha.Basavapatna@Sun.COM /*
1759*12011SSriharsha.Basavapatna@Sun.COM * vgen_ldc_msg_worker -- A per LDC worker thread. This thread is woken up by
1760*12011SSriharsha.Basavapatna@Sun.COM * the LDC interrupt handler to process LDC packets and receive data.
1761*12011SSriharsha.Basavapatna@Sun.COM */
1762*12011SSriharsha.Basavapatna@Sun.COM void
vgen_ldc_msg_worker(void * arg)1763*12011SSriharsha.Basavapatna@Sun.COM vgen_ldc_msg_worker(void *arg)
1764*12011SSriharsha.Basavapatna@Sun.COM {
1765*12011SSriharsha.Basavapatna@Sun.COM callb_cpr_t cprinfo;
1766*12011SSriharsha.Basavapatna@Sun.COM vgen_ldc_t *ldcp = (vgen_ldc_t *)arg;
1767*12011SSriharsha.Basavapatna@Sun.COM vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1768*12011SSriharsha.Basavapatna@Sun.COM int rv;
1769*12011SSriharsha.Basavapatna@Sun.COM
1770*12011SSriharsha.Basavapatna@Sun.COM DBG1(vgenp, ldcp, "enter\n");
1771*12011SSriharsha.Basavapatna@Sun.COM CALLB_CPR_INIT(&cprinfo, &ldcp->msg_thr_lock, callb_generic_cpr,
1772*12011SSriharsha.Basavapatna@Sun.COM "vnet_rcv_thread");
1773*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->msg_thr_lock);
1774*12011SSriharsha.Basavapatna@Sun.COM while (!(ldcp->msg_thr_flags & VGEN_WTHR_STOP)) {
1775*12011SSriharsha.Basavapatna@Sun.COM
1776*12011SSriharsha.Basavapatna@Sun.COM CALLB_CPR_SAFE_BEGIN(&cprinfo);
1777*12011SSriharsha.Basavapatna@Sun.COM /*
1778*12011SSriharsha.Basavapatna@Sun.COM * Wait until the data is received or a stop
1779*12011SSriharsha.Basavapatna@Sun.COM * request is received.
1780*12011SSriharsha.Basavapatna@Sun.COM */
1781*12011SSriharsha.Basavapatna@Sun.COM while (!(ldcp->msg_thr_flags &
1782*12011SSriharsha.Basavapatna@Sun.COM (VGEN_WTHR_DATARCVD | VGEN_WTHR_STOP))) {
1783*12011SSriharsha.Basavapatna@Sun.COM cv_wait(&ldcp->msg_thr_cv, &ldcp->msg_thr_lock);
1784*12011SSriharsha.Basavapatna@Sun.COM }
1785*12011SSriharsha.Basavapatna@Sun.COM CALLB_CPR_SAFE_END(&cprinfo, &ldcp->msg_thr_lock)
1786*12011SSriharsha.Basavapatna@Sun.COM
1787*12011SSriharsha.Basavapatna@Sun.COM /*
1788*12011SSriharsha.Basavapatna@Sun.COM * First process the stop request.
1789*12011SSriharsha.Basavapatna@Sun.COM */
1790*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->msg_thr_flags & VGEN_WTHR_STOP) {
1791*12011SSriharsha.Basavapatna@Sun.COM DBG2(vgenp, ldcp, "stopped\n");
1792*12011SSriharsha.Basavapatna@Sun.COM break;
1793*12011SSriharsha.Basavapatna@Sun.COM }
1794*12011SSriharsha.Basavapatna@Sun.COM ldcp->msg_thr_flags &= ~VGEN_WTHR_DATARCVD;
1795*12011SSriharsha.Basavapatna@Sun.COM ldcp->msg_thr_flags |= VGEN_WTHR_PROCESSING;
1796*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->msg_thr_lock);
1797*12011SSriharsha.Basavapatna@Sun.COM DBG2(vgenp, ldcp, "calling vgen_handle_evt_read\n");
1798*12011SSriharsha.Basavapatna@Sun.COM rv = vgen_handle_evt_read(ldcp, VGEN_MSG_THR);
1799*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->msg_thr_lock);
1800*12011SSriharsha.Basavapatna@Sun.COM ldcp->msg_thr_flags &= ~VGEN_WTHR_PROCESSING;
1801*12011SSriharsha.Basavapatna@Sun.COM if (rv != 0) {
1802*12011SSriharsha.Basavapatna@Sun.COM /*
1803*12011SSriharsha.Basavapatna@Sun.COM * Channel has been reset. The thread should now exit.
1804*12011SSriharsha.Basavapatna@Sun.COM * The thread may be recreated if TxDring is negotiated
1805*12011SSriharsha.Basavapatna@Sun.COM * on this channel after the channel comes back up
1806*12011SSriharsha.Basavapatna@Sun.COM * again.
1807*12011SSriharsha.Basavapatna@Sun.COM */
1808*12011SSriharsha.Basavapatna@Sun.COM ldcp->msg_thr_flags |= VGEN_WTHR_STOP;
1809*12011SSriharsha.Basavapatna@Sun.COM break;
1810*12011SSriharsha.Basavapatna@Sun.COM }
1811*12011SSriharsha.Basavapatna@Sun.COM }
1812*12011SSriharsha.Basavapatna@Sun.COM
1813*12011SSriharsha.Basavapatna@Sun.COM /*
1814*12011SSriharsha.Basavapatna@Sun.COM * Update the run status and wakeup the thread that
1815*12011SSriharsha.Basavapatna@Sun.COM * has sent the stop request.
1816*12011SSriharsha.Basavapatna@Sun.COM */
1817*12011SSriharsha.Basavapatna@Sun.COM ldcp->msg_thr_flags &= ~VGEN_WTHR_STOP;
1818*12011SSriharsha.Basavapatna@Sun.COM ldcp->msg_thread = NULL;
1819*12011SSriharsha.Basavapatna@Sun.COM CALLB_CPR_EXIT(&cprinfo);
1820*12011SSriharsha.Basavapatna@Sun.COM
1821*12011SSriharsha.Basavapatna@Sun.COM thread_exit();
1822*12011SSriharsha.Basavapatna@Sun.COM DBG1(vgenp, ldcp, "exit\n");
1823*12011SSriharsha.Basavapatna@Sun.COM }
1824*12011SSriharsha.Basavapatna@Sun.COM
1825*12011SSriharsha.Basavapatna@Sun.COM /* vgen_stop_msg_thread -- Co-ordinate with receive thread to stop it */
1826*12011SSriharsha.Basavapatna@Sun.COM void
vgen_stop_msg_thread(vgen_ldc_t * ldcp)1827*12011SSriharsha.Basavapatna@Sun.COM vgen_stop_msg_thread(vgen_ldc_t *ldcp)
1828*12011SSriharsha.Basavapatna@Sun.COM {
1829*12011SSriharsha.Basavapatna@Sun.COM kt_did_t tid = 0;
1830*12011SSriharsha.Basavapatna@Sun.COM vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1831*12011SSriharsha.Basavapatna@Sun.COM
1832*12011SSriharsha.Basavapatna@Sun.COM DBG1(vgenp, ldcp, "enter\n");
1833*12011SSriharsha.Basavapatna@Sun.COM /*
1834*12011SSriharsha.Basavapatna@Sun.COM * Send a stop request by setting the stop flag and
1835*12011SSriharsha.Basavapatna@Sun.COM * wait until the receive thread stops.
1836*12011SSriharsha.Basavapatna@Sun.COM */
1837*12011SSriharsha.Basavapatna@Sun.COM mutex_enter(&ldcp->msg_thr_lock);
1838*12011SSriharsha.Basavapatna@Sun.COM if (ldcp->msg_thread != NULL) {
1839*12011SSriharsha.Basavapatna@Sun.COM tid = ldcp->msg_thread->t_did;
1840*12011SSriharsha.Basavapatna@Sun.COM ldcp->msg_thr_flags |= VGEN_WTHR_STOP;
1841*12011SSriharsha.Basavapatna@Sun.COM cv_signal(&ldcp->msg_thr_cv);
1842*12011SSriharsha.Basavapatna@Sun.COM }
1843*12011SSriharsha.Basavapatna@Sun.COM mutex_exit(&ldcp->msg_thr_lock);
1844*12011SSriharsha.Basavapatna@Sun.COM
1845*12011SSriharsha.Basavapatna@Sun.COM if (tid != 0) {
1846*12011SSriharsha.Basavapatna@Sun.COM thread_join(tid);
1847*12011SSriharsha.Basavapatna@Sun.COM }
1848*12011SSriharsha.Basavapatna@Sun.COM DBG1(vgenp, ldcp, "exit\n");
1849*12011SSriharsha.Basavapatna@Sun.COM }
1850