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