xref: /titanic_44/usr/src/uts/sun4v/io/vnet_rxdring.c (revision 6a634c9dca3093f3922e4b7ab826d7bdf17bf78e)
17bd3a2e2SSriharsha Basavapatna /*
27bd3a2e2SSriharsha Basavapatna  * CDDL HEADER START
37bd3a2e2SSriharsha Basavapatna  *
47bd3a2e2SSriharsha Basavapatna  * The contents of this file are subject to the terms of the
57bd3a2e2SSriharsha Basavapatna  * Common Development and Distribution License (the "License").
67bd3a2e2SSriharsha Basavapatna  * You may not use this file except in compliance with the License.
77bd3a2e2SSriharsha Basavapatna  *
87bd3a2e2SSriharsha Basavapatna  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97bd3a2e2SSriharsha Basavapatna  * or http://www.opensolaris.org/os/licensing.
107bd3a2e2SSriharsha Basavapatna  * See the License for the specific language governing permissions
117bd3a2e2SSriharsha Basavapatna  * and limitations under the License.
127bd3a2e2SSriharsha Basavapatna  *
137bd3a2e2SSriharsha Basavapatna  * When distributing Covered Code, include this CDDL HEADER in each
147bd3a2e2SSriharsha Basavapatna  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157bd3a2e2SSriharsha Basavapatna  * If applicable, add the following below this CDDL HEADER, with the
167bd3a2e2SSriharsha Basavapatna  * fields enclosed by brackets "[]" replaced with your own identifying
177bd3a2e2SSriharsha Basavapatna  * information: Portions Copyright [yyyy] [name of copyright owner]
187bd3a2e2SSriharsha Basavapatna  *
197bd3a2e2SSriharsha Basavapatna  * CDDL HEADER END
207bd3a2e2SSriharsha Basavapatna  */
217bd3a2e2SSriharsha Basavapatna 
227bd3a2e2SSriharsha Basavapatna /*
238e512277SWENTAO YANG  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
247bd3a2e2SSriharsha Basavapatna  */
258e512277SWENTAO YANG 
267bd3a2e2SSriharsha Basavapatna #include <sys/types.h>
277bd3a2e2SSriharsha Basavapatna #include <sys/errno.h>
287bd3a2e2SSriharsha Basavapatna #include <sys/sysmacros.h>
297bd3a2e2SSriharsha Basavapatna #include <sys/param.h>
307bd3a2e2SSriharsha Basavapatna #include <sys/machsystm.h>
317bd3a2e2SSriharsha Basavapatna #include <sys/stream.h>
327bd3a2e2SSriharsha Basavapatna #include <sys/strsubr.h>
337bd3a2e2SSriharsha Basavapatna #include <sys/kmem.h>
347bd3a2e2SSriharsha Basavapatna #include <sys/strsun.h>
357bd3a2e2SSriharsha Basavapatna #include <sys/callb.h>
367bd3a2e2SSriharsha Basavapatna #include <sys/sdt.h>
377bd3a2e2SSriharsha Basavapatna #include <sys/ethernet.h>
387bd3a2e2SSriharsha Basavapatna #include <sys/mach_descrip.h>
397bd3a2e2SSriharsha Basavapatna #include <sys/mdeg.h>
407bd3a2e2SSriharsha Basavapatna #include <sys/vnet.h>
417bd3a2e2SSriharsha Basavapatna #include <sys/vio_mailbox.h>
427bd3a2e2SSriharsha Basavapatna #include <sys/vio_common.h>
437bd3a2e2SSriharsha Basavapatna #include <sys/vnet_common.h>
447bd3a2e2SSriharsha Basavapatna #include <sys/vnet_mailbox.h>
457bd3a2e2SSriharsha Basavapatna #include <sys/vio_util.h>
467bd3a2e2SSriharsha Basavapatna #include <sys/vnet_gen.h>
477bd3a2e2SSriharsha Basavapatna 
487bd3a2e2SSriharsha Basavapatna /*
497bd3a2e2SSriharsha Basavapatna  * This file contains the implementation of RxDringData transfer mode of VIO
507bd3a2e2SSriharsha Basavapatna  * Protocol in vnet. The functions in this file are invoked from vnet_gen.c
517bd3a2e2SSriharsha Basavapatna  * after RxDringData mode is negotiated with the peer during attribute phase of
527bd3a2e2SSriharsha Basavapatna  * handshake. This file contains functions that setup the transmit and receive
537bd3a2e2SSriharsha Basavapatna  * descriptor rings, and associated resources in RxDringData mode. It also
547bd3a2e2SSriharsha Basavapatna  * contains the transmit and receive data processing functions that are invoked
557bd3a2e2SSriharsha Basavapatna  * in RxDringData mode. The data processing routines in this file have the
567bd3a2e2SSriharsha Basavapatna  * suffix '_shm' to indicate the shared memory mechanism used in RxDringData
577bd3a2e2SSriharsha Basavapatna  * mode.
587bd3a2e2SSriharsha Basavapatna  */
597bd3a2e2SSriharsha Basavapatna 
607bd3a2e2SSriharsha Basavapatna /* Functions exported to vnet_gen.c */
617bd3a2e2SSriharsha Basavapatna int vgen_create_rx_dring(vgen_ldc_t *ldcp);
627bd3a2e2SSriharsha Basavapatna void vgen_destroy_rx_dring(vgen_ldc_t *ldcp);
637bd3a2e2SSriharsha Basavapatna int vgen_map_tx_dring(vgen_ldc_t *ldcp, void *pkt);
647bd3a2e2SSriharsha Basavapatna void vgen_unmap_tx_dring(vgen_ldc_t *ldcp);
657bd3a2e2SSriharsha Basavapatna int vgen_map_data(vgen_ldc_t *ldcp, void *pkt);
667bd3a2e2SSriharsha Basavapatna int vgen_dringsend_shm(void *arg, mblk_t *mp);
677bd3a2e2SSriharsha Basavapatna int vgen_handle_dringdata_shm(void *arg1, void *arg2);
687bd3a2e2SSriharsha Basavapatna mblk_t *vgen_poll_rcv_shm(vgen_ldc_t *ldcp, int bytes_to_pickup);
697bd3a2e2SSriharsha Basavapatna int vgen_send_dringack_shm(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp,
707bd3a2e2SSriharsha Basavapatna     uint32_t start, int32_t end, uint8_t pstate);
717bd3a2e2SSriharsha Basavapatna 
727bd3a2e2SSriharsha Basavapatna /* Internal functions */
737bd3a2e2SSriharsha Basavapatna static int vgen_handle_dringdata_info_shm(vgen_ldc_t *ldcp, vio_msg_tag_t *tp);
747bd3a2e2SSriharsha Basavapatna static int vgen_handle_dringdata_ack_shm(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
757bd3a2e2SSriharsha Basavapatna static int vgen_handle_dringdata_nack_shm(vgen_ldc_t *ldcp, vio_msg_tag_t *tp);
767bd3a2e2SSriharsha Basavapatna static int vgen_intr_rcv_shm(vgen_ldc_t *ldcp);
777bd3a2e2SSriharsha Basavapatna static int vgen_receive_packet(vgen_ldc_t *ldcp, mblk_t **bp, uint_t *size);
787bd3a2e2SSriharsha Basavapatna static int vgen_send_dringdata_shm(vgen_ldc_t *ldcp, uint32_t start,
797bd3a2e2SSriharsha Basavapatna     int32_t end);
807bd3a2e2SSriharsha Basavapatna static int vgen_sendmsg_shm(vgen_ldc_t *ldcp, caddr_t msg,  size_t msglen);
817bd3a2e2SSriharsha Basavapatna 
827bd3a2e2SSriharsha Basavapatna /* Functions imported from vnet_gen.c */
837bd3a2e2SSriharsha Basavapatna extern int vgen_handle_evt_read(vgen_ldc_t *ldcp, vgen_caller_t caller);
847bd3a2e2SSriharsha Basavapatna extern int vgen_handle_evt_reset(vgen_ldc_t *ldcp, vgen_caller_t caller);
857bd3a2e2SSriharsha Basavapatna extern void vgen_handle_pkt_data(void *arg1, void *arg2, uint32_t msglen);
867bd3a2e2SSriharsha Basavapatna extern void vgen_destroy_rxpools(void *arg);
877bd3a2e2SSriharsha Basavapatna 
887bd3a2e2SSriharsha Basavapatna /* Tunables */
897bd3a2e2SSriharsha Basavapatna extern uint32_t vnet_num_descriptors;
907bd3a2e2SSriharsha Basavapatna extern uint32_t vgen_chain_len;
917bd3a2e2SSriharsha Basavapatna extern uint32_t vgen_ldcwr_retries;
927bd3a2e2SSriharsha Basavapatna extern uint32_t vgen_recv_delay;
937bd3a2e2SSriharsha Basavapatna extern uint32_t vgen_recv_retries;
947bd3a2e2SSriharsha Basavapatna extern uint32_t vgen_nrbufs_factor;
957bd3a2e2SSriharsha Basavapatna 
967bd3a2e2SSriharsha Basavapatna #ifdef DEBUG
977bd3a2e2SSriharsha Basavapatna 
987bd3a2e2SSriharsha Basavapatna #define	DEBUG_PRINTF	vgen_debug_printf
997bd3a2e2SSriharsha Basavapatna 
1007bd3a2e2SSriharsha Basavapatna extern int vnet_dbglevel;
1017bd3a2e2SSriharsha Basavapatna extern int vgen_inject_err_flag;
1027bd3a2e2SSriharsha Basavapatna 
1037bd3a2e2SSriharsha Basavapatna extern void vgen_debug_printf(const char *fname, vgen_t *vgenp,
1047bd3a2e2SSriharsha Basavapatna 	vgen_ldc_t *ldcp, const char *fmt, ...);
1057bd3a2e2SSriharsha Basavapatna extern boolean_t vgen_inject_error(vgen_ldc_t *ldcp, int error);
1067bd3a2e2SSriharsha Basavapatna 
1077bd3a2e2SSriharsha Basavapatna #endif
1087bd3a2e2SSriharsha Basavapatna 
1097bd3a2e2SSriharsha Basavapatna /*
1107bd3a2e2SSriharsha Basavapatna  * Allocate receive resources for the channel. The resources consist of a
1117bd3a2e2SSriharsha Basavapatna  * receive descriptor ring and an associated receive buffer area.
1127bd3a2e2SSriharsha Basavapatna  */
1137bd3a2e2SSriharsha Basavapatna int
vgen_create_rx_dring(vgen_ldc_t * ldcp)1147bd3a2e2SSriharsha Basavapatna vgen_create_rx_dring(vgen_ldc_t *ldcp)
1157bd3a2e2SSriharsha Basavapatna {
1168e512277SWENTAO YANG 	int 				i, j;
1177bd3a2e2SSriharsha Basavapatna 	int 				rv;
1187bd3a2e2SSriharsha Basavapatna 	uint32_t			ncookies;
1197bd3a2e2SSriharsha Basavapatna 	ldc_mem_info_t			minfo;
1207bd3a2e2SSriharsha Basavapatna 	vnet_rx_dringdata_desc_t	*rxdp;
1217bd3a2e2SSriharsha Basavapatna 	size_t				data_sz;
1227bd3a2e2SSriharsha Basavapatna 	vio_mblk_t			*vmp;
1237bd3a2e2SSriharsha Basavapatna 	vio_mblk_t			**rxdp_to_vmp;
1247bd3a2e2SSriharsha Basavapatna 	uint32_t			rxdsize;
1257bd3a2e2SSriharsha Basavapatna 	caddr_t				datap = NULL;
1267bd3a2e2SSriharsha Basavapatna 	vgen_t				*vgenp = LDC_TO_VGEN(ldcp);
1277bd3a2e2SSriharsha Basavapatna 
1287bd3a2e2SSriharsha Basavapatna 	rxdsize = sizeof (vnet_rx_dringdata_desc_t);
1297bd3a2e2SSriharsha Basavapatna 	ldcp->num_rxds = vnet_num_descriptors;
130*34f94fbcSWENTAO YANG 	ldcp->num_rbufs = VGEN_RXDRING_NRBUFS;
1317bd3a2e2SSriharsha Basavapatna 
1327bd3a2e2SSriharsha Basavapatna 	/* Create the receive descriptor ring */
1337bd3a2e2SSriharsha Basavapatna 	rv = ldc_mem_dring_create(ldcp->num_rxds, rxdsize,
1347bd3a2e2SSriharsha Basavapatna 	    &ldcp->rx_dring_handle);
1357bd3a2e2SSriharsha Basavapatna 	if (rv != 0) {
1367bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "ldc_mem_dring_create() failed\n");
1377bd3a2e2SSriharsha Basavapatna 		goto fail;
1387bd3a2e2SSriharsha Basavapatna 	}
1397bd3a2e2SSriharsha Basavapatna 
1407bd3a2e2SSriharsha Basavapatna 	/* Get the addr of descriptor ring */
1417bd3a2e2SSriharsha Basavapatna 	rv = ldc_mem_dring_info(ldcp->rx_dring_handle, &minfo);
1427bd3a2e2SSriharsha Basavapatna 	if (rv != 0) {
1437bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "ldc_mem_dring_info() failed\n");
1447bd3a2e2SSriharsha Basavapatna 		goto fail;
1457bd3a2e2SSriharsha Basavapatna 	}
1467bd3a2e2SSriharsha Basavapatna 	ldcp->rxdp = (vnet_rx_dringdata_desc_t *)(minfo.vaddr);
1477bd3a2e2SSriharsha Basavapatna 	bzero(ldcp->rxdp, sizeof (*rxdp) * (ldcp->num_rxds));
1487bd3a2e2SSriharsha Basavapatna 
1497bd3a2e2SSriharsha Basavapatna 	/*
1507bd3a2e2SSriharsha Basavapatna 	 * Allocate a table that maps descriptor to its associated buffer;
1517bd3a2e2SSriharsha Basavapatna 	 * used while receiving to validate that the peer has not changed the
1527bd3a2e2SSriharsha Basavapatna 	 * buffer offset provided in the descriptor.
1537bd3a2e2SSriharsha Basavapatna 	 */
1547bd3a2e2SSriharsha Basavapatna 	rxdp_to_vmp = kmem_zalloc(ldcp->num_rxds * sizeof (uintptr_t),
1557bd3a2e2SSriharsha Basavapatna 	    KM_SLEEP);
1567bd3a2e2SSriharsha Basavapatna 	ldcp->rxdp_to_vmp = rxdp_to_vmp;
1577bd3a2e2SSriharsha Basavapatna 
1587bd3a2e2SSriharsha Basavapatna 	/*
1597bd3a2e2SSriharsha Basavapatna 	 * Allocate a single large buffer that serves as the rx buffer area.
1607bd3a2e2SSriharsha Basavapatna 	 * We allocate a ldc memory handle and export the buffer area as shared
1617bd3a2e2SSriharsha Basavapatna 	 * memory. We send the ldc memcookie for this buffer space to the peer,
1627bd3a2e2SSriharsha Basavapatna 	 * as part of dring registration phase during handshake. We manage this
1637bd3a2e2SSriharsha Basavapatna 	 * buffer area as individual buffers of max_frame_size and provide
1647bd3a2e2SSriharsha Basavapatna 	 * specific buffer offsets in each descriptor to the peer. Note that
1657bd3a2e2SSriharsha Basavapatna 	 * the factor used to compute the # of buffers (above) must be > 1 to
1667bd3a2e2SSriharsha Basavapatna 	 * ensure that there are more buffers than the # of descriptors. This
1677bd3a2e2SSriharsha Basavapatna 	 * is needed because, while the shared memory buffers are sent up our
1687bd3a2e2SSriharsha Basavapatna 	 * stack during receive, the sender needs additional buffers that can
1697bd3a2e2SSriharsha Basavapatna 	 * be used for further transmits. This also means there is no one to
1707bd3a2e2SSriharsha Basavapatna 	 * one correspondence between the descriptor index and buffer offset.
1717bd3a2e2SSriharsha Basavapatna 	 * The sender has to read the buffer offset in the descriptor and use
1727bd3a2e2SSriharsha Basavapatna 	 * the specified offset to copy the tx data into the shared buffer. We
1737bd3a2e2SSriharsha Basavapatna 	 * (receiver) manage the individual buffers and their state (see
1747bd3a2e2SSriharsha Basavapatna 	 * VIO_MBLK_STATEs in vio_util.h).
1757bd3a2e2SSriharsha Basavapatna 	 */
176*34f94fbcSWENTAO YANG 	data_sz = RXDRING_DBLK_SZ(vgenp->max_frame_size);
1777bd3a2e2SSriharsha Basavapatna 
1787bd3a2e2SSriharsha Basavapatna 	ldcp->rx_data_sz = data_sz * ldcp->num_rbufs;
1797bd3a2e2SSriharsha Basavapatna 	ldcp->rx_dblk_sz = data_sz;
1807bd3a2e2SSriharsha Basavapatna 	datap = kmem_zalloc(ldcp->rx_data_sz, KM_SLEEP);
1817bd3a2e2SSriharsha Basavapatna 	ldcp->rx_datap = datap;
1827bd3a2e2SSriharsha Basavapatna 
1837bd3a2e2SSriharsha Basavapatna 	/* Allocate a ldc memhandle for the entire rx data area */
1847bd3a2e2SSriharsha Basavapatna 	rv = ldc_mem_alloc_handle(ldcp->ldc_handle, &ldcp->rx_data_handle);
1857bd3a2e2SSriharsha Basavapatna 	if (rv) {
1867bd3a2e2SSriharsha Basavapatna 		ldcp->rx_data_handle = 0;
1877bd3a2e2SSriharsha Basavapatna 		goto fail;
1887bd3a2e2SSriharsha Basavapatna 	}
1897bd3a2e2SSriharsha Basavapatna 
1907bd3a2e2SSriharsha Basavapatna 	/* Allocate memory for the data cookies */
1917bd3a2e2SSriharsha Basavapatna 	ldcp->rx_data_cookie = kmem_zalloc(VNET_DATA_AREA_COOKIES *
1927bd3a2e2SSriharsha Basavapatna 	    sizeof (ldc_mem_cookie_t), KM_SLEEP);
1937bd3a2e2SSriharsha Basavapatna 
1947bd3a2e2SSriharsha Basavapatna 	/*
1957bd3a2e2SSriharsha Basavapatna 	 * Bind ldc memhandle to the corresponding rx data area.
1967bd3a2e2SSriharsha Basavapatna 	 */
1977bd3a2e2SSriharsha Basavapatna 	ncookies = 0;
1987bd3a2e2SSriharsha Basavapatna 	rv = ldc_mem_bind_handle(ldcp->rx_data_handle, (caddr_t)datap,
1997bd3a2e2SSriharsha Basavapatna 	    ldcp->rx_data_sz, LDC_DIRECT_MAP, LDC_MEM_W,
2007bd3a2e2SSriharsha Basavapatna 	    ldcp->rx_data_cookie, &ncookies);
2017bd3a2e2SSriharsha Basavapatna 	if (rv != 0) {
2027bd3a2e2SSriharsha Basavapatna 		goto fail;
2037bd3a2e2SSriharsha Basavapatna 	}
2047bd3a2e2SSriharsha Basavapatna 	if ((ncookies == 0) || (ncookies > VNET_DATA_AREA_COOKIES)) {
2057bd3a2e2SSriharsha Basavapatna 		goto fail;
2067bd3a2e2SSriharsha Basavapatna 	}
2077bd3a2e2SSriharsha Basavapatna 	ldcp->rx_data_ncookies = ncookies;
2087bd3a2e2SSriharsha Basavapatna 
2098e512277SWENTAO YANG 	for (j = 1; j < ncookies; j++) {
2108e512277SWENTAO YANG 		rv = ldc_mem_nextcookie(ldcp->rx_data_handle,
2118e512277SWENTAO YANG 		    &(ldcp->rx_data_cookie[j]));
2128e512277SWENTAO YANG 		if (rv != 0) {
2138e512277SWENTAO YANG 			DERR(vgenp, ldcp, "ldc_mem_nextcookie "
2148e512277SWENTAO YANG 			    "failed rv (%d)", rv);
2158e512277SWENTAO YANG 			goto fail;
2168e512277SWENTAO YANG 		}
2178e512277SWENTAO YANG 	}
2188e512277SWENTAO YANG 
2197bd3a2e2SSriharsha Basavapatna 	/*
2207bd3a2e2SSriharsha Basavapatna 	 * Successful in binding the handle to rx data area. Now setup mblks
2217bd3a2e2SSriharsha Basavapatna 	 * around each data buffer and setup the descriptors to point to these
2227bd3a2e2SSriharsha Basavapatna 	 * rx data buffers. We associate each descriptor with a buffer
2237bd3a2e2SSriharsha Basavapatna 	 * by specifying the buffer offset in the descriptor. When the peer
2247bd3a2e2SSriharsha Basavapatna 	 * needs to transmit data, this offset is read by the peer to determine
2257bd3a2e2SSriharsha Basavapatna 	 * the buffer in the mapped buffer area where the data to be
2267bd3a2e2SSriharsha Basavapatna 	 * transmitted should be copied, for a specific descriptor.
2277bd3a2e2SSriharsha Basavapatna 	 */
2287bd3a2e2SSriharsha Basavapatna 	rv = vio_create_mblks(ldcp->num_rbufs, data_sz, (uint8_t *)datap,
2297bd3a2e2SSriharsha Basavapatna 	    &ldcp->rx_vmp);
2307bd3a2e2SSriharsha Basavapatna 	if (rv != 0) {
2317bd3a2e2SSriharsha Basavapatna 		goto fail;
2327bd3a2e2SSriharsha Basavapatna 	}
2337bd3a2e2SSriharsha Basavapatna 
2347bd3a2e2SSriharsha Basavapatna 	for (i = 0; i < ldcp->num_rxds; i++) {
2357bd3a2e2SSriharsha Basavapatna 		rxdp = &(ldcp->rxdp[i]);
2367bd3a2e2SSriharsha Basavapatna 		/* allocate an mblk around this data buffer */
2377bd3a2e2SSriharsha Basavapatna 		vmp = vio_allocb(ldcp->rx_vmp);
2387bd3a2e2SSriharsha Basavapatna 		ASSERT(vmp != NULL);
2397bd3a2e2SSriharsha Basavapatna 		rxdp->data_buf_offset = VIO_MBLK_DATA_OFF(vmp) + VNET_IPALIGN;
2407bd3a2e2SSriharsha Basavapatna 		rxdp->dstate = VIO_DESC_FREE;
2417bd3a2e2SSriharsha Basavapatna 		rxdp_to_vmp[i] = vmp;
2427bd3a2e2SSriharsha Basavapatna 	}
2437bd3a2e2SSriharsha Basavapatna 
2447bd3a2e2SSriharsha Basavapatna 	/*
2457bd3a2e2SSriharsha Basavapatna 	 * The descriptors and the associated buffers are all ready;
2467bd3a2e2SSriharsha Basavapatna 	 * now bind descriptor ring to the channel.
2477bd3a2e2SSriharsha Basavapatna 	 */
2487bd3a2e2SSriharsha Basavapatna 	rv = ldc_mem_dring_bind(ldcp->ldc_handle, ldcp->rx_dring_handle,
2497bd3a2e2SSriharsha Basavapatna 	    LDC_DIRECT_MAP | LDC_SHADOW_MAP, LDC_MEM_RW,
2507bd3a2e2SSriharsha Basavapatna 	    &ldcp->rx_dring_cookie, &ncookies);
2517bd3a2e2SSriharsha Basavapatna 	if (rv != 0) {
2527bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "ldc_mem_dring_bind failed "
2537bd3a2e2SSriharsha Basavapatna 		    "rv(%x)\n", rv);
2547bd3a2e2SSriharsha Basavapatna 		goto fail;
2557bd3a2e2SSriharsha Basavapatna 	}
2567bd3a2e2SSriharsha Basavapatna 	ASSERT(ncookies == 1);
2577bd3a2e2SSriharsha Basavapatna 	ldcp->rx_dring_ncookies = ncookies;
2587bd3a2e2SSriharsha Basavapatna 
2597bd3a2e2SSriharsha Basavapatna 	/* initialize rx seqnum and index */
2607bd3a2e2SSriharsha Basavapatna 	ldcp->next_rxseq = VNET_ISS;
2617bd3a2e2SSriharsha Basavapatna 	ldcp->next_rxi = 0;
2627bd3a2e2SSriharsha Basavapatna 
2637bd3a2e2SSriharsha Basavapatna 	return (VGEN_SUCCESS);
2647bd3a2e2SSriharsha Basavapatna 
2657bd3a2e2SSriharsha Basavapatna fail:
2667bd3a2e2SSriharsha Basavapatna 	vgen_destroy_rx_dring(ldcp);
2677bd3a2e2SSriharsha Basavapatna 	return (VGEN_FAILURE);
2687bd3a2e2SSriharsha Basavapatna }
2697bd3a2e2SSriharsha Basavapatna 
2707bd3a2e2SSriharsha Basavapatna /*
2717bd3a2e2SSriharsha Basavapatna  * Free receive resources for the channel.
2727bd3a2e2SSriharsha Basavapatna  */
2737bd3a2e2SSriharsha Basavapatna void
vgen_destroy_rx_dring(vgen_ldc_t * ldcp)2747bd3a2e2SSriharsha Basavapatna vgen_destroy_rx_dring(vgen_ldc_t *ldcp)
2757bd3a2e2SSriharsha Basavapatna {
2767bd3a2e2SSriharsha Basavapatna 	vgen_t	*vgenp = LDC_TO_VGEN(ldcp);
2777bd3a2e2SSriharsha Basavapatna 
2787bd3a2e2SSriharsha Basavapatna 	/* We first unbind the descriptor ring */
2797bd3a2e2SSriharsha Basavapatna 	if (ldcp->rx_dring_ncookies != 0) {
2807bd3a2e2SSriharsha Basavapatna 		(void) ldc_mem_dring_unbind(ldcp->rx_dring_handle);
2817bd3a2e2SSriharsha Basavapatna 		ldcp->rx_dring_ncookies = 0;
2827bd3a2e2SSriharsha Basavapatna 	}
2837bd3a2e2SSriharsha Basavapatna 
2847bd3a2e2SSriharsha Basavapatna 	/* Destroy the mblks that are wrapped around the rx data buffers */
2857bd3a2e2SSriharsha Basavapatna 	if (ldcp->rx_vmp != NULL) {
2867bd3a2e2SSriharsha Basavapatna 		vio_clobber_pool(ldcp->rx_vmp);
2877bd3a2e2SSriharsha Basavapatna 		if (vio_destroy_mblks(ldcp->rx_vmp) != 0) {
2887bd3a2e2SSriharsha Basavapatna 			/*
2897bd3a2e2SSriharsha Basavapatna 			 * If we can't destroy the rx pool for this channel,
2907bd3a2e2SSriharsha Basavapatna 			 * dispatch a task to retry and clean up. Note that we
2917bd3a2e2SSriharsha Basavapatna 			 * don't need to wait for the task to complete. If the
2927bd3a2e2SSriharsha Basavapatna 			 * vnet device itself gets detached, it will wait for
2937bd3a2e2SSriharsha Basavapatna 			 * the task to complete implicitly in
2947bd3a2e2SSriharsha Basavapatna 			 * ddi_taskq_destroy().
2957bd3a2e2SSriharsha Basavapatna 			 */
2967bd3a2e2SSriharsha Basavapatna 			(void) ddi_taskq_dispatch(vgenp->rxp_taskq,
2977bd3a2e2SSriharsha Basavapatna 			    vgen_destroy_rxpools, ldcp->rx_vmp, DDI_SLEEP);
2987bd3a2e2SSriharsha Basavapatna 		}
2997bd3a2e2SSriharsha Basavapatna 		ldcp->rx_vmp = NULL;
3007bd3a2e2SSriharsha Basavapatna 	}
3017bd3a2e2SSriharsha Basavapatna 
3027bd3a2e2SSriharsha Basavapatna 	/* Free rx data area cookies */
3037bd3a2e2SSriharsha Basavapatna 	if (ldcp->rx_data_cookie != NULL) {
3047bd3a2e2SSriharsha Basavapatna 		kmem_free(ldcp->rx_data_cookie, VNET_DATA_AREA_COOKIES *
3057bd3a2e2SSriharsha Basavapatna 		    sizeof (ldc_mem_cookie_t));
3067bd3a2e2SSriharsha Basavapatna 		ldcp->rx_data_cookie = NULL;
3077bd3a2e2SSriharsha Basavapatna 	}
3087bd3a2e2SSriharsha Basavapatna 
3097bd3a2e2SSriharsha Basavapatna 	/* Unbind rx data area memhandle */
3107bd3a2e2SSriharsha Basavapatna 	if (ldcp->rx_data_ncookies != 0) {
3117bd3a2e2SSriharsha Basavapatna 		(void) ldc_mem_unbind_handle(ldcp->rx_data_handle);
3127bd3a2e2SSriharsha Basavapatna 		ldcp->rx_data_ncookies = 0;
3137bd3a2e2SSriharsha Basavapatna 	}
3147bd3a2e2SSriharsha Basavapatna 
3157bd3a2e2SSriharsha Basavapatna 	/* Free rx data area memhandle */
3167bd3a2e2SSriharsha Basavapatna 	if (ldcp->rx_data_handle != 0) {
3177bd3a2e2SSriharsha Basavapatna 		(void) ldc_mem_free_handle(ldcp->rx_data_handle);
3187bd3a2e2SSriharsha Basavapatna 		ldcp->rx_data_handle = 0;
3197bd3a2e2SSriharsha Basavapatna 	}
3207bd3a2e2SSriharsha Basavapatna 
3217bd3a2e2SSriharsha Basavapatna 	/* Now free the rx data area itself */
3227bd3a2e2SSriharsha Basavapatna 	if (ldcp->rx_datap != NULL) {
3237bd3a2e2SSriharsha Basavapatna 		/* prealloc'd rx data buffer */
3247bd3a2e2SSriharsha Basavapatna 		kmem_free(ldcp->rx_datap, ldcp->rx_data_sz);
3257bd3a2e2SSriharsha Basavapatna 		ldcp->rx_datap = NULL;
3267bd3a2e2SSriharsha Basavapatna 		ldcp->rx_data_sz = 0;
3277bd3a2e2SSriharsha Basavapatna 	}
3287bd3a2e2SSriharsha Basavapatna 
3297bd3a2e2SSriharsha Basavapatna 	/* Finally, free the receive descriptor ring */
3307bd3a2e2SSriharsha Basavapatna 	if (ldcp->rx_dring_handle != 0) {
3317bd3a2e2SSriharsha Basavapatna 		(void) ldc_mem_dring_destroy(ldcp->rx_dring_handle);
3327bd3a2e2SSriharsha Basavapatna 		ldcp->rx_dring_handle = 0;
3337bd3a2e2SSriharsha Basavapatna 		ldcp->rxdp = NULL;
3347bd3a2e2SSriharsha Basavapatna 	}
3357bd3a2e2SSriharsha Basavapatna 
3367bd3a2e2SSriharsha Basavapatna 	if (ldcp->rxdp_to_vmp != NULL) {
3377bd3a2e2SSriharsha Basavapatna 		kmem_free(ldcp->rxdp_to_vmp,
3387bd3a2e2SSriharsha Basavapatna 		    ldcp->num_rxds * sizeof (uintptr_t));
3397bd3a2e2SSriharsha Basavapatna 		ldcp->rxdp_to_vmp = NULL;
3407bd3a2e2SSriharsha Basavapatna 	}
3417bd3a2e2SSriharsha Basavapatna 
3427bd3a2e2SSriharsha Basavapatna 	/* Reset rx index and seqnum */
3437bd3a2e2SSriharsha Basavapatna 	ldcp->next_rxi = 0;
3447bd3a2e2SSriharsha Basavapatna 	ldcp->next_rxseq = VNET_ISS;
3457bd3a2e2SSriharsha Basavapatna }
3467bd3a2e2SSriharsha Basavapatna 
3477bd3a2e2SSriharsha Basavapatna /*
3487bd3a2e2SSriharsha Basavapatna  * Map the receive descriptor ring exported
3497bd3a2e2SSriharsha Basavapatna  * by the peer, as our transmit descriptor ring.
3507bd3a2e2SSriharsha Basavapatna  */
3517bd3a2e2SSriharsha Basavapatna int
vgen_map_tx_dring(vgen_ldc_t * ldcp,void * pkt)3527bd3a2e2SSriharsha Basavapatna vgen_map_tx_dring(vgen_ldc_t *ldcp, void *pkt)
3537bd3a2e2SSriharsha Basavapatna {
3547bd3a2e2SSriharsha Basavapatna 	int				i;
3557bd3a2e2SSriharsha Basavapatna 	int				rv;
3567bd3a2e2SSriharsha Basavapatna 	ldc_mem_info_t			minfo;
3577bd3a2e2SSriharsha Basavapatna 	ldc_mem_cookie_t		dcookie;
3587bd3a2e2SSriharsha Basavapatna 	uint32_t			ncookies;
3597bd3a2e2SSriharsha Basavapatna 	uint32_t 			num_desc;
3607bd3a2e2SSriharsha Basavapatna 	uint32_t			desc_size;
3617bd3a2e2SSriharsha Basavapatna 	vnet_rx_dringdata_desc_t	*txdp;
3627bd3a2e2SSriharsha Basavapatna 	on_trap_data_t			otd;
3637bd3a2e2SSriharsha Basavapatna 	vio_dring_reg_msg_t 		*msg = pkt;
3647bd3a2e2SSriharsha Basavapatna 
3657bd3a2e2SSriharsha Basavapatna 	ncookies = msg->ncookies;
3667bd3a2e2SSriharsha Basavapatna 	num_desc = msg->num_descriptors;
3677bd3a2e2SSriharsha Basavapatna 	desc_size = msg->descriptor_size;
3687bd3a2e2SSriharsha Basavapatna 
3697bd3a2e2SSriharsha Basavapatna 	/*
3707bd3a2e2SSriharsha Basavapatna 	 * Sanity check.
3717bd3a2e2SSriharsha Basavapatna 	 */
3727bd3a2e2SSriharsha Basavapatna 	if (num_desc < VGEN_NUM_DESCRIPTORS_MIN ||
3737bd3a2e2SSriharsha Basavapatna 	    desc_size < sizeof (vnet_rx_dringdata_desc_t) ||
3747bd3a2e2SSriharsha Basavapatna 	    ncookies > 1) {
3757bd3a2e2SSriharsha Basavapatna 		goto fail;
3767bd3a2e2SSriharsha Basavapatna 	}
3777bd3a2e2SSriharsha Basavapatna 
3787bd3a2e2SSriharsha Basavapatna 	bcopy(&msg->cookie[0], &dcookie, sizeof (ldc_mem_cookie_t));
3797bd3a2e2SSriharsha Basavapatna 
3807bd3a2e2SSriharsha Basavapatna 	/* Map the remote dring */
3817bd3a2e2SSriharsha Basavapatna 	rv = ldc_mem_dring_map(ldcp->ldc_handle, &dcookie, ncookies, num_desc,
3827bd3a2e2SSriharsha Basavapatna 	    desc_size, LDC_DIRECT_MAP, &(ldcp->tx_dring_handle));
3837bd3a2e2SSriharsha Basavapatna 	if (rv != 0) {
3847bd3a2e2SSriharsha Basavapatna 		goto fail;
3857bd3a2e2SSriharsha Basavapatna 	}
3867bd3a2e2SSriharsha Basavapatna 
3877bd3a2e2SSriharsha Basavapatna 	/*
3887bd3a2e2SSriharsha Basavapatna 	 * Sucessfully mapped; now try to get info about the mapped dring
3897bd3a2e2SSriharsha Basavapatna 	 */
3907bd3a2e2SSriharsha Basavapatna 	rv = ldc_mem_dring_info(ldcp->tx_dring_handle, &minfo);
3917bd3a2e2SSriharsha Basavapatna 	if (rv != 0) {
3927bd3a2e2SSriharsha Basavapatna 		goto fail;
3937bd3a2e2SSriharsha Basavapatna 	}
3947bd3a2e2SSriharsha Basavapatna 
3957bd3a2e2SSriharsha Basavapatna 	/*
3967bd3a2e2SSriharsha Basavapatna 	 * Save ring address, number of descriptors.
3977bd3a2e2SSriharsha Basavapatna 	 */
3987bd3a2e2SSriharsha Basavapatna 	ldcp->mtxdp = (vnet_rx_dringdata_desc_t *)(minfo.vaddr);
3997bd3a2e2SSriharsha Basavapatna 	bcopy(&dcookie, &(ldcp->tx_dring_cookie), sizeof (dcookie));
4007bd3a2e2SSriharsha Basavapatna 	ldcp->tx_dring_ncookies = ncookies;
4017bd3a2e2SSriharsha Basavapatna 	ldcp->num_txds = num_desc;
4027bd3a2e2SSriharsha Basavapatna 
4037bd3a2e2SSriharsha Basavapatna 	/* Initialize tx dring indexes and seqnum */
4040e263307SWENTAO YANG 	ldcp->next_txi = ldcp->cur_txi = ldcp->resched_peer_txi = 0;
4057bd3a2e2SSriharsha Basavapatna 	ldcp->next_txseq = VNET_ISS - 1;
4067bd3a2e2SSriharsha Basavapatna 	ldcp->resched_peer = B_TRUE;
4077bd3a2e2SSriharsha Basavapatna 	ldcp->dring_mtype = minfo.mtype;
4087bd3a2e2SSriharsha Basavapatna 	ldcp->dringdata_msgid = 0;
4097bd3a2e2SSriharsha Basavapatna 
4107bd3a2e2SSriharsha Basavapatna 	/* Save peer's dring_info values */
4117bd3a2e2SSriharsha Basavapatna 	bcopy(&dcookie, &(ldcp->peer_hparams.dring_cookie),
4127bd3a2e2SSriharsha Basavapatna 	    sizeof (ldc_mem_cookie_t));
4137bd3a2e2SSriharsha Basavapatna 	ldcp->peer_hparams.num_desc = num_desc;
4147bd3a2e2SSriharsha Basavapatna 	ldcp->peer_hparams.desc_size = desc_size;
4157bd3a2e2SSriharsha Basavapatna 	ldcp->peer_hparams.dring_ncookies = ncookies;
4167bd3a2e2SSriharsha Basavapatna 
4177bd3a2e2SSriharsha Basavapatna 	/* Set dring_ident for the peer */
4187bd3a2e2SSriharsha Basavapatna 	ldcp->peer_hparams.dring_ident = (uint64_t)ldcp->mtxdp;
4197bd3a2e2SSriharsha Basavapatna 
4207bd3a2e2SSriharsha Basavapatna 	/* Return the dring_ident in ack msg */
4217bd3a2e2SSriharsha Basavapatna 	msg->dring_ident = (uint64_t)ldcp->mtxdp;
4227bd3a2e2SSriharsha Basavapatna 
4237bd3a2e2SSriharsha Basavapatna 	/*
4247bd3a2e2SSriharsha Basavapatna 	 * Mark the descriptor state as 'done'. This is implementation specific
4257bd3a2e2SSriharsha Basavapatna 	 * and not required by the protocol. In our implementation, we only
4267bd3a2e2SSriharsha Basavapatna 	 * need the descripor to be in 'done' state to be used by the transmit
4277bd3a2e2SSriharsha Basavapatna 	 * function and the peer is not aware of it. As the protocol requires
4287bd3a2e2SSriharsha Basavapatna 	 * that during initial registration the exporting end point mark the
4297bd3a2e2SSriharsha Basavapatna 	 * dstate as 'free', we change it 'done' here. After this, the dstate
4307bd3a2e2SSriharsha Basavapatna 	 * in our implementation will keep moving between 'ready', set by our
4317bd3a2e2SSriharsha Basavapatna 	 * transmit function; and and 'done', set by the peer (per protocol)
4327bd3a2e2SSriharsha Basavapatna 	 * after receiving data.
4337bd3a2e2SSriharsha Basavapatna 	 * Setup on_trap() protection before accessing dring shared memory area.
4347bd3a2e2SSriharsha Basavapatna 	 */
4357bd3a2e2SSriharsha Basavapatna 	rv = LDC_ON_TRAP(&otd);
4367bd3a2e2SSriharsha Basavapatna 	if (rv != 0) {
4377bd3a2e2SSriharsha Basavapatna 		/*
4387bd3a2e2SSriharsha Basavapatna 		 * Data access fault occured down the code path below while
4397bd3a2e2SSriharsha Basavapatna 		 * accessing the descriptors. Return failure.
4407bd3a2e2SSriharsha Basavapatna 		 */
4417bd3a2e2SSriharsha Basavapatna 		goto fail;
4427bd3a2e2SSriharsha Basavapatna 	}
4437bd3a2e2SSriharsha Basavapatna 
4447bd3a2e2SSriharsha Basavapatna 	for (i = 0; i < num_desc; i++) {
4457bd3a2e2SSriharsha Basavapatna 		txdp = &ldcp->mtxdp[i];
4467bd3a2e2SSriharsha Basavapatna 		txdp->dstate = VIO_DESC_DONE;
4477bd3a2e2SSriharsha Basavapatna 	}
4487bd3a2e2SSriharsha Basavapatna 
4497bd3a2e2SSriharsha Basavapatna 	(void) LDC_NO_TRAP();
4507bd3a2e2SSriharsha Basavapatna 	return (VGEN_SUCCESS);
4517bd3a2e2SSriharsha Basavapatna 
4527bd3a2e2SSriharsha Basavapatna fail:
4537bd3a2e2SSriharsha Basavapatna 	if (ldcp->tx_dring_handle != 0) {
4547bd3a2e2SSriharsha Basavapatna 		(void) ldc_mem_dring_unmap(ldcp->tx_dring_handle);
4557bd3a2e2SSriharsha Basavapatna 		ldcp->tx_dring_handle = 0;
4567bd3a2e2SSriharsha Basavapatna 	}
4577bd3a2e2SSriharsha Basavapatna 	return (VGEN_FAILURE);
4587bd3a2e2SSriharsha Basavapatna }
4597bd3a2e2SSriharsha Basavapatna 
4607bd3a2e2SSriharsha Basavapatna /*
4617bd3a2e2SSriharsha Basavapatna  * Unmap the transmit descriptor ring.
4627bd3a2e2SSriharsha Basavapatna  */
4637bd3a2e2SSriharsha Basavapatna void
vgen_unmap_tx_dring(vgen_ldc_t * ldcp)4647bd3a2e2SSriharsha Basavapatna vgen_unmap_tx_dring(vgen_ldc_t *ldcp)
4657bd3a2e2SSriharsha Basavapatna {
4667bd3a2e2SSriharsha Basavapatna 	/* Unmap mapped tx data area */
4677bd3a2e2SSriharsha Basavapatna 	if (ldcp->tx_datap != NULL) {
4687bd3a2e2SSriharsha Basavapatna 		(void) ldc_mem_unmap(ldcp->tx_data_handle);
4697bd3a2e2SSriharsha Basavapatna 		ldcp->tx_datap = NULL;
4707bd3a2e2SSriharsha Basavapatna 	}
4717bd3a2e2SSriharsha Basavapatna 
4727bd3a2e2SSriharsha Basavapatna 	/* Free tx data area handle */
4737bd3a2e2SSriharsha Basavapatna 	if (ldcp->tx_data_handle != 0) {
4747bd3a2e2SSriharsha Basavapatna 		(void) ldc_mem_free_handle(ldcp->tx_data_handle);
4757bd3a2e2SSriharsha Basavapatna 		ldcp->tx_data_handle = 0;
4767bd3a2e2SSriharsha Basavapatna 	}
4777bd3a2e2SSriharsha Basavapatna 
4787bd3a2e2SSriharsha Basavapatna 	/* Free tx data area cookies */
4797bd3a2e2SSriharsha Basavapatna 	if (ldcp->tx_data_cookie != NULL) {
4807bd3a2e2SSriharsha Basavapatna 		kmem_free(ldcp->tx_data_cookie, ldcp->tx_data_ncookies *
4817bd3a2e2SSriharsha Basavapatna 		    sizeof (ldc_mem_cookie_t));
4827bd3a2e2SSriharsha Basavapatna 		ldcp->tx_data_cookie = NULL;
4837bd3a2e2SSriharsha Basavapatna 		ldcp->tx_data_ncookies = 0;
4847bd3a2e2SSriharsha Basavapatna 	}
4857bd3a2e2SSriharsha Basavapatna 
4867bd3a2e2SSriharsha Basavapatna 	/* Unmap peer's dring */
4877bd3a2e2SSriharsha Basavapatna 	if (ldcp->tx_dring_handle != 0) {
4887bd3a2e2SSriharsha Basavapatna 		(void) ldc_mem_dring_unmap(ldcp->tx_dring_handle);
4897bd3a2e2SSriharsha Basavapatna 		ldcp->tx_dring_handle = 0;
4907bd3a2e2SSriharsha Basavapatna 	}
4917bd3a2e2SSriharsha Basavapatna 
4927bd3a2e2SSriharsha Basavapatna 	/* clobber tx ring members */
4937bd3a2e2SSriharsha Basavapatna 	bzero(&ldcp->tx_dring_cookie, sizeof (ldcp->tx_dring_cookie));
4947bd3a2e2SSriharsha Basavapatna 	ldcp->mtxdp = NULL;
4950e263307SWENTAO YANG 	ldcp->next_txi = ldcp->cur_txi = ldcp->resched_peer_txi = 0;
4967bd3a2e2SSriharsha Basavapatna 	ldcp->num_txds = 0;
4977bd3a2e2SSriharsha Basavapatna 	ldcp->next_txseq = VNET_ISS - 1;
4987bd3a2e2SSriharsha Basavapatna 	ldcp->resched_peer = B_TRUE;
4997bd3a2e2SSriharsha Basavapatna }
5007bd3a2e2SSriharsha Basavapatna 
5017bd3a2e2SSriharsha Basavapatna /*
5027bd3a2e2SSriharsha Basavapatna  * Map the shared memory data buffer area exported by the peer.
5037bd3a2e2SSriharsha Basavapatna  */
5047bd3a2e2SSriharsha Basavapatna int
vgen_map_data(vgen_ldc_t * ldcp,void * pkt)5057bd3a2e2SSriharsha Basavapatna vgen_map_data(vgen_ldc_t *ldcp, void *pkt)
5067bd3a2e2SSriharsha Basavapatna {
5077bd3a2e2SSriharsha Basavapatna 	int			rv;
5087bd3a2e2SSriharsha Basavapatna 	vio_dring_reg_ext_msg_t	*emsg;
5097bd3a2e2SSriharsha Basavapatna 	vio_dring_reg_msg_t	*msg = (vio_dring_reg_msg_t *)pkt;
5107bd3a2e2SSriharsha Basavapatna 	uint8_t			*buf = (uint8_t *)msg->cookie;
5117bd3a2e2SSriharsha Basavapatna 	vgen_t			*vgenp = LDC_TO_VGEN(ldcp);
512*34f94fbcSWENTAO YANG 	ldc_mem_info_t		minfo;
5137bd3a2e2SSriharsha Basavapatna 
5147bd3a2e2SSriharsha Basavapatna 	/* skip over dring cookies */
5157bd3a2e2SSriharsha Basavapatna 	ASSERT(msg->ncookies == 1);
5167bd3a2e2SSriharsha Basavapatna 	buf += (msg->ncookies * sizeof (ldc_mem_cookie_t));
5177bd3a2e2SSriharsha Basavapatna 
5187bd3a2e2SSriharsha Basavapatna 	emsg = (vio_dring_reg_ext_msg_t *)buf;
5197bd3a2e2SSriharsha Basavapatna 	if (emsg->data_ncookies > VNET_DATA_AREA_COOKIES) {
5207bd3a2e2SSriharsha Basavapatna 		return (VGEN_FAILURE);
5217bd3a2e2SSriharsha Basavapatna 	}
5227bd3a2e2SSriharsha Basavapatna 
5237bd3a2e2SSriharsha Basavapatna 	/* save # of data area cookies */
5247bd3a2e2SSriharsha Basavapatna 	ldcp->tx_data_ncookies = emsg->data_ncookies;
5257bd3a2e2SSriharsha Basavapatna 
5267bd3a2e2SSriharsha Basavapatna 	/* save data area size */
5277bd3a2e2SSriharsha Basavapatna 	ldcp->tx_data_sz = emsg->data_area_size;
5287bd3a2e2SSriharsha Basavapatna 
5297bd3a2e2SSriharsha Basavapatna 	/* allocate ldc mem handle for data area */
5307bd3a2e2SSriharsha Basavapatna 	rv = ldc_mem_alloc_handle(ldcp->ldc_handle, &ldcp->tx_data_handle);
5317bd3a2e2SSriharsha Basavapatna 	if (rv != 0) {
5327bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "ldc_mem_alloc_handle() failed: %d\n", rv);
5337bd3a2e2SSriharsha Basavapatna 		return (VGEN_FAILURE);
5347bd3a2e2SSriharsha Basavapatna 	}
5357bd3a2e2SSriharsha Basavapatna 
5367bd3a2e2SSriharsha Basavapatna 	/* map the data area */
5377bd3a2e2SSriharsha Basavapatna 	rv = ldc_mem_map(ldcp->tx_data_handle, emsg->data_cookie,
5387bd3a2e2SSriharsha Basavapatna 	    emsg->data_ncookies, LDC_DIRECT_MAP, LDC_MEM_W,
5397bd3a2e2SSriharsha Basavapatna 	    (caddr_t *)&ldcp->tx_datap, NULL);
5407bd3a2e2SSriharsha Basavapatna 	if (rv != 0) {
5417bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "ldc_mem_map() failed: %d\n", rv);
542*34f94fbcSWENTAO YANG 		return (VGEN_FAILURE);
543*34f94fbcSWENTAO YANG 	}
544*34f94fbcSWENTAO YANG 
545*34f94fbcSWENTAO YANG 	/* get the map info */
546*34f94fbcSWENTAO YANG 	rv = ldc_mem_info(ldcp->tx_data_handle, &minfo);
547*34f94fbcSWENTAO YANG 	if (rv != 0) {
548*34f94fbcSWENTAO YANG 		DWARN(vgenp, ldcp, "ldc_mem_info() failed: %d\n", rv);
549*34f94fbcSWENTAO YANG 		return (VGEN_FAILURE);
550*34f94fbcSWENTAO YANG 	}
551*34f94fbcSWENTAO YANG 
552*34f94fbcSWENTAO YANG 	if (minfo.mtype != LDC_DIRECT_MAP) {
553*34f94fbcSWENTAO YANG 		DWARN(vgenp, ldcp, "mtype(%d) is not direct map\n",
554*34f94fbcSWENTAO YANG 		    minfo.mtype);
5557bd3a2e2SSriharsha Basavapatna 		return (VGEN_FAILURE);
5567bd3a2e2SSriharsha Basavapatna 	}
5577bd3a2e2SSriharsha Basavapatna 
5587bd3a2e2SSriharsha Basavapatna 	/* allocate memory for data area cookies */
5597bd3a2e2SSriharsha Basavapatna 	ldcp->tx_data_cookie = kmem_zalloc(emsg->data_ncookies *
5607bd3a2e2SSriharsha Basavapatna 	    sizeof (ldc_mem_cookie_t), KM_SLEEP);
5617bd3a2e2SSriharsha Basavapatna 
5627bd3a2e2SSriharsha Basavapatna 	/* save data area cookies */
5637bd3a2e2SSriharsha Basavapatna 	bcopy(emsg->data_cookie, ldcp->tx_data_cookie,
5647bd3a2e2SSriharsha Basavapatna 	    emsg->data_ncookies * sizeof (ldc_mem_cookie_t));
5657bd3a2e2SSriharsha Basavapatna 
5667bd3a2e2SSriharsha Basavapatna 	return (VGEN_SUCCESS);
5677bd3a2e2SSriharsha Basavapatna }
5687bd3a2e2SSriharsha Basavapatna 
5697bd3a2e2SSriharsha Basavapatna /*
5707bd3a2e2SSriharsha Basavapatna  * This function transmits normal data frames (non-priority) over the channel.
5717bd3a2e2SSriharsha Basavapatna  * It queues the frame into the transmit descriptor ring and sends a
5727bd3a2e2SSriharsha Basavapatna  * VIO_DRING_DATA message if needed, to wake up the peer to (re)start
5737bd3a2e2SSriharsha Basavapatna  * processing.
5747bd3a2e2SSriharsha Basavapatna  */
5757bd3a2e2SSriharsha Basavapatna int
vgen_dringsend_shm(void * arg,mblk_t * mp)5767bd3a2e2SSriharsha Basavapatna vgen_dringsend_shm(void *arg, mblk_t *mp)
5777bd3a2e2SSriharsha Basavapatna {
5787bd3a2e2SSriharsha Basavapatna 	uint32_t			next_txi;
5797bd3a2e2SSriharsha Basavapatna 	uint32_t			txi;
5807bd3a2e2SSriharsha Basavapatna 	vnet_rx_dringdata_desc_t	*txdp;
5817bd3a2e2SSriharsha Basavapatna 	struct ether_header		*ehp;
5827bd3a2e2SSriharsha Basavapatna 	size_t				mblksz;
5837bd3a2e2SSriharsha Basavapatna 	caddr_t				dst;
5847bd3a2e2SSriharsha Basavapatna 	mblk_t				*bp;
5857bd3a2e2SSriharsha Basavapatna 	size_t				size;
5867bd3a2e2SSriharsha Basavapatna 	uint32_t			buf_offset;
5877bd3a2e2SSriharsha Basavapatna 	on_trap_data_t			otd;
5887bd3a2e2SSriharsha Basavapatna 	int				rv = 0;
5897bd3a2e2SSriharsha Basavapatna 	boolean_t			is_bcast = B_FALSE;
5907bd3a2e2SSriharsha Basavapatna 	boolean_t			is_mcast = B_FALSE;
5917bd3a2e2SSriharsha Basavapatna 	vgen_ldc_t			*ldcp = (vgen_ldc_t *)arg;
5927bd3a2e2SSriharsha Basavapatna 	vgen_t				*vgenp = LDC_TO_VGEN(ldcp);
5937bd3a2e2SSriharsha Basavapatna 	vgen_stats_t			*statsp = &ldcp->stats;
5947bd3a2e2SSriharsha Basavapatna 	vgen_hparams_t			*lp = &ldcp->local_hparams;
5957bd3a2e2SSriharsha Basavapatna 	boolean_t			resched_peer = B_FALSE;
5967bd3a2e2SSriharsha Basavapatna 	boolean_t			tx_update = B_FALSE;
5977bd3a2e2SSriharsha Basavapatna 
5987bd3a2e2SSriharsha Basavapatna 	/* Drop the packet if ldc is not up or handshake is not done */
5997bd3a2e2SSriharsha Basavapatna 	if (ldcp->ldc_status != LDC_UP) {
6007bd3a2e2SSriharsha Basavapatna 		DBG2(vgenp, ldcp, "status(%d), dropping packet\n",
6017bd3a2e2SSriharsha Basavapatna 		    ldcp->ldc_status);
6027bd3a2e2SSriharsha Basavapatna 		goto dringsend_shm_exit;
6037bd3a2e2SSriharsha Basavapatna 	}
6047bd3a2e2SSriharsha Basavapatna 
6057bd3a2e2SSriharsha Basavapatna 	if (ldcp->hphase != VH_DONE) {
6067bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "hphase(%x), dropping packet\n",
6077bd3a2e2SSriharsha Basavapatna 		    ldcp->hphase);
6087bd3a2e2SSriharsha Basavapatna 		goto dringsend_shm_exit;
6097bd3a2e2SSriharsha Basavapatna 	}
6107bd3a2e2SSriharsha Basavapatna 
6117bd3a2e2SSriharsha Basavapatna 	size = msgsize(mp);
6127bd3a2e2SSriharsha Basavapatna 	if (size > (size_t)lp->mtu) {
6137bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "invalid size(%d)\n", size);
6147bd3a2e2SSriharsha Basavapatna 		goto dringsend_shm_exit;
6157bd3a2e2SSriharsha Basavapatna 	}
6167bd3a2e2SSriharsha Basavapatna 	if (size < ETHERMIN)
6177bd3a2e2SSriharsha Basavapatna 		size = ETHERMIN;
6187bd3a2e2SSriharsha Basavapatna 
6197bd3a2e2SSriharsha Basavapatna 	ehp = (struct ether_header *)mp->b_rptr;
6207bd3a2e2SSriharsha Basavapatna 	is_bcast = IS_BROADCAST(ehp);
6217bd3a2e2SSriharsha Basavapatna 	is_mcast = IS_MULTICAST(ehp);
6227bd3a2e2SSriharsha Basavapatna 
6237bd3a2e2SSriharsha Basavapatna 	/*
6247bd3a2e2SSriharsha Basavapatna 	 * Setup on_trap() protection before accessing shared memory areas
6257bd3a2e2SSriharsha Basavapatna 	 * (descriptor and data buffer). Note that we enable this protection a
6267bd3a2e2SSriharsha Basavapatna 	 * little early and turn it off slightly later, than keeping it enabled
6277bd3a2e2SSriharsha Basavapatna 	 * strictly at the points in code below where the descriptor and data
6287bd3a2e2SSriharsha Basavapatna 	 * buffer are accessed. This is done for performance reasons:
6297bd3a2e2SSriharsha Basavapatna 	 * (a) to avoid calling the trap protection code while holding mutex.
6307bd3a2e2SSriharsha Basavapatna 	 * (b) to avoid multiple on/off steps for descriptor and data accesses.
6317bd3a2e2SSriharsha Basavapatna 	 */
6327bd3a2e2SSriharsha Basavapatna 	rv = LDC_ON_TRAP(&otd);
6337bd3a2e2SSriharsha Basavapatna 	if (rv != 0) {
6347bd3a2e2SSriharsha Basavapatna 		/*
6357bd3a2e2SSriharsha Basavapatna 		 * Data access fault occured down the code path below while
6367bd3a2e2SSriharsha Basavapatna 		 * accessing either the descriptor or the data buffer. Release
6377bd3a2e2SSriharsha Basavapatna 		 * any locks that we might have acquired in the code below and
6387bd3a2e2SSriharsha Basavapatna 		 * return failure.
6397bd3a2e2SSriharsha Basavapatna 		 */
6407bd3a2e2SSriharsha Basavapatna 		DERR(vgenp, ldcp, "data access fault occured\n");
6417bd3a2e2SSriharsha Basavapatna 		statsp->oerrors++;
6427bd3a2e2SSriharsha Basavapatna 		if (mutex_owned(&ldcp->txlock)) {
6437bd3a2e2SSriharsha Basavapatna 			mutex_exit(&ldcp->txlock);
6447bd3a2e2SSriharsha Basavapatna 		}
6457bd3a2e2SSriharsha Basavapatna 		if (mutex_owned(&ldcp->wrlock)) {
6467bd3a2e2SSriharsha Basavapatna 			mutex_exit(&ldcp->wrlock);
6477bd3a2e2SSriharsha Basavapatna 		}
6487bd3a2e2SSriharsha Basavapatna 		goto dringsend_shm_exit;
6497bd3a2e2SSriharsha Basavapatna 	}
6507bd3a2e2SSriharsha Basavapatna 
6517bd3a2e2SSriharsha Basavapatna 	/*
6527bd3a2e2SSriharsha Basavapatna 	 * Allocate a descriptor
6537bd3a2e2SSriharsha Basavapatna 	 */
6547bd3a2e2SSriharsha Basavapatna 	mutex_enter(&ldcp->txlock);
6557bd3a2e2SSriharsha Basavapatna 	txi = next_txi = ldcp->next_txi;
6567bd3a2e2SSriharsha Basavapatna 	INCR_TXI(next_txi, ldcp);
6570e263307SWENTAO YANG 	txdp = &(ldcp->mtxdp[txi]);
6580e263307SWENTAO YANG 	if (txdp->dstate != VIO_DESC_DONE) { /* out of descriptors */
6597bd3a2e2SSriharsha Basavapatna 		if (ldcp->tx_blocked == B_FALSE) {
6607bd3a2e2SSriharsha Basavapatna 			ldcp->tx_blocked_lbolt = ddi_get_lbolt();
6617bd3a2e2SSriharsha Basavapatna 			ldcp->tx_blocked = B_TRUE;
6627bd3a2e2SSriharsha Basavapatna 		}
6637bd3a2e2SSriharsha Basavapatna 		statsp->tx_no_desc++;
6647bd3a2e2SSriharsha Basavapatna 		mutex_exit(&ldcp->txlock);
6657bd3a2e2SSriharsha Basavapatna 		(void) LDC_NO_TRAP();
6667bd3a2e2SSriharsha Basavapatna 		return (VGEN_TX_NORESOURCES);
6670e263307SWENTAO YANG 	} else {
6680e263307SWENTAO YANG 		txdp->dstate = VIO_DESC_INITIALIZING;
6697bd3a2e2SSriharsha Basavapatna 	}
6707bd3a2e2SSriharsha Basavapatna 
6717bd3a2e2SSriharsha Basavapatna 	if (ldcp->tx_blocked == B_TRUE) {
6727bd3a2e2SSriharsha Basavapatna 		ldcp->tx_blocked = B_FALSE;
6737bd3a2e2SSriharsha Basavapatna 		tx_update = B_TRUE;
6747bd3a2e2SSriharsha Basavapatna 	}
6757bd3a2e2SSriharsha Basavapatna 
6767bd3a2e2SSriharsha Basavapatna 	/* Update descriptor ring index */
6777bd3a2e2SSriharsha Basavapatna 	ldcp->next_txi = next_txi;
6787bd3a2e2SSriharsha Basavapatna 	mutex_exit(&ldcp->txlock);
6797bd3a2e2SSriharsha Basavapatna 
6807bd3a2e2SSriharsha Basavapatna 	if (tx_update == B_TRUE) {
6817bd3a2e2SSriharsha Basavapatna 		vio_net_tx_update_t vtx_update =
6827bd3a2e2SSriharsha Basavapatna 		    ldcp->portp->vcb.vio_net_tx_update;
6837bd3a2e2SSriharsha Basavapatna 
6847bd3a2e2SSriharsha Basavapatna 		vtx_update(ldcp->portp->vhp);
6857bd3a2e2SSriharsha Basavapatna 	}
6867bd3a2e2SSriharsha Basavapatna 
6877bd3a2e2SSriharsha Basavapatna 	/* Ensure load ordering of dstate (above) and data_buf_offset. */
6887bd3a2e2SSriharsha Basavapatna 	MEMBAR_CONSUMER();
6897bd3a2e2SSriharsha Basavapatna 
6907bd3a2e2SSriharsha Basavapatna 	/* Get the offset of the buffer to be used */
6917bd3a2e2SSriharsha Basavapatna 	buf_offset = txdp->data_buf_offset;
6927bd3a2e2SSriharsha Basavapatna 
6937bd3a2e2SSriharsha Basavapatna 	/* Access the buffer using the offset */
6947bd3a2e2SSriharsha Basavapatna 	dst = (caddr_t)ldcp->tx_datap + buf_offset;
6957bd3a2e2SSriharsha Basavapatna 
6967bd3a2e2SSriharsha Basavapatna 	/* Copy data into mapped transmit buffer */
6977bd3a2e2SSriharsha Basavapatna 	for (bp = mp; bp != NULL; bp = bp->b_cont) {
6987bd3a2e2SSriharsha Basavapatna 		mblksz = MBLKL(bp);
6997bd3a2e2SSriharsha Basavapatna 		bcopy(bp->b_rptr, dst, mblksz);
7007bd3a2e2SSriharsha Basavapatna 		dst += mblksz;
7017bd3a2e2SSriharsha Basavapatna 	}
7027bd3a2e2SSriharsha Basavapatna 
7037bd3a2e2SSriharsha Basavapatna 	/* Set the size of data in the descriptor */
7047bd3a2e2SSriharsha Basavapatna 	txdp->nbytes = size;
7057bd3a2e2SSriharsha Basavapatna 
7067bd3a2e2SSriharsha Basavapatna 	/*
7077bd3a2e2SSriharsha Basavapatna 	 * Ensure store ordering of nbytes and dstate (below); so that the peer
7087bd3a2e2SSriharsha Basavapatna 	 * sees the right nbytes value after it checks that the dstate is READY.
7097bd3a2e2SSriharsha Basavapatna 	 */
7107bd3a2e2SSriharsha Basavapatna 	MEMBAR_PRODUCER();
7117bd3a2e2SSriharsha Basavapatna 
7127bd3a2e2SSriharsha Basavapatna 	mutex_enter(&ldcp->wrlock);
7137bd3a2e2SSriharsha Basavapatna 
7140e263307SWENTAO YANG 	ASSERT(txdp->dstate == VIO_DESC_INITIALIZING);
7150e263307SWENTAO YANG 
7167bd3a2e2SSriharsha Basavapatna 	/* Mark the descriptor ready */
7177bd3a2e2SSriharsha Basavapatna 	txdp->dstate = VIO_DESC_READY;
7187bd3a2e2SSriharsha Basavapatna 
7197bd3a2e2SSriharsha Basavapatna 	/* Check if peer needs wake up (handled below) */
7200e263307SWENTAO YANG 	if (ldcp->resched_peer == B_TRUE && ldcp->resched_peer_txi == txi) {
7217bd3a2e2SSriharsha Basavapatna 		resched_peer = B_TRUE;
7220e263307SWENTAO YANG 		ldcp->resched_peer = B_FALSE;
7237bd3a2e2SSriharsha Basavapatna 	}
7247bd3a2e2SSriharsha Basavapatna 
7257bd3a2e2SSriharsha Basavapatna 	/* Update tx stats */
7267bd3a2e2SSriharsha Basavapatna 	statsp->opackets++;
7277bd3a2e2SSriharsha Basavapatna 	statsp->obytes += size;
7287bd3a2e2SSriharsha Basavapatna 	if (is_bcast)
7297bd3a2e2SSriharsha Basavapatna 		statsp->brdcstxmt++;
7307bd3a2e2SSriharsha Basavapatna 	else if (is_mcast)
7317bd3a2e2SSriharsha Basavapatna 		statsp->multixmt++;
7327bd3a2e2SSriharsha Basavapatna 
7337bd3a2e2SSriharsha Basavapatna 	mutex_exit(&ldcp->wrlock);
7347bd3a2e2SSriharsha Basavapatna 
7357bd3a2e2SSriharsha Basavapatna 	/*
7367bd3a2e2SSriharsha Basavapatna 	 * We are done accessing shared memory; clear trap protection.
7377bd3a2e2SSriharsha Basavapatna 	 */
7387bd3a2e2SSriharsha Basavapatna 	(void) LDC_NO_TRAP();
7397bd3a2e2SSriharsha Basavapatna 
7407bd3a2e2SSriharsha Basavapatna 	/*
7417bd3a2e2SSriharsha Basavapatna 	 * Need to wake up the peer ?
7427bd3a2e2SSriharsha Basavapatna 	 */
7437bd3a2e2SSriharsha Basavapatna 	if (resched_peer == B_TRUE) {
7447bd3a2e2SSriharsha Basavapatna 		rv = vgen_send_dringdata_shm(ldcp, (uint32_t)txi, -1);
7457bd3a2e2SSriharsha Basavapatna 		if (rv != 0) {
7467bd3a2e2SSriharsha Basavapatna 			/* error: drop the packet */
7477bd3a2e2SSriharsha Basavapatna 			DWARN(vgenp, ldcp, "failed sending dringdata msg "
7487bd3a2e2SSriharsha Basavapatna 			    "rv(%d) len(%d)\n", rv, size);
7497bd3a2e2SSriharsha Basavapatna 			mutex_enter(&ldcp->wrlock);
7507bd3a2e2SSriharsha Basavapatna 			statsp->oerrors++;
7517bd3a2e2SSriharsha Basavapatna 			ldcp->resched_peer = B_TRUE;
7527bd3a2e2SSriharsha Basavapatna 			mutex_exit(&ldcp->wrlock);
7537bd3a2e2SSriharsha Basavapatna 		}
7547bd3a2e2SSriharsha Basavapatna 	}
7557bd3a2e2SSriharsha Basavapatna 
7567bd3a2e2SSriharsha Basavapatna dringsend_shm_exit:
7577bd3a2e2SSriharsha Basavapatna 	if (rv == ECONNRESET || rv == EACCES) {
7587bd3a2e2SSriharsha Basavapatna 		(void) vgen_handle_evt_reset(ldcp, VGEN_OTHER);
7597bd3a2e2SSriharsha Basavapatna 	}
7607bd3a2e2SSriharsha Basavapatna 	freemsg(mp);
7617bd3a2e2SSriharsha Basavapatna 	return (VGEN_TX_SUCCESS);
7627bd3a2e2SSriharsha Basavapatna }
7637bd3a2e2SSriharsha Basavapatna 
7647bd3a2e2SSriharsha Basavapatna /*
7657bd3a2e2SSriharsha Basavapatna  * Process dring data messages (info/ack/nack)
7667bd3a2e2SSriharsha Basavapatna  */
7677bd3a2e2SSriharsha Basavapatna int
vgen_handle_dringdata_shm(void * arg1,void * arg2)7687bd3a2e2SSriharsha Basavapatna vgen_handle_dringdata_shm(void *arg1, void *arg2)
7697bd3a2e2SSriharsha Basavapatna {
7707bd3a2e2SSriharsha Basavapatna 	vgen_ldc_t	*ldcp = (vgen_ldc_t *)arg1;
7717bd3a2e2SSriharsha Basavapatna 	vio_msg_tag_t	*tagp = (vio_msg_tag_t *)arg2;
7727bd3a2e2SSriharsha Basavapatna 	vgen_t		*vgenp = LDC_TO_VGEN(ldcp);
7737bd3a2e2SSriharsha Basavapatna 	int		rv = 0;
7747bd3a2e2SSriharsha Basavapatna 
7757bd3a2e2SSriharsha Basavapatna 	switch (tagp->vio_subtype) {
7767bd3a2e2SSriharsha Basavapatna 
7777bd3a2e2SSriharsha Basavapatna 	case VIO_SUBTYPE_INFO:
7787bd3a2e2SSriharsha Basavapatna 		/*
7797bd3a2e2SSriharsha Basavapatna 		 * To reduce the locking contention, release the
7807bd3a2e2SSriharsha Basavapatna 		 * cblock here and re-acquire it once we are done
7817bd3a2e2SSriharsha Basavapatna 		 * receiving packets.
7827bd3a2e2SSriharsha Basavapatna 		 */
7837bd3a2e2SSriharsha Basavapatna 		mutex_exit(&ldcp->cblock);
7847bd3a2e2SSriharsha Basavapatna 		mutex_enter(&ldcp->rxlock);
7857bd3a2e2SSriharsha Basavapatna 		rv = vgen_handle_dringdata_info_shm(ldcp, tagp);
7867bd3a2e2SSriharsha Basavapatna 		mutex_exit(&ldcp->rxlock);
7877bd3a2e2SSriharsha Basavapatna 		mutex_enter(&ldcp->cblock);
7887bd3a2e2SSriharsha Basavapatna 		if (rv != 0) {
7897bd3a2e2SSriharsha Basavapatna 			DWARN(vgenp, ldcp, "handle_data_info failed(%d)\n", rv);
7907bd3a2e2SSriharsha Basavapatna 		}
7917bd3a2e2SSriharsha Basavapatna 		break;
7927bd3a2e2SSriharsha Basavapatna 
7937bd3a2e2SSriharsha Basavapatna 	case VIO_SUBTYPE_ACK:
7947bd3a2e2SSriharsha Basavapatna 		rv = vgen_handle_dringdata_ack_shm(ldcp, tagp);
7957bd3a2e2SSriharsha Basavapatna 		if (rv != 0) {
7967bd3a2e2SSriharsha Basavapatna 			DWARN(vgenp, ldcp, "handle_data_ack failed(%d)\n", rv);
7977bd3a2e2SSriharsha Basavapatna 		}
7987bd3a2e2SSriharsha Basavapatna 		break;
7997bd3a2e2SSriharsha Basavapatna 
8007bd3a2e2SSriharsha Basavapatna 	case VIO_SUBTYPE_NACK:
8017bd3a2e2SSriharsha Basavapatna 		rv = vgen_handle_dringdata_nack_shm(ldcp, tagp);
8027bd3a2e2SSriharsha Basavapatna 		if (rv != 0) {
8037bd3a2e2SSriharsha Basavapatna 			DWARN(vgenp, ldcp, "handle_data_nack failed(%d)\n", rv);
8047bd3a2e2SSriharsha Basavapatna 		}
8057bd3a2e2SSriharsha Basavapatna 		break;
8067bd3a2e2SSriharsha Basavapatna 	}
8077bd3a2e2SSriharsha Basavapatna 
8087bd3a2e2SSriharsha Basavapatna 	return (rv);
8097bd3a2e2SSriharsha Basavapatna }
8107bd3a2e2SSriharsha Basavapatna 
8117bd3a2e2SSriharsha Basavapatna static int
vgen_handle_dringdata_info_shm(vgen_ldc_t * ldcp,vio_msg_tag_t * tagp)8127bd3a2e2SSriharsha Basavapatna vgen_handle_dringdata_info_shm(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
8137bd3a2e2SSriharsha Basavapatna {
8147bd3a2e2SSriharsha Basavapatna 	uint32_t	start;
8157bd3a2e2SSriharsha Basavapatna 	int32_t		end;
8167bd3a2e2SSriharsha Basavapatna 	int		rv = 0;
8177bd3a2e2SSriharsha Basavapatna 	vio_dring_msg_t	*dringmsg = (vio_dring_msg_t *)tagp;
8187bd3a2e2SSriharsha Basavapatna 	vgen_t		*vgenp = LDC_TO_VGEN(ldcp);
8197bd3a2e2SSriharsha Basavapatna 	vgen_stats_t	*statsp = &ldcp->stats;
8207bd3a2e2SSriharsha Basavapatna 
8217bd3a2e2SSriharsha Basavapatna 	start = dringmsg->start_idx;
8227bd3a2e2SSriharsha Basavapatna 	end = dringmsg->end_idx;
8237bd3a2e2SSriharsha Basavapatna 
8247bd3a2e2SSriharsha Basavapatna 	DBG1(vgenp, ldcp, "INFO: start(%d), end(%d)\n",
8257bd3a2e2SSriharsha Basavapatna 	    start, end);
8267bd3a2e2SSriharsha Basavapatna 
8277bd3a2e2SSriharsha Basavapatna 	if (!(CHECK_RXI(start, ldcp)) ||
8287bd3a2e2SSriharsha Basavapatna 	    ((end != -1) && !(CHECK_RXI(end, ldcp)))) {
8297bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "Invalid Rx start(%d) or end(%d)\n",
8307bd3a2e2SSriharsha Basavapatna 		    start, end);
8317bd3a2e2SSriharsha Basavapatna 		/* drop the message if invalid index */
8327bd3a2e2SSriharsha Basavapatna 		return (0);
8337bd3a2e2SSriharsha Basavapatna 	}
8347bd3a2e2SSriharsha Basavapatna 
8357bd3a2e2SSriharsha Basavapatna 	/* validate dring_ident */
8367bd3a2e2SSriharsha Basavapatna 	if (dringmsg->dring_ident != ldcp->peer_hparams.dring_ident) {
8377bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "Invalid dring ident 0x%x\n",
8387bd3a2e2SSriharsha Basavapatna 		    dringmsg->dring_ident);
8397bd3a2e2SSriharsha Basavapatna 		/* invalid dring_ident, drop the msg */
8407bd3a2e2SSriharsha Basavapatna 		return (0);
8417bd3a2e2SSriharsha Basavapatna 	}
8427bd3a2e2SSriharsha Basavapatna 
8437bd3a2e2SSriharsha Basavapatna 	statsp->dring_data_msgs_rcvd++;
8447bd3a2e2SSriharsha Basavapatna 
8457bd3a2e2SSriharsha Basavapatna 	/*
8467bd3a2e2SSriharsha Basavapatna 	 * If we are in polling mode, return from here without processing the
8477bd3a2e2SSriharsha Basavapatna 	 * dring. We will process the dring in the context of polling thread.
8487bd3a2e2SSriharsha Basavapatna 	 */
8497bd3a2e2SSriharsha Basavapatna 	if (ldcp->polling_on == B_TRUE) {
8507bd3a2e2SSriharsha Basavapatna 		return (0);
8517bd3a2e2SSriharsha Basavapatna 	}
8527bd3a2e2SSriharsha Basavapatna 
8537bd3a2e2SSriharsha Basavapatna 	/*
8547bd3a2e2SSriharsha Basavapatna 	 * Process the dring and receive packets in intr context.
8557bd3a2e2SSriharsha Basavapatna 	 */
8567bd3a2e2SSriharsha Basavapatna 	rv = vgen_intr_rcv_shm(ldcp);
8577bd3a2e2SSriharsha Basavapatna 	if (rv != 0) {
8587bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "vgen_intr_rcv_shm() failed\n");
8597bd3a2e2SSriharsha Basavapatna 	}
8607bd3a2e2SSriharsha Basavapatna 	return (rv);
8617bd3a2e2SSriharsha Basavapatna }
8627bd3a2e2SSriharsha Basavapatna 
8637bd3a2e2SSriharsha Basavapatna /*
8647bd3a2e2SSriharsha Basavapatna  * Process the rx descriptor ring in the context of interrupt thread
8657bd3a2e2SSriharsha Basavapatna  * (vgen_ldc_cb() callback) and send the received packets up the stack.
8667bd3a2e2SSriharsha Basavapatna  */
8677bd3a2e2SSriharsha Basavapatna static int
vgen_intr_rcv_shm(vgen_ldc_t * ldcp)8687bd3a2e2SSriharsha Basavapatna vgen_intr_rcv_shm(vgen_ldc_t *ldcp)
8697bd3a2e2SSriharsha Basavapatna {
8707bd3a2e2SSriharsha Basavapatna 	int		rv;
8717bd3a2e2SSriharsha Basavapatna 	uint32_t	end_ix;
8727bd3a2e2SSriharsha Basavapatna 	vio_dring_msg_t msg;
8737bd3a2e2SSriharsha Basavapatna 	uint_t		mblk_sz;
8747bd3a2e2SSriharsha Basavapatna 	int		count = 0;
8757bd3a2e2SSriharsha Basavapatna 	int		total_count = 0;
8767bd3a2e2SSriharsha Basavapatna 	mblk_t		*bp = NULL;
8777bd3a2e2SSriharsha Basavapatna 	mblk_t		*bpt = NULL;
8787bd3a2e2SSriharsha Basavapatna 	mblk_t		*mp = NULL;
8797bd3a2e2SSriharsha Basavapatna 	vio_net_rx_cb_t vrx_cb = ldcp->portp->vcb.vio_net_rx_cb;
8807bd3a2e2SSriharsha Basavapatna 
8817bd3a2e2SSriharsha Basavapatna 	ASSERT(MUTEX_HELD(&ldcp->rxlock));
8827bd3a2e2SSriharsha Basavapatna 
8837bd3a2e2SSriharsha Basavapatna 	do {
8847bd3a2e2SSriharsha Basavapatna 		rv = vgen_receive_packet(ldcp, &mp, &mblk_sz);
8857bd3a2e2SSriharsha Basavapatna 		if (rv != 0) {
8867bd3a2e2SSriharsha Basavapatna 			if (rv == EINVAL) {
8877bd3a2e2SSriharsha Basavapatna 				/* Invalid descriptor error; get next */
8887bd3a2e2SSriharsha Basavapatna 				continue;
8897bd3a2e2SSriharsha Basavapatna 			}
8907bd3a2e2SSriharsha Basavapatna 			DTRACE_PROBE1(vgen_intr_nopkts, vgen_ldc_t *, ldcp);
8917bd3a2e2SSriharsha Basavapatna 			break;
8927bd3a2e2SSriharsha Basavapatna 		}
8937bd3a2e2SSriharsha Basavapatna 
8947bd3a2e2SSriharsha Basavapatna 		/* Build a chain of received packets */
8957bd3a2e2SSriharsha Basavapatna 		if (bp == NULL) {
8967bd3a2e2SSriharsha Basavapatna 			/* first pkt */
8977bd3a2e2SSriharsha Basavapatna 			bp = mp;
8987bd3a2e2SSriharsha Basavapatna 			bpt = bp;
8997bd3a2e2SSriharsha Basavapatna 			bpt->b_next = NULL;
9007bd3a2e2SSriharsha Basavapatna 		} else {
9017bd3a2e2SSriharsha Basavapatna 			mp->b_next = NULL;
9027bd3a2e2SSriharsha Basavapatna 			bpt->b_next = mp;
9037bd3a2e2SSriharsha Basavapatna 			bpt = mp;
9047bd3a2e2SSriharsha Basavapatna 		}
9057bd3a2e2SSriharsha Basavapatna 
9067bd3a2e2SSriharsha Basavapatna 		total_count++;
9077bd3a2e2SSriharsha Basavapatna 		count++;
9087bd3a2e2SSriharsha Basavapatna 
9097bd3a2e2SSriharsha Basavapatna 		/*
9107bd3a2e2SSriharsha Basavapatna 		 * We are receiving the packets in interrupt context. If we
9117bd3a2e2SSriharsha Basavapatna 		 * have gathered vgen_chain_len (tunable) # of packets in the
9127bd3a2e2SSriharsha Basavapatna 		 * chain, send them up. (See vgen_poll_rcv_shm() for receiving
9137bd3a2e2SSriharsha Basavapatna 		 * in polling thread context).
9147bd3a2e2SSriharsha Basavapatna 		 */
9157bd3a2e2SSriharsha Basavapatna 		if (count == vgen_chain_len) {
9167bd3a2e2SSriharsha Basavapatna 			DTRACE_PROBE2(vgen_intr_pkts, vgen_ldc_t *, ldcp,
9177bd3a2e2SSriharsha Basavapatna 			    int, count);
9187bd3a2e2SSriharsha Basavapatna 			mutex_exit(&ldcp->rxlock);
9197bd3a2e2SSriharsha Basavapatna 			vrx_cb(ldcp->portp->vhp, bp);
9207bd3a2e2SSriharsha Basavapatna 			mutex_enter(&ldcp->rxlock);
9217bd3a2e2SSriharsha Basavapatna 			bp = bpt = NULL;
9227bd3a2e2SSriharsha Basavapatna 			count = 0;
9237bd3a2e2SSriharsha Basavapatna 		}
9247bd3a2e2SSriharsha Basavapatna 
9257bd3a2e2SSriharsha Basavapatna 		/*
9267bd3a2e2SSriharsha Basavapatna 		 * Stop further processing if we processed the entire dring
9277bd3a2e2SSriharsha Basavapatna 		 * once; otherwise continue.
9287bd3a2e2SSriharsha Basavapatna 		 */
9297bd3a2e2SSriharsha Basavapatna 	} while (total_count < ldcp->num_rxds);
9307bd3a2e2SSriharsha Basavapatna 
9317bd3a2e2SSriharsha Basavapatna 	if (bp != NULL) {
9327bd3a2e2SSriharsha Basavapatna 		DTRACE_PROBE2(vgen_intr_pkts, vgen_ldc_t *, ldcp, int, count);
9337bd3a2e2SSriharsha Basavapatna 		mutex_exit(&ldcp->rxlock);
9347bd3a2e2SSriharsha Basavapatna 		vrx_cb(ldcp->portp->vhp, bp);
9357bd3a2e2SSriharsha Basavapatna 		mutex_enter(&ldcp->rxlock);
9367bd3a2e2SSriharsha Basavapatna 	}
9377bd3a2e2SSriharsha Basavapatna 
9387bd3a2e2SSriharsha Basavapatna 	if (ldcp->polling_on == B_FALSE) {
9397bd3a2e2SSriharsha Basavapatna 		/*
9407bd3a2e2SSriharsha Basavapatna 		 * We send a stopped message to peer (sender) while we are in
9417bd3a2e2SSriharsha Basavapatna 		 * intr mode only; allowing the peer to send further data intrs
9427bd3a2e2SSriharsha Basavapatna 		 * (dring data msgs) to us.
9437bd3a2e2SSriharsha Basavapatna 		 */
9447bd3a2e2SSriharsha Basavapatna 		end_ix = ldcp->next_rxi;
9457bd3a2e2SSriharsha Basavapatna 		DECR_RXI(end_ix, ldcp);
9467bd3a2e2SSriharsha Basavapatna 		msg.dring_ident = ldcp->peer_hparams.dring_ident;
9477bd3a2e2SSriharsha Basavapatna 		rv = vgen_send_dringack_shm(ldcp, (vio_msg_tag_t *)&msg,
9487bd3a2e2SSriharsha Basavapatna 		    VNET_START_IDX_UNSPEC, end_ix, VIO_DP_STOPPED);
9497bd3a2e2SSriharsha Basavapatna 		return (rv);
9507bd3a2e2SSriharsha Basavapatna 	}
9517bd3a2e2SSriharsha Basavapatna 
9527bd3a2e2SSriharsha Basavapatna 	return (0);
9537bd3a2e2SSriharsha Basavapatna }
9547bd3a2e2SSriharsha Basavapatna 
9557bd3a2e2SSriharsha Basavapatna /*
9567bd3a2e2SSriharsha Basavapatna  * Process the rx descriptor ring in the context of mac polling thread. Receive
9577bd3a2e2SSriharsha Basavapatna  * packets upto the limit specified by bytes_to_pickup or until there are no
9587bd3a2e2SSriharsha Basavapatna  * more packets, whichever occurs first. Return the chain of received packets.
9597bd3a2e2SSriharsha Basavapatna  */
9607bd3a2e2SSriharsha Basavapatna mblk_t *
vgen_poll_rcv_shm(vgen_ldc_t * ldcp,int bytes_to_pickup)9617bd3a2e2SSriharsha Basavapatna vgen_poll_rcv_shm(vgen_ldc_t *ldcp, int bytes_to_pickup)
9627bd3a2e2SSriharsha Basavapatna {
9637bd3a2e2SSriharsha Basavapatna 	uint_t		mblk_sz = 0;
9647bd3a2e2SSriharsha Basavapatna 	uint_t		sz = 0;
9657bd3a2e2SSriharsha Basavapatna 	mblk_t		*bp = NULL;
9667bd3a2e2SSriharsha Basavapatna 	mblk_t		*bpt = NULL;
9677bd3a2e2SSriharsha Basavapatna 	mblk_t		*mp = NULL;
9687bd3a2e2SSriharsha Basavapatna 	int		count = 0;
9697bd3a2e2SSriharsha Basavapatna 	int		rv;
9707bd3a2e2SSriharsha Basavapatna 
9717bd3a2e2SSriharsha Basavapatna 	mutex_enter(&ldcp->rxlock);
9727bd3a2e2SSriharsha Basavapatna 
9737bd3a2e2SSriharsha Basavapatna 	if (ldcp->hphase != VH_DONE) {
9747bd3a2e2SSriharsha Basavapatna 		/* Channel is being reset and handshake not complete */
9757bd3a2e2SSriharsha Basavapatna 		mutex_exit(&ldcp->rxlock);
9767bd3a2e2SSriharsha Basavapatna 		return (NULL);
9777bd3a2e2SSriharsha Basavapatna 	}
9787bd3a2e2SSriharsha Basavapatna 
9797bd3a2e2SSriharsha Basavapatna 	do {
9807bd3a2e2SSriharsha Basavapatna 		rv = vgen_receive_packet(ldcp, &mp, &mblk_sz);
9817bd3a2e2SSriharsha Basavapatna 		if (rv != 0) {
9827bd3a2e2SSriharsha Basavapatna 			if (rv == EINVAL) {
9837bd3a2e2SSriharsha Basavapatna 				/* Invalid descriptor error; get next */
9847bd3a2e2SSriharsha Basavapatna 				continue;
9857bd3a2e2SSriharsha Basavapatna 			}
9867bd3a2e2SSriharsha Basavapatna 			DTRACE_PROBE1(vgen_poll_nopkts, vgen_ldc_t *, ldcp);
9877bd3a2e2SSriharsha Basavapatna 			break;
9887bd3a2e2SSriharsha Basavapatna 		}
9897bd3a2e2SSriharsha Basavapatna 
9907bd3a2e2SSriharsha Basavapatna 		/* Build a chain of received packets */
9917bd3a2e2SSriharsha Basavapatna 		if (bp == NULL) {
9927bd3a2e2SSriharsha Basavapatna 			/* first pkt */
9937bd3a2e2SSriharsha Basavapatna 			bp = mp;
9947bd3a2e2SSriharsha Basavapatna 			bpt = bp;
9957bd3a2e2SSriharsha Basavapatna 			bpt->b_next = NULL;
9967bd3a2e2SSriharsha Basavapatna 		} else {
9977bd3a2e2SSriharsha Basavapatna 			mp->b_next = NULL;
9987bd3a2e2SSriharsha Basavapatna 			bpt->b_next = mp;
9997bd3a2e2SSriharsha Basavapatna 			bpt = mp;
10007bd3a2e2SSriharsha Basavapatna 		}
10017bd3a2e2SSriharsha Basavapatna 
10027bd3a2e2SSriharsha Basavapatna 		/* Compute total size accumulated */
10037bd3a2e2SSriharsha Basavapatna 		sz += mblk_sz;
10047bd3a2e2SSriharsha Basavapatna 		count++;
10057bd3a2e2SSriharsha Basavapatna 
10067bd3a2e2SSriharsha Basavapatna 		/* Reached the bytes limit; we are done. */
10077bd3a2e2SSriharsha Basavapatna 		if (sz >= bytes_to_pickup) {
10087bd3a2e2SSriharsha Basavapatna 			break;
10097bd3a2e2SSriharsha Basavapatna 		}
10107bd3a2e2SSriharsha Basavapatna 
10117bd3a2e2SSriharsha Basavapatna 	_NOTE(CONSTCOND)
10127bd3a2e2SSriharsha Basavapatna 	} while (1);
10137bd3a2e2SSriharsha Basavapatna 
10147bd3a2e2SSriharsha Basavapatna 	/*
10157bd3a2e2SSriharsha Basavapatna 	 * We prepend any high priority packets to the chain of packets; note
10167bd3a2e2SSriharsha Basavapatna 	 * that if we are already at the bytes_to_pickup limit, we might
10177bd3a2e2SSriharsha Basavapatna 	 * slightly exceed that in such cases. That should be ok, as these pkts
10187bd3a2e2SSriharsha Basavapatna 	 * are expected to be small in size and arrive at an interval in the
10197bd3a2e2SSriharsha Basavapatna 	 * the order of a few seconds.
10207bd3a2e2SSriharsha Basavapatna 	 */
10217bd3a2e2SSriharsha Basavapatna 	if (ldcp->rx_pktdata == vgen_handle_pkt_data &&
10227bd3a2e2SSriharsha Basavapatna 	    ldcp->rx_pri_head != NULL) {
10237bd3a2e2SSriharsha Basavapatna 		ldcp->rx_pri_tail->b_next = bp;
10247bd3a2e2SSriharsha Basavapatna 		bp = ldcp->rx_pri_head;
10257bd3a2e2SSriharsha Basavapatna 		ldcp->rx_pri_head = ldcp->rx_pri_tail = NULL;
10267bd3a2e2SSriharsha Basavapatna 	}
10277bd3a2e2SSriharsha Basavapatna 
10287bd3a2e2SSriharsha Basavapatna 	mutex_exit(&ldcp->rxlock);
10297bd3a2e2SSriharsha Basavapatna 
10307bd3a2e2SSriharsha Basavapatna 	DTRACE_PROBE2(vgen_poll_pkts, vgen_ldc_t *, ldcp, int, count);
10317bd3a2e2SSriharsha Basavapatna 	DTRACE_PROBE2(vgen_poll_bytes, vgen_ldc_t *, ldcp, uint_t, sz);
10327bd3a2e2SSriharsha Basavapatna 	return (bp);
10337bd3a2e2SSriharsha Basavapatna }
10347bd3a2e2SSriharsha Basavapatna 
10357bd3a2e2SSriharsha Basavapatna /*
10367bd3a2e2SSriharsha Basavapatna  * Process the next index in the rx dring and receive the associated packet.
10377bd3a2e2SSriharsha Basavapatna  *
10387bd3a2e2SSriharsha Basavapatna  * Returns:
10397bd3a2e2SSriharsha Basavapatna  *	bp:	Success: The received packet.
10407bd3a2e2SSriharsha Basavapatna  *		Failure: NULL
10417bd3a2e2SSriharsha Basavapatna  *      size:	Success: Size of received packet.
10427bd3a2e2SSriharsha Basavapatna  *		Failure: 0
10437bd3a2e2SSriharsha Basavapatna  *      retval:
10447bd3a2e2SSriharsha Basavapatna  *		Success: 0
10457bd3a2e2SSriharsha Basavapatna  *		Failure: EAGAIN: Descriptor not ready
10467bd3a2e2SSriharsha Basavapatna  *			 EIO:    Descriptor contents invalid.
10477bd3a2e2SSriharsha Basavapatna  */
10487bd3a2e2SSriharsha Basavapatna static int
vgen_receive_packet(vgen_ldc_t * ldcp,mblk_t ** bp,uint_t * size)10497bd3a2e2SSriharsha Basavapatna vgen_receive_packet(vgen_ldc_t *ldcp, mblk_t **bp, uint_t *size)
10507bd3a2e2SSriharsha Basavapatna {
10517bd3a2e2SSriharsha Basavapatna 	uint32_t			rxi;
10527bd3a2e2SSriharsha Basavapatna 	vio_mblk_t			*vmp;
10537bd3a2e2SSriharsha Basavapatna 	vio_mblk_t			*new_vmp;
10547bd3a2e2SSriharsha Basavapatna 	struct ether_header		*ehp;
10557bd3a2e2SSriharsha Basavapatna 	vnet_rx_dringdata_desc_t	*rxdp;
10567bd3a2e2SSriharsha Basavapatna 	int				err = 0;
10577bd3a2e2SSriharsha Basavapatna 	uint32_t			nbytes = 0;
10587bd3a2e2SSriharsha Basavapatna 	mblk_t				*mp = NULL;
10597bd3a2e2SSriharsha Basavapatna 	mblk_t				*dmp = NULL;
10607bd3a2e2SSriharsha Basavapatna 	vgen_stats_t			*statsp = &ldcp->stats;
10617bd3a2e2SSriharsha Basavapatna 	vgen_hparams_t			*lp = &ldcp->local_hparams;
10627bd3a2e2SSriharsha Basavapatna 
10637bd3a2e2SSriharsha Basavapatna 	rxi = ldcp->next_rxi;
10647bd3a2e2SSriharsha Basavapatna 	rxdp = &(ldcp->rxdp[rxi]);
10657bd3a2e2SSriharsha Basavapatna 	vmp = ldcp->rxdp_to_vmp[rxi];
10667bd3a2e2SSriharsha Basavapatna 
10677bd3a2e2SSriharsha Basavapatna 	if (rxdp->dstate != VIO_DESC_READY) {
10687bd3a2e2SSriharsha Basavapatna 		/*
10697bd3a2e2SSriharsha Basavapatna 		 * Descriptor is not ready.
10707bd3a2e2SSriharsha Basavapatna 		 */
10717bd3a2e2SSriharsha Basavapatna 		DTRACE_PROBE1(vgen_noready_rxds, vgen_ldc_t *, ldcp);
10727bd3a2e2SSriharsha Basavapatna 		return (EAGAIN);
10737bd3a2e2SSriharsha Basavapatna 	}
10747bd3a2e2SSriharsha Basavapatna 
10757bd3a2e2SSriharsha Basavapatna 	/*
10767bd3a2e2SSriharsha Basavapatna 	 * Ensure load ordering of dstate and nbytes.
10777bd3a2e2SSriharsha Basavapatna 	 */
10787bd3a2e2SSriharsha Basavapatna 	MEMBAR_CONSUMER();
10797bd3a2e2SSriharsha Basavapatna 
10807bd3a2e2SSriharsha Basavapatna 	nbytes = rxdp->nbytes;
10817bd3a2e2SSriharsha Basavapatna 
10827bd3a2e2SSriharsha Basavapatna 	if ((nbytes < ETHERMIN) ||
10837bd3a2e2SSriharsha Basavapatna 	    (nbytes > lp->mtu) ||
10847bd3a2e2SSriharsha Basavapatna 	    (rxdp->data_buf_offset !=
10857bd3a2e2SSriharsha Basavapatna 	    (VIO_MBLK_DATA_OFF(vmp) + VNET_IPALIGN))) {
10867bd3a2e2SSriharsha Basavapatna 		/*
10877bd3a2e2SSriharsha Basavapatna 		 * Descriptor contents invalid.
10887bd3a2e2SSriharsha Basavapatna 		 */
10897bd3a2e2SSriharsha Basavapatna 		statsp->ierrors++;
10907bd3a2e2SSriharsha Basavapatna 		rxdp->dstate = VIO_DESC_DONE;
10917bd3a2e2SSriharsha Basavapatna 		err = EIO;
10927bd3a2e2SSriharsha Basavapatna 		goto done;
10937bd3a2e2SSriharsha Basavapatna 	}
10947bd3a2e2SSriharsha Basavapatna 
10957bd3a2e2SSriharsha Basavapatna 	/*
10967bd3a2e2SSriharsha Basavapatna 	 * Now allocate a new buffer for this descriptor before sending up the
10977bd3a2e2SSriharsha Basavapatna 	 * buffer being processed. If that fails, stop processing; as we are
10987bd3a2e2SSriharsha Basavapatna 	 * out of receive buffers.
10997bd3a2e2SSriharsha Basavapatna 	 */
11007bd3a2e2SSriharsha Basavapatna 	new_vmp = vio_allocb(ldcp->rx_vmp);
11017bd3a2e2SSriharsha Basavapatna 
11027bd3a2e2SSriharsha Basavapatna 	/*
11037bd3a2e2SSriharsha Basavapatna 	 * Process the current buffer being received.
11047bd3a2e2SSriharsha Basavapatna 	 */
11057bd3a2e2SSriharsha Basavapatna 	mp = vmp->mp;
11067bd3a2e2SSriharsha Basavapatna 
11077bd3a2e2SSriharsha Basavapatna 	if (new_vmp == NULL) {
11087bd3a2e2SSriharsha Basavapatna 		/*
11097bd3a2e2SSriharsha Basavapatna 		 * We failed to get a new mapped buffer that is needed to
11107bd3a2e2SSriharsha Basavapatna 		 * refill the descriptor. In that case, leave the current
11117bd3a2e2SSriharsha Basavapatna 		 * buffer bound to the descriptor; allocate an mblk dynamically
11127bd3a2e2SSriharsha Basavapatna 		 * and copy the contents of the buffer to the mblk. Then send
11137bd3a2e2SSriharsha Basavapatna 		 * up this mblk. This way the sender has the same buffer as
11147bd3a2e2SSriharsha Basavapatna 		 * before that can be used to send new data.
11157bd3a2e2SSriharsha Basavapatna 		 */
11167bd3a2e2SSriharsha Basavapatna 		statsp->norcvbuf++;
11177bd3a2e2SSriharsha Basavapatna 		dmp = allocb(nbytes + VNET_IPALIGN, BPRI_MED);
11187bd3a2e2SSriharsha Basavapatna 		if (dmp == NULL) {
11197bd3a2e2SSriharsha Basavapatna 			statsp->ierrors++;
11207bd3a2e2SSriharsha Basavapatna 			return (ENOMEM);
11217bd3a2e2SSriharsha Basavapatna 		}
11227bd3a2e2SSriharsha Basavapatna 		bcopy(mp->b_rptr + VNET_IPALIGN,
11237bd3a2e2SSriharsha Basavapatna 		    dmp->b_rptr + VNET_IPALIGN, nbytes);
11247bd3a2e2SSriharsha Basavapatna 		mp = dmp;
11257bd3a2e2SSriharsha Basavapatna 	} else {
11267bd3a2e2SSriharsha Basavapatna 		/* Mark the status of the current rbuf */
11277bd3a2e2SSriharsha Basavapatna 		vmp->state = VIO_MBLK_HAS_DATA;
11287bd3a2e2SSriharsha Basavapatna 
11297bd3a2e2SSriharsha Basavapatna 		/* Set the offset of the new buffer in the descriptor */
11307bd3a2e2SSriharsha Basavapatna 		rxdp->data_buf_offset =
11317bd3a2e2SSriharsha Basavapatna 		    VIO_MBLK_DATA_OFF(new_vmp) + VNET_IPALIGN;
11327bd3a2e2SSriharsha Basavapatna 		ldcp->rxdp_to_vmp[rxi] = new_vmp;
11337bd3a2e2SSriharsha Basavapatna 	}
11347bd3a2e2SSriharsha Basavapatna 	mp->b_rptr += VNET_IPALIGN;
11357bd3a2e2SSriharsha Basavapatna 	mp->b_wptr = mp->b_rptr + nbytes;
11367bd3a2e2SSriharsha Basavapatna 
11377bd3a2e2SSriharsha Basavapatna 	/*
11387bd3a2e2SSriharsha Basavapatna 	 * Ensure store ordering of data_buf_offset and dstate; so that the
11397bd3a2e2SSriharsha Basavapatna 	 * peer sees the right data_buf_offset after it checks that the dstate
11407bd3a2e2SSriharsha Basavapatna 	 * is DONE.
11417bd3a2e2SSriharsha Basavapatna 	 */
11427bd3a2e2SSriharsha Basavapatna 	MEMBAR_PRODUCER();
11437bd3a2e2SSriharsha Basavapatna 
11447bd3a2e2SSriharsha Basavapatna 	/* Now mark the descriptor 'done' */
11457bd3a2e2SSriharsha Basavapatna 	rxdp->dstate = VIO_DESC_DONE;
11467bd3a2e2SSriharsha Basavapatna 
11477bd3a2e2SSriharsha Basavapatna 	/* Update stats */
11487bd3a2e2SSriharsha Basavapatna 	statsp->ipackets++;
11497bd3a2e2SSriharsha Basavapatna 	statsp->rbytes += rxdp->nbytes;
11507bd3a2e2SSriharsha Basavapatna 	ehp = (struct ether_header *)mp->b_rptr;
11517bd3a2e2SSriharsha Basavapatna 	if (IS_BROADCAST(ehp))
11527bd3a2e2SSriharsha Basavapatna 		statsp->brdcstrcv++;
11537bd3a2e2SSriharsha Basavapatna 	else if (IS_MULTICAST(ehp))
11547bd3a2e2SSriharsha Basavapatna 		statsp->multircv++;
11557bd3a2e2SSriharsha Basavapatna done:
11567bd3a2e2SSriharsha Basavapatna 	/* Update the next index to be processed */
11577bd3a2e2SSriharsha Basavapatna 	INCR_RXI(rxi, ldcp);
11587bd3a2e2SSriharsha Basavapatna 
11597bd3a2e2SSriharsha Basavapatna 	/* Save the new recv index */
11607bd3a2e2SSriharsha Basavapatna 	ldcp->next_rxi = rxi;
11617bd3a2e2SSriharsha Basavapatna 
11627bd3a2e2SSriharsha Basavapatna 	/* Return the packet received */
11637bd3a2e2SSriharsha Basavapatna 	*size = nbytes;
11647bd3a2e2SSriharsha Basavapatna 	*bp = mp;
11657bd3a2e2SSriharsha Basavapatna 	return (err);
11667bd3a2e2SSriharsha Basavapatna }
11677bd3a2e2SSriharsha Basavapatna 
11687bd3a2e2SSriharsha Basavapatna static int
vgen_handle_dringdata_ack_shm(vgen_ldc_t * ldcp,vio_msg_tag_t * tagp)11697bd3a2e2SSriharsha Basavapatna vgen_handle_dringdata_ack_shm(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
11707bd3a2e2SSriharsha Basavapatna {
11717bd3a2e2SSriharsha Basavapatna 	uint32_t			start;
11727bd3a2e2SSriharsha Basavapatna 	int32_t				end;
11737bd3a2e2SSriharsha Basavapatna 	uint32_t			txi;
11747bd3a2e2SSriharsha Basavapatna 	vgen_stats_t			*statsp;
11757bd3a2e2SSriharsha Basavapatna 	vnet_rx_dringdata_desc_t	*txdp;
11767bd3a2e2SSriharsha Basavapatna 	on_trap_data_t			otd;
11777bd3a2e2SSriharsha Basavapatna 	int				rv = 0;
11787bd3a2e2SSriharsha Basavapatna 	boolean_t			ready_txd = B_FALSE;
11797bd3a2e2SSriharsha Basavapatna 	vgen_t				*vgenp = LDC_TO_VGEN(ldcp);
11807bd3a2e2SSriharsha Basavapatna 	vio_dring_msg_t			*dringmsg = (vio_dring_msg_t *)tagp;
11817bd3a2e2SSriharsha Basavapatna 
11827bd3a2e2SSriharsha Basavapatna 	start = dringmsg->start_idx;
11837bd3a2e2SSriharsha Basavapatna 	end = dringmsg->end_idx;
11847bd3a2e2SSriharsha Basavapatna 	statsp = &ldcp->stats;
11857bd3a2e2SSriharsha Basavapatna 
11867bd3a2e2SSriharsha Basavapatna 	/*
11877bd3a2e2SSriharsha Basavapatna 	 * Received an ack for our transmits upto a certain dring index. This
11887bd3a2e2SSriharsha Basavapatna 	 * enables us to reclaim descriptors. We also send a new dring data msg
11897bd3a2e2SSriharsha Basavapatna 	 * to the peer to restart processing if there are pending transmit pkts.
11907bd3a2e2SSriharsha Basavapatna 	 */
11917bd3a2e2SSriharsha Basavapatna 	DBG2(vgenp, ldcp, "ACK:  start(%d), end(%d)\n", start, end);
11927bd3a2e2SSriharsha Basavapatna 
11937bd3a2e2SSriharsha Basavapatna 	/*
11947bd3a2e2SSriharsha Basavapatna 	 * In RxDringData mode (v1.6), start index of -1 can be used by the
11957bd3a2e2SSriharsha Basavapatna 	 * peer to indicate that it is unspecified. However, the end index
11967bd3a2e2SSriharsha Basavapatna 	 * must be set correctly indicating the last descriptor index processed.
11977bd3a2e2SSriharsha Basavapatna 	 */
11987bd3a2e2SSriharsha Basavapatna 	if (((start != VNET_START_IDX_UNSPEC) && !(CHECK_TXI(start, ldcp))) ||
11997bd3a2e2SSriharsha Basavapatna 	    !(CHECK_TXI(end, ldcp))) {
12007bd3a2e2SSriharsha Basavapatna 		/* drop the message if invalid index */
12017bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "Invalid Tx ack start(%d) or end(%d)\n",
12027bd3a2e2SSriharsha Basavapatna 		    start, end);
12037bd3a2e2SSriharsha Basavapatna 		return (rv);
12047bd3a2e2SSriharsha Basavapatna 	}
12057bd3a2e2SSriharsha Basavapatna 
12067bd3a2e2SSriharsha Basavapatna 	/* Validate dring_ident */
12077bd3a2e2SSriharsha Basavapatna 	if (dringmsg->dring_ident != ldcp->local_hparams.dring_ident) {
12087bd3a2e2SSriharsha Basavapatna 		/* invalid dring_ident, drop the msg */
12097bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "Invalid dring ident 0x%x\n",
12107bd3a2e2SSriharsha Basavapatna 		    dringmsg->dring_ident);
12117bd3a2e2SSriharsha Basavapatna 		return (rv);
12127bd3a2e2SSriharsha Basavapatna 	}
12137bd3a2e2SSriharsha Basavapatna 	statsp->dring_data_acks_rcvd++;
12147bd3a2e2SSriharsha Basavapatna 
12157bd3a2e2SSriharsha Basavapatna 	/*
12167bd3a2e2SSriharsha Basavapatna 	 * Clear transmit flow control condition
12177bd3a2e2SSriharsha Basavapatna 	 * as some descriptors should be free now.
12187bd3a2e2SSriharsha Basavapatna 	 */
12197bd3a2e2SSriharsha Basavapatna 	mutex_enter(&ldcp->txlock);
12207bd3a2e2SSriharsha Basavapatna 	if (ldcp->tx_blocked == B_TRUE) {
12217bd3a2e2SSriharsha Basavapatna 		vio_net_tx_update_t vtx_update =
12227bd3a2e2SSriharsha Basavapatna 		    ldcp->portp->vcb.vio_net_tx_update;
12237bd3a2e2SSriharsha Basavapatna 
12247bd3a2e2SSriharsha Basavapatna 		ldcp->tx_blocked = B_FALSE;
12257bd3a2e2SSriharsha Basavapatna 		vtx_update(ldcp->portp->vhp);
12267bd3a2e2SSriharsha Basavapatna 	}
12277bd3a2e2SSriharsha Basavapatna 	mutex_exit(&ldcp->txlock);
12287bd3a2e2SSriharsha Basavapatna 
12297bd3a2e2SSriharsha Basavapatna 	if (dringmsg->dring_process_state != VIO_DP_STOPPED) {
12307bd3a2e2SSriharsha Basavapatna 		/*
12317bd3a2e2SSriharsha Basavapatna 		 * Receiver continued processing
12327bd3a2e2SSriharsha Basavapatna 		 * dring after sending us the ack.
12337bd3a2e2SSriharsha Basavapatna 		 */
12347bd3a2e2SSriharsha Basavapatna 		return (rv);
12357bd3a2e2SSriharsha Basavapatna 	}
12367bd3a2e2SSriharsha Basavapatna 
12377bd3a2e2SSriharsha Basavapatna 	/*
12387bd3a2e2SSriharsha Basavapatna 	 * Receiver stopped processing descriptors.
12397bd3a2e2SSriharsha Basavapatna 	 */
12407bd3a2e2SSriharsha Basavapatna 	statsp->dring_stopped_acks_rcvd++;
12417bd3a2e2SSriharsha Basavapatna 
12427bd3a2e2SSriharsha Basavapatna 	/*
12437bd3a2e2SSriharsha Basavapatna 	 * Setup on_trap() protection before accessing dring shared memory area.
12447bd3a2e2SSriharsha Basavapatna 	 */
12457bd3a2e2SSriharsha Basavapatna 	rv = LDC_ON_TRAP(&otd);
12467bd3a2e2SSriharsha Basavapatna 	if (rv != 0) {
12477bd3a2e2SSriharsha Basavapatna 		/*
12487bd3a2e2SSriharsha Basavapatna 		 * Data access fault occured down the code path below while
12497bd3a2e2SSriharsha Basavapatna 		 * accessing the descriptors. Release any locks that we might
12507bd3a2e2SSriharsha Basavapatna 		 * have acquired in the code below and return failure.
12517bd3a2e2SSriharsha Basavapatna 		 */
12527bd3a2e2SSriharsha Basavapatna 		if (mutex_owned(&ldcp->wrlock)) {
12537bd3a2e2SSriharsha Basavapatna 			mutex_exit(&ldcp->wrlock);
12547bd3a2e2SSriharsha Basavapatna 		}
12557bd3a2e2SSriharsha Basavapatna 		return (ECONNRESET);
12567bd3a2e2SSriharsha Basavapatna 	}
12577bd3a2e2SSriharsha Basavapatna 
12587bd3a2e2SSriharsha Basavapatna 	/*
12597bd3a2e2SSriharsha Basavapatna 	 * Determine if there are any pending tx descriptors ready to be
12607bd3a2e2SSriharsha Basavapatna 	 * processed by the receiver(peer) and if so, send a message to the
12617bd3a2e2SSriharsha Basavapatna 	 * peer to restart receiving.
12627bd3a2e2SSriharsha Basavapatna 	 */
12637bd3a2e2SSriharsha Basavapatna 	mutex_enter(&ldcp->wrlock);
12647bd3a2e2SSriharsha Basavapatna 
12657bd3a2e2SSriharsha Basavapatna 	ready_txd = B_FALSE;
12667bd3a2e2SSriharsha Basavapatna 	txi = end;
12677bd3a2e2SSriharsha Basavapatna 	INCR_TXI(txi, ldcp);
12687bd3a2e2SSriharsha Basavapatna 	txdp = &ldcp->mtxdp[txi];
12697bd3a2e2SSriharsha Basavapatna 	if (txdp->dstate == VIO_DESC_READY) {
12707bd3a2e2SSriharsha Basavapatna 		ready_txd = B_TRUE;
12717bd3a2e2SSriharsha Basavapatna 	}
12727bd3a2e2SSriharsha Basavapatna 
12737bd3a2e2SSriharsha Basavapatna 	/*
12747bd3a2e2SSriharsha Basavapatna 	 * We are done accessing shared memory; clear trap protection.
12757bd3a2e2SSriharsha Basavapatna 	 */
12767bd3a2e2SSriharsha Basavapatna 	(void) LDC_NO_TRAP();
12777bd3a2e2SSriharsha Basavapatna 
12787bd3a2e2SSriharsha Basavapatna 	if (ready_txd == B_FALSE) {
12797bd3a2e2SSriharsha Basavapatna 		/*
12807bd3a2e2SSriharsha Basavapatna 		 * No ready tx descriptors. Set the flag to send a message to
12817bd3a2e2SSriharsha Basavapatna 		 * the peer when tx descriptors are ready in transmit routine.
12827bd3a2e2SSriharsha Basavapatna 		 */
12837bd3a2e2SSriharsha Basavapatna 		ldcp->resched_peer = B_TRUE;
12840e263307SWENTAO YANG 		ldcp->resched_peer_txi = txi;
12857bd3a2e2SSriharsha Basavapatna 		mutex_exit(&ldcp->wrlock);
12867bd3a2e2SSriharsha Basavapatna 		return (rv);
12877bd3a2e2SSriharsha Basavapatna 	}
12887bd3a2e2SSriharsha Basavapatna 
12897bd3a2e2SSriharsha Basavapatna 	/*
12907bd3a2e2SSriharsha Basavapatna 	 * We have some tx descriptors ready to be processed by the receiver.
12917bd3a2e2SSriharsha Basavapatna 	 * Send a dring data message to the peer to restart processing.
12927bd3a2e2SSriharsha Basavapatna 	 */
12937bd3a2e2SSriharsha Basavapatna 	ldcp->resched_peer = B_FALSE;
12947bd3a2e2SSriharsha Basavapatna 	mutex_exit(&ldcp->wrlock);
12957bd3a2e2SSriharsha Basavapatna 	rv = vgen_send_dringdata_shm(ldcp, txi, -1);
12967bd3a2e2SSriharsha Basavapatna 	if (rv != VGEN_SUCCESS) {
12977bd3a2e2SSriharsha Basavapatna 		mutex_enter(&ldcp->wrlock);
12987bd3a2e2SSriharsha Basavapatna 		ldcp->resched_peer = B_TRUE;
12997bd3a2e2SSriharsha Basavapatna 		mutex_exit(&ldcp->wrlock);
13007bd3a2e2SSriharsha Basavapatna 	}
13017bd3a2e2SSriharsha Basavapatna 
13027bd3a2e2SSriharsha Basavapatna 	return (rv);
13037bd3a2e2SSriharsha Basavapatna }
13047bd3a2e2SSriharsha Basavapatna 
13057bd3a2e2SSriharsha Basavapatna static int
vgen_handle_dringdata_nack_shm(vgen_ldc_t * ldcp,vio_msg_tag_t * tagp)13067bd3a2e2SSriharsha Basavapatna vgen_handle_dringdata_nack_shm(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
13077bd3a2e2SSriharsha Basavapatna {
13087bd3a2e2SSriharsha Basavapatna 	uint32_t			start;
13097bd3a2e2SSriharsha Basavapatna 	int32_t				end;
13107bd3a2e2SSriharsha Basavapatna 	uint32_t			txi;
13117bd3a2e2SSriharsha Basavapatna 	vnet_rx_dringdata_desc_t	*txdp;
13127bd3a2e2SSriharsha Basavapatna 	on_trap_data_t			otd;
13137bd3a2e2SSriharsha Basavapatna 	int				rv = 0;
13147bd3a2e2SSriharsha Basavapatna 	vgen_t				*vgenp = LDC_TO_VGEN(ldcp);
13157bd3a2e2SSriharsha Basavapatna 	vio_dring_msg_t			*dringmsg = (vio_dring_msg_t *)tagp;
13167bd3a2e2SSriharsha Basavapatna 
13177bd3a2e2SSriharsha Basavapatna 	DBG1(vgenp, ldcp, "enter\n");
13187bd3a2e2SSriharsha Basavapatna 	start = dringmsg->start_idx;
13197bd3a2e2SSriharsha Basavapatna 	end = dringmsg->end_idx;
13207bd3a2e2SSriharsha Basavapatna 
13217bd3a2e2SSriharsha Basavapatna 	/*
13227bd3a2e2SSriharsha Basavapatna 	 * Peer sent a NACK msg (to indicate bad descriptors ?). The start and
13237bd3a2e2SSriharsha Basavapatna 	 * end correspond to the range of descriptors which are being nack'd.
13247bd3a2e2SSriharsha Basavapatna 	 */
13257bd3a2e2SSriharsha Basavapatna 	DWARN(vgenp, ldcp, "NACK: start(%d), end(%d)\n", start, end);
13267bd3a2e2SSriharsha Basavapatna 
13277bd3a2e2SSriharsha Basavapatna 	/*
13287bd3a2e2SSriharsha Basavapatna 	 * In RxDringData mode (v1.6), start index of -1 can be used by
13297bd3a2e2SSriharsha Basavapatna 	 * the peer to indicate that it is unspecified. However, the end index
13307bd3a2e2SSriharsha Basavapatna 	 * must be set correctly indicating the last descriptor index processed.
13317bd3a2e2SSriharsha Basavapatna 	 */
13327bd3a2e2SSriharsha Basavapatna 	if (((start != VNET_START_IDX_UNSPEC) && !(CHECK_TXI(start, ldcp))) ||
13337bd3a2e2SSriharsha Basavapatna 	    !(CHECK_TXI(end, ldcp))) {
13347bd3a2e2SSriharsha Basavapatna 		/* drop the message if invalid index */
13357bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "Invalid Tx nack start(%d) or end(%d)\n",
13367bd3a2e2SSriharsha Basavapatna 		    start, end);
13377bd3a2e2SSriharsha Basavapatna 		return (rv);
13387bd3a2e2SSriharsha Basavapatna 	}
13397bd3a2e2SSriharsha Basavapatna 
13407bd3a2e2SSriharsha Basavapatna 	/* Validate dring_ident */
13417bd3a2e2SSriharsha Basavapatna 	if (dringmsg->dring_ident != ldcp->local_hparams.dring_ident) {
13427bd3a2e2SSriharsha Basavapatna 		/* invalid dring_ident, drop the msg */
13437bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "Invalid dring ident 0x%x\n",
13447bd3a2e2SSriharsha Basavapatna 		    dringmsg->dring_ident);
13457bd3a2e2SSriharsha Basavapatna 		return (rv);
13467bd3a2e2SSriharsha Basavapatna 	}
13477bd3a2e2SSriharsha Basavapatna 
13487bd3a2e2SSriharsha Basavapatna 	/*
13497bd3a2e2SSriharsha Basavapatna 	 * Setup on_trap() protection before accessing dring shared memory area.
13507bd3a2e2SSriharsha Basavapatna 	 */
13517bd3a2e2SSriharsha Basavapatna 	rv = LDC_ON_TRAP(&otd);
13527bd3a2e2SSriharsha Basavapatna 	if (rv != 0) {
13537bd3a2e2SSriharsha Basavapatna 		/*
13547bd3a2e2SSriharsha Basavapatna 		 * Data access fault occured down the code path below while
13557bd3a2e2SSriharsha Basavapatna 		 * accessing the descriptors. Release any locks that we might
13567bd3a2e2SSriharsha Basavapatna 		 * have acquired in the code below and return failure.
13577bd3a2e2SSriharsha Basavapatna 		 */
13587bd3a2e2SSriharsha Basavapatna 		mutex_exit(&ldcp->txlock);
13597bd3a2e2SSriharsha Basavapatna 		return (ECONNRESET);
13607bd3a2e2SSriharsha Basavapatna 	}
13617bd3a2e2SSriharsha Basavapatna 
13627bd3a2e2SSriharsha Basavapatna 	/* We just mark the descrs as free so they can be reused */
13637bd3a2e2SSriharsha Basavapatna 	mutex_enter(&ldcp->txlock);
13647bd3a2e2SSriharsha Basavapatna 	for (txi = start; txi <= end; ) {
13657bd3a2e2SSriharsha Basavapatna 		txdp = &(ldcp->mtxdp[txi]);
13667bd3a2e2SSriharsha Basavapatna 		if (txdp->dstate == VIO_DESC_READY)
13677bd3a2e2SSriharsha Basavapatna 			txdp->dstate = VIO_DESC_DONE;
13687bd3a2e2SSriharsha Basavapatna 		INCR_TXI(txi, ldcp);
13697bd3a2e2SSriharsha Basavapatna 	}
13707bd3a2e2SSriharsha Basavapatna 
13717bd3a2e2SSriharsha Basavapatna 	/*
13727bd3a2e2SSriharsha Basavapatna 	 * We are done accessing shared memory; clear trap protection.
13737bd3a2e2SSriharsha Basavapatna 	 */
13747bd3a2e2SSriharsha Basavapatna 	(void) LDC_NO_TRAP();
13757bd3a2e2SSriharsha Basavapatna 
13767bd3a2e2SSriharsha Basavapatna 	mutex_exit(&ldcp->txlock);
13777bd3a2e2SSriharsha Basavapatna 
13787bd3a2e2SSriharsha Basavapatna 	return (rv);
13797bd3a2e2SSriharsha Basavapatna }
13807bd3a2e2SSriharsha Basavapatna 
13817bd3a2e2SSriharsha Basavapatna /*
13827bd3a2e2SSriharsha Basavapatna  * Send descriptor ring data message to the peer over LDC.
13837bd3a2e2SSriharsha Basavapatna  */
13847bd3a2e2SSriharsha Basavapatna static int
vgen_send_dringdata_shm(vgen_ldc_t * ldcp,uint32_t start,int32_t end)13857bd3a2e2SSriharsha Basavapatna vgen_send_dringdata_shm(vgen_ldc_t *ldcp, uint32_t start, int32_t end)
13867bd3a2e2SSriharsha Basavapatna {
13877bd3a2e2SSriharsha Basavapatna 	vgen_t		*vgenp = LDC_TO_VGEN(ldcp);
13887bd3a2e2SSriharsha Basavapatna 	vio_dring_msg_t	dringmsg, *msgp = &dringmsg;
13897bd3a2e2SSriharsha Basavapatna 	vio_msg_tag_t	*tagp = &msgp->tag;
13907bd3a2e2SSriharsha Basavapatna 	vgen_stats_t	*statsp = &ldcp->stats;
13917bd3a2e2SSriharsha Basavapatna 	int		rv;
13927bd3a2e2SSriharsha Basavapatna 
13937bd3a2e2SSriharsha Basavapatna #ifdef DEBUG
13947bd3a2e2SSriharsha Basavapatna 	if (vgen_inject_error(ldcp, VGEN_ERR_TXTIMEOUT)) {
13957bd3a2e2SSriharsha Basavapatna 		return (VGEN_SUCCESS);
13967bd3a2e2SSriharsha Basavapatna 	}
13977bd3a2e2SSriharsha Basavapatna #endif
13987bd3a2e2SSriharsha Basavapatna 	bzero(msgp, sizeof (*msgp));
13997bd3a2e2SSriharsha Basavapatna 
14007bd3a2e2SSriharsha Basavapatna 	tagp->vio_msgtype = VIO_TYPE_DATA;
14017bd3a2e2SSriharsha Basavapatna 	tagp->vio_subtype = VIO_SUBTYPE_INFO;
14027bd3a2e2SSriharsha Basavapatna 	tagp->vio_subtype_env = VIO_DRING_DATA;
14037bd3a2e2SSriharsha Basavapatna 	tagp->vio_sid = ldcp->local_sid;
14047bd3a2e2SSriharsha Basavapatna 
14057bd3a2e2SSriharsha Basavapatna 	msgp->dring_ident = ldcp->local_hparams.dring_ident;
14067bd3a2e2SSriharsha Basavapatna 	msgp->start_idx = start;
14077bd3a2e2SSriharsha Basavapatna 	msgp->end_idx = end;
14087bd3a2e2SSriharsha Basavapatna 	msgp->seq_num = atomic_inc_32_nv(&ldcp->dringdata_msgid);
14097bd3a2e2SSriharsha Basavapatna 
14107bd3a2e2SSriharsha Basavapatna 	rv = vgen_sendmsg_shm(ldcp, (caddr_t)tagp, sizeof (dringmsg));
14117bd3a2e2SSriharsha Basavapatna 	if (rv != VGEN_SUCCESS) {
14127bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "vgen_sendmsg_shm() failed\n");
14137bd3a2e2SSriharsha Basavapatna 		return (rv);
14147bd3a2e2SSriharsha Basavapatna 	}
14157bd3a2e2SSriharsha Basavapatna 
14167bd3a2e2SSriharsha Basavapatna 	statsp->dring_data_msgs_sent++;
14177bd3a2e2SSriharsha Basavapatna 
14187bd3a2e2SSriharsha Basavapatna 	DBG2(vgenp, ldcp, "DRING_DATA_SENT \n");
14197bd3a2e2SSriharsha Basavapatna 
14207bd3a2e2SSriharsha Basavapatna 	return (VGEN_SUCCESS);
14217bd3a2e2SSriharsha Basavapatna }
14227bd3a2e2SSriharsha Basavapatna 
14237bd3a2e2SSriharsha Basavapatna /*
14247bd3a2e2SSriharsha Basavapatna  * Send dring data ack message.
14257bd3a2e2SSriharsha Basavapatna  */
14267bd3a2e2SSriharsha Basavapatna int
vgen_send_dringack_shm(vgen_ldc_t * ldcp,vio_msg_tag_t * tagp,uint32_t start,int32_t end,uint8_t pstate)14277bd3a2e2SSriharsha Basavapatna vgen_send_dringack_shm(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp, uint32_t start,
14287bd3a2e2SSriharsha Basavapatna     int32_t end, uint8_t pstate)
14297bd3a2e2SSriharsha Basavapatna {
14307bd3a2e2SSriharsha Basavapatna 	int		rv = 0;
14317bd3a2e2SSriharsha Basavapatna 	vgen_t		*vgenp = LDC_TO_VGEN(ldcp);
14327bd3a2e2SSriharsha Basavapatna 	vio_dring_msg_t	*msgp = (vio_dring_msg_t *)tagp;
14337bd3a2e2SSriharsha Basavapatna 	vgen_stats_t	*statsp = &ldcp->stats;
14347bd3a2e2SSriharsha Basavapatna 
14357bd3a2e2SSriharsha Basavapatna 	tagp->vio_msgtype = VIO_TYPE_DATA;
14367bd3a2e2SSriharsha Basavapatna 	tagp->vio_subtype = VIO_SUBTYPE_ACK;
14377bd3a2e2SSriharsha Basavapatna 	tagp->vio_subtype_env = VIO_DRING_DATA;
14387bd3a2e2SSriharsha Basavapatna 	tagp->vio_sid = ldcp->local_sid;
14397bd3a2e2SSriharsha Basavapatna 	msgp->start_idx = start;
14407bd3a2e2SSriharsha Basavapatna 	msgp->end_idx = end;
14417bd3a2e2SSriharsha Basavapatna 	msgp->dring_process_state = pstate;
14427bd3a2e2SSriharsha Basavapatna 	msgp->seq_num = atomic_inc_32_nv(&ldcp->dringdata_msgid);
14437bd3a2e2SSriharsha Basavapatna 
14447bd3a2e2SSriharsha Basavapatna 	rv = vgen_sendmsg_shm(ldcp, (caddr_t)tagp, sizeof (*msgp));
14457bd3a2e2SSriharsha Basavapatna 	if (rv != VGEN_SUCCESS) {
14467bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "vgen_sendmsg_shm() failed\n");
14477bd3a2e2SSriharsha Basavapatna 	}
14487bd3a2e2SSriharsha Basavapatna 
14497bd3a2e2SSriharsha Basavapatna 	statsp->dring_data_acks_sent++;
14507bd3a2e2SSriharsha Basavapatna 	if (pstate == VIO_DP_STOPPED) {
14517bd3a2e2SSriharsha Basavapatna 		statsp->dring_stopped_acks_sent++;
14527bd3a2e2SSriharsha Basavapatna 	}
14537bd3a2e2SSriharsha Basavapatna 
14547bd3a2e2SSriharsha Basavapatna 	return (rv);
14557bd3a2e2SSriharsha Basavapatna }
14567bd3a2e2SSriharsha Basavapatna 
14577bd3a2e2SSriharsha Basavapatna /*
14587bd3a2e2SSriharsha Basavapatna  * Send dring data msgs (info/ack/nack) over LDC.
14597bd3a2e2SSriharsha Basavapatna  */
14607bd3a2e2SSriharsha Basavapatna static int
vgen_sendmsg_shm(vgen_ldc_t * ldcp,caddr_t msg,size_t msglen)14617bd3a2e2SSriharsha Basavapatna vgen_sendmsg_shm(vgen_ldc_t *ldcp, caddr_t msg,  size_t msglen)
14627bd3a2e2SSriharsha Basavapatna {
14637bd3a2e2SSriharsha Basavapatna 	int			rv;
14647bd3a2e2SSriharsha Basavapatna 	size_t			len;
14657bd3a2e2SSriharsha Basavapatna 	uint32_t		retries = 0;
14667bd3a2e2SSriharsha Basavapatna 	vgen_t			*vgenp = LDC_TO_VGEN(ldcp);
14677bd3a2e2SSriharsha Basavapatna 
14687bd3a2e2SSriharsha Basavapatna 	len = msglen;
14697bd3a2e2SSriharsha Basavapatna 	if ((len == 0) || (msg == NULL))
14707bd3a2e2SSriharsha Basavapatna 		return (VGEN_FAILURE);
14717bd3a2e2SSriharsha Basavapatna 
14727bd3a2e2SSriharsha Basavapatna 	do {
14737bd3a2e2SSriharsha Basavapatna 		len = msglen;
14747bd3a2e2SSriharsha Basavapatna 		rv = ldc_write(ldcp->ldc_handle, (caddr_t)msg, &len);
14757bd3a2e2SSriharsha Basavapatna 		if (retries++ >= vgen_ldcwr_retries)
14767bd3a2e2SSriharsha Basavapatna 			break;
14777bd3a2e2SSriharsha Basavapatna 	} while (rv == EWOULDBLOCK);
14787bd3a2e2SSriharsha Basavapatna 
14797bd3a2e2SSriharsha Basavapatna 	if (rv != 0) {
14807bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "ldc_write failed: rv(%d) msglen(%d)\n",
14817bd3a2e2SSriharsha Basavapatna 		    rv, msglen);
14827bd3a2e2SSriharsha Basavapatna 		return (rv);
14837bd3a2e2SSriharsha Basavapatna 	}
14847bd3a2e2SSriharsha Basavapatna 
14857bd3a2e2SSriharsha Basavapatna 	if (len != msglen) {
14867bd3a2e2SSriharsha Basavapatna 		DWARN(vgenp, ldcp, "ldc_write failed: rv(%d) msglen (%d)\n",
14877bd3a2e2SSriharsha Basavapatna 		    rv, msglen);
14887bd3a2e2SSriharsha Basavapatna 		return (VGEN_FAILURE);
14897bd3a2e2SSriharsha Basavapatna 	}
14907bd3a2e2SSriharsha Basavapatna 
14917bd3a2e2SSriharsha Basavapatna 	return (VGEN_SUCCESS);
14927bd3a2e2SSriharsha Basavapatna }
1493