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