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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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