104b6cca3Slucy wang - Sun Microsystems - Beijing China /* 204b6cca3Slucy wang - Sun Microsystems - Beijing China * CDDL HEADER START 304b6cca3Slucy wang - Sun Microsystems - Beijing China * 404b6cca3Slucy wang - Sun Microsystems - Beijing China * The contents of this file are subject to the terms of the 504b6cca3Slucy wang - Sun Microsystems - Beijing China * Common Development and Distribution License (the "License"). 604b6cca3Slucy wang - Sun Microsystems - Beijing China * You may not use this file except in compliance with the License. 704b6cca3Slucy wang - Sun Microsystems - Beijing China * 804b6cca3Slucy wang - Sun Microsystems - Beijing China * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 904b6cca3Slucy wang - Sun Microsystems - Beijing China * or http://www.opensolaris.org/os/licensing. 1004b6cca3Slucy wang - Sun Microsystems - Beijing China * See the License for the specific language governing permissions 1104b6cca3Slucy wang - Sun Microsystems - Beijing China * and limitations under the License. 1204b6cca3Slucy wang - Sun Microsystems - Beijing China * 1304b6cca3Slucy wang - Sun Microsystems - Beijing China * When distributing Covered Code, include this CDDL HEADER in each 1404b6cca3Slucy wang - Sun Microsystems - Beijing China * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1504b6cca3Slucy wang - Sun Microsystems - Beijing China * If applicable, add the following below this CDDL HEADER, with the 1604b6cca3Slucy wang - Sun Microsystems - Beijing China * fields enclosed by brackets "[]" replaced with your own identifying 1704b6cca3Slucy wang - Sun Microsystems - Beijing China * information: Portions Copyright [yyyy] [name of copyright owner] 1804b6cca3Slucy wang - Sun Microsystems - Beijing China * 1904b6cca3Slucy wang - Sun Microsystems - Beijing China * CDDL HEADER END 2004b6cca3Slucy wang - Sun Microsystems - Beijing China */ 2104b6cca3Slucy wang - Sun Microsystems - Beijing China 2204b6cca3Slucy wang - Sun Microsystems - Beijing China /* 23a56d24eaSMark Johnson * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24a56d24eaSMark Johnson * Use is subject to license terms. 25a56d24eaSMark Johnson */ 26a56d24eaSMark Johnson 27a56d24eaSMark Johnson /* 2804b6cca3Slucy wang - Sun Microsystems - Beijing China * Copyright 2007-2009 Myricom, Inc. All rights reserved. 2904b6cca3Slucy wang - Sun Microsystems - Beijing China * Use is subject to license terms. 3004b6cca3Slucy wang - Sun Microsystems - Beijing China */ 3104b6cca3Slucy wang - Sun Microsystems - Beijing China 32*6d0043d8SRobert Mustacchi /* 33*6d0043d8SRobert Mustacchi * Copyright (c) 2014, Joyent, Inc. 34*6d0043d8SRobert Mustacchi */ 35*6d0043d8SRobert Mustacchi 3604b6cca3Slucy wang - Sun Microsystems - Beijing China #ifndef lint 3704b6cca3Slucy wang - Sun Microsystems - Beijing China static const char __idstring[] = 3804b6cca3Slucy wang - Sun Microsystems - Beijing China "@(#)$Id: myri10ge.c,v 1.186 2009-06-29 13:47:22 gallatin Exp $"; 3904b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 4004b6cca3Slucy wang - Sun Microsystems - Beijing China 4104b6cca3Slucy wang - Sun Microsystems - Beijing China #define MXGEFW_NDIS 4204b6cca3Slucy wang - Sun Microsystems - Beijing China #include "myri10ge_var.h" 4304b6cca3Slucy wang - Sun Microsystems - Beijing China #include "rss_eth_z8e.h" 4404b6cca3Slucy wang - Sun Microsystems - Beijing China #include "rss_ethp_z8e.h" 4504b6cca3Slucy wang - Sun Microsystems - Beijing China #include "mcp_gen_header.h" 4604b6cca3Slucy wang - Sun Microsystems - Beijing China 4704b6cca3Slucy wang - Sun Microsystems - Beijing China #define MYRI10GE_MAX_ETHER_MTU 9014 48*6d0043d8SRobert Mustacchi #define MYRI10GE_MAX_GLD_MTU 9000 49*6d0043d8SRobert Mustacchi #define MYRI10GE_MIN_GLD_MTU 1500 5004b6cca3Slucy wang - Sun Microsystems - Beijing China 5104b6cca3Slucy wang - Sun Microsystems - Beijing China #define MYRI10GE_ETH_STOPPED 0 5204b6cca3Slucy wang - Sun Microsystems - Beijing China #define MYRI10GE_ETH_STOPPING 1 5304b6cca3Slucy wang - Sun Microsystems - Beijing China #define MYRI10GE_ETH_STARTING 2 5404b6cca3Slucy wang - Sun Microsystems - Beijing China #define MYRI10GE_ETH_RUNNING 3 5504b6cca3Slucy wang - Sun Microsystems - Beijing China #define MYRI10GE_ETH_OPEN_FAILED 4 5604b6cca3Slucy wang - Sun Microsystems - Beijing China #define MYRI10GE_ETH_SUSPENDED_RUNNING 5 5704b6cca3Slucy wang - Sun Microsystems - Beijing China 5804b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_small_bytes = 510; 5904b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_intr_coal_delay = 125; 6004b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_flow_control = 1; 615ee6ac27SRichard Lowe #if defined __i386 || defined i386 || defined __i386__ || defined __x86_64__ 6204b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_nvidia_ecrc_enable = 1; 6304b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 6404b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_mtu_override = 0; 6504b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_tx_copylen = 512; 6604b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_deassert_wait = 1; 6704b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_verbose = 0; 6804b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_watchdog_reset = 0; 6904b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_use_msix = 1; 7004b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_max_slices = -1; 7104b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_use_msi = 1; 7204b6cca3Slucy wang - Sun Microsystems - Beijing China int myri10ge_force_firmware = 0; 7304b6cca3Slucy wang - Sun Microsystems - Beijing China static boolean_t myri10ge_use_lso = B_TRUE; 7404b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT; 7504b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_tx_hash = 1; 7691e18787Slucy wang - Sun Microsystems - Beijing China static int myri10ge_lro = 0; 7704b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_lro_cnt = 8; 7804b6cca3Slucy wang - Sun Microsystems - Beijing China int myri10ge_lro_max_aggr = 2; 7904b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_lso_copy = 0; 8004b6cca3Slucy wang - Sun Microsystems - Beijing China static mblk_t *myri10ge_send_wrapper(void *arg, mblk_t *mp); 8104b6cca3Slucy wang - Sun Microsystems - Beijing China int myri10ge_tx_handles_initial = 128; 8204b6cca3Slucy wang - Sun Microsystems - Beijing China 8304b6cca3Slucy wang - Sun Microsystems - Beijing China static kmutex_t myri10ge_param_lock; 8404b6cca3Slucy wang - Sun Microsystems - Beijing China static void* myri10ge_db_lastfree; 8504b6cca3Slucy wang - Sun Microsystems - Beijing China 8604b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 8704b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 8804b6cca3Slucy wang - Sun Microsystems - Beijing China static int myri10ge_quiesce(dev_info_t *dip); 8904b6cca3Slucy wang - Sun Microsystems - Beijing China 9004b6cca3Slucy wang - Sun Microsystems - Beijing China DDI_DEFINE_STREAM_OPS(myri10ge_ops, nulldev, nulldev, myri10ge_attach, 9104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_detach, nodev, NULL, D_MP, NULL, myri10ge_quiesce); 9204b6cca3Slucy wang - Sun Microsystems - Beijing China 9304b6cca3Slucy wang - Sun Microsystems - Beijing China 9404b6cca3Slucy wang - Sun Microsystems - Beijing China static struct modldrv modldrv = { 9504b6cca3Slucy wang - Sun Microsystems - Beijing China &mod_driverops, 9604b6cca3Slucy wang - Sun Microsystems - Beijing China "Myricom 10G driver (10GbE)", 9704b6cca3Slucy wang - Sun Microsystems - Beijing China &myri10ge_ops, 9804b6cca3Slucy wang - Sun Microsystems - Beijing China }; 9904b6cca3Slucy wang - Sun Microsystems - Beijing China 10004b6cca3Slucy wang - Sun Microsystems - Beijing China 10104b6cca3Slucy wang - Sun Microsystems - Beijing China static struct modlinkage modlinkage = { 10204b6cca3Slucy wang - Sun Microsystems - Beijing China MODREV_1, 10304b6cca3Slucy wang - Sun Microsystems - Beijing China {&modldrv, NULL}, 10404b6cca3Slucy wang - Sun Microsystems - Beijing China }; 10504b6cca3Slucy wang - Sun Microsystems - Beijing China 10604b6cca3Slucy wang - Sun Microsystems - Beijing China unsigned char myri10ge_broadcastaddr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 10704b6cca3Slucy wang - Sun Microsystems - Beijing China 10804b6cca3Slucy wang - Sun Microsystems - Beijing China static ddi_dma_attr_t myri10ge_misc_dma_attr = { 10904b6cca3Slucy wang - Sun Microsystems - Beijing China DMA_ATTR_V0, /* version number. */ 11004b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0, /* low address */ 11104b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0xffffffffffffffffULL, /* high address */ 11204b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0x7ffffff, /* address counter max */ 11304b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)4096, /* alignment */ 11404b6cca3Slucy wang - Sun Microsystems - Beijing China (uint_t)0x7f, /* burstsizes for 32b and 64b xfers */ 11504b6cca3Slucy wang - Sun Microsystems - Beijing China (uint32_t)0x1, /* minimum transfer size */ 11604b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0x7fffffff, /* maximum transfer size */ 11704b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0x7fffffff, /* maximum segment size */ 11804b6cca3Slucy wang - Sun Microsystems - Beijing China 1, /* scatter/gather list length */ 11904b6cca3Slucy wang - Sun Microsystems - Beijing China 1, /* granularity */ 12004b6cca3Slucy wang - Sun Microsystems - Beijing China 0 /* attribute flags */ 12104b6cca3Slucy wang - Sun Microsystems - Beijing China }; 12204b6cca3Slucy wang - Sun Microsystems - Beijing China 12304b6cca3Slucy wang - Sun Microsystems - Beijing China /* 12404b6cca3Slucy wang - Sun Microsystems - Beijing China * The Myri10GE NIC has the following constraints on receive buffers: 12504b6cca3Slucy wang - Sun Microsystems - Beijing China * 1) Buffers which cross a 4KB boundary must be aligned to 4KB 12604b6cca3Slucy wang - Sun Microsystems - Beijing China * 2) Buffers which are not aligned to 4KB must not cross a 4KB boundary 12704b6cca3Slucy wang - Sun Microsystems - Beijing China */ 12804b6cca3Slucy wang - Sun Microsystems - Beijing China 12904b6cca3Slucy wang - Sun Microsystems - Beijing China static ddi_dma_attr_t myri10ge_rx_jumbo_dma_attr = { 13004b6cca3Slucy wang - Sun Microsystems - Beijing China DMA_ATTR_V0, /* version number. */ 13104b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0, /* low address */ 13204b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0xffffffffffffffffULL, /* high address */ 13304b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0x7ffffff, /* address counter max */ 13404b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)4096, /* alignment */ 13504b6cca3Slucy wang - Sun Microsystems - Beijing China (uint_t)0x7f, /* burstsizes for 32b and 64b xfers */ 13604b6cca3Slucy wang - Sun Microsystems - Beijing China (uint32_t)0x1, /* minimum transfer size */ 13704b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0x7fffffff, /* maximum transfer size */ 13804b6cca3Slucy wang - Sun Microsystems - Beijing China UINT64_MAX, /* maximum segment size */ 13904b6cca3Slucy wang - Sun Microsystems - Beijing China 1, /* scatter/gather list length */ 14004b6cca3Slucy wang - Sun Microsystems - Beijing China 1, /* granularity */ 14104b6cca3Slucy wang - Sun Microsystems - Beijing China 0 /* attribute flags */ 14204b6cca3Slucy wang - Sun Microsystems - Beijing China }; 14304b6cca3Slucy wang - Sun Microsystems - Beijing China 14404b6cca3Slucy wang - Sun Microsystems - Beijing China static ddi_dma_attr_t myri10ge_rx_std_dma_attr = { 14504b6cca3Slucy wang - Sun Microsystems - Beijing China DMA_ATTR_V0, /* version number. */ 14604b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0, /* low address */ 14704b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0xffffffffffffffffULL, /* high address */ 14804b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0x7ffffff, /* address counter max */ 14904b6cca3Slucy wang - Sun Microsystems - Beijing China #if defined sparc64 || defined __sparcv9 15004b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)4096, /* alignment */ 15104b6cca3Slucy wang - Sun Microsystems - Beijing China #else 15204b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0x80, /* alignment */ 15304b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 15404b6cca3Slucy wang - Sun Microsystems - Beijing China (uint_t)0x7f, /* burstsizes for 32b and 64b xfers */ 15504b6cca3Slucy wang - Sun Microsystems - Beijing China (uint32_t)0x1, /* minimum transfer size */ 15604b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0x7fffffff, /* maximum transfer size */ 15704b6cca3Slucy wang - Sun Microsystems - Beijing China #if defined sparc64 || defined __sparcv9 15804b6cca3Slucy wang - Sun Microsystems - Beijing China UINT64_MAX, /* maximum segment size */ 15904b6cca3Slucy wang - Sun Microsystems - Beijing China #else 16004b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0xfff, /* maximum segment size */ 16104b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 16204b6cca3Slucy wang - Sun Microsystems - Beijing China 1, /* scatter/gather list length */ 16304b6cca3Slucy wang - Sun Microsystems - Beijing China 1, /* granularity */ 16404b6cca3Slucy wang - Sun Microsystems - Beijing China 0 /* attribute flags */ 16504b6cca3Slucy wang - Sun Microsystems - Beijing China }; 16604b6cca3Slucy wang - Sun Microsystems - Beijing China 16704b6cca3Slucy wang - Sun Microsystems - Beijing China static ddi_dma_attr_t myri10ge_tx_dma_attr = { 16804b6cca3Slucy wang - Sun Microsystems - Beijing China DMA_ATTR_V0, /* version number. */ 16904b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0, /* low address */ 17004b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0xffffffffffffffffULL, /* high address */ 17104b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0x7ffffff, /* address counter max */ 17204b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)1, /* alignment */ 17304b6cca3Slucy wang - Sun Microsystems - Beijing China (uint_t)0x7f, /* burstsizes for 32b and 64b xfers */ 17404b6cca3Slucy wang - Sun Microsystems - Beijing China (uint32_t)0x1, /* minimum transfer size */ 17504b6cca3Slucy wang - Sun Microsystems - Beijing China (uint64_t)0x7fffffff, /* maximum transfer size */ 17604b6cca3Slucy wang - Sun Microsystems - Beijing China UINT64_MAX, /* maximum segment size */ 17704b6cca3Slucy wang - Sun Microsystems - Beijing China INT32_MAX, /* scatter/gather list length */ 17804b6cca3Slucy wang - Sun Microsystems - Beijing China 1, /* granularity */ 17904b6cca3Slucy wang - Sun Microsystems - Beijing China 0 /* attribute flags */ 18004b6cca3Slucy wang - Sun Microsystems - Beijing China }; 18104b6cca3Slucy wang - Sun Microsystems - Beijing China 18204b6cca3Slucy wang - Sun Microsystems - Beijing China #if defined sparc64 || defined __sparcv9 18304b6cca3Slucy wang - Sun Microsystems - Beijing China #define WC 0 18404b6cca3Slucy wang - Sun Microsystems - Beijing China #else 18504b6cca3Slucy wang - Sun Microsystems - Beijing China #define WC 1 18604b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 18704b6cca3Slucy wang - Sun Microsystems - Beijing China 18804b6cca3Slucy wang - Sun Microsystems - Beijing China struct ddi_device_acc_attr myri10ge_dev_access_attr = { 18904b6cca3Slucy wang - Sun Microsystems - Beijing China DDI_DEVICE_ATTR_V0, /* version */ 19004b6cca3Slucy wang - Sun Microsystems - Beijing China DDI_NEVERSWAP_ACC, /* endian flash */ 19104b6cca3Slucy wang - Sun Microsystems - Beijing China #if WC 19204b6cca3Slucy wang - Sun Microsystems - Beijing China DDI_MERGING_OK_ACC /* data order */ 19304b6cca3Slucy wang - Sun Microsystems - Beijing China #else 19404b6cca3Slucy wang - Sun Microsystems - Beijing China DDI_STRICTORDER_ACC 19504b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 19604b6cca3Slucy wang - Sun Microsystems - Beijing China }; 19704b6cca3Slucy wang - Sun Microsystems - Beijing China 19804b6cca3Slucy wang - Sun Microsystems - Beijing China static void myri10ge_watchdog(void *arg); 19904b6cca3Slucy wang - Sun Microsystems - Beijing China 20004b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef MYRICOM_PRIV 20104b6cca3Slucy wang - Sun Microsystems - Beijing China int myri10ge_mtu = MYRI10GE_MAX_ETHER_MTU + MXGEFW_PAD + VLAN_TAGSZ; 202*6d0043d8SRobert Mustacchi #define MYRI10GE_DEFAULT_GLD_MTU MYRI10GE_MAX_GLD_MTU 20304b6cca3Slucy wang - Sun Microsystems - Beijing China #else 20404b6cca3Slucy wang - Sun Microsystems - Beijing China int myri10ge_mtu = ETHERMAX + MXGEFW_PAD + VLAN_TAGSZ; 205*6d0043d8SRobert Mustacchi #define MYRI10GE_DEFAULT_GLD_MTU MYRI10GE_MIN_GLD_MTU 20604b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 20704b6cca3Slucy wang - Sun Microsystems - Beijing China int myri10ge_bigbufs_initial = 1024; 20804b6cca3Slucy wang - Sun Microsystems - Beijing China int myri10ge_bigbufs_max = 4096; 20904b6cca3Slucy wang - Sun Microsystems - Beijing China 21004b6cca3Slucy wang - Sun Microsystems - Beijing China 21104b6cca3Slucy wang - Sun Microsystems - Beijing China caddr_t 21204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dma_alloc(dev_info_t *dip, size_t len, 21304b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_dma_attr_t *attr, ddi_device_acc_attr_t *accattr, 21404b6cca3Slucy wang - Sun Microsystems - Beijing China uint_t alloc_flags, int bind_flags, struct myri10ge_dma_stuff *dma, 21504b6cca3Slucy wang - Sun Microsystems - Beijing China int warn, int (*wait)(caddr_t)) 21604b6cca3Slucy wang - Sun Microsystems - Beijing China { 21704b6cca3Slucy wang - Sun Microsystems - Beijing China caddr_t kaddr; 21804b6cca3Slucy wang - Sun Microsystems - Beijing China size_t real_length; 21904b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_dma_cookie_t cookie; 22004b6cca3Slucy wang - Sun Microsystems - Beijing China uint_t count; 22104b6cca3Slucy wang - Sun Microsystems - Beijing China int err; 22204b6cca3Slucy wang - Sun Microsystems - Beijing China 22304b6cca3Slucy wang - Sun Microsystems - Beijing China err = ddi_dma_alloc_handle(dip, attr, wait, 22404b6cca3Slucy wang - Sun Microsystems - Beijing China NULL, &dma->handle); 22504b6cca3Slucy wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 22604b6cca3Slucy wang - Sun Microsystems - Beijing China if (warn) 22704b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 22804b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge: ddi_dma_alloc_handle failed\n"); 22904b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_nothing; 23004b6cca3Slucy wang - Sun Microsystems - Beijing China } 23104b6cca3Slucy wang - Sun Microsystems - Beijing China 23204b6cca3Slucy wang - Sun Microsystems - Beijing China err = ddi_dma_mem_alloc(dma->handle, len, accattr, alloc_flags, 23304b6cca3Slucy wang - Sun Microsystems - Beijing China wait, NULL, &kaddr, &real_length, 23404b6cca3Slucy wang - Sun Microsystems - Beijing China &dma->acc_handle); 23504b6cca3Slucy wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 23604b6cca3Slucy wang - Sun Microsystems - Beijing China if (warn) 23704b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 23804b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge: ddi_dma_mem_alloc failed\n"); 23904b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_handle; 24004b6cca3Slucy wang - Sun Microsystems - Beijing China } 24104b6cca3Slucy wang - Sun Microsystems - Beijing China 24204b6cca3Slucy wang - Sun Microsystems - Beijing China err = ddi_dma_addr_bind_handle(dma->handle, NULL, kaddr, len, 24304b6cca3Slucy wang - Sun Microsystems - Beijing China bind_flags, wait, NULL, &cookie, &count); 24404b6cca3Slucy wang - Sun Microsystems - Beijing China 24504b6cca3Slucy wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 24604b6cca3Slucy wang - Sun Microsystems - Beijing China if (warn) 24704b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 24804b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge: ddi_dma_addr_bind_handle failed\n"); 24904b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_mem; 25004b6cca3Slucy wang - Sun Microsystems - Beijing China } 25104b6cca3Slucy wang - Sun Microsystems - Beijing China 25204b6cca3Slucy wang - Sun Microsystems - Beijing China if (count != 1) { 25304b6cca3Slucy wang - Sun Microsystems - Beijing China if (warn) 25404b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 25504b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge: got too many dma segments "); 25604b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_bind; 25704b6cca3Slucy wang - Sun Microsystems - Beijing China } 25804b6cca3Slucy wang - Sun Microsystems - Beijing China dma->low = htonl(MYRI10GE_LOWPART_TO_U32(cookie.dmac_laddress)); 25904b6cca3Slucy wang - Sun Microsystems - Beijing China dma->high = htonl(MYRI10GE_HIGHPART_TO_U32(cookie.dmac_laddress)); 26004b6cca3Slucy wang - Sun Microsystems - Beijing China return (kaddr); 26104b6cca3Slucy wang - Sun Microsystems - Beijing China 26204b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_bind: 26304b6cca3Slucy wang - Sun Microsystems - Beijing China (void) ddi_dma_unbind_handle(dma->handle); 26404b6cca3Slucy wang - Sun Microsystems - Beijing China 26504b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_mem: 26604b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_dma_mem_free(&dma->acc_handle); 26704b6cca3Slucy wang - Sun Microsystems - Beijing China 26804b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_handle: 26904b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_dma_free_handle(&dma->handle); 27004b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_nothing: 27104b6cca3Slucy wang - Sun Microsystems - Beijing China if (warn) { 27204b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "myri10ge: myri10ge_dma_alloc failed.\n "); 27304b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "args: dip=%p len=0x%lx ddi_dma_attr=%p\n", 27404b6cca3Slucy wang - Sun Microsystems - Beijing China (void*) dip, len, (void*) attr); 27504b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 27604b6cca3Slucy wang - Sun Microsystems - Beijing China "args: ddi_device_acc_attr=%p alloc_flags=0x%x\n", 27704b6cca3Slucy wang - Sun Microsystems - Beijing China (void*) accattr, alloc_flags); 27804b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "args: bind_flags=0x%x dmastuff=%p", 27904b6cca3Slucy wang - Sun Microsystems - Beijing China bind_flags, (void*) dma); 28004b6cca3Slucy wang - Sun Microsystems - Beijing China } 28104b6cca3Slucy wang - Sun Microsystems - Beijing China return (NULL); 28204b6cca3Slucy wang - Sun Microsystems - Beijing China 28304b6cca3Slucy wang - Sun Microsystems - Beijing China } 28404b6cca3Slucy wang - Sun Microsystems - Beijing China 28504b6cca3Slucy wang - Sun Microsystems - Beijing China void 28604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dma_free(struct myri10ge_dma_stuff *dma) 28704b6cca3Slucy wang - Sun Microsystems - Beijing China { 28804b6cca3Slucy wang - Sun Microsystems - Beijing China (void) ddi_dma_unbind_handle(dma->handle); 28904b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_dma_mem_free(&dma->acc_handle); 29004b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_dma_free_handle(&dma->handle); 29104b6cca3Slucy wang - Sun Microsystems - Beijing China } 29204b6cca3Slucy wang - Sun Microsystems - Beijing China 29304b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void 29404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy32(void *to, uint32_t *from32, size_t size) 29504b6cca3Slucy wang - Sun Microsystems - Beijing China { 29604b6cca3Slucy wang - Sun Microsystems - Beijing China register volatile uint32_t *to32; 29704b6cca3Slucy wang - Sun Microsystems - Beijing China size_t i; 29804b6cca3Slucy wang - Sun Microsystems - Beijing China 29904b6cca3Slucy wang - Sun Microsystems - Beijing China to32 = (volatile uint32_t *) to; 30004b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = (size / 4); i; i--) { 30104b6cca3Slucy wang - Sun Microsystems - Beijing China *to32 = *from32; 30204b6cca3Slucy wang - Sun Microsystems - Beijing China to32++; 30304b6cca3Slucy wang - Sun Microsystems - Beijing China from32++; 30404b6cca3Slucy wang - Sun Microsystems - Beijing China } 30504b6cca3Slucy wang - Sun Microsystems - Beijing China } 30604b6cca3Slucy wang - Sun Microsystems - Beijing China 30704b6cca3Slucy wang - Sun Microsystems - Beijing China #if defined(_LP64) 30804b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void 30904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy64(void *to, uint64_t *from64, size_t size) 31004b6cca3Slucy wang - Sun Microsystems - Beijing China { 31104b6cca3Slucy wang - Sun Microsystems - Beijing China register volatile uint64_t *to64; 31204b6cca3Slucy wang - Sun Microsystems - Beijing China size_t i; 31304b6cca3Slucy wang - Sun Microsystems - Beijing China 31404b6cca3Slucy wang - Sun Microsystems - Beijing China to64 = (volatile uint64_t *) to; 31504b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = (size / 8); i; i--) { 31604b6cca3Slucy wang - Sun Microsystems - Beijing China *to64 = *from64; 31704b6cca3Slucy wang - Sun Microsystems - Beijing China to64++; 31804b6cca3Slucy wang - Sun Microsystems - Beijing China from64++; 31904b6cca3Slucy wang - Sun Microsystems - Beijing China } 32004b6cca3Slucy wang - Sun Microsystems - Beijing China } 32104b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 32204b6cca3Slucy wang - Sun Microsystems - Beijing China 32304b6cca3Slucy wang - Sun Microsystems - Beijing China /* 32404b6cca3Slucy wang - Sun Microsystems - Beijing China * This routine copies memory from the host to the NIC. 32504b6cca3Slucy wang - Sun Microsystems - Beijing China * The "size" argument must always be a multiple of 32604b6cca3Slucy wang - Sun Microsystems - Beijing China * the size of long (4 or 8 bytes), and to/from must also 32704b6cca3Slucy wang - Sun Microsystems - Beijing China * be naturally aligned. 32804b6cca3Slucy wang - Sun Microsystems - Beijing China */ 32904b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void 33004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy(void *to, void *from, size_t size) 33104b6cca3Slucy wang - Sun Microsystems - Beijing China { 33204b6cca3Slucy wang - Sun Microsystems - Beijing China #if !defined(_LP64) 33304b6cca3Slucy wang - Sun Microsystems - Beijing China ASSERT((size % 4) == 0); 33404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy32(to, (uint32_t *)from, size); 33504b6cca3Slucy wang - Sun Microsystems - Beijing China #else 33604b6cca3Slucy wang - Sun Microsystems - Beijing China ASSERT((size % 8) == 0); 33704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy64(to, (uint64_t *)from, size); 33804b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 33904b6cca3Slucy wang - Sun Microsystems - Beijing China } 34004b6cca3Slucy wang - Sun Microsystems - Beijing China 34104b6cca3Slucy wang - Sun Microsystems - Beijing China 34204b6cca3Slucy wang - Sun Microsystems - Beijing China /* 34304b6cca3Slucy wang - Sun Microsystems - Beijing China * Due to various bugs in Solaris (especially bug 6186772 where the 34404b6cca3Slucy wang - Sun Microsystems - Beijing China * TCP/UDP checksum is calculated incorrectly on mblk chains with more 34504b6cca3Slucy wang - Sun Microsystems - Beijing China * than two elements), and the design bug where hardware checksums are 34604b6cca3Slucy wang - Sun Microsystems - Beijing China * ignored on mblk chains with more than 2 elements, we need to 34704b6cca3Slucy wang - Sun Microsystems - Beijing China * allocate private pool of physically contiguous receive buffers. 34804b6cca3Slucy wang - Sun Microsystems - Beijing China */ 34904b6cca3Slucy wang - Sun Microsystems - Beijing China 35004b6cca3Slucy wang - Sun Microsystems - Beijing China static void 35104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_jpool_init(struct myri10ge_slice_state *ss) 35204b6cca3Slucy wang - Sun Microsystems - Beijing China { 35304b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_stuff *jpool = &ss->jpool; 35404b6cca3Slucy wang - Sun Microsystems - Beijing China 35504b6cca3Slucy wang - Sun Microsystems - Beijing China bzero(jpool, sizeof (*jpool)); 35604b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_init(&jpool->mtx, NULL, MUTEX_DRIVER, 35704b6cca3Slucy wang - Sun Microsystems - Beijing China ss->mgp->icookie); 35804b6cca3Slucy wang - Sun Microsystems - Beijing China jpool->head = NULL; 35904b6cca3Slucy wang - Sun Microsystems - Beijing China } 36004b6cca3Slucy wang - Sun Microsystems - Beijing China 36104b6cca3Slucy wang - Sun Microsystems - Beijing China static void 36204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_jpool_fini(struct myri10ge_slice_state *ss) 36304b6cca3Slucy wang - Sun Microsystems - Beijing China { 36404b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_stuff *jpool = &ss->jpool; 36504b6cca3Slucy wang - Sun Microsystems - Beijing China 36604b6cca3Slucy wang - Sun Microsystems - Beijing China if (jpool->head != NULL) { 36704b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 36804b6cca3Slucy wang - Sun Microsystems - Beijing China "%s: BUG! myri10ge_jpool_fini called on non-empty pool\n", 36904b6cca3Slucy wang - Sun Microsystems - Beijing China ss->mgp->name); 37004b6cca3Slucy wang - Sun Microsystems - Beijing China } 37104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_destroy(&jpool->mtx); 37204b6cca3Slucy wang - Sun Microsystems - Beijing China } 37304b6cca3Slucy wang - Sun Microsystems - Beijing China 37404b6cca3Slucy wang - Sun Microsystems - Beijing China 37504b6cca3Slucy wang - Sun Microsystems - Beijing China /* 37604b6cca3Slucy wang - Sun Microsystems - Beijing China * copy an array of mcp_kreq_ether_recv_t's to the mcp. Copy 37704b6cca3Slucy wang - Sun Microsystems - Beijing China * at most 32 bytes at a time, so as to avoid involving the software 37804b6cca3Slucy wang - Sun Microsystems - Beijing China * pio handler in the nic. We re-write the first segment's low 37904b6cca3Slucy wang - Sun Microsystems - Beijing China * DMA address to mark it valid only after we write the entire chunk 38004b6cca3Slucy wang - Sun Microsystems - Beijing China * in a burst 38104b6cca3Slucy wang - Sun Microsystems - Beijing China */ 38204b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void 38304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_submit_8rx(mcp_kreq_ether_recv_t *dst, mcp_kreq_ether_recv_t *src) 38404b6cca3Slucy wang - Sun Microsystems - Beijing China { 38504b6cca3Slucy wang - Sun Microsystems - Beijing China src->addr_low |= BE_32(1); 38604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy(dst, src, 4 * sizeof (*src)); 38704b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 38804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy(dst + 4, src + 4, 4 * sizeof (*src)); 38904b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 39004b6cca3Slucy wang - Sun Microsystems - Beijing China src->addr_low &= ~(BE_32(1)); 39104b6cca3Slucy wang - Sun Microsystems - Beijing China dst->addr_low = src->addr_low; 39204b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 39304b6cca3Slucy wang - Sun Microsystems - Beijing China } 39404b6cca3Slucy wang - Sun Microsystems - Beijing China 39504b6cca3Slucy wang - Sun Microsystems - Beijing China static void 39604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pull_jpool(struct myri10ge_slice_state *ss) 39704b6cca3Slucy wang - Sun Microsystems - Beijing China { 39804b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_stuff *jpool = &ss->jpool; 39904b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_entry *jtail, *j, *jfree; 40004b6cca3Slucy wang - Sun Microsystems - Beijing China volatile uintptr_t *putp; 40104b6cca3Slucy wang - Sun Microsystems - Beijing China uintptr_t put; 40204b6cca3Slucy wang - Sun Microsystems - Beijing China int i; 40304b6cca3Slucy wang - Sun Microsystems - Beijing China 40404b6cca3Slucy wang - Sun Microsystems - Beijing China /* find tail */ 40504b6cca3Slucy wang - Sun Microsystems - Beijing China jtail = NULL; 40604b6cca3Slucy wang - Sun Microsystems - Beijing China if (jpool->head != NULL) { 40704b6cca3Slucy wang - Sun Microsystems - Beijing China j = jpool->head; 40804b6cca3Slucy wang - Sun Microsystems - Beijing China while (j->next != NULL) 40904b6cca3Slucy wang - Sun Microsystems - Beijing China j = j->next; 41004b6cca3Slucy wang - Sun Microsystems - Beijing China jtail = j; 41104b6cca3Slucy wang - Sun Microsystems - Beijing China } 41204b6cca3Slucy wang - Sun Microsystems - Beijing China 41304b6cca3Slucy wang - Sun Microsystems - Beijing China /* 41404b6cca3Slucy wang - Sun Microsystems - Beijing China * iterate over all per-CPU caches, and add contents into 41504b6cca3Slucy wang - Sun Microsystems - Beijing China * jpool 41604b6cca3Slucy wang - Sun Microsystems - Beijing China */ 41704b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < MYRI10GE_MAX_CPUS; i++) { 41804b6cca3Slucy wang - Sun Microsystems - Beijing China /* take per-CPU free list */ 41904b6cca3Slucy wang - Sun Microsystems - Beijing China putp = (void *)&jpool->cpu[i & MYRI10GE_MAX_CPU_MASK].head; 42004b6cca3Slucy wang - Sun Microsystems - Beijing China if (*putp == NULL) 42104b6cca3Slucy wang - Sun Microsystems - Beijing China continue; 42204b6cca3Slucy wang - Sun Microsystems - Beijing China put = atomic_swap_ulong(putp, 0); 42304b6cca3Slucy wang - Sun Microsystems - Beijing China jfree = (struct myri10ge_jpool_entry *)put; 42404b6cca3Slucy wang - Sun Microsystems - Beijing China 42504b6cca3Slucy wang - Sun Microsystems - Beijing China /* append to pool */ 42604b6cca3Slucy wang - Sun Microsystems - Beijing China if (jtail == NULL) { 42704b6cca3Slucy wang - Sun Microsystems - Beijing China jpool->head = jfree; 42804b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 42904b6cca3Slucy wang - Sun Microsystems - Beijing China jtail->next = jfree; 43004b6cca3Slucy wang - Sun Microsystems - Beijing China } 43104b6cca3Slucy wang - Sun Microsystems - Beijing China j = jfree; 43204b6cca3Slucy wang - Sun Microsystems - Beijing China while (j->next != NULL) 43304b6cca3Slucy wang - Sun Microsystems - Beijing China j = j->next; 43404b6cca3Slucy wang - Sun Microsystems - Beijing China jtail = j; 43504b6cca3Slucy wang - Sun Microsystems - Beijing China } 43604b6cca3Slucy wang - Sun Microsystems - Beijing China } 43704b6cca3Slucy wang - Sun Microsystems - Beijing China 43804b6cca3Slucy wang - Sun Microsystems - Beijing China /* 43904b6cca3Slucy wang - Sun Microsystems - Beijing China * Transfers buffers from the free pool to the nic 44004b6cca3Slucy wang - Sun Microsystems - Beijing China * Must be called holding the jpool mutex. 44104b6cca3Slucy wang - Sun Microsystems - Beijing China */ 44204b6cca3Slucy wang - Sun Microsystems - Beijing China 44304b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void 44404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_restock_jumbos(struct myri10ge_slice_state *ss) 44504b6cca3Slucy wang - Sun Microsystems - Beijing China { 44604b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_stuff *jpool = &ss->jpool; 44704b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_entry *j; 44804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rx_ring_t *rx; 44904b6cca3Slucy wang - Sun Microsystems - Beijing China int i, idx, limit; 45004b6cca3Slucy wang - Sun Microsystems - Beijing China 45104b6cca3Slucy wang - Sun Microsystems - Beijing China rx = &ss->rx_big; 45204b6cca3Slucy wang - Sun Microsystems - Beijing China limit = ss->j_rx_cnt + (rx->mask + 1); 45304b6cca3Slucy wang - Sun Microsystems - Beijing China 45404b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = rx->cnt; i != limit; i++) { 45504b6cca3Slucy wang - Sun Microsystems - Beijing China idx = i & (rx->mask); 45604b6cca3Slucy wang - Sun Microsystems - Beijing China j = jpool->head; 45704b6cca3Slucy wang - Sun Microsystems - Beijing China if (j == NULL) { 45804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pull_jpool(ss); 45904b6cca3Slucy wang - Sun Microsystems - Beijing China j = jpool->head; 46004b6cca3Slucy wang - Sun Microsystems - Beijing China if (j == NULL) { 46104b6cca3Slucy wang - Sun Microsystems - Beijing China break; 46204b6cca3Slucy wang - Sun Microsystems - Beijing China } 46304b6cca3Slucy wang - Sun Microsystems - Beijing China } 46404b6cca3Slucy wang - Sun Microsystems - Beijing China jpool->head = j->next; 46504b6cca3Slucy wang - Sun Microsystems - Beijing China rx->info[idx].j = j; 46604b6cca3Slucy wang - Sun Microsystems - Beijing China rx->shadow[idx].addr_low = j->dma.low; 46704b6cca3Slucy wang - Sun Microsystems - Beijing China rx->shadow[idx].addr_high = j->dma.high; 46804b6cca3Slucy wang - Sun Microsystems - Beijing China /* copy 4 descriptors (32-bytes) to the mcp at a time */ 46904b6cca3Slucy wang - Sun Microsystems - Beijing China if ((idx & 7) == 7) { 47004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_submit_8rx(&rx->lanai[idx - 7], 47104b6cca3Slucy wang - Sun Microsystems - Beijing China &rx->shadow[idx - 7]); 47204b6cca3Slucy wang - Sun Microsystems - Beijing China } 47304b6cca3Slucy wang - Sun Microsystems - Beijing China } 47404b6cca3Slucy wang - Sun Microsystems - Beijing China rx->cnt = i; 47504b6cca3Slucy wang - Sun Microsystems - Beijing China } 47604b6cca3Slucy wang - Sun Microsystems - Beijing China 47704b6cca3Slucy wang - Sun Microsystems - Beijing China /* 47804b6cca3Slucy wang - Sun Microsystems - Beijing China * Transfer buffers from the nic to the free pool. 47904b6cca3Slucy wang - Sun Microsystems - Beijing China * Should be called holding the jpool mutex 48004b6cca3Slucy wang - Sun Microsystems - Beijing China */ 48104b6cca3Slucy wang - Sun Microsystems - Beijing China 48204b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void 48304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_unstock_jumbos(struct myri10ge_slice_state *ss) 48404b6cca3Slucy wang - Sun Microsystems - Beijing China { 48504b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_stuff *jpool = &ss->jpool; 48604b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_entry *j; 48704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rx_ring_t *rx; 48804b6cca3Slucy wang - Sun Microsystems - Beijing China int i; 48904b6cca3Slucy wang - Sun Microsystems - Beijing China 49004b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&jpool->mtx); 49104b6cca3Slucy wang - Sun Microsystems - Beijing China rx = &ss->rx_big; 49204b6cca3Slucy wang - Sun Microsystems - Beijing China 49304b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < rx->mask + 1; i++) { 49404b6cca3Slucy wang - Sun Microsystems - Beijing China j = rx->info[i].j; 49504b6cca3Slucy wang - Sun Microsystems - Beijing China rx->info[i].j = NULL; 49604b6cca3Slucy wang - Sun Microsystems - Beijing China if (j == NULL) 49704b6cca3Slucy wang - Sun Microsystems - Beijing China continue; 49804b6cca3Slucy wang - Sun Microsystems - Beijing China j->next = jpool->head; 49904b6cca3Slucy wang - Sun Microsystems - Beijing China jpool->head = j; 50004b6cca3Slucy wang - Sun Microsystems - Beijing China } 50104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&jpool->mtx); 50204b6cca3Slucy wang - Sun Microsystems - Beijing China 50304b6cca3Slucy wang - Sun Microsystems - Beijing China } 50404b6cca3Slucy wang - Sun Microsystems - Beijing China 50504b6cca3Slucy wang - Sun Microsystems - Beijing China 50604b6cca3Slucy wang - Sun Microsystems - Beijing China /* 50704b6cca3Slucy wang - Sun Microsystems - Beijing China * Free routine which is called when the mblk allocated via 50804b6cca3Slucy wang - Sun Microsystems - Beijing China * esballoc() is freed. Here we return the jumbo buffer 50904b6cca3Slucy wang - Sun Microsystems - Beijing China * to the free pool, and possibly pass some jumbo buffers 51004b6cca3Slucy wang - Sun Microsystems - Beijing China * to the nic 51104b6cca3Slucy wang - Sun Microsystems - Beijing China */ 51204b6cca3Slucy wang - Sun Microsystems - Beijing China 51304b6cca3Slucy wang - Sun Microsystems - Beijing China static void 51404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_jfree_rtn(void *arg) 51504b6cca3Slucy wang - Sun Microsystems - Beijing China { 51604b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_entry *j = (struct myri10ge_jpool_entry *)arg; 51704b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_stuff *jpool; 51804b6cca3Slucy wang - Sun Microsystems - Beijing China volatile uintptr_t *putp; 51904b6cca3Slucy wang - Sun Microsystems - Beijing China uintptr_t old, new; 52004b6cca3Slucy wang - Sun Microsystems - Beijing China 52104b6cca3Slucy wang - Sun Microsystems - Beijing China jpool = &j->ss->jpool; 52204b6cca3Slucy wang - Sun Microsystems - Beijing China 52304b6cca3Slucy wang - Sun Microsystems - Beijing China /* prepend buffer locklessly to per-CPU freelist */ 52404b6cca3Slucy wang - Sun Microsystems - Beijing China putp = (void *)&jpool->cpu[CPU->cpu_seqid & MYRI10GE_MAX_CPU_MASK].head; 52504b6cca3Slucy wang - Sun Microsystems - Beijing China new = (uintptr_t)j; 52604b6cca3Slucy wang - Sun Microsystems - Beijing China do { 52704b6cca3Slucy wang - Sun Microsystems - Beijing China old = *putp; 52804b6cca3Slucy wang - Sun Microsystems - Beijing China j->next = (void *)old; 52904b6cca3Slucy wang - Sun Microsystems - Beijing China } while (atomic_cas_ulong(putp, old, new) != old); 53004b6cca3Slucy wang - Sun Microsystems - Beijing China } 53104b6cca3Slucy wang - Sun Microsystems - Beijing China 53204b6cca3Slucy wang - Sun Microsystems - Beijing China static void 53304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_remove_jbuf(struct myri10ge_jpool_entry *j) 53404b6cca3Slucy wang - Sun Microsystems - Beijing China { 53504b6cca3Slucy wang - Sun Microsystems - Beijing China (void) ddi_dma_unbind_handle(j->dma_handle); 53604b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_dma_mem_free(&j->acc_handle); 53704b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_dma_free_handle(&j->dma_handle); 53804b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(j, sizeof (*j)); 53904b6cca3Slucy wang - Sun Microsystems - Beijing China } 54004b6cca3Slucy wang - Sun Microsystems - Beijing China 54104b6cca3Slucy wang - Sun Microsystems - Beijing China 54204b6cca3Slucy wang - Sun Microsystems - Beijing China /* 54304b6cca3Slucy wang - Sun Microsystems - Beijing China * Allocates one physically contiguous descriptor 54404b6cca3Slucy wang - Sun Microsystems - Beijing China * and add it to the jumbo buffer pool. 54504b6cca3Slucy wang - Sun Microsystems - Beijing China */ 54604b6cca3Slucy wang - Sun Microsystems - Beijing China 54704b6cca3Slucy wang - Sun Microsystems - Beijing China static int 54804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_add_jbuf(struct myri10ge_slice_state *ss) 54904b6cca3Slucy wang - Sun Microsystems - Beijing China { 55004b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_entry *j; 55104b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_stuff *jpool = &ss->jpool; 55204b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_dma_attr_t *rx_dma_attr; 55304b6cca3Slucy wang - Sun Microsystems - Beijing China size_t real_length; 55404b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_dma_cookie_t cookie; 55504b6cca3Slucy wang - Sun Microsystems - Beijing China uint_t count; 55604b6cca3Slucy wang - Sun Microsystems - Beijing China int err; 55704b6cca3Slucy wang - Sun Microsystems - Beijing China 55804b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_mtu < 2048) 55904b6cca3Slucy wang - Sun Microsystems - Beijing China rx_dma_attr = &myri10ge_rx_std_dma_attr; 56004b6cca3Slucy wang - Sun Microsystems - Beijing China else 56104b6cca3Slucy wang - Sun Microsystems - Beijing China rx_dma_attr = &myri10ge_rx_jumbo_dma_attr; 56204b6cca3Slucy wang - Sun Microsystems - Beijing China 56304b6cca3Slucy wang - Sun Microsystems - Beijing China again: 56404b6cca3Slucy wang - Sun Microsystems - Beijing China j = (struct myri10ge_jpool_entry *) 56504b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_alloc(sizeof (*j), KM_SLEEP); 56604b6cca3Slucy wang - Sun Microsystems - Beijing China err = ddi_dma_alloc_handle(ss->mgp->dip, rx_dma_attr, 56704b6cca3Slucy wang - Sun Microsystems - Beijing China DDI_DMA_DONTWAIT, NULL, &j->dma_handle); 56804b6cca3Slucy wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) 56904b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_j; 57004b6cca3Slucy wang - Sun Microsystems - Beijing China 57104b6cca3Slucy wang - Sun Microsystems - Beijing China err = ddi_dma_mem_alloc(j->dma_handle, myri10ge_mtu, 57204b6cca3Slucy wang - Sun Microsystems - Beijing China &myri10ge_dev_access_attr, DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 57304b6cca3Slucy wang - Sun Microsystems - Beijing China NULL, &j->buf, &real_length, &j->acc_handle); 57404b6cca3Slucy wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) 57504b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_handle; 57604b6cca3Slucy wang - Sun Microsystems - Beijing China 57704b6cca3Slucy wang - Sun Microsystems - Beijing China err = ddi_dma_addr_bind_handle(j->dma_handle, NULL, j->buf, 57804b6cca3Slucy wang - Sun Microsystems - Beijing China real_length, DDI_DMA_READ|DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 57904b6cca3Slucy wang - Sun Microsystems - Beijing China NULL, &cookie, &count); 58004b6cca3Slucy wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) 58104b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_mem; 58204b6cca3Slucy wang - Sun Microsystems - Beijing China 58304b6cca3Slucy wang - Sun Microsystems - Beijing China /* 58404b6cca3Slucy wang - Sun Microsystems - Beijing China * Make certain std MTU buffers do not cross a 4KB boundary: 58504b6cca3Slucy wang - Sun Microsystems - Beijing China * 58604b6cca3Slucy wang - Sun Microsystems - Beijing China * Setting dma_attr_align=4096 will do this, but the system 58704b6cca3Slucy wang - Sun Microsystems - Beijing China * will only allocate 1 RX buffer per 4KB page, rather than 2. 58804b6cca3Slucy wang - Sun Microsystems - Beijing China * Setting dma_attr_granular=4096 *seems* to work around this, 58904b6cca3Slucy wang - Sun Microsystems - Beijing China * but I'm paranoid about future systems no longer honoring 59004b6cca3Slucy wang - Sun Microsystems - Beijing China * this, so fall back to the safe, but memory wasting way if a 59104b6cca3Slucy wang - Sun Microsystems - Beijing China * buffer crosses a 4KB boundary. 59204b6cca3Slucy wang - Sun Microsystems - Beijing China */ 59304b6cca3Slucy wang - Sun Microsystems - Beijing China 59404b6cca3Slucy wang - Sun Microsystems - Beijing China if (rx_dma_attr == &myri10ge_rx_std_dma_attr && 59504b6cca3Slucy wang - Sun Microsystems - Beijing China rx_dma_attr->dma_attr_align != 4096) { 59604b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t start, end; 59704b6cca3Slucy wang - Sun Microsystems - Beijing China 59804b6cca3Slucy wang - Sun Microsystems - Beijing China start = MYRI10GE_LOWPART_TO_U32(cookie.dmac_laddress); 59904b6cca3Slucy wang - Sun Microsystems - Beijing China end = start + myri10ge_mtu; 60004b6cca3Slucy wang - Sun Microsystems - Beijing China if (((end >> 12) != (start >> 12)) && (start & 4095U)) { 60104b6cca3Slucy wang - Sun Microsystems - Beijing China printf("std buffer crossed a 4KB boundary!\n"); 60204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_remove_jbuf(j); 60304b6cca3Slucy wang - Sun Microsystems - Beijing China rx_dma_attr->dma_attr_align = 4096; 60404b6cca3Slucy wang - Sun Microsystems - Beijing China rx_dma_attr->dma_attr_seg = UINT64_MAX; 60504b6cca3Slucy wang - Sun Microsystems - Beijing China goto again; 60604b6cca3Slucy wang - Sun Microsystems - Beijing China } 60704b6cca3Slucy wang - Sun Microsystems - Beijing China } 60804b6cca3Slucy wang - Sun Microsystems - Beijing China 60904b6cca3Slucy wang - Sun Microsystems - Beijing China j->dma.low = 61004b6cca3Slucy wang - Sun Microsystems - Beijing China htonl(MYRI10GE_LOWPART_TO_U32(cookie.dmac_laddress)); 61104b6cca3Slucy wang - Sun Microsystems - Beijing China j->dma.high = 61204b6cca3Slucy wang - Sun Microsystems - Beijing China htonl(MYRI10GE_HIGHPART_TO_U32(cookie.dmac_laddress)); 61304b6cca3Slucy wang - Sun Microsystems - Beijing China j->ss = ss; 61404b6cca3Slucy wang - Sun Microsystems - Beijing China 61504b6cca3Slucy wang - Sun Microsystems - Beijing China 61604b6cca3Slucy wang - Sun Microsystems - Beijing China j->free_func.free_func = myri10ge_jfree_rtn; 61704b6cca3Slucy wang - Sun Microsystems - Beijing China j->free_func.free_arg = (char *)j; 61804b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&jpool->mtx); 61904b6cca3Slucy wang - Sun Microsystems - Beijing China j->next = jpool->head; 62004b6cca3Slucy wang - Sun Microsystems - Beijing China jpool->head = j; 62104b6cca3Slucy wang - Sun Microsystems - Beijing China jpool->num_alloc++; 62204b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&jpool->mtx); 62304b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 62404b6cca3Slucy wang - Sun Microsystems - Beijing China 62504b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_mem: 62604b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_dma_mem_free(&j->acc_handle); 62704b6cca3Slucy wang - Sun Microsystems - Beijing China 62804b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_handle: 62904b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_dma_free_handle(&j->dma_handle); 63004b6cca3Slucy wang - Sun Microsystems - Beijing China 63104b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_j: 63204b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(j, sizeof (*j)); 63304b6cca3Slucy wang - Sun Microsystems - Beijing China 63404b6cca3Slucy wang - Sun Microsystems - Beijing China /* 63504b6cca3Slucy wang - Sun Microsystems - Beijing China * If an allocation failed, perhaps it failed because it could 63604b6cca3Slucy wang - Sun Microsystems - Beijing China * not satisfy granularity requirement. Disable that, and 63704b6cca3Slucy wang - Sun Microsystems - Beijing China * try agin. 63804b6cca3Slucy wang - Sun Microsystems - Beijing China */ 63904b6cca3Slucy wang - Sun Microsystems - Beijing China if (rx_dma_attr == &myri10ge_rx_std_dma_attr && 64004b6cca3Slucy wang - Sun Microsystems - Beijing China rx_dma_attr->dma_attr_align != 4096) { 64104b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_NOTE, 64204b6cca3Slucy wang - Sun Microsystems - Beijing China "!alloc failed, reverting to gran=1\n"); 64304b6cca3Slucy wang - Sun Microsystems - Beijing China rx_dma_attr->dma_attr_align = 4096; 64404b6cca3Slucy wang - Sun Microsystems - Beijing China rx_dma_attr->dma_attr_seg = UINT64_MAX; 64504b6cca3Slucy wang - Sun Microsystems - Beijing China goto again; 64604b6cca3Slucy wang - Sun Microsystems - Beijing China } 64704b6cca3Slucy wang - Sun Microsystems - Beijing China return (err); 64804b6cca3Slucy wang - Sun Microsystems - Beijing China } 64904b6cca3Slucy wang - Sun Microsystems - Beijing China 65004b6cca3Slucy wang - Sun Microsystems - Beijing China static int 65104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_jfree_cnt(struct myri10ge_jpool_stuff *jpool) 65204b6cca3Slucy wang - Sun Microsystems - Beijing China { 65304b6cca3Slucy wang - Sun Microsystems - Beijing China int i; 65404b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_entry *j; 65504b6cca3Slucy wang - Sun Microsystems - Beijing China 65604b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&jpool->mtx); 65704b6cca3Slucy wang - Sun Microsystems - Beijing China j = jpool->head; 65804b6cca3Slucy wang - Sun Microsystems - Beijing China i = 0; 65904b6cca3Slucy wang - Sun Microsystems - Beijing China while (j != NULL) { 66004b6cca3Slucy wang - Sun Microsystems - Beijing China i++; 66104b6cca3Slucy wang - Sun Microsystems - Beijing China j = j->next; 66204b6cca3Slucy wang - Sun Microsystems - Beijing China } 66304b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&jpool->mtx); 66404b6cca3Slucy wang - Sun Microsystems - Beijing China return (i); 66504b6cca3Slucy wang - Sun Microsystems - Beijing China } 66604b6cca3Slucy wang - Sun Microsystems - Beijing China 66704b6cca3Slucy wang - Sun Microsystems - Beijing China static int 66804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_add_jbufs(struct myri10ge_slice_state *ss, int num, int total) 66904b6cca3Slucy wang - Sun Microsystems - Beijing China { 67004b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_stuff *jpool = &ss->jpool; 67104b6cca3Slucy wang - Sun Microsystems - Beijing China int allocated = 0; 67204b6cca3Slucy wang - Sun Microsystems - Beijing China int err; 67304b6cca3Slucy wang - Sun Microsystems - Beijing China int needed; 67404b6cca3Slucy wang - Sun Microsystems - Beijing China 67504b6cca3Slucy wang - Sun Microsystems - Beijing China /* 67604b6cca3Slucy wang - Sun Microsystems - Beijing China * if total is set, user wants "num" jbufs in the pool, 67704b6cca3Slucy wang - Sun Microsystems - Beijing China * otherwise the user wants to "num" additional jbufs 67804b6cca3Slucy wang - Sun Microsystems - Beijing China * added to the pool 67904b6cca3Slucy wang - Sun Microsystems - Beijing China */ 68004b6cca3Slucy wang - Sun Microsystems - Beijing China if (total && jpool->num_alloc) { 68104b6cca3Slucy wang - Sun Microsystems - Beijing China allocated = myri10ge_jfree_cnt(jpool); 68204b6cca3Slucy wang - Sun Microsystems - Beijing China needed = num - allocated; 68304b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 68404b6cca3Slucy wang - Sun Microsystems - Beijing China needed = num; 68504b6cca3Slucy wang - Sun Microsystems - Beijing China } 68604b6cca3Slucy wang - Sun Microsystems - Beijing China 68704b6cca3Slucy wang - Sun Microsystems - Beijing China while (needed > 0) { 68804b6cca3Slucy wang - Sun Microsystems - Beijing China needed--; 68904b6cca3Slucy wang - Sun Microsystems - Beijing China err = myri10ge_add_jbuf(ss); 69004b6cca3Slucy wang - Sun Microsystems - Beijing China if (err == 0) { 69104b6cca3Slucy wang - Sun Microsystems - Beijing China allocated++; 69204b6cca3Slucy wang - Sun Microsystems - Beijing China } 69304b6cca3Slucy wang - Sun Microsystems - Beijing China } 69404b6cca3Slucy wang - Sun Microsystems - Beijing China return (allocated); 69504b6cca3Slucy wang - Sun Microsystems - Beijing China } 69604b6cca3Slucy wang - Sun Microsystems - Beijing China 69704b6cca3Slucy wang - Sun Microsystems - Beijing China static void 69804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_remove_jbufs(struct myri10ge_slice_state *ss) 69904b6cca3Slucy wang - Sun Microsystems - Beijing China { 70004b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_stuff *jpool = &ss->jpool; 70104b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_entry *j; 70204b6cca3Slucy wang - Sun Microsystems - Beijing China 70304b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&jpool->mtx); 70404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pull_jpool(ss); 70504b6cca3Slucy wang - Sun Microsystems - Beijing China while (jpool->head != NULL) { 70604b6cca3Slucy wang - Sun Microsystems - Beijing China jpool->num_alloc--; 70704b6cca3Slucy wang - Sun Microsystems - Beijing China j = jpool->head; 70804b6cca3Slucy wang - Sun Microsystems - Beijing China jpool->head = j->next; 70904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_remove_jbuf(j); 71004b6cca3Slucy wang - Sun Microsystems - Beijing China } 71104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&jpool->mtx); 71204b6cca3Slucy wang - Sun Microsystems - Beijing China } 71304b6cca3Slucy wang - Sun Microsystems - Beijing China 71404b6cca3Slucy wang - Sun Microsystems - Beijing China static void 71504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_carve_up_jbufs_into_small_ring(struct myri10ge_slice_state *ss) 71604b6cca3Slucy wang - Sun Microsystems - Beijing China { 71704b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_stuff *jpool = &ss->jpool; 71804b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_entry *j = NULL; 71904b6cca3Slucy wang - Sun Microsystems - Beijing China caddr_t ptr; 72004b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t dma_low, dma_high; 72104b6cca3Slucy wang - Sun Microsystems - Beijing China int idx, len; 72204b6cca3Slucy wang - Sun Microsystems - Beijing China unsigned int alloc_size; 72304b6cca3Slucy wang - Sun Microsystems - Beijing China 72404b6cca3Slucy wang - Sun Microsystems - Beijing China dma_low = dma_high = len = 0; 72504b6cca3Slucy wang - Sun Microsystems - Beijing China alloc_size = myri10ge_small_bytes + MXGEFW_PAD; 72604b6cca3Slucy wang - Sun Microsystems - Beijing China ptr = NULL; 72704b6cca3Slucy wang - Sun Microsystems - Beijing China for (idx = 0; idx < ss->rx_small.mask + 1; idx++) { 72804b6cca3Slucy wang - Sun Microsystems - Beijing China /* Allocate a jumbo frame and carve it into small frames */ 72904b6cca3Slucy wang - Sun Microsystems - Beijing China if (len < alloc_size) { 73004b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&jpool->mtx); 73104b6cca3Slucy wang - Sun Microsystems - Beijing China /* remove jumbo from freelist */ 73204b6cca3Slucy wang - Sun Microsystems - Beijing China j = jpool->head; 73304b6cca3Slucy wang - Sun Microsystems - Beijing China jpool->head = j->next; 73404b6cca3Slucy wang - Sun Microsystems - Beijing China /* place it onto small list */ 73504b6cca3Slucy wang - Sun Microsystems - Beijing China j->next = ss->small_jpool; 73604b6cca3Slucy wang - Sun Microsystems - Beijing China ss->small_jpool = j; 73704b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&jpool->mtx); 73804b6cca3Slucy wang - Sun Microsystems - Beijing China len = myri10ge_mtu; 73904b6cca3Slucy wang - Sun Microsystems - Beijing China dma_low = ntohl(j->dma.low); 74004b6cca3Slucy wang - Sun Microsystems - Beijing China dma_high = ntohl(j->dma.high); 74104b6cca3Slucy wang - Sun Microsystems - Beijing China ptr = j->buf; 74204b6cca3Slucy wang - Sun Microsystems - Beijing China } 74304b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_small.info[idx].ptr = ptr; 74404b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_small.shadow[idx].addr_low = htonl(dma_low); 74504b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_small.shadow[idx].addr_high = htonl(dma_high); 74604b6cca3Slucy wang - Sun Microsystems - Beijing China len -= alloc_size; 74704b6cca3Slucy wang - Sun Microsystems - Beijing China ptr += alloc_size; 74804b6cca3Slucy wang - Sun Microsystems - Beijing China dma_low += alloc_size; 74904b6cca3Slucy wang - Sun Microsystems - Beijing China } 75004b6cca3Slucy wang - Sun Microsystems - Beijing China } 75104b6cca3Slucy wang - Sun Microsystems - Beijing China 75204b6cca3Slucy wang - Sun Microsystems - Beijing China /* 75304b6cca3Slucy wang - Sun Microsystems - Beijing China * Return the jumbo bufs we carved up for small to the jumbo pool 75404b6cca3Slucy wang - Sun Microsystems - Beijing China */ 75504b6cca3Slucy wang - Sun Microsystems - Beijing China 75604b6cca3Slucy wang - Sun Microsystems - Beijing China static void 75704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_release_small_jbufs(struct myri10ge_slice_state *ss) 75804b6cca3Slucy wang - Sun Microsystems - Beijing China { 75904b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_stuff *jpool = &ss->jpool; 76004b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_entry *j = NULL; 76104b6cca3Slucy wang - Sun Microsystems - Beijing China 76204b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&jpool->mtx); 76304b6cca3Slucy wang - Sun Microsystems - Beijing China while (ss->small_jpool != NULL) { 76404b6cca3Slucy wang - Sun Microsystems - Beijing China j = ss->small_jpool; 76504b6cca3Slucy wang - Sun Microsystems - Beijing China ss->small_jpool = j->next; 76604b6cca3Slucy wang - Sun Microsystems - Beijing China j->next = jpool->head; 76704b6cca3Slucy wang - Sun Microsystems - Beijing China jpool->head = j; 76804b6cca3Slucy wang - Sun Microsystems - Beijing China } 76904b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&jpool->mtx); 77004b6cca3Slucy wang - Sun Microsystems - Beijing China ss->jbufs_for_smalls = 0; 77104b6cca3Slucy wang - Sun Microsystems - Beijing China } 77204b6cca3Slucy wang - Sun Microsystems - Beijing China 77304b6cca3Slucy wang - Sun Microsystems - Beijing China static int 77404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_add_tx_handle(struct myri10ge_slice_state *ss) 77504b6cca3Slucy wang - Sun Microsystems - Beijing China { 77604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_ring_t *tx = &ss->tx; 77704b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = ss->mgp; 77804b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_tx_dma_handle *handle; 77904b6cca3Slucy wang - Sun Microsystems - Beijing China int err; 78004b6cca3Slucy wang - Sun Microsystems - Beijing China 78104b6cca3Slucy wang - Sun Microsystems - Beijing China handle = kmem_zalloc(sizeof (*handle), KM_SLEEP); 78204b6cca3Slucy wang - Sun Microsystems - Beijing China err = ddi_dma_alloc_handle(mgp->dip, 78304b6cca3Slucy wang - Sun Microsystems - Beijing China &myri10ge_tx_dma_attr, 78404b6cca3Slucy wang - Sun Microsystems - Beijing China DDI_DMA_SLEEP, NULL, 78504b6cca3Slucy wang - Sun Microsystems - Beijing China &handle->h); 78604b6cca3Slucy wang - Sun Microsystems - Beijing China if (err) { 78704b6cca3Slucy wang - Sun Microsystems - Beijing China static int limit = 0; 78804b6cca3Slucy wang - Sun Microsystems - Beijing China if (limit == 0) 78904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: Falled to alloc tx dma handle\n", 79004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 79104b6cca3Slucy wang - Sun Microsystems - Beijing China limit++; 79204b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(handle, sizeof (*handle)); 79304b6cca3Slucy wang - Sun Microsystems - Beijing China return (err); 79404b6cca3Slucy wang - Sun Microsystems - Beijing China } 79504b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&tx->handle_lock); 79604b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_SLICE_STAT_INC(tx_handles_alloced); 79704b6cca3Slucy wang - Sun Microsystems - Beijing China handle->next = tx->free_tx_handles; 79804b6cca3Slucy wang - Sun Microsystems - Beijing China tx->free_tx_handles = handle; 79904b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&tx->handle_lock); 80004b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 80104b6cca3Slucy wang - Sun Microsystems - Beijing China } 80204b6cca3Slucy wang - Sun Microsystems - Beijing China 80304b6cca3Slucy wang - Sun Microsystems - Beijing China static void 80404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_remove_tx_handles(struct myri10ge_slice_state *ss) 80504b6cca3Slucy wang - Sun Microsystems - Beijing China { 80604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_ring_t *tx = &ss->tx; 80704b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_tx_dma_handle *handle; 80804b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&tx->handle_lock); 80904b6cca3Slucy wang - Sun Microsystems - Beijing China 81004b6cca3Slucy wang - Sun Microsystems - Beijing China handle = tx->free_tx_handles; 81104b6cca3Slucy wang - Sun Microsystems - Beijing China while (handle != NULL) { 81204b6cca3Slucy wang - Sun Microsystems - Beijing China tx->free_tx_handles = handle->next; 81304b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_dma_free_handle(&handle->h); 81404b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(handle, sizeof (*handle)); 81504b6cca3Slucy wang - Sun Microsystems - Beijing China handle = tx->free_tx_handles; 81604b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_SLICE_STAT_DEC(tx_handles_alloced); 81704b6cca3Slucy wang - Sun Microsystems - Beijing China } 81804b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&tx->handle_lock); 81904b6cca3Slucy wang - Sun Microsystems - Beijing China if (MYRI10GE_SLICE_STAT(tx_handles_alloced) != 0) { 82004b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: %d tx dma handles allocated at close\n", 82104b6cca3Slucy wang - Sun Microsystems - Beijing China ss->mgp->name, 82204b6cca3Slucy wang - Sun Microsystems - Beijing China (int)MYRI10GE_SLICE_STAT(tx_handles_alloced)); 82304b6cca3Slucy wang - Sun Microsystems - Beijing China } 82404b6cca3Slucy wang - Sun Microsystems - Beijing China } 82504b6cca3Slucy wang - Sun Microsystems - Beijing China 82604b6cca3Slucy wang - Sun Microsystems - Beijing China static void 82704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_free_tx_handles(myri10ge_tx_ring_t *tx, 82804b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_tx_dma_handle_head *list) 82904b6cca3Slucy wang - Sun Microsystems - Beijing China { 83004b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&tx->handle_lock); 83104b6cca3Slucy wang - Sun Microsystems - Beijing China list->tail->next = tx->free_tx_handles; 83204b6cca3Slucy wang - Sun Microsystems - Beijing China tx->free_tx_handles = list->head; 83304b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&tx->handle_lock); 83404b6cca3Slucy wang - Sun Microsystems - Beijing China } 83504b6cca3Slucy wang - Sun Microsystems - Beijing China 83604b6cca3Slucy wang - Sun Microsystems - Beijing China static void 83704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_free_tx_handle_slist(myri10ge_tx_ring_t *tx, 83804b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_tx_dma_handle *handle) 83904b6cca3Slucy wang - Sun Microsystems - Beijing China { 84004b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_tx_dma_handle_head list; 84104b6cca3Slucy wang - Sun Microsystems - Beijing China 84204b6cca3Slucy wang - Sun Microsystems - Beijing China if (handle == NULL) 84304b6cca3Slucy wang - Sun Microsystems - Beijing China return; 84404b6cca3Slucy wang - Sun Microsystems - Beijing China list.head = handle; 84504b6cca3Slucy wang - Sun Microsystems - Beijing China list.tail = handle; 84604b6cca3Slucy wang - Sun Microsystems - Beijing China while (handle != NULL) { 84704b6cca3Slucy wang - Sun Microsystems - Beijing China list.tail = handle; 84804b6cca3Slucy wang - Sun Microsystems - Beijing China handle = handle->next; 84904b6cca3Slucy wang - Sun Microsystems - Beijing China } 85004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_free_tx_handles(tx, &list); 85104b6cca3Slucy wang - Sun Microsystems - Beijing China } 85204b6cca3Slucy wang - Sun Microsystems - Beijing China 85304b6cca3Slucy wang - Sun Microsystems - Beijing China static int 85404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_alloc_tx_handles(struct myri10ge_slice_state *ss, int count, 85504b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_tx_dma_handle **ret) 85604b6cca3Slucy wang - Sun Microsystems - Beijing China { 85704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_ring_t *tx = &ss->tx; 85804b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_tx_dma_handle *handle; 85904b6cca3Slucy wang - Sun Microsystems - Beijing China int err, i; 86004b6cca3Slucy wang - Sun Microsystems - Beijing China 86104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&tx->handle_lock); 86204b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < count; i++) { 86304b6cca3Slucy wang - Sun Microsystems - Beijing China handle = tx->free_tx_handles; 86404b6cca3Slucy wang - Sun Microsystems - Beijing China while (handle == NULL) { 86504b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&tx->handle_lock); 86604b6cca3Slucy wang - Sun Microsystems - Beijing China err = myri10ge_add_tx_handle(ss); 86704b6cca3Slucy wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 86804b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_handles; 86904b6cca3Slucy wang - Sun Microsystems - Beijing China } 87004b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&tx->handle_lock); 87104b6cca3Slucy wang - Sun Microsystems - Beijing China handle = tx->free_tx_handles; 87204b6cca3Slucy wang - Sun Microsystems - Beijing China } 87304b6cca3Slucy wang - Sun Microsystems - Beijing China tx->free_tx_handles = handle->next; 87404b6cca3Slucy wang - Sun Microsystems - Beijing China handle->next = *ret; 87504b6cca3Slucy wang - Sun Microsystems - Beijing China *ret = handle; 87604b6cca3Slucy wang - Sun Microsystems - Beijing China } 87704b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&tx->handle_lock); 87804b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 87904b6cca3Slucy wang - Sun Microsystems - Beijing China 88004b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_handles: 88104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_free_tx_handle_slist(tx, *ret); 88204b6cca3Slucy wang - Sun Microsystems - Beijing China return (err); 88304b6cca3Slucy wang - Sun Microsystems - Beijing China } 88404b6cca3Slucy wang - Sun Microsystems - Beijing China 88504b6cca3Slucy wang - Sun Microsystems - Beijing China 88604b6cca3Slucy wang - Sun Microsystems - Beijing China /* 88704b6cca3Slucy wang - Sun Microsystems - Beijing China * Frees DMA resources associated with the send ring 88804b6cca3Slucy wang - Sun Microsystems - Beijing China */ 88904b6cca3Slucy wang - Sun Microsystems - Beijing China static void 89004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_unprepare_tx_ring(struct myri10ge_slice_state *ss) 89104b6cca3Slucy wang - Sun Microsystems - Beijing China { 89204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_ring_t *tx; 89304b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_tx_dma_handle_head handles; 89404b6cca3Slucy wang - Sun Microsystems - Beijing China size_t bytes; 89504b6cca3Slucy wang - Sun Microsystems - Beijing China int idx; 89604b6cca3Slucy wang - Sun Microsystems - Beijing China 89704b6cca3Slucy wang - Sun Microsystems - Beijing China tx = &ss->tx; 89804b6cca3Slucy wang - Sun Microsystems - Beijing China handles.head = NULL; 89904b6cca3Slucy wang - Sun Microsystems - Beijing China handles.tail = NULL; 90004b6cca3Slucy wang - Sun Microsystems - Beijing China for (idx = 0; idx < ss->tx.mask + 1; idx++) { 90104b6cca3Slucy wang - Sun Microsystems - Beijing China if (tx->info[idx].m) { 90204b6cca3Slucy wang - Sun Microsystems - Beijing China (void) ddi_dma_unbind_handle(tx->info[idx].handle->h); 90304b6cca3Slucy wang - Sun Microsystems - Beijing China handles.head = tx->info[idx].handle; 90404b6cca3Slucy wang - Sun Microsystems - Beijing China if (handles.tail == NULL) 90504b6cca3Slucy wang - Sun Microsystems - Beijing China handles.tail = tx->info[idx].handle; 90604b6cca3Slucy wang - Sun Microsystems - Beijing China freeb(tx->info[idx].m); 90704b6cca3Slucy wang - Sun Microsystems - Beijing China tx->info[idx].m = 0; 90804b6cca3Slucy wang - Sun Microsystems - Beijing China tx->info[idx].handle = 0; 90904b6cca3Slucy wang - Sun Microsystems - Beijing China } 91004b6cca3Slucy wang - Sun Microsystems - Beijing China tx->cp[idx].va = NULL; 91104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dma_free(&tx->cp[idx].dma); 91204b6cca3Slucy wang - Sun Microsystems - Beijing China } 91304b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = sizeof (*tx->cp) * (tx->mask + 1); 91404b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(tx->cp, bytes); 91504b6cca3Slucy wang - Sun Microsystems - Beijing China tx->cp = NULL; 91604b6cca3Slucy wang - Sun Microsystems - Beijing China if (handles.head != NULL) 91704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_free_tx_handles(tx, &handles); 91804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_remove_tx_handles(ss); 91904b6cca3Slucy wang - Sun Microsystems - Beijing China } 92004b6cca3Slucy wang - Sun Microsystems - Beijing China 92104b6cca3Slucy wang - Sun Microsystems - Beijing China /* 92204b6cca3Slucy wang - Sun Microsystems - Beijing China * Allocates DMA handles associated with the send ring 92304b6cca3Slucy wang - Sun Microsystems - Beijing China */ 92404b6cca3Slucy wang - Sun Microsystems - Beijing China static inline int 92504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_prepare_tx_ring(struct myri10ge_slice_state *ss) 92604b6cca3Slucy wang - Sun Microsystems - Beijing China { 92704b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_tx_dma_handle *handles; 92804b6cca3Slucy wang - Sun Microsystems - Beijing China int h; 92904b6cca3Slucy wang - Sun Microsystems - Beijing China size_t bytes; 93004b6cca3Slucy wang - Sun Microsystems - Beijing China 93104b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = sizeof (*ss->tx.cp) * (ss->tx.mask + 1); 93204b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.cp = kmem_zalloc(bytes, KM_SLEEP); 93304b6cca3Slucy wang - Sun Microsystems - Beijing China if (ss->tx.cp == NULL) { 93404b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 93504b6cca3Slucy wang - Sun Microsystems - Beijing China "%s: Failed to allocate tx copyblock storage\n", 93604b6cca3Slucy wang - Sun Microsystems - Beijing China ss->mgp->name); 93704b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 93804b6cca3Slucy wang - Sun Microsystems - Beijing China } 93904b6cca3Slucy wang - Sun Microsystems - Beijing China 94004b6cca3Slucy wang - Sun Microsystems - Beijing China 94104b6cca3Slucy wang - Sun Microsystems - Beijing China /* allocate the TX copyblocks */ 94204b6cca3Slucy wang - Sun Microsystems - Beijing China for (h = 0; h < ss->tx.mask + 1; h++) { 94304b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.cp[h].va = myri10ge_dma_alloc(ss->mgp->dip, 94404b6cca3Slucy wang - Sun Microsystems - Beijing China 4096, &myri10ge_rx_jumbo_dma_attr, 94504b6cca3Slucy wang - Sun Microsystems - Beijing China &myri10ge_dev_access_attr, DDI_DMA_STREAMING, 94604b6cca3Slucy wang - Sun Microsystems - Beijing China DDI_DMA_WRITE|DDI_DMA_STREAMING, &ss->tx.cp[h].dma, 1, 94704b6cca3Slucy wang - Sun Microsystems - Beijing China DDI_DMA_DONTWAIT); 94804b6cca3Slucy wang - Sun Microsystems - Beijing China if (ss->tx.cp[h].va == NULL) { 94904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: Failed to allocate tx " 95004b6cca3Slucy wang - Sun Microsystems - Beijing China "copyblock %d\n", ss->mgp->name, h); 95104b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_copyblocks; 95204b6cca3Slucy wang - Sun Microsystems - Beijing China } 95304b6cca3Slucy wang - Sun Microsystems - Beijing China } 95404b6cca3Slucy wang - Sun Microsystems - Beijing China /* pre-allocate transmit handles */ 95504b6cca3Slucy wang - Sun Microsystems - Beijing China handles = NULL; 95604b6cca3Slucy wang - Sun Microsystems - Beijing China (void) myri10ge_alloc_tx_handles(ss, myri10ge_tx_handles_initial, 95704b6cca3Slucy wang - Sun Microsystems - Beijing China &handles); 95804b6cca3Slucy wang - Sun Microsystems - Beijing China if (handles != NULL) 95904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_free_tx_handle_slist(&ss->tx, handles); 96004b6cca3Slucy wang - Sun Microsystems - Beijing China 96104b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 96204b6cca3Slucy wang - Sun Microsystems - Beijing China 96304b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_copyblocks: 96404b6cca3Slucy wang - Sun Microsystems - Beijing China while (h > 0) { 96504b6cca3Slucy wang - Sun Microsystems - Beijing China h--; 96604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dma_free(&ss->tx.cp[h].dma); 96704b6cca3Slucy wang - Sun Microsystems - Beijing China } 96804b6cca3Slucy wang - Sun Microsystems - Beijing China 96904b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = sizeof (*ss->tx.cp) * (ss->tx.mask + 1); 97004b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(ss->tx.cp, bytes); 97104b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.cp = NULL; 97204b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 97304b6cca3Slucy wang - Sun Microsystems - Beijing China } 97404b6cca3Slucy wang - Sun Microsystems - Beijing China 97504b6cca3Slucy wang - Sun Microsystems - Beijing China /* 97604b6cca3Slucy wang - Sun Microsystems - Beijing China * The eeprom strings on the lanaiX have the format 97704b6cca3Slucy wang - Sun Microsystems - Beijing China * SN=x\0 97804b6cca3Slucy wang - Sun Microsystems - Beijing China * MAC=x:x:x:x:x:x\0 97904b6cca3Slucy wang - Sun Microsystems - Beijing China * PT:ddd mmm xx xx:xx:xx xx\0 98004b6cca3Slucy wang - Sun Microsystems - Beijing China * PV:ddd mmm xx xx:xx:xx xx\0 98104b6cca3Slucy wang - Sun Microsystems - Beijing China */ 98204b6cca3Slucy wang - Sun Microsystems - Beijing China static int 98304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_read_mac_addr(struct myri10ge_priv *mgp) 98404b6cca3Slucy wang - Sun Microsystems - Beijing China { 98504b6cca3Slucy wang - Sun Microsystems - Beijing China #define MYRI10GE_NEXT_STRING(p) while (ptr < limit && *ptr++) 98604b6cca3Slucy wang - Sun Microsystems - Beijing China #define myri10ge_digit(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \ 98704b6cca3Slucy wang - Sun Microsystems - Beijing China (((c) >= 'A' && (c) <= 'F') ? (10 + (c) - 'A') : \ 98804b6cca3Slucy wang - Sun Microsystems - Beijing China (((c) >= 'a' && (c) <= 'f') ? (10 + (c) - 'a') : -1))) 98904b6cca3Slucy wang - Sun Microsystems - Beijing China 99004b6cca3Slucy wang - Sun Microsystems - Beijing China char *ptr, *limit; 99104b6cca3Slucy wang - Sun Microsystems - Beijing China int i, hv, lv; 99204b6cca3Slucy wang - Sun Microsystems - Beijing China 99304b6cca3Slucy wang - Sun Microsystems - Beijing China ptr = mgp->eeprom_strings; 99404b6cca3Slucy wang - Sun Microsystems - Beijing China limit = mgp->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE; 99504b6cca3Slucy wang - Sun Microsystems - Beijing China 99604b6cca3Slucy wang - Sun Microsystems - Beijing China while (*ptr != '\0' && ptr < limit) { 99704b6cca3Slucy wang - Sun Microsystems - Beijing China if (memcmp(ptr, "MAC=", 4) == 0) { 99804b6cca3Slucy wang - Sun Microsystems - Beijing China ptr += 4; 99904b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_verbose) 100004b6cca3Slucy wang - Sun Microsystems - Beijing China printf("%s: mac address = %s\n", mgp->name, 100104b6cca3Slucy wang - Sun Microsystems - Beijing China ptr); 100204b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->mac_addr_string = ptr; 100304b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < 6; i++) { 100404b6cca3Slucy wang - Sun Microsystems - Beijing China if ((ptr + 2) > limit) 100504b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort; 100604b6cca3Slucy wang - Sun Microsystems - Beijing China 100704b6cca3Slucy wang - Sun Microsystems - Beijing China if (*(ptr+1) == ':') { 100804b6cca3Slucy wang - Sun Microsystems - Beijing China hv = 0; 100904b6cca3Slucy wang - Sun Microsystems - Beijing China lv = myri10ge_digit(*ptr); ptr++; 101004b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 101104b6cca3Slucy wang - Sun Microsystems - Beijing China hv = myri10ge_digit(*ptr); ptr++; 101204b6cca3Slucy wang - Sun Microsystems - Beijing China lv = myri10ge_digit(*ptr); ptr++; 101304b6cca3Slucy wang - Sun Microsystems - Beijing China } 101404b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->mac_addr[i] = (hv << 4) | lv; 101504b6cca3Slucy wang - Sun Microsystems - Beijing China ptr++; 101604b6cca3Slucy wang - Sun Microsystems - Beijing China } 101704b6cca3Slucy wang - Sun Microsystems - Beijing China } 101804b6cca3Slucy wang - Sun Microsystems - Beijing China if (memcmp((const void *)ptr, "SN=", 3) == 0) { 101904b6cca3Slucy wang - Sun Microsystems - Beijing China ptr += 3; 102004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->sn_str = (char *)ptr; 102104b6cca3Slucy wang - Sun Microsystems - Beijing China } 102204b6cca3Slucy wang - Sun Microsystems - Beijing China if (memcmp((const void *)ptr, "PC=", 3) == 0) { 102304b6cca3Slucy wang - Sun Microsystems - Beijing China ptr += 3; 102404b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->pc_str = (char *)ptr; 102504b6cca3Slucy wang - Sun Microsystems - Beijing China } 102604b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_NEXT_STRING(ptr); 102704b6cca3Slucy wang - Sun Microsystems - Beijing China } 102804b6cca3Slucy wang - Sun Microsystems - Beijing China 102904b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 103004b6cca3Slucy wang - Sun Microsystems - Beijing China 103104b6cca3Slucy wang - Sun Microsystems - Beijing China abort: 103204b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: failed to parse eeprom_strings", mgp->name); 103304b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENXIO); 103404b6cca3Slucy wang - Sun Microsystems - Beijing China } 103504b6cca3Slucy wang - Sun Microsystems - Beijing China 103604b6cca3Slucy wang - Sun Microsystems - Beijing China 103704b6cca3Slucy wang - Sun Microsystems - Beijing China /* 103804b6cca3Slucy wang - Sun Microsystems - Beijing China * Determine the register set containing the PCI resource we 103904b6cca3Slucy wang - Sun Microsystems - Beijing China * want to map: the memory-mappable part of the interface. We do 104004b6cca3Slucy wang - Sun Microsystems - Beijing China * this by scanning the DDI "reg" property of the interface, 104104b6cca3Slucy wang - Sun Microsystems - Beijing China * which is an array of mx_ddi_reg_set structures. 104204b6cca3Slucy wang - Sun Microsystems - Beijing China */ 104304b6cca3Slucy wang - Sun Microsystems - Beijing China static int 104404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_reg_set(dev_info_t *dip, int *reg_set, int *span, 104504b6cca3Slucy wang - Sun Microsystems - Beijing China unsigned long *busno, unsigned long *devno, 104604b6cca3Slucy wang - Sun Microsystems - Beijing China unsigned long *funcno) 104704b6cca3Slucy wang - Sun Microsystems - Beijing China { 104804b6cca3Slucy wang - Sun Microsystems - Beijing China 104904b6cca3Slucy wang - Sun Microsystems - Beijing China #define REGISTER_NUMBER(ip) (ip[0] >> 0 & 0xff) 105004b6cca3Slucy wang - Sun Microsystems - Beijing China #define FUNCTION_NUMBER(ip) (ip[0] >> 8 & 0x07) 105104b6cca3Slucy wang - Sun Microsystems - Beijing China #define DEVICE_NUMBER(ip) (ip[0] >> 11 & 0x1f) 105204b6cca3Slucy wang - Sun Microsystems - Beijing China #define BUS_NUMBER(ip) (ip[0] >> 16 & 0xff) 105304b6cca3Slucy wang - Sun Microsystems - Beijing China #define ADDRESS_SPACE(ip) (ip[0] >> 24 & 0x03) 105404b6cca3Slucy wang - Sun Microsystems - Beijing China #define PCI_ADDR_HIGH(ip) (ip[1]) 105504b6cca3Slucy wang - Sun Microsystems - Beijing China #define PCI_ADDR_LOW(ip) (ip[2]) 105604b6cca3Slucy wang - Sun Microsystems - Beijing China #define PCI_SPAN_HIGH(ip) (ip[3]) 105704b6cca3Slucy wang - Sun Microsystems - Beijing China #define PCI_SPAN_LOW(ip) (ip[4]) 105804b6cca3Slucy wang - Sun Microsystems - Beijing China 105904b6cca3Slucy wang - Sun Microsystems - Beijing China #define MX_DDI_REG_SET_32_BIT_MEMORY_SPACE 2 106004b6cca3Slucy wang - Sun Microsystems - Beijing China #define MX_DDI_REG_SET_64_BIT_MEMORY_SPACE 3 106104b6cca3Slucy wang - Sun Microsystems - Beijing China 106204b6cca3Slucy wang - Sun Microsystems - Beijing China int *data, i, *rs; 106304b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t nelementsp; 106404b6cca3Slucy wang - Sun Microsystems - Beijing China 106504b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef MYRI10GE_REGSET_VERBOSE 106604b6cca3Slucy wang - Sun Microsystems - Beijing China char *address_space_name[] = { "Configuration Space", 106704b6cca3Slucy wang - Sun Microsystems - Beijing China "I/O Space", 106804b6cca3Slucy wang - Sun Microsystems - Beijing China "32-bit Memory Space", 106904b6cca3Slucy wang - Sun Microsystems - Beijing China "64-bit Memory Space" 107004b6cca3Slucy wang - Sun Microsystems - Beijing China }; 107104b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 107204b6cca3Slucy wang - Sun Microsystems - Beijing China 107304b6cca3Slucy wang - Sun Microsystems - Beijing China if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 107404b6cca3Slucy wang - Sun Microsystems - Beijing China "reg", &data, &nelementsp) != DDI_SUCCESS) { 107504b6cca3Slucy wang - Sun Microsystems - Beijing China printf("Could not determine register set.\n"); 107604b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENXIO); 107704b6cca3Slucy wang - Sun Microsystems - Beijing China } 107804b6cca3Slucy wang - Sun Microsystems - Beijing China 107904b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef MYRI10GE_REGSET_VERBOSE 108004b6cca3Slucy wang - Sun Microsystems - Beijing China printf("There are %d register sets.\n", nelementsp / 5); 108104b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 108204b6cca3Slucy wang - Sun Microsystems - Beijing China if (!nelementsp) { 108304b6cca3Slucy wang - Sun Microsystems - Beijing China printf("Didn't find any \"reg\" properties.\n"); 108404b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_prop_free(data); 108504b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENODEV); 108604b6cca3Slucy wang - Sun Microsystems - Beijing China } 108704b6cca3Slucy wang - Sun Microsystems - Beijing China 108804b6cca3Slucy wang - Sun Microsystems - Beijing China /* Scan for the register number. */ 108904b6cca3Slucy wang - Sun Microsystems - Beijing China rs = &data[0]; 109004b6cca3Slucy wang - Sun Microsystems - Beijing China *busno = BUS_NUMBER(rs); 109104b6cca3Slucy wang - Sun Microsystems - Beijing China *devno = DEVICE_NUMBER(rs); 109204b6cca3Slucy wang - Sun Microsystems - Beijing China *funcno = FUNCTION_NUMBER(rs); 109304b6cca3Slucy wang - Sun Microsystems - Beijing China 109404b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef MYRI10GE_REGSET_VERBOSE 109504b6cca3Slucy wang - Sun Microsystems - Beijing China printf("*** Scanning for register number.\n"); 109604b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 109704b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < nelementsp / 5; i++) { 109804b6cca3Slucy wang - Sun Microsystems - Beijing China rs = &data[5 * i]; 109904b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef MYRI10GE_REGSET_VERBOSE 110004b6cca3Slucy wang - Sun Microsystems - Beijing China printf("Examining register set %d:\n", i); 110104b6cca3Slucy wang - Sun Microsystems - Beijing China printf(" Register number = %d.\n", REGISTER_NUMBER(rs)); 110204b6cca3Slucy wang - Sun Microsystems - Beijing China printf(" Function number = %d.\n", FUNCTION_NUMBER(rs)); 110304b6cca3Slucy wang - Sun Microsystems - Beijing China printf(" Device number = %d.\n", DEVICE_NUMBER(rs)); 110404b6cca3Slucy wang - Sun Microsystems - Beijing China printf(" Bus number = %d.\n", BUS_NUMBER(rs)); 110504b6cca3Slucy wang - Sun Microsystems - Beijing China printf(" Address space = %d (%s ).\n", ADDRESS_SPACE(rs), 110604b6cca3Slucy wang - Sun Microsystems - Beijing China address_space_name[ADDRESS_SPACE(rs)]); 110704b6cca3Slucy wang - Sun Microsystems - Beijing China printf(" pci address 0x%08x %08x\n", PCI_ADDR_HIGH(rs), 110804b6cca3Slucy wang - Sun Microsystems - Beijing China PCI_ADDR_LOW(rs)); 110904b6cca3Slucy wang - Sun Microsystems - Beijing China printf(" pci span 0x%08x %08x\n", PCI_SPAN_HIGH(rs), 111004b6cca3Slucy wang - Sun Microsystems - Beijing China PCI_SPAN_LOW(rs)); 111104b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 111204b6cca3Slucy wang - Sun Microsystems - Beijing China /* We are looking for a memory property. */ 111304b6cca3Slucy wang - Sun Microsystems - Beijing China 111404b6cca3Slucy wang - Sun Microsystems - Beijing China if (ADDRESS_SPACE(rs) == MX_DDI_REG_SET_64_BIT_MEMORY_SPACE || 111504b6cca3Slucy wang - Sun Microsystems - Beijing China ADDRESS_SPACE(rs) == MX_DDI_REG_SET_32_BIT_MEMORY_SPACE) { 111604b6cca3Slucy wang - Sun Microsystems - Beijing China *reg_set = i; 111704b6cca3Slucy wang - Sun Microsystems - Beijing China 111804b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef MYRI10GE_REGSET_VERBOSE 111904b6cca3Slucy wang - Sun Microsystems - Beijing China printf("%s uses register set %d.\n", 112004b6cca3Slucy wang - Sun Microsystems - Beijing China address_space_name[ADDRESS_SPACE(rs)], *reg_set); 112104b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 112204b6cca3Slucy wang - Sun Microsystems - Beijing China 112304b6cca3Slucy wang - Sun Microsystems - Beijing China *span = (PCI_SPAN_LOW(rs)); 112404b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef MYRI10GE_REGSET_VERBOSE 112504b6cca3Slucy wang - Sun Microsystems - Beijing China printf("Board span is 0x%x\n", *span); 112604b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 112704b6cca3Slucy wang - Sun Microsystems - Beijing China break; 112804b6cca3Slucy wang - Sun Microsystems - Beijing China } 112904b6cca3Slucy wang - Sun Microsystems - Beijing China } 113004b6cca3Slucy wang - Sun Microsystems - Beijing China 113104b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_prop_free(data); 113204b6cca3Slucy wang - Sun Microsystems - Beijing China 113304b6cca3Slucy wang - Sun Microsystems - Beijing China /* If no match, fail. */ 113404b6cca3Slucy wang - Sun Microsystems - Beijing China if (i >= nelementsp / 5) { 113504b6cca3Slucy wang - Sun Microsystems - Beijing China return (EIO); 113604b6cca3Slucy wang - Sun Microsystems - Beijing China } 113704b6cca3Slucy wang - Sun Microsystems - Beijing China 113804b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 113904b6cca3Slucy wang - Sun Microsystems - Beijing China } 114004b6cca3Slucy wang - Sun Microsystems - Beijing China 114104b6cca3Slucy wang - Sun Microsystems - Beijing China 114204b6cca3Slucy wang - Sun Microsystems - Beijing China static int 114304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_load_firmware_from_zlib(struct myri10ge_priv *mgp, uint32_t *limit) 114404b6cca3Slucy wang - Sun Microsystems - Beijing China { 114504b6cca3Slucy wang - Sun Microsystems - Beijing China void *inflate_buffer; 114604b6cca3Slucy wang - Sun Microsystems - Beijing China int rv, status; 114704b6cca3Slucy wang - Sun Microsystems - Beijing China size_t sram_size = mgp->sram_size - MYRI10GE_EEPROM_STRINGS_SIZE; 114804b6cca3Slucy wang - Sun Microsystems - Beijing China size_t destlen; 114904b6cca3Slucy wang - Sun Microsystems - Beijing China mcp_gen_header_t *hdr; 115004b6cca3Slucy wang - Sun Microsystems - Beijing China unsigned hdr_offset, i; 115104b6cca3Slucy wang - Sun Microsystems - Beijing China 115204b6cca3Slucy wang - Sun Microsystems - Beijing China 115304b6cca3Slucy wang - Sun Microsystems - Beijing China *limit = 0; /* -Wuninitialized */ 115404b6cca3Slucy wang - Sun Microsystems - Beijing China status = 0; 115504b6cca3Slucy wang - Sun Microsystems - Beijing China 115604b6cca3Slucy wang - Sun Microsystems - Beijing China inflate_buffer = kmem_zalloc(sram_size, KM_NOSLEEP); 115704b6cca3Slucy wang - Sun Microsystems - Beijing China if (!inflate_buffer) { 115804b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 115904b6cca3Slucy wang - Sun Microsystems - Beijing China "%s: Could not allocate buffer to inflate mcp\n", 116004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 116104b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENOMEM); 116204b6cca3Slucy wang - Sun Microsystems - Beijing China } 116304b6cca3Slucy wang - Sun Microsystems - Beijing China 116404b6cca3Slucy wang - Sun Microsystems - Beijing China destlen = sram_size; 116504b6cca3Slucy wang - Sun Microsystems - Beijing China rv = z_uncompress(inflate_buffer, &destlen, mgp->eth_z8e, 116604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->eth_z8e_length); 116704b6cca3Slucy wang - Sun Microsystems - Beijing China 116804b6cca3Slucy wang - Sun Microsystems - Beijing China if (rv != Z_OK) { 116904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: Could not inflate mcp: %s\n", 117004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, z_strerror(rv)); 117104b6cca3Slucy wang - Sun Microsystems - Beijing China status = ENXIO; 117204b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort; 117304b6cca3Slucy wang - Sun Microsystems - Beijing China } 117404b6cca3Slucy wang - Sun Microsystems - Beijing China 117504b6cca3Slucy wang - Sun Microsystems - Beijing China *limit = (uint32_t)destlen; 117604b6cca3Slucy wang - Sun Microsystems - Beijing China 117704b6cca3Slucy wang - Sun Microsystems - Beijing China hdr_offset = htonl(*(uint32_t *)(void *)((char *)inflate_buffer + 117804b6cca3Slucy wang - Sun Microsystems - Beijing China MCP_HEADER_PTR_OFFSET)); 117904b6cca3Slucy wang - Sun Microsystems - Beijing China hdr = (void *)((char *)inflate_buffer + hdr_offset); 118004b6cca3Slucy wang - Sun Microsystems - Beijing China if (ntohl(hdr->mcp_type) != MCP_TYPE_ETH) { 118104b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: Bad firmware type: 0x%x\n", mgp->name, 118204b6cca3Slucy wang - Sun Microsystems - Beijing China ntohl(hdr->mcp_type)); 118304b6cca3Slucy wang - Sun Microsystems - Beijing China status = EIO; 118404b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort; 118504b6cca3Slucy wang - Sun Microsystems - Beijing China } 118604b6cca3Slucy wang - Sun Microsystems - Beijing China 118704b6cca3Slucy wang - Sun Microsystems - Beijing China /* save firmware version for kstat */ 118804b6cca3Slucy wang - Sun Microsystems - Beijing China (void) strncpy(mgp->fw_version, hdr->version, sizeof (mgp->fw_version)); 118904b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_verbose) 119004b6cca3Slucy wang - Sun Microsystems - Beijing China printf("%s: firmware id: %s\n", mgp->name, hdr->version); 119104b6cca3Slucy wang - Sun Microsystems - Beijing China 119204b6cca3Slucy wang - Sun Microsystems - Beijing China /* Copy the inflated firmware to NIC SRAM. */ 119304b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < *limit; i += 256) { 119404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy((char *)mgp->sram + MYRI10GE_FW_OFFSET + i, 119504b6cca3Slucy wang - Sun Microsystems - Beijing China (char *)inflate_buffer + i, 119604b6cca3Slucy wang - Sun Microsystems - Beijing China min(256U, (unsigned)(*limit - i))); 119704b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 119804b6cca3Slucy wang - Sun Microsystems - Beijing China (void) *(int *)(void *)mgp->sram; 119904b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 120004b6cca3Slucy wang - Sun Microsystems - Beijing China } 120104b6cca3Slucy wang - Sun Microsystems - Beijing China 120204b6cca3Slucy wang - Sun Microsystems - Beijing China abort: 120304b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(inflate_buffer, sram_size); 120404b6cca3Slucy wang - Sun Microsystems - Beijing China 120504b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 120604b6cca3Slucy wang - Sun Microsystems - Beijing China 120704b6cca3Slucy wang - Sun Microsystems - Beijing China } 120804b6cca3Slucy wang - Sun Microsystems - Beijing China 120904b6cca3Slucy wang - Sun Microsystems - Beijing China 121004b6cca3Slucy wang - Sun Microsystems - Beijing China int 121104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_send_cmd(struct myri10ge_priv *mgp, uint32_t cmd, 121204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_cmd_t *data) 121304b6cca3Slucy wang - Sun Microsystems - Beijing China { 121404b6cca3Slucy wang - Sun Microsystems - Beijing China mcp_cmd_t *buf; 121504b6cca3Slucy wang - Sun Microsystems - Beijing China char buf_bytes[sizeof (*buf) + 8]; 121604b6cca3Slucy wang - Sun Microsystems - Beijing China volatile mcp_cmd_response_t *response = mgp->cmd; 121704b6cca3Slucy wang - Sun Microsystems - Beijing China volatile char *cmd_addr = 121804b6cca3Slucy wang - Sun Microsystems - Beijing China (volatile char *)mgp->sram + MXGEFW_ETH_CMD; 121904b6cca3Slucy wang - Sun Microsystems - Beijing China int sleep_total = 0; 122004b6cca3Slucy wang - Sun Microsystems - Beijing China 122104b6cca3Slucy wang - Sun Microsystems - Beijing China /* ensure buf is aligned to 8 bytes */ 122204b6cca3Slucy wang - Sun Microsystems - Beijing China buf = (mcp_cmd_t *)((unsigned long)(buf_bytes + 7) & ~7UL); 122304b6cca3Slucy wang - Sun Microsystems - Beijing China 122404b6cca3Slucy wang - Sun Microsystems - Beijing China buf->data0 = htonl(data->data0); 122504b6cca3Slucy wang - Sun Microsystems - Beijing China buf->data1 = htonl(data->data1); 122604b6cca3Slucy wang - Sun Microsystems - Beijing China buf->data2 = htonl(data->data2); 122704b6cca3Slucy wang - Sun Microsystems - Beijing China buf->cmd = htonl(cmd); 122804b6cca3Slucy wang - Sun Microsystems - Beijing China buf->response_addr.low = mgp->cmd_dma.low; 122904b6cca3Slucy wang - Sun Microsystems - Beijing China buf->response_addr.high = mgp->cmd_dma.high; 123004b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&mgp->cmd_lock); 123104b6cca3Slucy wang - Sun Microsystems - Beijing China response->result = 0xffffffff; 123204b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 123304b6cca3Slucy wang - Sun Microsystems - Beijing China 123404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy((void *)cmd_addr, buf, sizeof (*buf)); 123504b6cca3Slucy wang - Sun Microsystems - Beijing China 123604b6cca3Slucy wang - Sun Microsystems - Beijing China /* wait up to 20ms */ 123704b6cca3Slucy wang - Sun Microsystems - Beijing China for (sleep_total = 0; sleep_total < 20; sleep_total++) { 123804b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 123904b6cca3Slucy wang - Sun Microsystems - Beijing China if (response->result != 0xffffffff) { 124004b6cca3Slucy wang - Sun Microsystems - Beijing China if (response->result == 0) { 124104b6cca3Slucy wang - Sun Microsystems - Beijing China data->data0 = ntohl(response->data); 124204b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->cmd_lock); 124304b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 124404b6cca3Slucy wang - Sun Microsystems - Beijing China } else if (ntohl(response->result) 124504b6cca3Slucy wang - Sun Microsystems - Beijing China == MXGEFW_CMD_UNKNOWN) { 124604b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->cmd_lock); 124704b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENOSYS); 124804b6cca3Slucy wang - Sun Microsystems - Beijing China } else if (ntohl(response->result) 124904b6cca3Slucy wang - Sun Microsystems - Beijing China == MXGEFW_CMD_ERROR_UNALIGNED) { 125004b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->cmd_lock); 125104b6cca3Slucy wang - Sun Microsystems - Beijing China return (E2BIG); 125204b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 125304b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 125404b6cca3Slucy wang - Sun Microsystems - Beijing China "%s: command %d failed, result = %d\n", 125504b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, cmd, ntohl(response->result)); 125604b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->cmd_lock); 125704b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENXIO); 125804b6cca3Slucy wang - Sun Microsystems - Beijing China } 125904b6cca3Slucy wang - Sun Microsystems - Beijing China } 126004b6cca3Slucy wang - Sun Microsystems - Beijing China drv_usecwait(1000); 126104b6cca3Slucy wang - Sun Microsystems - Beijing China } 126204b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->cmd_lock); 126304b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: command %d timed out, result = %d\n", 126404b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, cmd, ntohl(response->result)); 126504b6cca3Slucy wang - Sun Microsystems - Beijing China return (EAGAIN); 126604b6cca3Slucy wang - Sun Microsystems - Beijing China } 126704b6cca3Slucy wang - Sun Microsystems - Beijing China 126804b6cca3Slucy wang - Sun Microsystems - Beijing China /* 126904b6cca3Slucy wang - Sun Microsystems - Beijing China * Enable or disable periodic RDMAs from the host to make certain 127004b6cca3Slucy wang - Sun Microsystems - Beijing China * chipsets resend dropped PCIe messages 127104b6cca3Slucy wang - Sun Microsystems - Beijing China */ 127204b6cca3Slucy wang - Sun Microsystems - Beijing China 127304b6cca3Slucy wang - Sun Microsystems - Beijing China static void 127404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable) 127504b6cca3Slucy wang - Sun Microsystems - Beijing China { 127604b6cca3Slucy wang - Sun Microsystems - Beijing China char buf_bytes[72]; 127704b6cca3Slucy wang - Sun Microsystems - Beijing China volatile uint32_t *confirm; 127804b6cca3Slucy wang - Sun Microsystems - Beijing China volatile char *submit; 127904b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t *buf; 128004b6cca3Slucy wang - Sun Microsystems - Beijing China int i; 128104b6cca3Slucy wang - Sun Microsystems - Beijing China 128204b6cca3Slucy wang - Sun Microsystems - Beijing China buf = (uint32_t *)((unsigned long)(buf_bytes + 7) & ~7UL); 128304b6cca3Slucy wang - Sun Microsystems - Beijing China 128404b6cca3Slucy wang - Sun Microsystems - Beijing China /* clear confirmation addr */ 128504b6cca3Slucy wang - Sun Microsystems - Beijing China confirm = (volatile uint32_t *)mgp->cmd; 128604b6cca3Slucy wang - Sun Microsystems - Beijing China *confirm = 0; 128704b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 128804b6cca3Slucy wang - Sun Microsystems - Beijing China 128904b6cca3Slucy wang - Sun Microsystems - Beijing China /* 129004b6cca3Slucy wang - Sun Microsystems - Beijing China * send an rdma command to the PCIe engine, and wait for the 129104b6cca3Slucy wang - Sun Microsystems - Beijing China * response in the confirmation address. The firmware should 129204b6cca3Slucy wang - Sun Microsystems - Beijing China * write a -1 there to indicate it is alive and well 129304b6cca3Slucy wang - Sun Microsystems - Beijing China */ 129404b6cca3Slucy wang - Sun Microsystems - Beijing China 129504b6cca3Slucy wang - Sun Microsystems - Beijing China buf[0] = mgp->cmd_dma.high; /* confirm addr MSW */ 129604b6cca3Slucy wang - Sun Microsystems - Beijing China buf[1] = mgp->cmd_dma.low; /* confirm addr LSW */ 129704b6cca3Slucy wang - Sun Microsystems - Beijing China buf[2] = htonl(0xffffffff); /* confirm data */ 129804b6cca3Slucy wang - Sun Microsystems - Beijing China buf[3] = htonl(mgp->cmd_dma.high); /* dummy addr MSW */ 129904b6cca3Slucy wang - Sun Microsystems - Beijing China buf[4] = htonl(mgp->cmd_dma.low); /* dummy addr LSW */ 130004b6cca3Slucy wang - Sun Microsystems - Beijing China buf[5] = htonl(enable); /* enable? */ 130104b6cca3Slucy wang - Sun Microsystems - Beijing China 130204b6cca3Slucy wang - Sun Microsystems - Beijing China 130304b6cca3Slucy wang - Sun Microsystems - Beijing China submit = (volatile char *)(mgp->sram + MXGEFW_BOOT_DUMMY_RDMA); 130404b6cca3Slucy wang - Sun Microsystems - Beijing China 130504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy((char *)submit, buf, 64); 130604b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 130704b6cca3Slucy wang - Sun Microsystems - Beijing China drv_usecwait(1000); 130804b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 130904b6cca3Slucy wang - Sun Microsystems - Beijing China i = 0; 131004b6cca3Slucy wang - Sun Microsystems - Beijing China while (*confirm != 0xffffffff && i < 20) { 131104b6cca3Slucy wang - Sun Microsystems - Beijing China drv_usecwait(1000); 131204b6cca3Slucy wang - Sun Microsystems - Beijing China i++; 131304b6cca3Slucy wang - Sun Microsystems - Beijing China } 131404b6cca3Slucy wang - Sun Microsystems - Beijing China if (*confirm != 0xffffffff) { 131504b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: dummy rdma %s failed (%p = 0x%x)", 131604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, 131704b6cca3Slucy wang - Sun Microsystems - Beijing China (enable ? "enable" : "disable"), (void*) confirm, *confirm); 131804b6cca3Slucy wang - Sun Microsystems - Beijing China } 131904b6cca3Slucy wang - Sun Microsystems - Beijing China } 132004b6cca3Slucy wang - Sun Microsystems - Beijing China 132104b6cca3Slucy wang - Sun Microsystems - Beijing China static int 132204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_load_firmware(struct myri10ge_priv *mgp) 132304b6cca3Slucy wang - Sun Microsystems - Beijing China { 132404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_cmd_t cmd; 132504b6cca3Slucy wang - Sun Microsystems - Beijing China volatile uint32_t *confirm; 132604b6cca3Slucy wang - Sun Microsystems - Beijing China volatile char *submit; 132704b6cca3Slucy wang - Sun Microsystems - Beijing China char buf_bytes[72]; 132804b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t *buf, size; 132904b6cca3Slucy wang - Sun Microsystems - Beijing China int status, i; 133004b6cca3Slucy wang - Sun Microsystems - Beijing China 133104b6cca3Slucy wang - Sun Microsystems - Beijing China buf = (uint32_t *)((unsigned long)(buf_bytes + 7) & ~7UL); 133204b6cca3Slucy wang - Sun Microsystems - Beijing China 133304b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_load_firmware_from_zlib(mgp, &size); 133404b6cca3Slucy wang - Sun Microsystems - Beijing China if (status) { 133504b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: firmware loading failed\n", mgp->name); 133604b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 133704b6cca3Slucy wang - Sun Microsystems - Beijing China } 133804b6cca3Slucy wang - Sun Microsystems - Beijing China 133904b6cca3Slucy wang - Sun Microsystems - Beijing China /* clear confirmation addr */ 134004b6cca3Slucy wang - Sun Microsystems - Beijing China confirm = (volatile uint32_t *)mgp->cmd; 134104b6cca3Slucy wang - Sun Microsystems - Beijing China *confirm = 0; 134204b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 134304b6cca3Slucy wang - Sun Microsystems - Beijing China 134404b6cca3Slucy wang - Sun Microsystems - Beijing China /* 134504b6cca3Slucy wang - Sun Microsystems - Beijing China * send a reload command to the bootstrap MCP, and wait for the 134604b6cca3Slucy wang - Sun Microsystems - Beijing China * response in the confirmation address. The firmware should 134704b6cca3Slucy wang - Sun Microsystems - Beijing China * write a -1 there to indicate it is alive and well 134804b6cca3Slucy wang - Sun Microsystems - Beijing China */ 134904b6cca3Slucy wang - Sun Microsystems - Beijing China 135004b6cca3Slucy wang - Sun Microsystems - Beijing China buf[0] = mgp->cmd_dma.high; /* confirm addr MSW */ 135104b6cca3Slucy wang - Sun Microsystems - Beijing China buf[1] = mgp->cmd_dma.low; /* confirm addr LSW */ 135204b6cca3Slucy wang - Sun Microsystems - Beijing China buf[2] = htonl(0xffffffff); /* confirm data */ 135304b6cca3Slucy wang - Sun Microsystems - Beijing China 135404b6cca3Slucy wang - Sun Microsystems - Beijing China /* 135504b6cca3Slucy wang - Sun Microsystems - Beijing China * FIX: All newest firmware should un-protect the bottom of 135604b6cca3Slucy wang - Sun Microsystems - Beijing China * the sram before handoff. However, the very first interfaces 135704b6cca3Slucy wang - Sun Microsystems - Beijing China * do not. Therefore the handoff copy must skip the first 8 bytes 135804b6cca3Slucy wang - Sun Microsystems - Beijing China */ 135904b6cca3Slucy wang - Sun Microsystems - Beijing China buf[3] = htonl(MYRI10GE_FW_OFFSET + 8); /* where the code starts */ 136004b6cca3Slucy wang - Sun Microsystems - Beijing China buf[4] = htonl(size - 8); /* length of code */ 136104b6cca3Slucy wang - Sun Microsystems - Beijing China buf[5] = htonl(8); /* where to copy to */ 136204b6cca3Slucy wang - Sun Microsystems - Beijing China buf[6] = htonl(0); /* where to jump to */ 136304b6cca3Slucy wang - Sun Microsystems - Beijing China 136404b6cca3Slucy wang - Sun Microsystems - Beijing China submit = (volatile char *)(mgp->sram + MXGEFW_BOOT_HANDOFF); 136504b6cca3Slucy wang - Sun Microsystems - Beijing China 136604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy((char *)submit, buf, 64); 136704b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 136804b6cca3Slucy wang - Sun Microsystems - Beijing China drv_usecwait(1000); 136904b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 137004b6cca3Slucy wang - Sun Microsystems - Beijing China i = 0; 137104b6cca3Slucy wang - Sun Microsystems - Beijing China while (*confirm != 0xffffffff && i < 1000) { 137204b6cca3Slucy wang - Sun Microsystems - Beijing China drv_usecwait(1000); 137304b6cca3Slucy wang - Sun Microsystems - Beijing China i++; 137404b6cca3Slucy wang - Sun Microsystems - Beijing China } 137504b6cca3Slucy wang - Sun Microsystems - Beijing China if (*confirm != 0xffffffff) { 137604b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: handoff failed (%p = 0x%x)", 137704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, (void *) confirm, *confirm); 137804b6cca3Slucy wang - Sun Microsystems - Beijing China 137904b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENXIO); 138004b6cca3Slucy wang - Sun Microsystems - Beijing China } 138104b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd); 138204b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 138304b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: failed MXGEFW_CMD_GET_RX_RING_SIZE\n", 138404b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 138504b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENXIO); 138604b6cca3Slucy wang - Sun Microsystems - Beijing China } 138704b6cca3Slucy wang - Sun Microsystems - Beijing China 138804b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->max_intr_slots = 2 * (cmd.data0 / sizeof (mcp_dma_addr_t)); 138904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dummy_rdma(mgp, 1); 139004b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 139104b6cca3Slucy wang - Sun Microsystems - Beijing China } 139204b6cca3Slucy wang - Sun Microsystems - Beijing China 139304b6cca3Slucy wang - Sun Microsystems - Beijing China static int 139404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_unicst(void *arg, const uint8_t *addr) 139504b6cca3Slucy wang - Sun Microsystems - Beijing China { 139604b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = arg; 139704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_cmd_t cmd; 139804b6cca3Slucy wang - Sun Microsystems - Beijing China int status; 139904b6cca3Slucy wang - Sun Microsystems - Beijing China 140004b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = ((addr[0] << 24) | (addr[1] << 16) 140104b6cca3Slucy wang - Sun Microsystems - Beijing China | (addr[2] << 8) | addr[3]); 140204b6cca3Slucy wang - Sun Microsystems - Beijing China 140304b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data1 = ((addr[4] << 8) | (addr[5])); 140404b6cca3Slucy wang - Sun Microsystems - Beijing China 140504b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_SET_MAC_ADDRESS, &cmd); 140604b6cca3Slucy wang - Sun Microsystems - Beijing China if (status == 0 && (addr != mgp->mac_addr)) 140704b6cca3Slucy wang - Sun Microsystems - Beijing China (void) memcpy(mgp->mac_addr, addr, sizeof (mgp->mac_addr)); 140804b6cca3Slucy wang - Sun Microsystems - Beijing China 140904b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 141004b6cca3Slucy wang - Sun Microsystems - Beijing China } 141104b6cca3Slucy wang - Sun Microsystems - Beijing China 141204b6cca3Slucy wang - Sun Microsystems - Beijing China static int 141304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_change_pause(struct myri10ge_priv *mgp, int pause) 141404b6cca3Slucy wang - Sun Microsystems - Beijing China { 141504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_cmd_t cmd; 141604b6cca3Slucy wang - Sun Microsystems - Beijing China int status; 141704b6cca3Slucy wang - Sun Microsystems - Beijing China 141804b6cca3Slucy wang - Sun Microsystems - Beijing China if (pause) 141904b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_ENABLE_FLOW_CONTROL, 142004b6cca3Slucy wang - Sun Microsystems - Beijing China &cmd); 142104b6cca3Slucy wang - Sun Microsystems - Beijing China else 142204b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_DISABLE_FLOW_CONTROL, 142304b6cca3Slucy wang - Sun Microsystems - Beijing China &cmd); 142404b6cca3Slucy wang - Sun Microsystems - Beijing China 142504b6cca3Slucy wang - Sun Microsystems - Beijing China if (status) { 142604b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: Failed to set flow control mode\n", 142704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 142804b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENXIO); 142904b6cca3Slucy wang - Sun Microsystems - Beijing China } 143004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->pause = pause; 143104b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 143204b6cca3Slucy wang - Sun Microsystems - Beijing China } 143304b6cca3Slucy wang - Sun Microsystems - Beijing China 143404b6cca3Slucy wang - Sun Microsystems - Beijing China static void 143504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_change_promisc(struct myri10ge_priv *mgp, int promisc) 143604b6cca3Slucy wang - Sun Microsystems - Beijing China { 143704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_cmd_t cmd; 143804b6cca3Slucy wang - Sun Microsystems - Beijing China int status; 143904b6cca3Slucy wang - Sun Microsystems - Beijing China 144004b6cca3Slucy wang - Sun Microsystems - Beijing China if (promisc) 144104b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_ENABLE_PROMISC, &cmd); 144204b6cca3Slucy wang - Sun Microsystems - Beijing China else 144304b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_DISABLE_PROMISC, &cmd); 144404b6cca3Slucy wang - Sun Microsystems - Beijing China 144504b6cca3Slucy wang - Sun Microsystems - Beijing China if (status) { 144604b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: Failed to set promisc mode\n", 144704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 144804b6cca3Slucy wang - Sun Microsystems - Beijing China } 144904b6cca3Slucy wang - Sun Microsystems - Beijing China } 145004b6cca3Slucy wang - Sun Microsystems - Beijing China 145104b6cca3Slucy wang - Sun Microsystems - Beijing China static int 145204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dma_test(struct myri10ge_priv *mgp, int test_type) 145304b6cca3Slucy wang - Sun Microsystems - Beijing China { 145404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_cmd_t cmd; 145504b6cca3Slucy wang - Sun Microsystems - Beijing China int status; 145604b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t len; 145704b6cca3Slucy wang - Sun Microsystems - Beijing China void *dmabench; 145804b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_dma_stuff dmabench_dma; 145904b6cca3Slucy wang - Sun Microsystems - Beijing China char *test = " "; 146004b6cca3Slucy wang - Sun Microsystems - Beijing China 146104b6cca3Slucy wang - Sun Microsystems - Beijing China /* 146204b6cca3Slucy wang - Sun Microsystems - Beijing China * Run a small DMA test. 146304b6cca3Slucy wang - Sun Microsystems - Beijing China * The magic multipliers to the length tell the firmware 146404b6cca3Slucy wang - Sun Microsystems - Beijing China * tp do DMA read, write, or read+write tests. The 146504b6cca3Slucy wang - Sun Microsystems - Beijing China * results are returned in cmd.data0. The upper 16 146604b6cca3Slucy wang - Sun Microsystems - Beijing China * bits or the return is the number of transfers completed. 146704b6cca3Slucy wang - Sun Microsystems - Beijing China * The lower 16 bits is the time in 0.5us ticks that the 146804b6cca3Slucy wang - Sun Microsystems - Beijing China * transfers took to complete 146904b6cca3Slucy wang - Sun Microsystems - Beijing China */ 147004b6cca3Slucy wang - Sun Microsystems - Beijing China 147104b6cca3Slucy wang - Sun Microsystems - Beijing China len = mgp->tx_boundary; 147204b6cca3Slucy wang - Sun Microsystems - Beijing China 147304b6cca3Slucy wang - Sun Microsystems - Beijing China dmabench = myri10ge_dma_alloc(mgp->dip, len, 147404b6cca3Slucy wang - Sun Microsystems - Beijing China &myri10ge_rx_jumbo_dma_attr, &myri10ge_dev_access_attr, 147504b6cca3Slucy wang - Sun Microsystems - Beijing China DDI_DMA_STREAMING, DDI_DMA_RDWR|DDI_DMA_STREAMING, 147604b6cca3Slucy wang - Sun Microsystems - Beijing China &dmabench_dma, 1, DDI_DMA_DONTWAIT); 147704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->read_dma = mgp->write_dma = mgp->read_write_dma = 0; 147804b6cca3Slucy wang - Sun Microsystems - Beijing China if (dmabench == NULL) { 147904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s dma benchmark aborted\n", mgp->name); 148004b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENOMEM); 148104b6cca3Slucy wang - Sun Microsystems - Beijing China } 148204b6cca3Slucy wang - Sun Microsystems - Beijing China 148304b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = ntohl(dmabench_dma.low); 148404b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data1 = ntohl(dmabench_dma.high); 148504b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data2 = len * 0x10000; 148604b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, test_type, &cmd); 148704b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 148804b6cca3Slucy wang - Sun Microsystems - Beijing China test = "read"; 148904b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort; 149004b6cca3Slucy wang - Sun Microsystems - Beijing China } 149104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->read_dma = ((cmd.data0>>16) * len * 2) / (cmd.data0 & 0xffff); 149204b6cca3Slucy wang - Sun Microsystems - Beijing China 149304b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = ntohl(dmabench_dma.low); 149404b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data1 = ntohl(dmabench_dma.high); 149504b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data2 = len * 0x1; 149604b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, test_type, &cmd); 149704b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 149804b6cca3Slucy wang - Sun Microsystems - Beijing China test = "write"; 149904b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort; 150004b6cca3Slucy wang - Sun Microsystems - Beijing China } 150104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->write_dma = ((cmd.data0>>16) * len * 2) / (cmd.data0 & 0xffff); 150204b6cca3Slucy wang - Sun Microsystems - Beijing China 150304b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = ntohl(dmabench_dma.low); 150404b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data1 = ntohl(dmabench_dma.high); 150504b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data2 = len * 0x10001; 150604b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, test_type, &cmd); 150704b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 150804b6cca3Slucy wang - Sun Microsystems - Beijing China test = "read/write"; 150904b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort; 151004b6cca3Slucy wang - Sun Microsystems - Beijing China } 151104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->read_write_dma = ((cmd.data0>>16) * len * 2 * 2) / 151204b6cca3Slucy wang - Sun Microsystems - Beijing China (cmd.data0 & 0xffff); 151304b6cca3Slucy wang - Sun Microsystems - Beijing China 151404b6cca3Slucy wang - Sun Microsystems - Beijing China 151504b6cca3Slucy wang - Sun Microsystems - Beijing China abort: 151604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dma_free(&dmabench_dma); 151704b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0 && test_type != MXGEFW_CMD_UNALIGNED_TEST) 151804b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s %s dma benchmark failed\n", mgp->name, 151904b6cca3Slucy wang - Sun Microsystems - Beijing China test); 152004b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 152104b6cca3Slucy wang - Sun Microsystems - Beijing China } 152204b6cca3Slucy wang - Sun Microsystems - Beijing China 152304b6cca3Slucy wang - Sun Microsystems - Beijing China static int 152404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_reset(struct myri10ge_priv *mgp) 152504b6cca3Slucy wang - Sun Microsystems - Beijing China { 152604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_cmd_t cmd; 152704b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_nic_stat *ethstat; 152804b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_slice_state *ss; 152904b6cca3Slucy wang - Sun Microsystems - Beijing China int i, status; 153004b6cca3Slucy wang - Sun Microsystems - Beijing China size_t bytes; 153104b6cca3Slucy wang - Sun Microsystems - Beijing China 153204b6cca3Slucy wang - Sun Microsystems - Beijing China /* send a reset command to the card to see if it is alive */ 153304b6cca3Slucy wang - Sun Microsystems - Beijing China (void) memset(&cmd, 0, sizeof (cmd)); 153404b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_RESET, &cmd); 153504b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 153604b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: failed reset\n", mgp->name); 153704b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENXIO); 153804b6cca3Slucy wang - Sun Microsystems - Beijing China } 153904b6cca3Slucy wang - Sun Microsystems - Beijing China 154004b6cca3Slucy wang - Sun Microsystems - Beijing China /* Now exchange information about interrupts */ 154104b6cca3Slucy wang - Sun Microsystems - Beijing China 154204b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = mgp->max_intr_slots * sizeof (*mgp->ss[0].rx_done.entry); 154304b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = (uint32_t)bytes; 154404b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_SIZE, &cmd); 154504b6cca3Slucy wang - Sun Microsystems - Beijing China 154604b6cca3Slucy wang - Sun Microsystems - Beijing China /* 154704b6cca3Slucy wang - Sun Microsystems - Beijing China * Even though we already know how many slices are supported 154804b6cca3Slucy wang - Sun Microsystems - Beijing China * via myri10ge_probe_slices() MXGEFW_CMD_GET_MAX_RSS_QUEUES 154904b6cca3Slucy wang - Sun Microsystems - Beijing China * has magic side effects, and must be called after a reset. 155004b6cca3Slucy wang - Sun Microsystems - Beijing China * It must be called prior to calling any RSS related cmds, 155104b6cca3Slucy wang - Sun Microsystems - Beijing China * including assigning an interrupt queue for anything but 155204b6cca3Slucy wang - Sun Microsystems - Beijing China * slice 0. It must also be called *after* 155304b6cca3Slucy wang - Sun Microsystems - Beijing China * MXGEFW_CMD_SET_INTRQ_SIZE, since the intrq size is used by 155404b6cca3Slucy wang - Sun Microsystems - Beijing China * the firmware to compute offsets. 155504b6cca3Slucy wang - Sun Microsystems - Beijing China */ 155604b6cca3Slucy wang - Sun Microsystems - Beijing China 155704b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->num_slices > 1) { 155804b6cca3Slucy wang - Sun Microsystems - Beijing China 155904b6cca3Slucy wang - Sun Microsystems - Beijing China /* ask the maximum number of slices it supports */ 156004b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_RSS_QUEUES, 156104b6cca3Slucy wang - Sun Microsystems - Beijing China &cmd); 156204b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 156304b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 156404b6cca3Slucy wang - Sun Microsystems - Beijing China "%s: failed to get number of slices\n", 156504b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 156604b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 156704b6cca3Slucy wang - Sun Microsystems - Beijing China } 156804b6cca3Slucy wang - Sun Microsystems - Beijing China 156904b6cca3Slucy wang - Sun Microsystems - Beijing China /* 157004b6cca3Slucy wang - Sun Microsystems - Beijing China * MXGEFW_CMD_ENABLE_RSS_QUEUES must be called prior 157104b6cca3Slucy wang - Sun Microsystems - Beijing China * to setting up the interrupt queue DMA 157204b6cca3Slucy wang - Sun Microsystems - Beijing China */ 157304b6cca3Slucy wang - Sun Microsystems - Beijing China 157404b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = mgp->num_slices; 157504b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE | 157604b6cca3Slucy wang - Sun Microsystems - Beijing China MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES; 157704b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES, 157804b6cca3Slucy wang - Sun Microsystems - Beijing China &cmd); 157904b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 158004b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 158104b6cca3Slucy wang - Sun Microsystems - Beijing China "%s: failed to set number of slices\n", 158204b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 158304b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 158404b6cca3Slucy wang - Sun Microsystems - Beijing China } 158504b6cca3Slucy wang - Sun Microsystems - Beijing China } 158604b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 158704b6cca3Slucy wang - Sun Microsystems - Beijing China ss = &mgp->ss[i]; 158804b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = ntohl(ss->rx_done.dma.low); 158904b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data1 = ntohl(ss->rx_done.dma.high); 159004b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data2 = i; 159104b6cca3Slucy wang - Sun Microsystems - Beijing China status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_DMA, 159204b6cca3Slucy wang - Sun Microsystems - Beijing China &cmd); 159304b6cca3Slucy wang - Sun Microsystems - Beijing China }; 159404b6cca3Slucy wang - Sun Microsystems - Beijing China 159504b6cca3Slucy wang - Sun Microsystems - Beijing China status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd); 159604b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 159704b6cca3Slucy wang - Sun Microsystems - Beijing China ss = &mgp->ss[i]; 159804b6cca3Slucy wang - Sun Microsystems - Beijing China ss->irq_claim = (volatile unsigned int *) 159904b6cca3Slucy wang - Sun Microsystems - Beijing China (void *)(mgp->sram + cmd.data0 + 8 * i); 160004b6cca3Slucy wang - Sun Microsystems - Beijing China } 160104b6cca3Slucy wang - Sun Microsystems - Beijing China 160204b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->ddi_intr_type == DDI_INTR_TYPE_FIXED) { 160304b6cca3Slucy wang - Sun Microsystems - Beijing China status |= myri10ge_send_cmd(mgp, 160404b6cca3Slucy wang - Sun Microsystems - Beijing China MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, &cmd); 160504b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->irq_deassert = (uint32_t *)(void *)(mgp->sram + cmd.data0); 160604b6cca3Slucy wang - Sun Microsystems - Beijing China } 160704b6cca3Slucy wang - Sun Microsystems - Beijing China 160804b6cca3Slucy wang - Sun Microsystems - Beijing China status |= myri10ge_send_cmd(mgp, 160904b6cca3Slucy wang - Sun Microsystems - Beijing China MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, &cmd); 161004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->intr_coal_delay_ptr = (uint32_t *)(void *)(mgp->sram + cmd.data0); 161104b6cca3Slucy wang - Sun Microsystems - Beijing China 161204b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 161304b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: failed set interrupt parameters\n", 161404b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 161504b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 161604b6cca3Slucy wang - Sun Microsystems - Beijing China } 161704b6cca3Slucy wang - Sun Microsystems - Beijing China 161804b6cca3Slucy wang - Sun Microsystems - Beijing China *mgp->intr_coal_delay_ptr = htonl(mgp->intr_coal_delay); 161904b6cca3Slucy wang - Sun Microsystems - Beijing China (void) myri10ge_dma_test(mgp, MXGEFW_DMA_TEST); 162004b6cca3Slucy wang - Sun Microsystems - Beijing China 162104b6cca3Slucy wang - Sun Microsystems - Beijing China /* reset mcp/driver shared state back to 0 */ 162204b6cca3Slucy wang - Sun Microsystems - Beijing China 162304b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 162404b6cca3Slucy wang - Sun Microsystems - Beijing China ss = &mgp->ss[i]; 162504b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = mgp->max_intr_slots * 162604b6cca3Slucy wang - Sun Microsystems - Beijing China sizeof (*mgp->ss[0].rx_done.entry); 162704b6cca3Slucy wang - Sun Microsystems - Beijing China (void) memset(ss->rx_done.entry, 0, bytes); 162804b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.req = 0; 162904b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.done = 0; 163004b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.pkt_done = 0; 163104b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_big.cnt = 0; 163204b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_small.cnt = 0; 163304b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_done.idx = 0; 163404b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_done.cnt = 0; 163504b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_token = 0; 163604b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.watchdog_done = 0; 163704b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.watchdog_req = 0; 163804b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.active = 0; 163904b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.activate = 0; 164004b6cca3Slucy wang - Sun Microsystems - Beijing China } 164104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->watchdog_rx_pause = 0; 164204b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->ksp_stat != NULL) { 164304b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat = (struct myri10ge_nic_stat *)mgp->ksp_stat->ks_data; 164404b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->link_changes.value.ul = 0; 164504b6cca3Slucy wang - Sun Microsystems - Beijing China } 164604b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_m_unicst(mgp, mgp->mac_addr); 164704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_change_promisc(mgp, 0); 164804b6cca3Slucy wang - Sun Microsystems - Beijing China (void) myri10ge_change_pause(mgp, mgp->pause); 164904b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 165004b6cca3Slucy wang - Sun Microsystems - Beijing China } 165104b6cca3Slucy wang - Sun Microsystems - Beijing China 165204b6cca3Slucy wang - Sun Microsystems - Beijing China static int 165304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_init_toeplitz(struct myri10ge_priv *mgp) 165404b6cca3Slucy wang - Sun Microsystems - Beijing China { 165504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_cmd_t cmd; 165604b6cca3Slucy wang - Sun Microsystems - Beijing China int i, b, s, t, j; 165704b6cca3Slucy wang - Sun Microsystems - Beijing China int status; 165804b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t k[8]; 165904b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t tmp; 166004b6cca3Slucy wang - Sun Microsystems - Beijing China uint8_t *key; 166104b6cca3Slucy wang - Sun Microsystems - Beijing China 166204b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RSS_KEY_OFFSET, 166304b6cca3Slucy wang - Sun Microsystems - Beijing China &cmd); 166404b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 166504b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: failed to get rss key\n", 166604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 166704b6cca3Slucy wang - Sun Microsystems - Beijing China return (EIO); 166804b6cca3Slucy wang - Sun Microsystems - Beijing China } 166904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy32(mgp->rss_key, 167004b6cca3Slucy wang - Sun Microsystems - Beijing China (uint32_t *)(void*)((char *)mgp->sram + cmd.data0), 167104b6cca3Slucy wang - Sun Microsystems - Beijing China sizeof (mgp->rss_key)); 167204b6cca3Slucy wang - Sun Microsystems - Beijing China 167304b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->toeplitz_hash_table = kmem_alloc(sizeof (uint32_t) * 12 * 256, 167404b6cca3Slucy wang - Sun Microsystems - Beijing China KM_SLEEP); 167504b6cca3Slucy wang - Sun Microsystems - Beijing China key = (uint8_t *)mgp->rss_key; 167604b6cca3Slucy wang - Sun Microsystems - Beijing China t = 0; 167704b6cca3Slucy wang - Sun Microsystems - Beijing China for (b = 0; b < 12; b++) { 167804b6cca3Slucy wang - Sun Microsystems - Beijing China for (s = 0; s < 8; s++) { 167904b6cca3Slucy wang - Sun Microsystems - Beijing China /* Bits: b*8+s, ..., b*8+s+31 */ 168004b6cca3Slucy wang - Sun Microsystems - Beijing China k[s] = 0; 168104b6cca3Slucy wang - Sun Microsystems - Beijing China for (j = 0; j < 32; j++) { 168204b6cca3Slucy wang - Sun Microsystems - Beijing China int bit = b*8+s+j; 168304b6cca3Slucy wang - Sun Microsystems - Beijing China bit = 0x1 & (key[bit / 8] >> (7 -(bit & 0x7))); 168404b6cca3Slucy wang - Sun Microsystems - Beijing China k[s] |= bit << (31 - j); 168504b6cca3Slucy wang - Sun Microsystems - Beijing China } 168604b6cca3Slucy wang - Sun Microsystems - Beijing China } 168704b6cca3Slucy wang - Sun Microsystems - Beijing China 168804b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i <= 0xff; i++) { 168904b6cca3Slucy wang - Sun Microsystems - Beijing China tmp = 0; 169004b6cca3Slucy wang - Sun Microsystems - Beijing China if (i & (1 << 7)) { tmp ^= k[0]; } 169104b6cca3Slucy wang - Sun Microsystems - Beijing China if (i & (1 << 6)) { tmp ^= k[1]; } 169204b6cca3Slucy wang - Sun Microsystems - Beijing China if (i & (1 << 5)) { tmp ^= k[2]; } 169304b6cca3Slucy wang - Sun Microsystems - Beijing China if (i & (1 << 4)) { tmp ^= k[3]; } 169404b6cca3Slucy wang - Sun Microsystems - Beijing China if (i & (1 << 3)) { tmp ^= k[4]; } 169504b6cca3Slucy wang - Sun Microsystems - Beijing China if (i & (1 << 2)) { tmp ^= k[5]; } 169604b6cca3Slucy wang - Sun Microsystems - Beijing China if (i & (1 << 1)) { tmp ^= k[6]; } 169704b6cca3Slucy wang - Sun Microsystems - Beijing China if (i & (1 << 0)) { tmp ^= k[7]; } 169804b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->toeplitz_hash_table[t++] = tmp; 169904b6cca3Slucy wang - Sun Microsystems - Beijing China } 170004b6cca3Slucy wang - Sun Microsystems - Beijing China } 170104b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 170204b6cca3Slucy wang - Sun Microsystems - Beijing China } 170304b6cca3Slucy wang - Sun Microsystems - Beijing China 170404b6cca3Slucy wang - Sun Microsystems - Beijing China static inline struct myri10ge_slice_state * 170504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_toeplitz_send_hash(struct myri10ge_priv *mgp, struct ip *ip) 170604b6cca3Slucy wang - Sun Microsystems - Beijing China { 170704b6cca3Slucy wang - Sun Microsystems - Beijing China struct tcphdr *hdr; 170804b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t saddr, daddr; 170904b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t hash, slice; 171004b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t *table = mgp->toeplitz_hash_table; 171104b6cca3Slucy wang - Sun Microsystems - Beijing China uint16_t src, dst; 171204b6cca3Slucy wang - Sun Microsystems - Beijing China 171304b6cca3Slucy wang - Sun Microsystems - Beijing China /* 171404b6cca3Slucy wang - Sun Microsystems - Beijing China * Note hashing order is reversed from how it is done 171504b6cca3Slucy wang - Sun Microsystems - Beijing China * in the NIC, so as to generate the same hash value 171604b6cca3Slucy wang - Sun Microsystems - Beijing China * for the connection to try to keep connections CPU local 171704b6cca3Slucy wang - Sun Microsystems - Beijing China */ 171804b6cca3Slucy wang - Sun Microsystems - Beijing China 171904b6cca3Slucy wang - Sun Microsystems - Beijing China /* hash on IPv4 src/dst address */ 172004b6cca3Slucy wang - Sun Microsystems - Beijing China saddr = ntohl(ip->ip_src.s_addr); 172104b6cca3Slucy wang - Sun Microsystems - Beijing China daddr = ntohl(ip->ip_dst.s_addr); 172204b6cca3Slucy wang - Sun Microsystems - Beijing China hash = table[(256 * 0) + ((daddr >> 24) & 0xff)]; 172304b6cca3Slucy wang - Sun Microsystems - Beijing China hash ^= table[(256 * 1) + ((daddr >> 16) & 0xff)]; 172404b6cca3Slucy wang - Sun Microsystems - Beijing China hash ^= table[(256 * 2) + ((daddr >> 8) & 0xff)]; 172504b6cca3Slucy wang - Sun Microsystems - Beijing China hash ^= table[(256 * 3) + ((daddr) & 0xff)]; 172604b6cca3Slucy wang - Sun Microsystems - Beijing China hash ^= table[(256 * 4) + ((saddr >> 24) & 0xff)]; 172704b6cca3Slucy wang - Sun Microsystems - Beijing China hash ^= table[(256 * 5) + ((saddr >> 16) & 0xff)]; 172804b6cca3Slucy wang - Sun Microsystems - Beijing China hash ^= table[(256 * 6) + ((saddr >> 8) & 0xff)]; 172904b6cca3Slucy wang - Sun Microsystems - Beijing China hash ^= table[(256 * 7) + ((saddr) & 0xff)]; 173004b6cca3Slucy wang - Sun Microsystems - Beijing China /* hash on TCP port, if required */ 173104b6cca3Slucy wang - Sun Microsystems - Beijing China if ((myri10ge_rss_hash & MXGEFW_RSS_HASH_TYPE_TCP_IPV4) && 173204b6cca3Slucy wang - Sun Microsystems - Beijing China ip->ip_p == IPPROTO_TCP) { 173304b6cca3Slucy wang - Sun Microsystems - Beijing China hdr = (struct tcphdr *)(void *) 173404b6cca3Slucy wang - Sun Microsystems - Beijing China (((uint8_t *)ip) + (ip->ip_hl << 2)); 173504b6cca3Slucy wang - Sun Microsystems - Beijing China src = ntohs(hdr->th_sport); 173604b6cca3Slucy wang - Sun Microsystems - Beijing China dst = ntohs(hdr->th_dport); 173704b6cca3Slucy wang - Sun Microsystems - Beijing China 173804b6cca3Slucy wang - Sun Microsystems - Beijing China hash ^= table[(256 * 8) + ((dst >> 8) & 0xff)]; 173904b6cca3Slucy wang - Sun Microsystems - Beijing China hash ^= table[(256 * 9) + ((dst) & 0xff)]; 174004b6cca3Slucy wang - Sun Microsystems - Beijing China hash ^= table[(256 * 10) + ((src >> 8) & 0xff)]; 174104b6cca3Slucy wang - Sun Microsystems - Beijing China hash ^= table[(256 * 11) + ((src) & 0xff)]; 174204b6cca3Slucy wang - Sun Microsystems - Beijing China } 174304b6cca3Slucy wang - Sun Microsystems - Beijing China slice = (mgp->num_slices - 1) & hash; 174404b6cca3Slucy wang - Sun Microsystems - Beijing China return (&mgp->ss[slice]); 174504b6cca3Slucy wang - Sun Microsystems - Beijing China 174604b6cca3Slucy wang - Sun Microsystems - Beijing China } 174704b6cca3Slucy wang - Sun Microsystems - Beijing China 174804b6cca3Slucy wang - Sun Microsystems - Beijing China static inline struct myri10ge_slice_state * 174904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_simple_send_hash(struct myri10ge_priv *mgp, struct ip *ip) 175004b6cca3Slucy wang - Sun Microsystems - Beijing China { 175104b6cca3Slucy wang - Sun Microsystems - Beijing China struct tcphdr *hdr; 175204b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t slice, hash_val; 175304b6cca3Slucy wang - Sun Microsystems - Beijing China 175404b6cca3Slucy wang - Sun Microsystems - Beijing China 175504b6cca3Slucy wang - Sun Microsystems - Beijing China if (ip->ip_p != IPPROTO_TCP && ip->ip_p != IPPROTO_UDP) { 175604b6cca3Slucy wang - Sun Microsystems - Beijing China return (&mgp->ss[0]); 175704b6cca3Slucy wang - Sun Microsystems - Beijing China } 175804b6cca3Slucy wang - Sun Microsystems - Beijing China hdr = (struct tcphdr *)(void *)(((uint8_t *)ip) + (ip->ip_hl << 2)); 175904b6cca3Slucy wang - Sun Microsystems - Beijing China 176004b6cca3Slucy wang - Sun Microsystems - Beijing China /* 176104b6cca3Slucy wang - Sun Microsystems - Beijing China * Use the second byte of the *destination* address for 176204b6cca3Slucy wang - Sun Microsystems - Beijing China * MXGEFW_RSS_HASH_TYPE_SRC_PORT, so as to match NIC's hashing 176304b6cca3Slucy wang - Sun Microsystems - Beijing China */ 176404b6cca3Slucy wang - Sun Microsystems - Beijing China hash_val = ntohs(hdr->th_dport) & 0xff; 176504b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_rss_hash == MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT) 176604b6cca3Slucy wang - Sun Microsystems - Beijing China hash_val += ntohs(hdr->th_sport) & 0xff; 176704b6cca3Slucy wang - Sun Microsystems - Beijing China 176804b6cca3Slucy wang - Sun Microsystems - Beijing China slice = (mgp->num_slices - 1) & hash_val; 176904b6cca3Slucy wang - Sun Microsystems - Beijing China return (&mgp->ss[slice]); 177004b6cca3Slucy wang - Sun Microsystems - Beijing China } 177104b6cca3Slucy wang - Sun Microsystems - Beijing China 177204b6cca3Slucy wang - Sun Microsystems - Beijing China static inline struct myri10ge_slice_state * 177304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_send_hash(struct myri10ge_priv *mgp, mblk_t *mp) 177404b6cca3Slucy wang - Sun Microsystems - Beijing China { 177504b6cca3Slucy wang - Sun Microsystems - Beijing China unsigned int slice = 0; 177604b6cca3Slucy wang - Sun Microsystems - Beijing China struct ether_header *eh; 177704b6cca3Slucy wang - Sun Microsystems - Beijing China struct ether_vlan_header *vh; 177804b6cca3Slucy wang - Sun Microsystems - Beijing China struct ip *ip; 177904b6cca3Slucy wang - Sun Microsystems - Beijing China int ehl, ihl; 178004b6cca3Slucy wang - Sun Microsystems - Beijing China 178104b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->num_slices == 1) 178204b6cca3Slucy wang - Sun Microsystems - Beijing China return (&mgp->ss[0]); 178304b6cca3Slucy wang - Sun Microsystems - Beijing China 178404b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_tx_hash == 0) { 178504b6cca3Slucy wang - Sun Microsystems - Beijing China slice = CPU->cpu_id & (mgp->num_slices - 1); 178604b6cca3Slucy wang - Sun Microsystems - Beijing China return (&mgp->ss[slice]); 178704b6cca3Slucy wang - Sun Microsystems - Beijing China } 178804b6cca3Slucy wang - Sun Microsystems - Beijing China 178904b6cca3Slucy wang - Sun Microsystems - Beijing China /* 179004b6cca3Slucy wang - Sun Microsystems - Beijing China * ensure it is a TCP or UDP over IPv4 packet, and that the 179104b6cca3Slucy wang - Sun Microsystems - Beijing China * headers are in the 1st mblk. Otherwise, punt 179204b6cca3Slucy wang - Sun Microsystems - Beijing China */ 179304b6cca3Slucy wang - Sun Microsystems - Beijing China ehl = sizeof (*eh); 179404b6cca3Slucy wang - Sun Microsystems - Beijing China ihl = sizeof (*ip); 179504b6cca3Slucy wang - Sun Microsystems - Beijing China if ((MBLKL(mp)) < (ehl + ihl + 8)) 179604b6cca3Slucy wang - Sun Microsystems - Beijing China return (&mgp->ss[0]); 179704b6cca3Slucy wang - Sun Microsystems - Beijing China eh = (struct ether_header *)(void *)mp->b_rptr; 179804b6cca3Slucy wang - Sun Microsystems - Beijing China ip = (struct ip *)(void *)(eh + 1); 179904b6cca3Slucy wang - Sun Microsystems - Beijing China if (eh->ether_type != BE_16(ETHERTYPE_IP)) { 180004b6cca3Slucy wang - Sun Microsystems - Beijing China if (eh->ether_type != BE_16(ETHERTYPE_VLAN)) 180104b6cca3Slucy wang - Sun Microsystems - Beijing China return (&mgp->ss[0]); 180204b6cca3Slucy wang - Sun Microsystems - Beijing China vh = (struct ether_vlan_header *)(void *)mp->b_rptr; 180304b6cca3Slucy wang - Sun Microsystems - Beijing China if (vh->ether_type != BE_16(ETHERTYPE_IP)) 180404b6cca3Slucy wang - Sun Microsystems - Beijing China return (&mgp->ss[0]); 180504b6cca3Slucy wang - Sun Microsystems - Beijing China ehl += 4; 180604b6cca3Slucy wang - Sun Microsystems - Beijing China ip = (struct ip *)(void *)(vh + 1); 180704b6cca3Slucy wang - Sun Microsystems - Beijing China } 180804b6cca3Slucy wang - Sun Microsystems - Beijing China ihl = ip->ip_hl << 2; 180904b6cca3Slucy wang - Sun Microsystems - Beijing China if (MBLKL(mp) < (ehl + ihl + 8)) 181004b6cca3Slucy wang - Sun Microsystems - Beijing China return (&mgp->ss[0]); 181104b6cca3Slucy wang - Sun Microsystems - Beijing China switch (myri10ge_rss_hash) { 181204b6cca3Slucy wang - Sun Microsystems - Beijing China case MXGEFW_RSS_HASH_TYPE_IPV4: 181304b6cca3Slucy wang - Sun Microsystems - Beijing China /* fallthru */ 181404b6cca3Slucy wang - Sun Microsystems - Beijing China case MXGEFW_RSS_HASH_TYPE_TCP_IPV4: 181504b6cca3Slucy wang - Sun Microsystems - Beijing China /* fallthru */ 181604b6cca3Slucy wang - Sun Microsystems - Beijing China case (MXGEFW_RSS_HASH_TYPE_IPV4|MXGEFW_RSS_HASH_TYPE_TCP_IPV4): 181704b6cca3Slucy wang - Sun Microsystems - Beijing China return (myri10ge_toeplitz_send_hash(mgp, ip)); 181804b6cca3Slucy wang - Sun Microsystems - Beijing China case MXGEFW_RSS_HASH_TYPE_SRC_PORT: 181904b6cca3Slucy wang - Sun Microsystems - Beijing China /* fallthru */ 182004b6cca3Slucy wang - Sun Microsystems - Beijing China case MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT: 182104b6cca3Slucy wang - Sun Microsystems - Beijing China return (myri10ge_simple_send_hash(mgp, ip)); 182204b6cca3Slucy wang - Sun Microsystems - Beijing China default: 182304b6cca3Slucy wang - Sun Microsystems - Beijing China break; 182404b6cca3Slucy wang - Sun Microsystems - Beijing China } 182504b6cca3Slucy wang - Sun Microsystems - Beijing China return (&mgp->ss[0]); 182604b6cca3Slucy wang - Sun Microsystems - Beijing China } 182704b6cca3Slucy wang - Sun Microsystems - Beijing China 182804b6cca3Slucy wang - Sun Microsystems - Beijing China static int 182904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_setup_slice(struct myri10ge_slice_state *ss) 183004b6cca3Slucy wang - Sun Microsystems - Beijing China { 183104b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = ss->mgp; 183204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_cmd_t cmd; 183304b6cca3Slucy wang - Sun Microsystems - Beijing China int tx_ring_size, rx_ring_size; 183404b6cca3Slucy wang - Sun Microsystems - Beijing China int tx_ring_entries, rx_ring_entries; 183504b6cca3Slucy wang - Sun Microsystems - Beijing China int slice, status; 183604b6cca3Slucy wang - Sun Microsystems - Beijing China int allocated, idx; 183704b6cca3Slucy wang - Sun Microsystems - Beijing China size_t bytes; 183804b6cca3Slucy wang - Sun Microsystems - Beijing China 183904b6cca3Slucy wang - Sun Microsystems - Beijing China slice = ss - mgp->ss; 184004b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = slice; 184104b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_RING_SIZE, &cmd); 184204b6cca3Slucy wang - Sun Microsystems - Beijing China tx_ring_size = cmd.data0; 184304b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = slice; 184404b6cca3Slucy wang - Sun Microsystems - Beijing China status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd); 184504b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) 184604b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 184704b6cca3Slucy wang - Sun Microsystems - Beijing China rx_ring_size = cmd.data0; 184804b6cca3Slucy wang - Sun Microsystems - Beijing China 184904b6cca3Slucy wang - Sun Microsystems - Beijing China tx_ring_entries = tx_ring_size / sizeof (struct mcp_kreq_ether_send); 185004b6cca3Slucy wang - Sun Microsystems - Beijing China rx_ring_entries = rx_ring_size / sizeof (struct mcp_dma_addr); 185104b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.mask = tx_ring_entries - 1; 185204b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_small.mask = ss->rx_big.mask = rx_ring_entries - 1; 185304b6cca3Slucy wang - Sun Microsystems - Beijing China 185404b6cca3Slucy wang - Sun Microsystems - Beijing China /* get the lanai pointers to the send and receive rings */ 185504b6cca3Slucy wang - Sun Microsystems - Beijing China 185604b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = slice; 185704b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd); 185804b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.lanai = (mcp_kreq_ether_send_t *)(void *)(mgp->sram + cmd.data0); 185904b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->num_slices > 1) { 186004b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.go = (char *)mgp->sram + MXGEFW_ETH_SEND_GO + 64 * slice; 186104b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.stop = (char *)mgp->sram + MXGEFW_ETH_SEND_STOP + 186204b6cca3Slucy wang - Sun Microsystems - Beijing China 64 * slice; 186304b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 186404b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.go = NULL; 186504b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.stop = NULL; 186604b6cca3Slucy wang - Sun Microsystems - Beijing China } 186704b6cca3Slucy wang - Sun Microsystems - Beijing China 186804b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = slice; 186904b6cca3Slucy wang - Sun Microsystems - Beijing China status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SMALL_RX_OFFSET, &cmd); 187004b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_small.lanai = (mcp_kreq_ether_recv_t *) 187104b6cca3Slucy wang - Sun Microsystems - Beijing China (void *)(mgp->sram + cmd.data0); 187204b6cca3Slucy wang - Sun Microsystems - Beijing China 187304b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = slice; 187404b6cca3Slucy wang - Sun Microsystems - Beijing China status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_BIG_RX_OFFSET, &cmd); 187504b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_big.lanai = (mcp_kreq_ether_recv_t *)(void *) 187604b6cca3Slucy wang - Sun Microsystems - Beijing China (mgp->sram + cmd.data0); 187704b6cca3Slucy wang - Sun Microsystems - Beijing China 187804b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 187904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 188004b6cca3Slucy wang - Sun Microsystems - Beijing China "%s: failed to get ring sizes or locations\n", mgp->name); 188104b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 188204b6cca3Slucy wang - Sun Microsystems - Beijing China } 188304b6cca3Slucy wang - Sun Microsystems - Beijing China 188404b6cca3Slucy wang - Sun Microsystems - Beijing China status = ENOMEM; 188504b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = rx_ring_entries * sizeof (*ss->rx_small.shadow); 188604b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_small.shadow = kmem_zalloc(bytes, KM_SLEEP); 188704b6cca3Slucy wang - Sun Microsystems - Beijing China if (ss->rx_small.shadow == NULL) 188804b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort; 188904b6cca3Slucy wang - Sun Microsystems - Beijing China (void) memset(ss->rx_small.shadow, 0, bytes); 189004b6cca3Slucy wang - Sun Microsystems - Beijing China 189104b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = rx_ring_entries * sizeof (*ss->rx_big.shadow); 189204b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_big.shadow = kmem_zalloc(bytes, KM_SLEEP); 189304b6cca3Slucy wang - Sun Microsystems - Beijing China if (ss->rx_big.shadow == NULL) 189404b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_rx_small_shadow; 189504b6cca3Slucy wang - Sun Microsystems - Beijing China (void) memset(ss->rx_big.shadow, 0, bytes); 189604b6cca3Slucy wang - Sun Microsystems - Beijing China 189704b6cca3Slucy wang - Sun Microsystems - Beijing China /* allocate the host info rings */ 189804b6cca3Slucy wang - Sun Microsystems - Beijing China 189904b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = tx_ring_entries * sizeof (*ss->tx.info); 190004b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.info = kmem_zalloc(bytes, KM_SLEEP); 190104b6cca3Slucy wang - Sun Microsystems - Beijing China if (ss->tx.info == NULL) 190204b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_rx_big_shadow; 190304b6cca3Slucy wang - Sun Microsystems - Beijing China (void) memset(ss->tx.info, 0, bytes); 190404b6cca3Slucy wang - Sun Microsystems - Beijing China 190504b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = rx_ring_entries * sizeof (*ss->rx_small.info); 190604b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_small.info = kmem_zalloc(bytes, KM_SLEEP); 190704b6cca3Slucy wang - Sun Microsystems - Beijing China if (ss->rx_small.info == NULL) 190804b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_tx_info; 190904b6cca3Slucy wang - Sun Microsystems - Beijing China (void) memset(ss->rx_small.info, 0, bytes); 191004b6cca3Slucy wang - Sun Microsystems - Beijing China 191104b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = rx_ring_entries * sizeof (*ss->rx_big.info); 191204b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_big.info = kmem_zalloc(bytes, KM_SLEEP); 191304b6cca3Slucy wang - Sun Microsystems - Beijing China if (ss->rx_big.info == NULL) 191404b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_rx_small_info; 191504b6cca3Slucy wang - Sun Microsystems - Beijing China (void) memset(ss->rx_big.info, 0, bytes); 191604b6cca3Slucy wang - Sun Microsystems - Beijing China 191704b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.stall = ss->tx.sched = 0; 191804b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.stall_early = ss->tx.stall_late = 0; 191904b6cca3Slucy wang - Sun Microsystems - Beijing China 192004b6cca3Slucy wang - Sun Microsystems - Beijing China ss->jbufs_for_smalls = 1 + (1 + ss->rx_small.mask) / 192104b6cca3Slucy wang - Sun Microsystems - Beijing China (myri10ge_mtu / (myri10ge_small_bytes + MXGEFW_PAD)); 192204b6cca3Slucy wang - Sun Microsystems - Beijing China 192304b6cca3Slucy wang - Sun Microsystems - Beijing China allocated = myri10ge_add_jbufs(ss, 192404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_bigbufs_initial + ss->jbufs_for_smalls, 1); 192504b6cca3Slucy wang - Sun Microsystems - Beijing China if (allocated < ss->jbufs_for_smalls + myri10ge_bigbufs_initial) { 192604b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 192704b6cca3Slucy wang - Sun Microsystems - Beijing China "%s: Could not allocate enough receive buffers (%d/%d)\n", 192804b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, allocated, 192904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_bigbufs_initial + ss->jbufs_for_smalls); 193004b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_jumbos; 193104b6cca3Slucy wang - Sun Microsystems - Beijing China } 193204b6cca3Slucy wang - Sun Microsystems - Beijing China 193304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_carve_up_jbufs_into_small_ring(ss); 193404b6cca3Slucy wang - Sun Microsystems - Beijing China ss->j_rx_cnt = 0; 193504b6cca3Slucy wang - Sun Microsystems - Beijing China 193604b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&ss->jpool.mtx); 193704b6cca3Slucy wang - Sun Microsystems - Beijing China if (allocated < rx_ring_entries) 193804b6cca3Slucy wang - Sun Microsystems - Beijing China ss->jpool.low_water = allocated / 4; 193904b6cca3Slucy wang - Sun Microsystems - Beijing China else 194004b6cca3Slucy wang - Sun Microsystems - Beijing China ss->jpool.low_water = rx_ring_entries / 2; 194104b6cca3Slucy wang - Sun Microsystems - Beijing China 194204b6cca3Slucy wang - Sun Microsystems - Beijing China /* 194304b6cca3Slucy wang - Sun Microsystems - Beijing China * invalidate the big receive ring in case we do not 194404b6cca3Slucy wang - Sun Microsystems - Beijing China * allocate sufficient jumbos to fill it 194504b6cca3Slucy wang - Sun Microsystems - Beijing China */ 194604b6cca3Slucy wang - Sun Microsystems - Beijing China (void) memset(ss->rx_big.shadow, 1, 194704b6cca3Slucy wang - Sun Microsystems - Beijing China (ss->rx_big.mask + 1) * sizeof (ss->rx_big.shadow[0])); 194804b6cca3Slucy wang - Sun Microsystems - Beijing China for (idx = 7; idx <= ss->rx_big.mask; idx += 8) { 194904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_submit_8rx(&ss->rx_big.lanai[idx - 7], 195004b6cca3Slucy wang - Sun Microsystems - Beijing China &ss->rx_big.shadow[idx - 7]); 195104b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 195204b6cca3Slucy wang - Sun Microsystems - Beijing China } 195304b6cca3Slucy wang - Sun Microsystems - Beijing China 195404b6cca3Slucy wang - Sun Microsystems - Beijing China 195504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_restock_jumbos(ss); 195604b6cca3Slucy wang - Sun Microsystems - Beijing China 195704b6cca3Slucy wang - Sun Microsystems - Beijing China for (idx = 7; idx <= ss->rx_small.mask; idx += 8) { 195804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_submit_8rx(&ss->rx_small.lanai[idx - 7], 195904b6cca3Slucy wang - Sun Microsystems - Beijing China &ss->rx_small.shadow[idx - 7]); 196004b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 196104b6cca3Slucy wang - Sun Microsystems - Beijing China } 196204b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_small.cnt = ss->rx_small.mask + 1; 196304b6cca3Slucy wang - Sun Microsystems - Beijing China 196404b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&ss->jpool.mtx); 196504b6cca3Slucy wang - Sun Microsystems - Beijing China 196604b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_prepare_tx_ring(ss); 196704b6cca3Slucy wang - Sun Microsystems - Beijing China 196804b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) 196904b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_small_jbufs; 197004b6cca3Slucy wang - Sun Microsystems - Beijing China 197104b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = ntohl(ss->fw_stats_dma.low); 197204b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data1 = ntohl(ss->fw_stats_dma.high); 197304b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data2 = sizeof (mcp_irq_data_t); 197404b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data2 |= (slice << 16); 197504b6cca3Slucy wang - Sun Microsystems - Beijing China bzero(ss->fw_stats, sizeof (*ss->fw_stats)); 197604b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA_V2, &cmd); 197704b6cca3Slucy wang - Sun Microsystems - Beijing China if (status == ENOSYS) { 197804b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = ntohl(ss->fw_stats_dma.low) + 197904b6cca3Slucy wang - Sun Microsystems - Beijing China offsetof(mcp_irq_data_t, send_done_count); 198004b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data1 = ntohl(ss->fw_stats_dma.high); 198104b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, 198204b6cca3Slucy wang - Sun Microsystems - Beijing China MXGEFW_CMD_SET_STATS_DMA_OBSOLETE, &cmd); 198304b6cca3Slucy wang - Sun Microsystems - Beijing China } 198404b6cca3Slucy wang - Sun Microsystems - Beijing China if (status) { 198504b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: Couldn't set stats DMA\n", mgp->name); 198604b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_tx; 198704b6cca3Slucy wang - Sun Microsystems - Beijing China } 198804b6cca3Slucy wang - Sun Microsystems - Beijing China 198904b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 199004b6cca3Slucy wang - Sun Microsystems - Beijing China 199104b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_tx: 199204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_unprepare_tx_ring(ss); 199304b6cca3Slucy wang - Sun Microsystems - Beijing China 199404b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_small_jbufs: 199504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_release_small_jbufs(ss); 199604b6cca3Slucy wang - Sun Microsystems - Beijing China 199704b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_jumbos: 199804b6cca3Slucy wang - Sun Microsystems - Beijing China if (allocated != 0) { 199904b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&ss->jpool.mtx); 200004b6cca3Slucy wang - Sun Microsystems - Beijing China ss->jpool.low_water = 0; 200104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&ss->jpool.mtx); 200204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_unstock_jumbos(ss); 200304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_remove_jbufs(ss); 200404b6cca3Slucy wang - Sun Microsystems - Beijing China } 200504b6cca3Slucy wang - Sun Microsystems - Beijing China 200604b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = rx_ring_entries * sizeof (*ss->rx_big.info); 200704b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(ss->rx_big.info, bytes); 200804b6cca3Slucy wang - Sun Microsystems - Beijing China 200904b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_rx_small_info: 201004b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = rx_ring_entries * sizeof (*ss->rx_small.info); 201104b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(ss->rx_small.info, bytes); 201204b6cca3Slucy wang - Sun Microsystems - Beijing China 201304b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_tx_info: 201404b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = tx_ring_entries * sizeof (*ss->tx.info); 201504b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(ss->tx.info, bytes); 201604b6cca3Slucy wang - Sun Microsystems - Beijing China 201704b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_rx_big_shadow: 201804b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = rx_ring_entries * sizeof (*ss->rx_big.shadow); 201904b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(ss->rx_big.shadow, bytes); 202004b6cca3Slucy wang - Sun Microsystems - Beijing China 202104b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_rx_small_shadow: 202204b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = rx_ring_entries * sizeof (*ss->rx_small.shadow); 202304b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(ss->rx_small.shadow, bytes); 202404b6cca3Slucy wang - Sun Microsystems - Beijing China abort: 202504b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 202604b6cca3Slucy wang - Sun Microsystems - Beijing China 202704b6cca3Slucy wang - Sun Microsystems - Beijing China } 202804b6cca3Slucy wang - Sun Microsystems - Beijing China 202904b6cca3Slucy wang - Sun Microsystems - Beijing China static void 203004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_teardown_slice(struct myri10ge_slice_state *ss) 203104b6cca3Slucy wang - Sun Microsystems - Beijing China { 203204b6cca3Slucy wang - Sun Microsystems - Beijing China int tx_ring_entries, rx_ring_entries; 203304b6cca3Slucy wang - Sun Microsystems - Beijing China size_t bytes; 203404b6cca3Slucy wang - Sun Microsystems - Beijing China 203504b6cca3Slucy wang - Sun Microsystems - Beijing China /* ignore slices that have not been fully setup */ 203604b6cca3Slucy wang - Sun Microsystems - Beijing China if (ss->tx.cp == NULL) 203704b6cca3Slucy wang - Sun Microsystems - Beijing China return; 203804b6cca3Slucy wang - Sun Microsystems - Beijing China /* Free the TX copy buffers */ 203904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_unprepare_tx_ring(ss); 204004b6cca3Slucy wang - Sun Microsystems - Beijing China 204104b6cca3Slucy wang - Sun Microsystems - Beijing China /* stop passing returned buffers to firmware */ 204204b6cca3Slucy wang - Sun Microsystems - Beijing China 204304b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&ss->jpool.mtx); 204404b6cca3Slucy wang - Sun Microsystems - Beijing China ss->jpool.low_water = 0; 204504b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&ss->jpool.mtx); 204604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_release_small_jbufs(ss); 204704b6cca3Slucy wang - Sun Microsystems - Beijing China 204804b6cca3Slucy wang - Sun Microsystems - Beijing China /* Release the free jumbo frame pool */ 204904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_unstock_jumbos(ss); 205004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_remove_jbufs(ss); 205104b6cca3Slucy wang - Sun Microsystems - Beijing China 205204b6cca3Slucy wang - Sun Microsystems - Beijing China rx_ring_entries = ss->rx_big.mask + 1; 205304b6cca3Slucy wang - Sun Microsystems - Beijing China tx_ring_entries = ss->tx.mask + 1; 205404b6cca3Slucy wang - Sun Microsystems - Beijing China 205504b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = rx_ring_entries * sizeof (*ss->rx_big.info); 205604b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(ss->rx_big.info, bytes); 205704b6cca3Slucy wang - Sun Microsystems - Beijing China 205804b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = rx_ring_entries * sizeof (*ss->rx_small.info); 205904b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(ss->rx_small.info, bytes); 206004b6cca3Slucy wang - Sun Microsystems - Beijing China 206104b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = tx_ring_entries * sizeof (*ss->tx.info); 206204b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(ss->tx.info, bytes); 206304b6cca3Slucy wang - Sun Microsystems - Beijing China 206404b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = rx_ring_entries * sizeof (*ss->rx_big.shadow); 206504b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(ss->rx_big.shadow, bytes); 206604b6cca3Slucy wang - Sun Microsystems - Beijing China 206704b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = rx_ring_entries * sizeof (*ss->rx_small.shadow); 206804b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(ss->rx_small.shadow, bytes); 206904b6cca3Slucy wang - Sun Microsystems - Beijing China 207004b6cca3Slucy wang - Sun Microsystems - Beijing China } 207104b6cca3Slucy wang - Sun Microsystems - Beijing China static int 207204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_start_locked(struct myri10ge_priv *mgp) 207304b6cca3Slucy wang - Sun Microsystems - Beijing China { 207404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_cmd_t cmd; 207504b6cca3Slucy wang - Sun Microsystems - Beijing China int status, big_pow2, i; 207604b6cca3Slucy wang - Sun Microsystems - Beijing China volatile uint8_t *itable; 207704b6cca3Slucy wang - Sun Microsystems - Beijing China 207804b6cca3Slucy wang - Sun Microsystems - Beijing China status = DDI_SUCCESS; 207904b6cca3Slucy wang - Sun Microsystems - Beijing China /* Allocate DMA resources and receive buffers */ 208004b6cca3Slucy wang - Sun Microsystems - Beijing China 208104b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_reset(mgp); 208204b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 208304b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: failed reset\n", mgp->name); 208404b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 208504b6cca3Slucy wang - Sun Microsystems - Beijing China } 208604b6cca3Slucy wang - Sun Microsystems - Beijing China 208704b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->num_slices > 1) { 208804b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = mgp->num_slices; 208904b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data1 = 1; /* use MSI-X */ 209004b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES, 209104b6cca3Slucy wang - Sun Microsystems - Beijing China &cmd); 209204b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 209304b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 209404b6cca3Slucy wang - Sun Microsystems - Beijing China "%s: failed to set number of slices\n", 209504b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 209604b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_nothing; 209704b6cca3Slucy wang - Sun Microsystems - Beijing China } 209804b6cca3Slucy wang - Sun Microsystems - Beijing China /* setup the indirection table */ 209904b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = mgp->num_slices; 210004b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_RSS_TABLE_SIZE, 210104b6cca3Slucy wang - Sun Microsystems - Beijing China &cmd); 210204b6cca3Slucy wang - Sun Microsystems - Beijing China 210304b6cca3Slucy wang - Sun Microsystems - Beijing China status |= myri10ge_send_cmd(mgp, 210404b6cca3Slucy wang - Sun Microsystems - Beijing China MXGEFW_CMD_GET_RSS_TABLE_OFFSET, &cmd); 210504b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 210604b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 210704b6cca3Slucy wang - Sun Microsystems - Beijing China "%s: failed to setup rss tables\n", mgp->name); 210804b6cca3Slucy wang - Sun Microsystems - Beijing China } 210904b6cca3Slucy wang - Sun Microsystems - Beijing China 211004b6cca3Slucy wang - Sun Microsystems - Beijing China /* just enable an identity mapping */ 211104b6cca3Slucy wang - Sun Microsystems - Beijing China itable = mgp->sram + cmd.data0; 211204b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) 211304b6cca3Slucy wang - Sun Microsystems - Beijing China itable[i] = (uint8_t)i; 211404b6cca3Slucy wang - Sun Microsystems - Beijing China 211504b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_rss_hash & MYRI10GE_TOEPLITZ_HASH) { 211604b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_init_toeplitz(mgp); 211704b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 211804b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: failed to setup " 211904b6cca3Slucy wang - Sun Microsystems - Beijing China "toeplitz tx hash table", mgp->name); 212004b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_nothing; 212104b6cca3Slucy wang - Sun Microsystems - Beijing China } 212204b6cca3Slucy wang - Sun Microsystems - Beijing China } 212304b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = 1; 212404b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data1 = myri10ge_rss_hash; 212504b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_RSS_ENABLE, 212604b6cca3Slucy wang - Sun Microsystems - Beijing China &cmd); 212704b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 212804b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 212904b6cca3Slucy wang - Sun Microsystems - Beijing China "%s: failed to enable slices\n", mgp->name); 213004b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_toeplitz; 213104b6cca3Slucy wang - Sun Microsystems - Beijing China } 213204b6cca3Slucy wang - Sun Microsystems - Beijing China } 213304b6cca3Slucy wang - Sun Microsystems - Beijing China 213404b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 213504b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_setup_slice(&mgp->ss[i]); 213604b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) 213704b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_slices; 213804b6cca3Slucy wang - Sun Microsystems - Beijing China } 213904b6cca3Slucy wang - Sun Microsystems - Beijing China 214004b6cca3Slucy wang - Sun Microsystems - Beijing China /* 214104b6cca3Slucy wang - Sun Microsystems - Beijing China * Tell the MCP how many buffers he has, and to 214204b6cca3Slucy wang - Sun Microsystems - Beijing China * bring the ethernet interface up 214304b6cca3Slucy wang - Sun Microsystems - Beijing China * 214404b6cca3Slucy wang - Sun Microsystems - Beijing China * Firmware needs the big buff size as a power of 2. Lie and 214504b6cca3Slucy wang - Sun Microsystems - Beijing China * tell him the buffer is larger, because we only use 1 214604b6cca3Slucy wang - Sun Microsystems - Beijing China * buffer/pkt, and the mtu will prevent overruns 214704b6cca3Slucy wang - Sun Microsystems - Beijing China */ 214804b6cca3Slucy wang - Sun Microsystems - Beijing China big_pow2 = myri10ge_mtu + MXGEFW_PAD; 2149de710d24SJosef 'Jeff' Sipek while (!ISP2(big_pow2)) 215004b6cca3Slucy wang - Sun Microsystems - Beijing China big_pow2++; 215104b6cca3Slucy wang - Sun Microsystems - Beijing China 215204b6cca3Slucy wang - Sun Microsystems - Beijing China /* now give firmware buffers sizes, and MTU */ 215304b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = myri10ge_mtu; 215404b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_MTU, &cmd); 215504b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = myri10ge_small_bytes; 215604b6cca3Slucy wang - Sun Microsystems - Beijing China status |= 215704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_SMALL_BUFFER_SIZE, &cmd); 215804b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = big_pow2; 215904b6cca3Slucy wang - Sun Microsystems - Beijing China status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_BIG_BUFFER_SIZE, &cmd); 216004b6cca3Slucy wang - Sun Microsystems - Beijing China if (status) { 216104b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: Couldn't set buffer sizes\n", mgp->name); 216204b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_slices; 216304b6cca3Slucy wang - Sun Microsystems - Beijing China } 216404b6cca3Slucy wang - Sun Microsystems - Beijing China 216504b6cca3Slucy wang - Sun Microsystems - Beijing China 216604b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = 1; 216704b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_TSO_MODE, &cmd); 216804b6cca3Slucy wang - Sun Microsystems - Beijing China if (status) { 216904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: unable to setup TSO (%d)\n", 217004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, status); 217104b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 217204b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->features |= MYRI10GE_TSO; 217304b6cca3Slucy wang - Sun Microsystems - Beijing China } 217404b6cca3Slucy wang - Sun Microsystems - Beijing China 217504b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->link_state = -1; 217604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->rdma_tags_available = 15; 217704b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd); 217804b6cca3Slucy wang - Sun Microsystems - Beijing China if (status) { 217904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: unable to start ethernet\n", mgp->name); 218004b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_slices; 218104b6cca3Slucy wang - Sun Microsystems - Beijing China } 218204b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->running = MYRI10GE_ETH_RUNNING; 218304b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 218404b6cca3Slucy wang - Sun Microsystems - Beijing China 218504b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_slices: 218604b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) 218704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_teardown_slice(&mgp->ss[i]); 218804b6cca3Slucy wang - Sun Microsystems - Beijing China 218904b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->running = MYRI10GE_ETH_STOPPED; 219004b6cca3Slucy wang - Sun Microsystems - Beijing China 219104b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_toeplitz: 219204b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->toeplitz_hash_table != NULL) { 219304b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(mgp->toeplitz_hash_table, 219404b6cca3Slucy wang - Sun Microsystems - Beijing China sizeof (uint32_t) * 12 * 256); 219504b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->toeplitz_hash_table = NULL; 219604b6cca3Slucy wang - Sun Microsystems - Beijing China } 219704b6cca3Slucy wang - Sun Microsystems - Beijing China 219804b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_nothing: 219904b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 220004b6cca3Slucy wang - Sun Microsystems - Beijing China } 220104b6cca3Slucy wang - Sun Microsystems - Beijing China 220204b6cca3Slucy wang - Sun Microsystems - Beijing China static void 220304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_stop_locked(struct myri10ge_priv *mgp) 220404b6cca3Slucy wang - Sun Microsystems - Beijing China { 220504b6cca3Slucy wang - Sun Microsystems - Beijing China int status, old_down_cnt; 220604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_cmd_t cmd; 220704b6cca3Slucy wang - Sun Microsystems - Beijing China int wait_time = 10; 220804b6cca3Slucy wang - Sun Microsystems - Beijing China int i, polling; 220904b6cca3Slucy wang - Sun Microsystems - Beijing China 221004b6cca3Slucy wang - Sun Microsystems - Beijing China old_down_cnt = mgp->down_cnt; 221104b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 221204b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd); 221304b6cca3Slucy wang - Sun Microsystems - Beijing China if (status) { 221404b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: Couldn't bring down link\n", mgp->name); 221504b6cca3Slucy wang - Sun Microsystems - Beijing China } 221604b6cca3Slucy wang - Sun Microsystems - Beijing China 221704b6cca3Slucy wang - Sun Microsystems - Beijing China while (old_down_cnt == *((volatile int *)&mgp->down_cnt)) { 221804b6cca3Slucy wang - Sun Microsystems - Beijing China delay(1 * drv_usectohz(1000000)); 221904b6cca3Slucy wang - Sun Microsystems - Beijing China wait_time--; 222004b6cca3Slucy wang - Sun Microsystems - Beijing China if (wait_time == 0) 222104b6cca3Slucy wang - Sun Microsystems - Beijing China break; 222204b6cca3Slucy wang - Sun Microsystems - Beijing China } 222304b6cca3Slucy wang - Sun Microsystems - Beijing China again: 222404b6cca3Slucy wang - Sun Microsystems - Beijing China if (old_down_cnt == *((volatile int *)&mgp->down_cnt)) { 222504b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: didn't get down irq\n", mgp->name); 222604b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 222704b6cca3Slucy wang - Sun Microsystems - Beijing China /* 222804b6cca3Slucy wang - Sun Microsystems - Beijing China * take and release the rx lock to ensure 222904b6cca3Slucy wang - Sun Microsystems - Beijing China * that no interrupt thread is blocked 223004b6cca3Slucy wang - Sun Microsystems - Beijing China * elsewhere in the stack, preventing 223104b6cca3Slucy wang - Sun Microsystems - Beijing China * completion 223204b6cca3Slucy wang - Sun Microsystems - Beijing China */ 223304b6cca3Slucy wang - Sun Microsystems - Beijing China 223404b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&mgp->ss[i].rx_lock); 223504b6cca3Slucy wang - Sun Microsystems - Beijing China printf("%s: slice %d rx irq idle\n", 223604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, i); 223704b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->ss[i].rx_lock); 223804b6cca3Slucy wang - Sun Microsystems - Beijing China 223904b6cca3Slucy wang - Sun Microsystems - Beijing China /* verify that the poll handler is inactive */ 224004b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&mgp->ss->poll_lock); 224104b6cca3Slucy wang - Sun Microsystems - Beijing China polling = mgp->ss->rx_polling; 224204b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->ss->poll_lock); 224304b6cca3Slucy wang - Sun Microsystems - Beijing China if (polling) { 224404b6cca3Slucy wang - Sun Microsystems - Beijing China printf("%s: slice %d is polling\n", 224504b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, i); 224604b6cca3Slucy wang - Sun Microsystems - Beijing China delay(1 * drv_usectohz(1000000)); 224704b6cca3Slucy wang - Sun Microsystems - Beijing China goto again; 224804b6cca3Slucy wang - Sun Microsystems - Beijing China } 224904b6cca3Slucy wang - Sun Microsystems - Beijing China } 225004b6cca3Slucy wang - Sun Microsystems - Beijing China delay(1 * drv_usectohz(1000000)); 225104b6cca3Slucy wang - Sun Microsystems - Beijing China if (old_down_cnt == *((volatile int *)&mgp->down_cnt)) { 225204b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: Never got down irq\n", mgp->name); 225304b6cca3Slucy wang - Sun Microsystems - Beijing China } 225404b6cca3Slucy wang - Sun Microsystems - Beijing China } 225504b6cca3Slucy wang - Sun Microsystems - Beijing China 225604b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) 225704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_teardown_slice(&mgp->ss[i]); 225804b6cca3Slucy wang - Sun Microsystems - Beijing China 225904b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->toeplitz_hash_table != NULL) { 226004b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(mgp->toeplitz_hash_table, 226104b6cca3Slucy wang - Sun Microsystems - Beijing China sizeof (uint32_t) * 12 * 256); 226204b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->toeplitz_hash_table = NULL; 226304b6cca3Slucy wang - Sun Microsystems - Beijing China } 226404b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->running = MYRI10GE_ETH_STOPPED; 226504b6cca3Slucy wang - Sun Microsystems - Beijing China } 226604b6cca3Slucy wang - Sun Microsystems - Beijing China 226704b6cca3Slucy wang - Sun Microsystems - Beijing China static int 226804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_start(void *arg) 226904b6cca3Slucy wang - Sun Microsystems - Beijing China { 227004b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = arg; 227104b6cca3Slucy wang - Sun Microsystems - Beijing China int status; 227204b6cca3Slucy wang - Sun Microsystems - Beijing China 227304b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&mgp->intrlock); 227404b6cca3Slucy wang - Sun Microsystems - Beijing China 227504b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->running != MYRI10GE_ETH_STOPPED) { 227604b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->intrlock); 227704b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 227804b6cca3Slucy wang - Sun Microsystems - Beijing China } 227904b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_start_locked(mgp); 228004b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->intrlock); 228104b6cca3Slucy wang - Sun Microsystems - Beijing China 228204b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != DDI_SUCCESS) 228304b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 228404b6cca3Slucy wang - Sun Microsystems - Beijing China 228504b6cca3Slucy wang - Sun Microsystems - Beijing China /* start the watchdog timer */ 228604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->timer_id = timeout(myri10ge_watchdog, mgp, 228704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->timer_ticks); 228804b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 228904b6cca3Slucy wang - Sun Microsystems - Beijing China 229004b6cca3Slucy wang - Sun Microsystems - Beijing China } 229104b6cca3Slucy wang - Sun Microsystems - Beijing China 229204b6cca3Slucy wang - Sun Microsystems - Beijing China static void 229304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_stop(void *arg) 229404b6cca3Slucy wang - Sun Microsystems - Beijing China { 229504b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = arg; 229604b6cca3Slucy wang - Sun Microsystems - Beijing China 229704b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&mgp->intrlock); 229804b6cca3Slucy wang - Sun Microsystems - Beijing China /* if the device not running give up */ 229904b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->running != MYRI10GE_ETH_RUNNING) { 230004b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->intrlock); 230104b6cca3Slucy wang - Sun Microsystems - Beijing China return; 230204b6cca3Slucy wang - Sun Microsystems - Beijing China } 230304b6cca3Slucy wang - Sun Microsystems - Beijing China 230404b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->running = MYRI10GE_ETH_STOPPING; 230504b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->intrlock); 230604b6cca3Slucy wang - Sun Microsystems - Beijing China (void) untimeout(mgp->timer_id); 230704b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&mgp->intrlock); 230804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_stop_locked(mgp); 230904b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->intrlock); 231004b6cca3Slucy wang - Sun Microsystems - Beijing China 231104b6cca3Slucy wang - Sun Microsystems - Beijing China } 231204b6cca3Slucy wang - Sun Microsystems - Beijing China 231304b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void 231404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rx_csum(mblk_t *mp, struct myri10ge_rx_ring_stats *s, uint32_t csum) 231504b6cca3Slucy wang - Sun Microsystems - Beijing China { 231604b6cca3Slucy wang - Sun Microsystems - Beijing China struct ether_header *eh; 231704b6cca3Slucy wang - Sun Microsystems - Beijing China struct ip *ip; 231804b6cca3Slucy wang - Sun Microsystems - Beijing China struct ip6_hdr *ip6; 231904b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t start, stuff, end, partial, hdrlen; 232004b6cca3Slucy wang - Sun Microsystems - Beijing China 232104b6cca3Slucy wang - Sun Microsystems - Beijing China 232204b6cca3Slucy wang - Sun Microsystems - Beijing China csum = ntohs((uint16_t)csum); 232304b6cca3Slucy wang - Sun Microsystems - Beijing China eh = (struct ether_header *)(void *)mp->b_rptr; 232404b6cca3Slucy wang - Sun Microsystems - Beijing China hdrlen = sizeof (*eh); 232504b6cca3Slucy wang - Sun Microsystems - Beijing China if (eh->ether_dhost.ether_addr_octet[0] & 1) { 232604b6cca3Slucy wang - Sun Microsystems - Beijing China if (0 == (bcmp(eh->ether_dhost.ether_addr_octet, 232704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_broadcastaddr, sizeof (eh->ether_dhost)))) 232804b6cca3Slucy wang - Sun Microsystems - Beijing China s->brdcstrcv++; 232904b6cca3Slucy wang - Sun Microsystems - Beijing China else 233004b6cca3Slucy wang - Sun Microsystems - Beijing China s->multircv++; 233104b6cca3Slucy wang - Sun Microsystems - Beijing China } 233204b6cca3Slucy wang - Sun Microsystems - Beijing China 233304b6cca3Slucy wang - Sun Microsystems - Beijing China if (eh->ether_type == BE_16(ETHERTYPE_VLAN)) { 233404b6cca3Slucy wang - Sun Microsystems - Beijing China /* 233504b6cca3Slucy wang - Sun Microsystems - Beijing China * fix checksum by subtracting 4 bytes after what the 233604b6cca3Slucy wang - Sun Microsystems - Beijing China * firmware thought was the end of the ether hdr 233704b6cca3Slucy wang - Sun Microsystems - Beijing China */ 233804b6cca3Slucy wang - Sun Microsystems - Beijing China partial = *(uint32_t *) 233904b6cca3Slucy wang - Sun Microsystems - Beijing China (void *)(mp->b_rptr + ETHERNET_HEADER_SIZE); 234004b6cca3Slucy wang - Sun Microsystems - Beijing China csum += ~partial; 234104b6cca3Slucy wang - Sun Microsystems - Beijing China csum += (csum < ~partial); 234204b6cca3Slucy wang - Sun Microsystems - Beijing China csum = (csum >> 16) + (csum & 0xFFFF); 234304b6cca3Slucy wang - Sun Microsystems - Beijing China csum = (csum >> 16) + (csum & 0xFFFF); 234404b6cca3Slucy wang - Sun Microsystems - Beijing China hdrlen += VLAN_TAGSZ; 234504b6cca3Slucy wang - Sun Microsystems - Beijing China } 234604b6cca3Slucy wang - Sun Microsystems - Beijing China 234704b6cca3Slucy wang - Sun Microsystems - Beijing China if (eh->ether_type == BE_16(ETHERTYPE_IP)) { 234804b6cca3Slucy wang - Sun Microsystems - Beijing China ip = (struct ip *)(void *)(mp->b_rptr + hdrlen); 234904b6cca3Slucy wang - Sun Microsystems - Beijing China start = ip->ip_hl << 2; 235004b6cca3Slucy wang - Sun Microsystems - Beijing China 235104b6cca3Slucy wang - Sun Microsystems - Beijing China if (ip->ip_p == IPPROTO_TCP) 235204b6cca3Slucy wang - Sun Microsystems - Beijing China stuff = start + offsetof(struct tcphdr, th_sum); 235304b6cca3Slucy wang - Sun Microsystems - Beijing China else if (ip->ip_p == IPPROTO_UDP) 235404b6cca3Slucy wang - Sun Microsystems - Beijing China stuff = start + offsetof(struct udphdr, uh_sum); 235504b6cca3Slucy wang - Sun Microsystems - Beijing China else 235604b6cca3Slucy wang - Sun Microsystems - Beijing China return; 235704b6cca3Slucy wang - Sun Microsystems - Beijing China end = ntohs(ip->ip_len); 235804b6cca3Slucy wang - Sun Microsystems - Beijing China } else if (eh->ether_type == BE_16(ETHERTYPE_IPV6)) { 235904b6cca3Slucy wang - Sun Microsystems - Beijing China ip6 = (struct ip6_hdr *)(void *)(mp->b_rptr + hdrlen); 236004b6cca3Slucy wang - Sun Microsystems - Beijing China start = sizeof (*ip6); 236104b6cca3Slucy wang - Sun Microsystems - Beijing China if (ip6->ip6_nxt == IPPROTO_TCP) { 236204b6cca3Slucy wang - Sun Microsystems - Beijing China stuff = start + offsetof(struct tcphdr, th_sum); 236304b6cca3Slucy wang - Sun Microsystems - Beijing China } else if (ip6->ip6_nxt == IPPROTO_UDP) 236404b6cca3Slucy wang - Sun Microsystems - Beijing China stuff = start + offsetof(struct udphdr, uh_sum); 236504b6cca3Slucy wang - Sun Microsystems - Beijing China else 236604b6cca3Slucy wang - Sun Microsystems - Beijing China return; 236704b6cca3Slucy wang - Sun Microsystems - Beijing China end = start + ntohs(ip6->ip6_plen); 236804b6cca3Slucy wang - Sun Microsystems - Beijing China /* 236904b6cca3Slucy wang - Sun Microsystems - Beijing China * IPv6 headers do not contain a checksum, and hence 237004b6cca3Slucy wang - Sun Microsystems - Beijing China * do not checksum to zero, so they don't "fall out" 237104b6cca3Slucy wang - Sun Microsystems - Beijing China * of the partial checksum calculation like IPv4 237204b6cca3Slucy wang - Sun Microsystems - Beijing China * headers do. We need to fix the partial checksum by 237304b6cca3Slucy wang - Sun Microsystems - Beijing China * subtracting the checksum of the IPv6 header. 237404b6cca3Slucy wang - Sun Microsystems - Beijing China */ 237504b6cca3Slucy wang - Sun Microsystems - Beijing China 237604b6cca3Slucy wang - Sun Microsystems - Beijing China partial = myri10ge_csum_generic((uint16_t *)ip6, sizeof (*ip6)); 237704b6cca3Slucy wang - Sun Microsystems - Beijing China csum += ~partial; 237804b6cca3Slucy wang - Sun Microsystems - Beijing China csum += (csum < ~partial); 237904b6cca3Slucy wang - Sun Microsystems - Beijing China csum = (csum >> 16) + (csum & 0xFFFF); 238004b6cca3Slucy wang - Sun Microsystems - Beijing China csum = (csum >> 16) + (csum & 0xFFFF); 238104b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 238204b6cca3Slucy wang - Sun Microsystems - Beijing China return; 238304b6cca3Slucy wang - Sun Microsystems - Beijing China } 238404b6cca3Slucy wang - Sun Microsystems - Beijing China 238504b6cca3Slucy wang - Sun Microsystems - Beijing China if (MBLKL(mp) > hdrlen + end) { 238604b6cca3Slucy wang - Sun Microsystems - Beijing China /* padded frame, so hw csum may be invalid */ 238704b6cca3Slucy wang - Sun Microsystems - Beijing China return; 238804b6cca3Slucy wang - Sun Microsystems - Beijing China } 238904b6cca3Slucy wang - Sun Microsystems - Beijing China 23900dc2366fSVenugopal Iyer mac_hcksum_set(mp, start, stuff, end, csum, HCK_PARTIALCKSUM); 239104b6cca3Slucy wang - Sun Microsystems - Beijing China } 239204b6cca3Slucy wang - Sun Microsystems - Beijing China 239304b6cca3Slucy wang - Sun Microsystems - Beijing China static mblk_t * 239404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rx_done_small(struct myri10ge_slice_state *ss, uint32_t len, 239504b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t csum) 239604b6cca3Slucy wang - Sun Microsystems - Beijing China { 239704b6cca3Slucy wang - Sun Microsystems - Beijing China mblk_t *mp; 239804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rx_ring_t *rx; 239904b6cca3Slucy wang - Sun Microsystems - Beijing China int idx; 240004b6cca3Slucy wang - Sun Microsystems - Beijing China 240104b6cca3Slucy wang - Sun Microsystems - Beijing China rx = &ss->rx_small; 240204b6cca3Slucy wang - Sun Microsystems - Beijing China idx = rx->cnt & rx->mask; 240304b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_small.cnt++; 240404b6cca3Slucy wang - Sun Microsystems - Beijing China 240504b6cca3Slucy wang - Sun Microsystems - Beijing China /* allocate a new buffer to pass up the stack */ 240604b6cca3Slucy wang - Sun Microsystems - Beijing China mp = allocb(len + MXGEFW_PAD, 0); 240704b6cca3Slucy wang - Sun Microsystems - Beijing China if (mp == NULL) { 240804b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_ATOMIC_SLICE_STAT_INC(rx_small_nobuf); 240904b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort; 241004b6cca3Slucy wang - Sun Microsystems - Beijing China } 241104b6cca3Slucy wang - Sun Microsystems - Beijing China bcopy(ss->rx_small.info[idx].ptr, 241204b6cca3Slucy wang - Sun Microsystems - Beijing China (caddr_t)mp->b_wptr, len + MXGEFW_PAD); 241304b6cca3Slucy wang - Sun Microsystems - Beijing China mp->b_wptr += len + MXGEFW_PAD; 241404b6cca3Slucy wang - Sun Microsystems - Beijing China mp->b_rptr += MXGEFW_PAD; 241504b6cca3Slucy wang - Sun Microsystems - Beijing China 241604b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_stats.ibytes += len; 241704b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_stats.ipackets += 1; 241804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rx_csum(mp, &ss->rx_stats, csum); 241904b6cca3Slucy wang - Sun Microsystems - Beijing China 242004b6cca3Slucy wang - Sun Microsystems - Beijing China abort: 242104b6cca3Slucy wang - Sun Microsystems - Beijing China if ((idx & 7) == 7) { 242204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_submit_8rx(&rx->lanai[idx - 7], 242304b6cca3Slucy wang - Sun Microsystems - Beijing China &rx->shadow[idx - 7]); 242404b6cca3Slucy wang - Sun Microsystems - Beijing China } 242504b6cca3Slucy wang - Sun Microsystems - Beijing China 242604b6cca3Slucy wang - Sun Microsystems - Beijing China return (mp); 242704b6cca3Slucy wang - Sun Microsystems - Beijing China } 242804b6cca3Slucy wang - Sun Microsystems - Beijing China 242904b6cca3Slucy wang - Sun Microsystems - Beijing China 243004b6cca3Slucy wang - Sun Microsystems - Beijing China static mblk_t * 243104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rx_done_big(struct myri10ge_slice_state *ss, uint32_t len, 243204b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t csum) 243304b6cca3Slucy wang - Sun Microsystems - Beijing China { 243404b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_stuff *jpool; 243504b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_jpool_entry *j; 243604b6cca3Slucy wang - Sun Microsystems - Beijing China mblk_t *mp; 243704b6cca3Slucy wang - Sun Microsystems - Beijing China int idx, num_owned_by_mcp; 243804b6cca3Slucy wang - Sun Microsystems - Beijing China 243904b6cca3Slucy wang - Sun Microsystems - Beijing China jpool = &ss->jpool; 244004b6cca3Slucy wang - Sun Microsystems - Beijing China idx = ss->j_rx_cnt & ss->rx_big.mask; 244104b6cca3Slucy wang - Sun Microsystems - Beijing China j = ss->rx_big.info[idx].j; 244204b6cca3Slucy wang - Sun Microsystems - Beijing China 244304b6cca3Slucy wang - Sun Microsystems - Beijing China if (j == NULL) { 244404b6cca3Slucy wang - Sun Microsystems - Beijing China printf("%s: null j at idx=%d, rx_big.cnt = %d, j_rx_cnt=%d\n", 244504b6cca3Slucy wang - Sun Microsystems - Beijing China ss->mgp->name, idx, ss->rx_big.cnt, ss->j_rx_cnt); 244604b6cca3Slucy wang - Sun Microsystems - Beijing China return (NULL); 244704b6cca3Slucy wang - Sun Microsystems - Beijing China } 244804b6cca3Slucy wang - Sun Microsystems - Beijing China 244904b6cca3Slucy wang - Sun Microsystems - Beijing China 245004b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_big.info[idx].j = NULL; 245104b6cca3Slucy wang - Sun Microsystems - Beijing China ss->j_rx_cnt++; 245204b6cca3Slucy wang - Sun Microsystems - Beijing China 245304b6cca3Slucy wang - Sun Microsystems - Beijing China 245404b6cca3Slucy wang - Sun Microsystems - Beijing China /* 245504b6cca3Slucy wang - Sun Microsystems - Beijing China * Check to see if we are low on rx buffers. 245604b6cca3Slucy wang - Sun Microsystems - Beijing China * Note that we must leave at least 8 free so there are 245704b6cca3Slucy wang - Sun Microsystems - Beijing China * enough to free in a single 64-byte write. 245804b6cca3Slucy wang - Sun Microsystems - Beijing China */ 245904b6cca3Slucy wang - Sun Microsystems - Beijing China num_owned_by_mcp = ss->rx_big.cnt - ss->j_rx_cnt; 246004b6cca3Slucy wang - Sun Microsystems - Beijing China if (num_owned_by_mcp < jpool->low_water) { 246104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&jpool->mtx); 246204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_restock_jumbos(ss); 246304b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&jpool->mtx); 246404b6cca3Slucy wang - Sun Microsystems - Beijing China num_owned_by_mcp = ss->rx_big.cnt - ss->j_rx_cnt; 246504b6cca3Slucy wang - Sun Microsystems - Beijing China /* if we are still low, then we have to copy */ 246604b6cca3Slucy wang - Sun Microsystems - Beijing China if (num_owned_by_mcp < 16) { 246704b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_ATOMIC_SLICE_STAT_INC(rx_copy); 246804b6cca3Slucy wang - Sun Microsystems - Beijing China /* allocate a new buffer to pass up the stack */ 246904b6cca3Slucy wang - Sun Microsystems - Beijing China mp = allocb(len + MXGEFW_PAD, 0); 247004b6cca3Slucy wang - Sun Microsystems - Beijing China if (mp == NULL) { 247104b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort; 247204b6cca3Slucy wang - Sun Microsystems - Beijing China } 247304b6cca3Slucy wang - Sun Microsystems - Beijing China bcopy(j->buf, 247404b6cca3Slucy wang - Sun Microsystems - Beijing China (caddr_t)mp->b_wptr, len + MXGEFW_PAD); 247504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_jfree_rtn(j); 247604b6cca3Slucy wang - Sun Microsystems - Beijing China /* push buffer back to NIC */ 247704b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&jpool->mtx); 247804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_restock_jumbos(ss); 247904b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&jpool->mtx); 248004b6cca3Slucy wang - Sun Microsystems - Beijing China goto set_len; 248104b6cca3Slucy wang - Sun Microsystems - Beijing China } 248204b6cca3Slucy wang - Sun Microsystems - Beijing China } 248304b6cca3Slucy wang - Sun Microsystems - Beijing China 248404b6cca3Slucy wang - Sun Microsystems - Beijing China /* loan our buffer to the stack */ 248504b6cca3Slucy wang - Sun Microsystems - Beijing China mp = desballoc((unsigned char *)j->buf, myri10ge_mtu, 0, &j->free_func); 248604b6cca3Slucy wang - Sun Microsystems - Beijing China if (mp == NULL) { 248704b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort; 248804b6cca3Slucy wang - Sun Microsystems - Beijing China } 248904b6cca3Slucy wang - Sun Microsystems - Beijing China 249004b6cca3Slucy wang - Sun Microsystems - Beijing China set_len: 249104b6cca3Slucy wang - Sun Microsystems - Beijing China mp->b_rptr += MXGEFW_PAD; 249204b6cca3Slucy wang - Sun Microsystems - Beijing China mp->b_wptr = ((unsigned char *) mp->b_rptr + len); 249304b6cca3Slucy wang - Sun Microsystems - Beijing China 249404b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_stats.ibytes += len; 249504b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_stats.ipackets += 1; 249604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rx_csum(mp, &ss->rx_stats, csum); 249704b6cca3Slucy wang - Sun Microsystems - Beijing China 249804b6cca3Slucy wang - Sun Microsystems - Beijing China return (mp); 249904b6cca3Slucy wang - Sun Microsystems - Beijing China 250004b6cca3Slucy wang - Sun Microsystems - Beijing China abort: 250104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_jfree_rtn(j); 250204b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_ATOMIC_SLICE_STAT_INC(rx_big_nobuf); 250304b6cca3Slucy wang - Sun Microsystems - Beijing China return (NULL); 250404b6cca3Slucy wang - Sun Microsystems - Beijing China } 250504b6cca3Slucy wang - Sun Microsystems - Beijing China 250604b6cca3Slucy wang - Sun Microsystems - Beijing China /* 250704b6cca3Slucy wang - Sun Microsystems - Beijing China * Free all transmit buffers up until the specified index 250804b6cca3Slucy wang - Sun Microsystems - Beijing China */ 250904b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void 251004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_done(struct myri10ge_slice_state *ss, uint32_t mcp_index) 251104b6cca3Slucy wang - Sun Microsystems - Beijing China { 251204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_ring_t *tx; 251304b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_tx_dma_handle_head handles; 251404b6cca3Slucy wang - Sun Microsystems - Beijing China int idx; 251504b6cca3Slucy wang - Sun Microsystems - Beijing China int limit = 0; 251604b6cca3Slucy wang - Sun Microsystems - Beijing China 251704b6cca3Slucy wang - Sun Microsystems - Beijing China tx = &ss->tx; 251804b6cca3Slucy wang - Sun Microsystems - Beijing China handles.head = NULL; 251904b6cca3Slucy wang - Sun Microsystems - Beijing China handles.tail = NULL; 252004b6cca3Slucy wang - Sun Microsystems - Beijing China while (tx->pkt_done != (int)mcp_index) { 252104b6cca3Slucy wang - Sun Microsystems - Beijing China idx = tx->done & tx->mask; 252204b6cca3Slucy wang - Sun Microsystems - Beijing China 252304b6cca3Slucy wang - Sun Microsystems - Beijing China /* 252404b6cca3Slucy wang - Sun Microsystems - Beijing China * mblk & DMA handle attached only to first slot 252504b6cca3Slucy wang - Sun Microsystems - Beijing China * per buffer in the packet 252604b6cca3Slucy wang - Sun Microsystems - Beijing China */ 252704b6cca3Slucy wang - Sun Microsystems - Beijing China 252804b6cca3Slucy wang - Sun Microsystems - Beijing China if (tx->info[idx].m) { 252904b6cca3Slucy wang - Sun Microsystems - Beijing China (void) ddi_dma_unbind_handle(tx->info[idx].handle->h); 253004b6cca3Slucy wang - Sun Microsystems - Beijing China tx->info[idx].handle->next = handles.head; 253104b6cca3Slucy wang - Sun Microsystems - Beijing China handles.head = tx->info[idx].handle; 253204b6cca3Slucy wang - Sun Microsystems - Beijing China if (handles.tail == NULL) 253304b6cca3Slucy wang - Sun Microsystems - Beijing China handles.tail = tx->info[idx].handle; 253404b6cca3Slucy wang - Sun Microsystems - Beijing China freeb(tx->info[idx].m); 253504b6cca3Slucy wang - Sun Microsystems - Beijing China tx->info[idx].m = 0; 253604b6cca3Slucy wang - Sun Microsystems - Beijing China tx->info[idx].handle = 0; 253704b6cca3Slucy wang - Sun Microsystems - Beijing China } 253804b6cca3Slucy wang - Sun Microsystems - Beijing China if (tx->info[idx].ostat.opackets != 0) { 253904b6cca3Slucy wang - Sun Microsystems - Beijing China tx->stats.multixmt += tx->info[idx].ostat.multixmt; 254004b6cca3Slucy wang - Sun Microsystems - Beijing China tx->stats.brdcstxmt += tx->info[idx].ostat.brdcstxmt; 254104b6cca3Slucy wang - Sun Microsystems - Beijing China tx->stats.obytes += tx->info[idx].ostat.obytes; 254204b6cca3Slucy wang - Sun Microsystems - Beijing China tx->stats.opackets += tx->info[idx].ostat.opackets; 254304b6cca3Slucy wang - Sun Microsystems - Beijing China tx->info[idx].stat.un.all = 0; 254404b6cca3Slucy wang - Sun Microsystems - Beijing China tx->pkt_done++; 254504b6cca3Slucy wang - Sun Microsystems - Beijing China } 254604b6cca3Slucy wang - Sun Microsystems - Beijing China 254704b6cca3Slucy wang - Sun Microsystems - Beijing China tx->done++; 254804b6cca3Slucy wang - Sun Microsystems - Beijing China /* 254904b6cca3Slucy wang - Sun Microsystems - Beijing China * if we stalled the queue, wake it. But Wait until 255004b6cca3Slucy wang - Sun Microsystems - Beijing China * we have at least 1/2 our slots free. 255104b6cca3Slucy wang - Sun Microsystems - Beijing China */ 255204b6cca3Slucy wang - Sun Microsystems - Beijing China if ((tx->req - tx->done) < (tx->mask >> 1) && 255304b6cca3Slucy wang - Sun Microsystems - Beijing China tx->stall != tx->sched) { 255404b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&ss->tx.lock); 255504b6cca3Slucy wang - Sun Microsystems - Beijing China tx->sched = tx->stall; 255604b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&ss->tx.lock); 255704b6cca3Slucy wang - Sun Microsystems - Beijing China mac_tx_ring_update(ss->mgp->mh, tx->rh); 255804b6cca3Slucy wang - Sun Microsystems - Beijing China } 255904b6cca3Slucy wang - Sun Microsystems - Beijing China 256004b6cca3Slucy wang - Sun Microsystems - Beijing China /* limit potential for livelock */ 256104b6cca3Slucy wang - Sun Microsystems - Beijing China if (unlikely(++limit > 2 * tx->mask)) 256204b6cca3Slucy wang - Sun Microsystems - Beijing China break; 256304b6cca3Slucy wang - Sun Microsystems - Beijing China } 256404b6cca3Slucy wang - Sun Microsystems - Beijing China if (tx->req == tx->done && tx->stop != NULL) { 256504b6cca3Slucy wang - Sun Microsystems - Beijing China /* 256604b6cca3Slucy wang - Sun Microsystems - Beijing China * Nic has sent all pending requests, allow him 256704b6cca3Slucy wang - Sun Microsystems - Beijing China * to stop polling this queue 256804b6cca3Slucy wang - Sun Microsystems - Beijing China */ 256904b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&tx->lock); 257004b6cca3Slucy wang - Sun Microsystems - Beijing China if (tx->req == tx->done && tx->active) { 257104b6cca3Slucy wang - Sun Microsystems - Beijing China *(int *)(void *)tx->stop = 1; 257204b6cca3Slucy wang - Sun Microsystems - Beijing China tx->active = 0; 257304b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 257404b6cca3Slucy wang - Sun Microsystems - Beijing China } 257504b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&tx->lock); 257604b6cca3Slucy wang - Sun Microsystems - Beijing China } 257704b6cca3Slucy wang - Sun Microsystems - Beijing China if (handles.head != NULL) 257804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_free_tx_handles(tx, &handles); 257904b6cca3Slucy wang - Sun Microsystems - Beijing China } 258004b6cca3Slucy wang - Sun Microsystems - Beijing China 258104b6cca3Slucy wang - Sun Microsystems - Beijing China static void 258204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_mbl_init(struct myri10ge_mblk_list *mbl) 258304b6cca3Slucy wang - Sun Microsystems - Beijing China { 258404b6cca3Slucy wang - Sun Microsystems - Beijing China mbl->head = NULL; 258504b6cca3Slucy wang - Sun Microsystems - Beijing China mbl->tail = &mbl->head; 258604b6cca3Slucy wang - Sun Microsystems - Beijing China mbl->cnt = 0; 258704b6cca3Slucy wang - Sun Microsystems - Beijing China } 258804b6cca3Slucy wang - Sun Microsystems - Beijing China 258904b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/ 259004b6cca3Slucy wang - Sun Microsystems - Beijing China void 259104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_mbl_append(struct myri10ge_slice_state *ss, 259204b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_mblk_list *mbl, mblk_t *mp) 259304b6cca3Slucy wang - Sun Microsystems - Beijing China { 259404b6cca3Slucy wang - Sun Microsystems - Beijing China *(mbl->tail) = mp; 259504b6cca3Slucy wang - Sun Microsystems - Beijing China mbl->tail = &mp->b_next; 259604b6cca3Slucy wang - Sun Microsystems - Beijing China mp->b_next = NULL; 259704b6cca3Slucy wang - Sun Microsystems - Beijing China mbl->cnt++; 259804b6cca3Slucy wang - Sun Microsystems - Beijing China } 259904b6cca3Slucy wang - Sun Microsystems - Beijing China 260004b6cca3Slucy wang - Sun Microsystems - Beijing China 260104b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void 260204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, 260304b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_mblk_list *mbl, int limit, boolean_t *stop) 260404b6cca3Slucy wang - Sun Microsystems - Beijing China { 260504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rx_done_t *rx_done = &ss->rx_done; 260604b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = ss->mgp; 260704b6cca3Slucy wang - Sun Microsystems - Beijing China mblk_t *mp; 260804b6cca3Slucy wang - Sun Microsystems - Beijing China struct lro_entry *lro; 260904b6cca3Slucy wang - Sun Microsystems - Beijing China uint16_t length; 261004b6cca3Slucy wang - Sun Microsystems - Beijing China uint16_t checksum; 261104b6cca3Slucy wang - Sun Microsystems - Beijing China 261204b6cca3Slucy wang - Sun Microsystems - Beijing China 261304b6cca3Slucy wang - Sun Microsystems - Beijing China while (rx_done->entry[rx_done->idx].length != 0) { 261404b6cca3Slucy wang - Sun Microsystems - Beijing China if (unlikely (*stop)) { 261504b6cca3Slucy wang - Sun Microsystems - Beijing China break; 261604b6cca3Slucy wang - Sun Microsystems - Beijing China } 261704b6cca3Slucy wang - Sun Microsystems - Beijing China length = ntohs(rx_done->entry[rx_done->idx].length); 261804b6cca3Slucy wang - Sun Microsystems - Beijing China length &= (~MXGEFW_RSS_HASH_MASK); 261904b6cca3Slucy wang - Sun Microsystems - Beijing China 262004b6cca3Slucy wang - Sun Microsystems - Beijing China /* limit potential for livelock */ 262104b6cca3Slucy wang - Sun Microsystems - Beijing China limit -= length; 262204b6cca3Slucy wang - Sun Microsystems - Beijing China if (unlikely(limit < 0)) 262304b6cca3Slucy wang - Sun Microsystems - Beijing China break; 262404b6cca3Slucy wang - Sun Microsystems - Beijing China 262504b6cca3Slucy wang - Sun Microsystems - Beijing China rx_done->entry[rx_done->idx].length = 0; 262604b6cca3Slucy wang - Sun Microsystems - Beijing China checksum = ntohs(rx_done->entry[rx_done->idx].checksum); 262704b6cca3Slucy wang - Sun Microsystems - Beijing China if (length <= myri10ge_small_bytes) 262804b6cca3Slucy wang - Sun Microsystems - Beijing China mp = myri10ge_rx_done_small(ss, length, checksum); 262904b6cca3Slucy wang - Sun Microsystems - Beijing China else 263004b6cca3Slucy wang - Sun Microsystems - Beijing China mp = myri10ge_rx_done_big(ss, length, checksum); 263104b6cca3Slucy wang - Sun Microsystems - Beijing China if (mp != NULL) { 263204b6cca3Slucy wang - Sun Microsystems - Beijing China if (!myri10ge_lro || 263304b6cca3Slucy wang - Sun Microsystems - Beijing China 0 != myri10ge_lro_rx(ss, mp, checksum, mbl)) 263404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_mbl_append(ss, mbl, mp); 263504b6cca3Slucy wang - Sun Microsystems - Beijing China } 263604b6cca3Slucy wang - Sun Microsystems - Beijing China rx_done->cnt++; 263704b6cca3Slucy wang - Sun Microsystems - Beijing China rx_done->idx = rx_done->cnt & (mgp->max_intr_slots - 1); 263804b6cca3Slucy wang - Sun Microsystems - Beijing China } 263904b6cca3Slucy wang - Sun Microsystems - Beijing China while (ss->lro_active != NULL) { 264004b6cca3Slucy wang - Sun Microsystems - Beijing China lro = ss->lro_active; 264104b6cca3Slucy wang - Sun Microsystems - Beijing China ss->lro_active = lro->next; 264204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_lro_flush(ss, lro, mbl); 264304b6cca3Slucy wang - Sun Microsystems - Beijing China } 264404b6cca3Slucy wang - Sun Microsystems - Beijing China } 264504b6cca3Slucy wang - Sun Microsystems - Beijing China 264604b6cca3Slucy wang - Sun Microsystems - Beijing China static void 264704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_intr_rx(struct myri10ge_slice_state *ss) 264804b6cca3Slucy wang - Sun Microsystems - Beijing China { 264904b6cca3Slucy wang - Sun Microsystems - Beijing China uint64_t gen; 265004b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_mblk_list mbl; 265104b6cca3Slucy wang - Sun Microsystems - Beijing China 265204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_mbl_init(&mbl); 265304b6cca3Slucy wang - Sun Microsystems - Beijing China if (mutex_tryenter(&ss->rx_lock) == 0) 265404b6cca3Slucy wang - Sun Microsystems - Beijing China return; 265504b6cca3Slucy wang - Sun Microsystems - Beijing China gen = ss->rx_gen_num; 265604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_clean_rx_done(ss, &mbl, MYRI10GE_POLL_NULL, 265704b6cca3Slucy wang - Sun Microsystems - Beijing China &ss->rx_polling); 265804b6cca3Slucy wang - Sun Microsystems - Beijing China if (mbl.head != NULL) 265904b6cca3Slucy wang - Sun Microsystems - Beijing China mac_rx_ring(ss->mgp->mh, ss->rx_rh, mbl.head, gen); 266004b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&ss->rx_lock); 266104b6cca3Slucy wang - Sun Microsystems - Beijing China 266204b6cca3Slucy wang - Sun Microsystems - Beijing China } 266304b6cca3Slucy wang - Sun Microsystems - Beijing China 266404b6cca3Slucy wang - Sun Microsystems - Beijing China static mblk_t * 266504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_poll_rx(void *arg, int bytes) 266604b6cca3Slucy wang - Sun Microsystems - Beijing China { 266704b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_slice_state *ss = arg; 266804b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_mblk_list mbl; 266904b6cca3Slucy wang - Sun Microsystems - Beijing China boolean_t dummy = B_FALSE; 267004b6cca3Slucy wang - Sun Microsystems - Beijing China 267104b6cca3Slucy wang - Sun Microsystems - Beijing China if (bytes == 0) 267204b6cca3Slucy wang - Sun Microsystems - Beijing China return (NULL); 267304b6cca3Slucy wang - Sun Microsystems - Beijing China 267404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_mbl_init(&mbl); 267504b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&ss->rx_lock); 267604b6cca3Slucy wang - Sun Microsystems - Beijing China if (ss->rx_polling) 267704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_clean_rx_done(ss, &mbl, bytes, &dummy); 267804b6cca3Slucy wang - Sun Microsystems - Beijing China else 267904b6cca3Slucy wang - Sun Microsystems - Beijing China printf("%d: poll_rx: token=%d, polling=%d\n", (int)(ss - 268004b6cca3Slucy wang - Sun Microsystems - Beijing China ss->mgp->ss), ss->rx_token, ss->rx_polling); 268104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&ss->rx_lock); 268204b6cca3Slucy wang - Sun Microsystems - Beijing China return (mbl.head); 268304b6cca3Slucy wang - Sun Microsystems - Beijing China } 268404b6cca3Slucy wang - Sun Microsystems - Beijing China 268504b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/ 268604b6cca3Slucy wang - Sun Microsystems - Beijing China static uint_t 268704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_intr(caddr_t arg0, caddr_t arg1) 268804b6cca3Slucy wang - Sun Microsystems - Beijing China { 268904b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_slice_state *ss = 269004b6cca3Slucy wang - Sun Microsystems - Beijing China (struct myri10ge_slice_state *)(void *)arg0; 269104b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = ss->mgp; 269204b6cca3Slucy wang - Sun Microsystems - Beijing China mcp_irq_data_t *stats = ss->fw_stats; 269304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_ring_t *tx = &ss->tx; 269404b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t send_done_count; 269504b6cca3Slucy wang - Sun Microsystems - Beijing China uint8_t valid; 269604b6cca3Slucy wang - Sun Microsystems - Beijing China 269704b6cca3Slucy wang - Sun Microsystems - Beijing China 269804b6cca3Slucy wang - Sun Microsystems - Beijing China /* make sure the DMA has finished */ 269904b6cca3Slucy wang - Sun Microsystems - Beijing China if (!stats->valid) { 270004b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_INTR_UNCLAIMED); 270104b6cca3Slucy wang - Sun Microsystems - Beijing China } 270204b6cca3Slucy wang - Sun Microsystems - Beijing China valid = stats->valid; 270304b6cca3Slucy wang - Sun Microsystems - Beijing China 270404b6cca3Slucy wang - Sun Microsystems - Beijing China /* low bit indicates receives are present */ 270504b6cca3Slucy wang - Sun Microsystems - Beijing China if (valid & 1) 270604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_intr_rx(ss); 270704b6cca3Slucy wang - Sun Microsystems - Beijing China 270804b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->ddi_intr_type == DDI_INTR_TYPE_FIXED) { 270904b6cca3Slucy wang - Sun Microsystems - Beijing China /* lower legacy IRQ */ 271004b6cca3Slucy wang - Sun Microsystems - Beijing China *mgp->irq_deassert = 0; 271104b6cca3Slucy wang - Sun Microsystems - Beijing China if (!myri10ge_deassert_wait) 271204b6cca3Slucy wang - Sun Microsystems - Beijing China /* don't wait for conf. that irq is low */ 271304b6cca3Slucy wang - Sun Microsystems - Beijing China stats->valid = 0; 271404b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 271504b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 271604b6cca3Slucy wang - Sun Microsystems - Beijing China /* no need to wait for conf. that irq is low */ 271704b6cca3Slucy wang - Sun Microsystems - Beijing China stats->valid = 0; 271804b6cca3Slucy wang - Sun Microsystems - Beijing China } 271904b6cca3Slucy wang - Sun Microsystems - Beijing China 272004b6cca3Slucy wang - Sun Microsystems - Beijing China do { 272104b6cca3Slucy wang - Sun Microsystems - Beijing China /* check for transmit completes and receives */ 272204b6cca3Slucy wang - Sun Microsystems - Beijing China send_done_count = ntohl(stats->send_done_count); 272304b6cca3Slucy wang - Sun Microsystems - Beijing China if (send_done_count != tx->pkt_done) 272404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_done(ss, (int)send_done_count); 272504b6cca3Slucy wang - Sun Microsystems - Beijing China } while (*((volatile uint8_t *) &stats->valid)); 272604b6cca3Slucy wang - Sun Microsystems - Beijing China 272704b6cca3Slucy wang - Sun Microsystems - Beijing China if (stats->stats_updated) { 272804b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->link_state != stats->link_up || stats->link_down) { 272904b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->link_state = stats->link_up; 273004b6cca3Slucy wang - Sun Microsystems - Beijing China if (stats->link_down) { 273104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->down_cnt += stats->link_down; 273204b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->link_state = 0; 273304b6cca3Slucy wang - Sun Microsystems - Beijing China } 273404b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->link_state) { 273504b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_verbose) 273604b6cca3Slucy wang - Sun Microsystems - Beijing China printf("%s: link up\n", mgp->name); 273704b6cca3Slucy wang - Sun Microsystems - Beijing China mac_link_update(mgp->mh, LINK_STATE_UP); 273804b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 273904b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_verbose) 274004b6cca3Slucy wang - Sun Microsystems - Beijing China printf("%s: link down\n", mgp->name); 274104b6cca3Slucy wang - Sun Microsystems - Beijing China mac_link_update(mgp->mh, LINK_STATE_DOWN); 274204b6cca3Slucy wang - Sun Microsystems - Beijing China } 274304b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_NIC_STAT_INC(link_changes); 274404b6cca3Slucy wang - Sun Microsystems - Beijing China } 274504b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->rdma_tags_available != 274604b6cca3Slucy wang - Sun Microsystems - Beijing China ntohl(ss->fw_stats->rdma_tags_available)) { 274704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->rdma_tags_available = 274804b6cca3Slucy wang - Sun Microsystems - Beijing China ntohl(ss->fw_stats->rdma_tags_available); 274904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_NOTE, "%s: RDMA timed out! " 275004b6cca3Slucy wang - Sun Microsystems - Beijing China "%d tags left\n", mgp->name, 275104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->rdma_tags_available); 275204b6cca3Slucy wang - Sun Microsystems - Beijing China } 275304b6cca3Slucy wang - Sun Microsystems - Beijing China } 275404b6cca3Slucy wang - Sun Microsystems - Beijing China 275504b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 275604b6cca3Slucy wang - Sun Microsystems - Beijing China /* check to see if we have rx token to pass back */ 275704b6cca3Slucy wang - Sun Microsystems - Beijing China if (valid & 0x1) { 275804b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&ss->poll_lock); 275904b6cca3Slucy wang - Sun Microsystems - Beijing China if (ss->rx_polling) { 276004b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_token = 1; 276104b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 276204b6cca3Slucy wang - Sun Microsystems - Beijing China *ss->irq_claim = BE_32(3); 276304b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_token = 0; 276404b6cca3Slucy wang - Sun Microsystems - Beijing China } 276504b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&ss->poll_lock); 276604b6cca3Slucy wang - Sun Microsystems - Beijing China } 276704b6cca3Slucy wang - Sun Microsystems - Beijing China *(ss->irq_claim + 1) = BE_32(3); 276804b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_INTR_CLAIMED); 276904b6cca3Slucy wang - Sun Microsystems - Beijing China } 277004b6cca3Slucy wang - Sun Microsystems - Beijing China 277104b6cca3Slucy wang - Sun Microsystems - Beijing China /* 277204b6cca3Slucy wang - Sun Microsystems - Beijing China * Add or remove a multicast address. This is called with our 277304b6cca3Slucy wang - Sun Microsystems - Beijing China * macinfo's lock held by GLD, so we do not need to worry about 277404b6cca3Slucy wang - Sun Microsystems - Beijing China * our own locking here. 277504b6cca3Slucy wang - Sun Microsystems - Beijing China */ 277604b6cca3Slucy wang - Sun Microsystems - Beijing China static int 277704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_multicst(void *arg, boolean_t add, const uint8_t *multicastaddr) 277804b6cca3Slucy wang - Sun Microsystems - Beijing China { 277904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_cmd_t cmd; 278004b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = arg; 278104b6cca3Slucy wang - Sun Microsystems - Beijing China int status, join_leave; 278204b6cca3Slucy wang - Sun Microsystems - Beijing China 278304b6cca3Slucy wang - Sun Microsystems - Beijing China if (add) 278404b6cca3Slucy wang - Sun Microsystems - Beijing China join_leave = MXGEFW_JOIN_MULTICAST_GROUP; 278504b6cca3Slucy wang - Sun Microsystems - Beijing China else 278604b6cca3Slucy wang - Sun Microsystems - Beijing China join_leave = MXGEFW_LEAVE_MULTICAST_GROUP; 278704b6cca3Slucy wang - Sun Microsystems - Beijing China (void) memcpy(&cmd.data0, multicastaddr, 4); 278804b6cca3Slucy wang - Sun Microsystems - Beijing China (void) memcpy(&cmd.data1, multicastaddr + 4, 2); 278904b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = htonl(cmd.data0); 279004b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data1 = htonl(cmd.data1); 279104b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, join_leave, &cmd); 279204b6cca3Slucy wang - Sun Microsystems - Beijing China if (status == 0) 279304b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 279404b6cca3Slucy wang - Sun Microsystems - Beijing China 279504b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: failed to set multicast address\n", 279604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 279704b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 279804b6cca3Slucy wang - Sun Microsystems - Beijing China } 279904b6cca3Slucy wang - Sun Microsystems - Beijing China 280004b6cca3Slucy wang - Sun Microsystems - Beijing China 280104b6cca3Slucy wang - Sun Microsystems - Beijing China static int 280204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_promisc(void *arg, boolean_t on) 280304b6cca3Slucy wang - Sun Microsystems - Beijing China { 280404b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = arg; 280504b6cca3Slucy wang - Sun Microsystems - Beijing China 280604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_change_promisc(mgp, on); 280704b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 280804b6cca3Slucy wang - Sun Microsystems - Beijing China } 280904b6cca3Slucy wang - Sun Microsystems - Beijing China 281004b6cca3Slucy wang - Sun Microsystems - Beijing China /* 281104b6cca3Slucy wang - Sun Microsystems - Beijing China * copy an array of mcp_kreq_ether_send_t's to the mcp. Copy 281204b6cca3Slucy wang - Sun Microsystems - Beijing China * backwards one at a time and handle ring wraps 281304b6cca3Slucy wang - Sun Microsystems - Beijing China */ 281404b6cca3Slucy wang - Sun Microsystems - Beijing China 281504b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void 281604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_submit_req_backwards(myri10ge_tx_ring_t *tx, 281704b6cca3Slucy wang - Sun Microsystems - Beijing China mcp_kreq_ether_send_t *src, int cnt) 281804b6cca3Slucy wang - Sun Microsystems - Beijing China { 281904b6cca3Slucy wang - Sun Microsystems - Beijing China int idx, starting_slot; 282004b6cca3Slucy wang - Sun Microsystems - Beijing China starting_slot = tx->req; 282104b6cca3Slucy wang - Sun Microsystems - Beijing China while (cnt > 1) { 282204b6cca3Slucy wang - Sun Microsystems - Beijing China cnt--; 282304b6cca3Slucy wang - Sun Microsystems - Beijing China idx = (starting_slot + cnt) & tx->mask; 282404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy(&tx->lanai[idx], 282504b6cca3Slucy wang - Sun Microsystems - Beijing China &src[cnt], sizeof (*src)); 282604b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 282704b6cca3Slucy wang - Sun Microsystems - Beijing China } 282804b6cca3Slucy wang - Sun Microsystems - Beijing China } 282904b6cca3Slucy wang - Sun Microsystems - Beijing China 283004b6cca3Slucy wang - Sun Microsystems - Beijing China /* 283104b6cca3Slucy wang - Sun Microsystems - Beijing China * copy an array of mcp_kreq_ether_send_t's to the mcp. Copy 283204b6cca3Slucy wang - Sun Microsystems - Beijing China * at most 32 bytes at a time, so as to avoid involving the software 283304b6cca3Slucy wang - Sun Microsystems - Beijing China * pio handler in the nic. We re-write the first segment's flags 283404b6cca3Slucy wang - Sun Microsystems - Beijing China * to mark them valid only after writing the entire chain 283504b6cca3Slucy wang - Sun Microsystems - Beijing China */ 283604b6cca3Slucy wang - Sun Microsystems - Beijing China 283704b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void 283804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_submit_req(myri10ge_tx_ring_t *tx, mcp_kreq_ether_send_t *src, 283904b6cca3Slucy wang - Sun Microsystems - Beijing China int cnt) 284004b6cca3Slucy wang - Sun Microsystems - Beijing China { 284104b6cca3Slucy wang - Sun Microsystems - Beijing China int idx, i; 284204b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t *src_ints, *dst_ints; 284304b6cca3Slucy wang - Sun Microsystems - Beijing China mcp_kreq_ether_send_t *srcp, *dstp, *dst; 284404b6cca3Slucy wang - Sun Microsystems - Beijing China uint8_t last_flags; 284504b6cca3Slucy wang - Sun Microsystems - Beijing China 284604b6cca3Slucy wang - Sun Microsystems - Beijing China idx = tx->req & tx->mask; 284704b6cca3Slucy wang - Sun Microsystems - Beijing China 284804b6cca3Slucy wang - Sun Microsystems - Beijing China last_flags = src->flags; 284904b6cca3Slucy wang - Sun Microsystems - Beijing China src->flags = 0; 285004b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 285104b6cca3Slucy wang - Sun Microsystems - Beijing China dst = dstp = &tx->lanai[idx]; 285204b6cca3Slucy wang - Sun Microsystems - Beijing China srcp = src; 285304b6cca3Slucy wang - Sun Microsystems - Beijing China 285404b6cca3Slucy wang - Sun Microsystems - Beijing China if ((idx + cnt) < tx->mask) { 285504b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < (cnt - 1); i += 2) { 285604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy(dstp, srcp, 2 * sizeof (*src)); 285704b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); /* force write every 32 bytes */ 285804b6cca3Slucy wang - Sun Microsystems - Beijing China srcp += 2; 285904b6cca3Slucy wang - Sun Microsystems - Beijing China dstp += 2; 286004b6cca3Slucy wang - Sun Microsystems - Beijing China } 286104b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 286204b6cca3Slucy wang - Sun Microsystems - Beijing China /* 286304b6cca3Slucy wang - Sun Microsystems - Beijing China * submit all but the first request, and ensure 286404b6cca3Slucy wang - Sun Microsystems - Beijing China * that it is submitted below 286504b6cca3Slucy wang - Sun Microsystems - Beijing China */ 286604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_submit_req_backwards(tx, src, cnt); 286704b6cca3Slucy wang - Sun Microsystems - Beijing China i = 0; 286804b6cca3Slucy wang - Sun Microsystems - Beijing China } 286904b6cca3Slucy wang - Sun Microsystems - Beijing China if (i < cnt) { 287004b6cca3Slucy wang - Sun Microsystems - Beijing China /* submit the first request */ 287104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy(dstp, srcp, sizeof (*src)); 287204b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); /* barrier before setting valid flag */ 287304b6cca3Slucy wang - Sun Microsystems - Beijing China } 287404b6cca3Slucy wang - Sun Microsystems - Beijing China 287504b6cca3Slucy wang - Sun Microsystems - Beijing China /* re-write the last 32-bits with the valid flags */ 287604b6cca3Slucy wang - Sun Microsystems - Beijing China src->flags |= last_flags; 287704b6cca3Slucy wang - Sun Microsystems - Beijing China src_ints = (uint32_t *)src; 287804b6cca3Slucy wang - Sun Microsystems - Beijing China src_ints += 3; 287904b6cca3Slucy wang - Sun Microsystems - Beijing China dst_ints = (uint32_t *)dst; 288004b6cca3Slucy wang - Sun Microsystems - Beijing China dst_ints += 3; 288104b6cca3Slucy wang - Sun Microsystems - Beijing China *dst_ints = *src_ints; 288204b6cca3Slucy wang - Sun Microsystems - Beijing China tx->req += cnt; 288304b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 288404b6cca3Slucy wang - Sun Microsystems - Beijing China /* notify NIC to poll this tx ring */ 288504b6cca3Slucy wang - Sun Microsystems - Beijing China if (!tx->active && tx->go != NULL) { 288604b6cca3Slucy wang - Sun Microsystems - Beijing China *(int *)(void *)tx->go = 1; 288704b6cca3Slucy wang - Sun Microsystems - Beijing China tx->active = 1; 288804b6cca3Slucy wang - Sun Microsystems - Beijing China tx->activate++; 288904b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 289004b6cca3Slucy wang - Sun Microsystems - Beijing China } 289104b6cca3Slucy wang - Sun Microsystems - Beijing China } 289204b6cca3Slucy wang - Sun Microsystems - Beijing China 289304b6cca3Slucy wang - Sun Microsystems - Beijing China /* ARGSUSED */ 289404b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void 289504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_lso_info_get(mblk_t *mp, uint32_t *mss, uint32_t *flags) 289604b6cca3Slucy wang - Sun Microsystems - Beijing China { 289704b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t lso_flag; 28980dc2366fSVenugopal Iyer mac_lso_get(mp, mss, &lso_flag); 289904b6cca3Slucy wang - Sun Microsystems - Beijing China (*flags) |= lso_flag; 290004b6cca3Slucy wang - Sun Microsystems - Beijing China } 290104b6cca3Slucy wang - Sun Microsystems - Beijing China 290204b6cca3Slucy wang - Sun Microsystems - Beijing China 290304b6cca3Slucy wang - Sun Microsystems - Beijing China /* like pullupmsg, except preserve hcksum/LSO attributes */ 290404b6cca3Slucy wang - Sun Microsystems - Beijing China static int 290504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pullup(struct myri10ge_slice_state *ss, mblk_t *mp) 290604b6cca3Slucy wang - Sun Microsystems - Beijing China { 290704b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t start, stuff, tx_offload_flags, mss; 290804b6cca3Slucy wang - Sun Microsystems - Beijing China int ok; 290904b6cca3Slucy wang - Sun Microsystems - Beijing China 291004b6cca3Slucy wang - Sun Microsystems - Beijing China mss = 0; 29110dc2366fSVenugopal Iyer mac_hcksum_get(mp, &start, &stuff, NULL, NULL, &tx_offload_flags); 291204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_lso_info_get(mp, &mss, &tx_offload_flags); 291304b6cca3Slucy wang - Sun Microsystems - Beijing China 291404b6cca3Slucy wang - Sun Microsystems - Beijing China ok = pullupmsg(mp, -1); 291504b6cca3Slucy wang - Sun Microsystems - Beijing China if (!ok) { 291604b6cca3Slucy wang - Sun Microsystems - Beijing China printf("pullupmsg failed"); 291704b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 291804b6cca3Slucy wang - Sun Microsystems - Beijing China } 291904b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_pullup); 29200dc2366fSVenugopal Iyer mac_hcksum_set(mp, start, stuff, NULL, NULL, tx_offload_flags); 292104b6cca3Slucy wang - Sun Microsystems - Beijing China if (tx_offload_flags & HW_LSO) 292204b6cca3Slucy wang - Sun Microsystems - Beijing China DB_LSOMSS(mp) = (uint16_t)mss; 292304b6cca3Slucy wang - Sun Microsystems - Beijing China lso_info_set(mp, mss, tx_offload_flags); 292404b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 292504b6cca3Slucy wang - Sun Microsystems - Beijing China } 292604b6cca3Slucy wang - Sun Microsystems - Beijing China 292704b6cca3Slucy wang - Sun Microsystems - Beijing China static inline void 292804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_stat(struct myri10ge_tx_pkt_stats *s, struct ether_header *eh, 292904b6cca3Slucy wang - Sun Microsystems - Beijing China int opackets, int obytes) 293004b6cca3Slucy wang - Sun Microsystems - Beijing China { 293104b6cca3Slucy wang - Sun Microsystems - Beijing China s->un.all = 0; 293204b6cca3Slucy wang - Sun Microsystems - Beijing China if (eh->ether_dhost.ether_addr_octet[0] & 1) { 293304b6cca3Slucy wang - Sun Microsystems - Beijing China if (0 == (bcmp(eh->ether_dhost.ether_addr_octet, 293404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_broadcastaddr, sizeof (eh->ether_dhost)))) 293504b6cca3Slucy wang - Sun Microsystems - Beijing China s->un.s.brdcstxmt = 1; 293604b6cca3Slucy wang - Sun Microsystems - Beijing China else 293704b6cca3Slucy wang - Sun Microsystems - Beijing China s->un.s.multixmt = 1; 293804b6cca3Slucy wang - Sun Microsystems - Beijing China } 293904b6cca3Slucy wang - Sun Microsystems - Beijing China s->un.s.opackets = (uint16_t)opackets; 294004b6cca3Slucy wang - Sun Microsystems - Beijing China s->un.s.obytes = obytes; 294104b6cca3Slucy wang - Sun Microsystems - Beijing China } 294204b6cca3Slucy wang - Sun Microsystems - Beijing China 294304b6cca3Slucy wang - Sun Microsystems - Beijing China static int 294404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_copy(struct myri10ge_slice_state *ss, mblk_t *mp, 294504b6cca3Slucy wang - Sun Microsystems - Beijing China mcp_kreq_ether_send_t *req) 294604b6cca3Slucy wang - Sun Microsystems - Beijing China { 294704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_ring_t *tx = &ss->tx; 294804b6cca3Slucy wang - Sun Microsystems - Beijing China caddr_t ptr; 294904b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_tx_copybuf *cp; 295004b6cca3Slucy wang - Sun Microsystems - Beijing China mblk_t *bp; 295104b6cca3Slucy wang - Sun Microsystems - Beijing China int idx, mblen, avail; 295204b6cca3Slucy wang - Sun Microsystems - Beijing China uint16_t len; 295304b6cca3Slucy wang - Sun Microsystems - Beijing China 295404b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&tx->lock); 295504b6cca3Slucy wang - Sun Microsystems - Beijing China avail = tx->mask - (tx->req - tx->done); 295604b6cca3Slucy wang - Sun Microsystems - Beijing China if (avail <= 1) { 295704b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&tx->lock); 295804b6cca3Slucy wang - Sun Microsystems - Beijing China return (EBUSY); 295904b6cca3Slucy wang - Sun Microsystems - Beijing China } 296004b6cca3Slucy wang - Sun Microsystems - Beijing China idx = tx->req & tx->mask; 296104b6cca3Slucy wang - Sun Microsystems - Beijing China cp = &tx->cp[idx]; 296204b6cca3Slucy wang - Sun Microsystems - Beijing China ptr = cp->va; 296304b6cca3Slucy wang - Sun Microsystems - Beijing China for (len = 0, bp = mp; bp != NULL; bp = bp->b_cont) { 296404b6cca3Slucy wang - Sun Microsystems - Beijing China mblen = MBLKL(bp); 296504b6cca3Slucy wang - Sun Microsystems - Beijing China bcopy(bp->b_rptr, ptr, mblen); 296604b6cca3Slucy wang - Sun Microsystems - Beijing China ptr += mblen; 296704b6cca3Slucy wang - Sun Microsystems - Beijing China len += mblen; 296804b6cca3Slucy wang - Sun Microsystems - Beijing China } 296904b6cca3Slucy wang - Sun Microsystems - Beijing China /* ensure runts are padded to 60 bytes */ 297004b6cca3Slucy wang - Sun Microsystems - Beijing China if (len < 60) { 297104b6cca3Slucy wang - Sun Microsystems - Beijing China bzero(ptr, 64 - len); 297204b6cca3Slucy wang - Sun Microsystems - Beijing China len = 60; 297304b6cca3Slucy wang - Sun Microsystems - Beijing China } 297404b6cca3Slucy wang - Sun Microsystems - Beijing China req->addr_low = cp->dma.low; 297504b6cca3Slucy wang - Sun Microsystems - Beijing China req->addr_high = cp->dma.high; 297604b6cca3Slucy wang - Sun Microsystems - Beijing China req->length = htons(len); 297704b6cca3Slucy wang - Sun Microsystems - Beijing China req->pad = 0; 297804b6cca3Slucy wang - Sun Microsystems - Beijing China req->rdma_count = 1; 297904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_stat(&tx->info[idx].stat, 298004b6cca3Slucy wang - Sun Microsystems - Beijing China (struct ether_header *)(void *)cp->va, 1, len); 298104b6cca3Slucy wang - Sun Microsystems - Beijing China (void) ddi_dma_sync(cp->dma.handle, 0, len, DDI_DMA_SYNC_FORDEV); 298204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_submit_req(&ss->tx, req, 1); 298304b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&tx->lock); 298404b6cca3Slucy wang - Sun Microsystems - Beijing China freemsg(mp); 298504b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 298604b6cca3Slucy wang - Sun Microsystems - Beijing China } 298704b6cca3Slucy wang - Sun Microsystems - Beijing China 298804b6cca3Slucy wang - Sun Microsystems - Beijing China 298904b6cca3Slucy wang - Sun Microsystems - Beijing China static void 299004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_send_locked(myri10ge_tx_ring_t *tx, mcp_kreq_ether_send_t *req_list, 299104b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_tx_buffer_state *tx_info, 299204b6cca3Slucy wang - Sun Microsystems - Beijing China int count) 299304b6cca3Slucy wang - Sun Microsystems - Beijing China { 299404b6cca3Slucy wang - Sun Microsystems - Beijing China int i, idx; 299504b6cca3Slucy wang - Sun Microsystems - Beijing China 299604b6cca3Slucy wang - Sun Microsystems - Beijing China idx = 0; /* gcc -Wuninitialized */ 299704b6cca3Slucy wang - Sun Microsystems - Beijing China /* store unmapping and bp info for tx irq handler */ 299804b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < count; i++) { 299904b6cca3Slucy wang - Sun Microsystems - Beijing China idx = (tx->req + i) & tx->mask; 300004b6cca3Slucy wang - Sun Microsystems - Beijing China tx->info[idx].m = tx_info[i].m; 300104b6cca3Slucy wang - Sun Microsystems - Beijing China tx->info[idx].handle = tx_info[i].handle; 300204b6cca3Slucy wang - Sun Microsystems - Beijing China } 300304b6cca3Slucy wang - Sun Microsystems - Beijing China tx->info[idx].stat.un.all = tx_info[0].stat.un.all; 300404b6cca3Slucy wang - Sun Microsystems - Beijing China 300504b6cca3Slucy wang - Sun Microsystems - Beijing China /* submit the frame to the nic */ 300604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_submit_req(tx, req_list, count); 300704b6cca3Slucy wang - Sun Microsystems - Beijing China 300804b6cca3Slucy wang - Sun Microsystems - Beijing China 300904b6cca3Slucy wang - Sun Microsystems - Beijing China } 301004b6cca3Slucy wang - Sun Microsystems - Beijing China 301104b6cca3Slucy wang - Sun Microsystems - Beijing China 301204b6cca3Slucy wang - Sun Microsystems - Beijing China 301304b6cca3Slucy wang - Sun Microsystems - Beijing China static void 301404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_copydata(mblk_t *mp, int off, int len, caddr_t buf) 301504b6cca3Slucy wang - Sun Microsystems - Beijing China { 301604b6cca3Slucy wang - Sun Microsystems - Beijing China mblk_t *bp; 301704b6cca3Slucy wang - Sun Microsystems - Beijing China int seglen; 301804b6cca3Slucy wang - Sun Microsystems - Beijing China uint_t count; 301904b6cca3Slucy wang - Sun Microsystems - Beijing China 302004b6cca3Slucy wang - Sun Microsystems - Beijing China bp = mp; 302104b6cca3Slucy wang - Sun Microsystems - Beijing China 302204b6cca3Slucy wang - Sun Microsystems - Beijing China while (off > 0) { 302304b6cca3Slucy wang - Sun Microsystems - Beijing China seglen = MBLKL(bp); 302404b6cca3Slucy wang - Sun Microsystems - Beijing China if (off < seglen) 302504b6cca3Slucy wang - Sun Microsystems - Beijing China break; 302604b6cca3Slucy wang - Sun Microsystems - Beijing China off -= seglen; 302704b6cca3Slucy wang - Sun Microsystems - Beijing China bp = bp->b_cont; 302804b6cca3Slucy wang - Sun Microsystems - Beijing China } 302904b6cca3Slucy wang - Sun Microsystems - Beijing China while (len > 0) { 303004b6cca3Slucy wang - Sun Microsystems - Beijing China seglen = MBLKL(bp); 303104b6cca3Slucy wang - Sun Microsystems - Beijing China count = min(seglen - off, len); 303204b6cca3Slucy wang - Sun Microsystems - Beijing China bcopy(bp->b_rptr + off, buf, count); 303304b6cca3Slucy wang - Sun Microsystems - Beijing China len -= count; 303404b6cca3Slucy wang - Sun Microsystems - Beijing China buf += count; 303504b6cca3Slucy wang - Sun Microsystems - Beijing China off = 0; 303604b6cca3Slucy wang - Sun Microsystems - Beijing China bp = bp->b_cont; 303704b6cca3Slucy wang - Sun Microsystems - Beijing China } 303804b6cca3Slucy wang - Sun Microsystems - Beijing China } 303904b6cca3Slucy wang - Sun Microsystems - Beijing China 304004b6cca3Slucy wang - Sun Microsystems - Beijing China static int 304104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_ether_parse_header(mblk_t *mp) 304204b6cca3Slucy wang - Sun Microsystems - Beijing China { 304304b6cca3Slucy wang - Sun Microsystems - Beijing China struct ether_header eh_copy; 304404b6cca3Slucy wang - Sun Microsystems - Beijing China struct ether_header *eh; 304504b6cca3Slucy wang - Sun Microsystems - Beijing China int eth_hdr_len, seglen; 304604b6cca3Slucy wang - Sun Microsystems - Beijing China 304704b6cca3Slucy wang - Sun Microsystems - Beijing China seglen = MBLKL(mp); 304804b6cca3Slucy wang - Sun Microsystems - Beijing China eth_hdr_len = sizeof (*eh); 304904b6cca3Slucy wang - Sun Microsystems - Beijing China if (seglen < eth_hdr_len) { 305004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_copydata(mp, 0, eth_hdr_len, (caddr_t)&eh_copy); 305104b6cca3Slucy wang - Sun Microsystems - Beijing China eh = &eh_copy; 305204b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 305304b6cca3Slucy wang - Sun Microsystems - Beijing China eh = (struct ether_header *)(void *)mp->b_rptr; 305404b6cca3Slucy wang - Sun Microsystems - Beijing China } 305504b6cca3Slucy wang - Sun Microsystems - Beijing China if (eh->ether_type == BE_16(ETHERTYPE_VLAN)) { 305604b6cca3Slucy wang - Sun Microsystems - Beijing China eth_hdr_len += 4; 305704b6cca3Slucy wang - Sun Microsystems - Beijing China } 305804b6cca3Slucy wang - Sun Microsystems - Beijing China 305904b6cca3Slucy wang - Sun Microsystems - Beijing China return (eth_hdr_len); 306004b6cca3Slucy wang - Sun Microsystems - Beijing China } 306104b6cca3Slucy wang - Sun Microsystems - Beijing China 306204b6cca3Slucy wang - Sun Microsystems - Beijing China static int 306304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_lso_parse_header(mblk_t *mp, int off) 306404b6cca3Slucy wang - Sun Microsystems - Beijing China { 306504b6cca3Slucy wang - Sun Microsystems - Beijing China char buf[128]; 306691e18787Slucy wang - Sun Microsystems - Beijing China int seglen, sum_off; 306704b6cca3Slucy wang - Sun Microsystems - Beijing China struct ip *ip; 306804b6cca3Slucy wang - Sun Microsystems - Beijing China struct tcphdr *tcp; 306904b6cca3Slucy wang - Sun Microsystems - Beijing China 307004b6cca3Slucy wang - Sun Microsystems - Beijing China seglen = MBLKL(mp); 307104b6cca3Slucy wang - Sun Microsystems - Beijing China if (seglen < off + sizeof (*ip)) { 307204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_copydata(mp, off, sizeof (*ip), buf); 307304b6cca3Slucy wang - Sun Microsystems - Beijing China ip = (struct ip *)(void *)buf; 307404b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 307504b6cca3Slucy wang - Sun Microsystems - Beijing China ip = (struct ip *)(void *)(mp->b_rptr + off); 307604b6cca3Slucy wang - Sun Microsystems - Beijing China } 307704b6cca3Slucy wang - Sun Microsystems - Beijing China if (seglen < off + (ip->ip_hl << 2) + sizeof (*tcp)) { 307804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_copydata(mp, off, 307904b6cca3Slucy wang - Sun Microsystems - Beijing China (ip->ip_hl << 2) + sizeof (*tcp), buf); 308004b6cca3Slucy wang - Sun Microsystems - Beijing China ip = (struct ip *)(void *)buf; 308104b6cca3Slucy wang - Sun Microsystems - Beijing China } 308204b6cca3Slucy wang - Sun Microsystems - Beijing China tcp = (struct tcphdr *)(void *)((char *)ip + (ip->ip_hl << 2)); 308391e18787Slucy wang - Sun Microsystems - Beijing China 308491e18787Slucy wang - Sun Microsystems - Beijing China /* 308591e18787Slucy wang - Sun Microsystems - Beijing China * NIC expects ip_sum to be zero. Recent changes to 308691e18787Slucy wang - Sun Microsystems - Beijing China * OpenSolaris leave the correct ip checksum there, rather 308791e18787Slucy wang - Sun Microsystems - Beijing China * than the required zero, so we need to zero it. Otherwise, 308891e18787Slucy wang - Sun Microsystems - Beijing China * the NIC will produce bad checksums when sending LSO packets. 308991e18787Slucy wang - Sun Microsystems - Beijing China */ 309091e18787Slucy wang - Sun Microsystems - Beijing China if (ip->ip_sum != 0) { 309191e18787Slucy wang - Sun Microsystems - Beijing China if (((char *)ip) != buf) { 309291e18787Slucy wang - Sun Microsystems - Beijing China /* ip points into mblk, so just zero it */ 309391e18787Slucy wang - Sun Microsystems - Beijing China ip->ip_sum = 0; 309491e18787Slucy wang - Sun Microsystems - Beijing China } else { 309591e18787Slucy wang - Sun Microsystems - Beijing China /* 309691e18787Slucy wang - Sun Microsystems - Beijing China * ip points into a copy, so walk the chain 309791e18787Slucy wang - Sun Microsystems - Beijing China * to find the ip_csum, then zero it 309891e18787Slucy wang - Sun Microsystems - Beijing China */ 309991e18787Slucy wang - Sun Microsystems - Beijing China sum_off = off + _PTRDIFF(&ip->ip_sum, buf); 310091e18787Slucy wang - Sun Microsystems - Beijing China while (sum_off > (int)(MBLKL(mp) - 1)) { 310191e18787Slucy wang - Sun Microsystems - Beijing China sum_off -= MBLKL(mp); 310291e18787Slucy wang - Sun Microsystems - Beijing China mp = mp->b_cont; 310391e18787Slucy wang - Sun Microsystems - Beijing China } 310491e18787Slucy wang - Sun Microsystems - Beijing China mp->b_rptr[sum_off] = 0; 310591e18787Slucy wang - Sun Microsystems - Beijing China sum_off++; 310691e18787Slucy wang - Sun Microsystems - Beijing China while (sum_off > MBLKL(mp) - 1) { 310791e18787Slucy wang - Sun Microsystems - Beijing China sum_off -= MBLKL(mp); 310891e18787Slucy wang - Sun Microsystems - Beijing China mp = mp->b_cont; 310991e18787Slucy wang - Sun Microsystems - Beijing China } 311091e18787Slucy wang - Sun Microsystems - Beijing China mp->b_rptr[sum_off] = 0; 311191e18787Slucy wang - Sun Microsystems - Beijing China } 311291e18787Slucy wang - Sun Microsystems - Beijing China } 311304b6cca3Slucy wang - Sun Microsystems - Beijing China return (off + ((ip->ip_hl + tcp->th_off) << 2)); 311404b6cca3Slucy wang - Sun Microsystems - Beijing China } 311504b6cca3Slucy wang - Sun Microsystems - Beijing China 311604b6cca3Slucy wang - Sun Microsystems - Beijing China static int 311704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_tso_copy(struct myri10ge_slice_state *ss, mblk_t *mp, 311804b6cca3Slucy wang - Sun Microsystems - Beijing China mcp_kreq_ether_send_t *req_list, int hdr_size, int pkt_size, 311904b6cca3Slucy wang - Sun Microsystems - Beijing China uint16_t mss, uint8_t cksum_offset) 312004b6cca3Slucy wang - Sun Microsystems - Beijing China { 312104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_ring_t *tx = &ss->tx; 312204b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = ss->mgp; 312304b6cca3Slucy wang - Sun Microsystems - Beijing China mblk_t *bp; 312404b6cca3Slucy wang - Sun Microsystems - Beijing China mcp_kreq_ether_send_t *req; 312504b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_tx_copybuf *cp; 312604b6cca3Slucy wang - Sun Microsystems - Beijing China caddr_t rptr, ptr; 312704b6cca3Slucy wang - Sun Microsystems - Beijing China int mblen, count, cum_len, mss_resid, tx_req, pkt_size_tmp; 312804b6cca3Slucy wang - Sun Microsystems - Beijing China int resid, avail, idx, hdr_size_tmp, tx_boundary; 312904b6cca3Slucy wang - Sun Microsystems - Beijing China int rdma_count; 313004b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t seglen, len, boundary, low, high_swapped; 313104b6cca3Slucy wang - Sun Microsystems - Beijing China uint16_t pseudo_hdr_offset = htons(mss); 313204b6cca3Slucy wang - Sun Microsystems - Beijing China uint8_t flags; 313304b6cca3Slucy wang - Sun Microsystems - Beijing China 313404b6cca3Slucy wang - Sun Microsystems - Beijing China tx_boundary = mgp->tx_boundary; 313504b6cca3Slucy wang - Sun Microsystems - Beijing China hdr_size_tmp = hdr_size; 313604b6cca3Slucy wang - Sun Microsystems - Beijing China resid = tx_boundary; 313704b6cca3Slucy wang - Sun Microsystems - Beijing China count = 1; 313804b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&tx->lock); 313904b6cca3Slucy wang - Sun Microsystems - Beijing China 314004b6cca3Slucy wang - Sun Microsystems - Beijing China /* check to see if the slots are really there */ 314104b6cca3Slucy wang - Sun Microsystems - Beijing China avail = tx->mask - (tx->req - tx->done); 314204b6cca3Slucy wang - Sun Microsystems - Beijing China if (unlikely(avail <= MYRI10GE_MAX_SEND_DESC_TSO)) { 31431a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&tx->stall); 314404b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&tx->lock); 314504b6cca3Slucy wang - Sun Microsystems - Beijing China return (EBUSY); 314604b6cca3Slucy wang - Sun Microsystems - Beijing China } 314704b6cca3Slucy wang - Sun Microsystems - Beijing China 314804b6cca3Slucy wang - Sun Microsystems - Beijing China /* copy */ 314904b6cca3Slucy wang - Sun Microsystems - Beijing China cum_len = -hdr_size; 315004b6cca3Slucy wang - Sun Microsystems - Beijing China count = 0; 315104b6cca3Slucy wang - Sun Microsystems - Beijing China req = req_list; 315204b6cca3Slucy wang - Sun Microsystems - Beijing China idx = tx->mask & tx->req; 315304b6cca3Slucy wang - Sun Microsystems - Beijing China cp = &tx->cp[idx]; 315404b6cca3Slucy wang - Sun Microsystems - Beijing China low = ntohl(cp->dma.low); 315504b6cca3Slucy wang - Sun Microsystems - Beijing China ptr = cp->va; 315604b6cca3Slucy wang - Sun Microsystems - Beijing China cp->len = 0; 315704b6cca3Slucy wang - Sun Microsystems - Beijing China if (mss) { 315804b6cca3Slucy wang - Sun Microsystems - Beijing China int payload = pkt_size - hdr_size; 315904b6cca3Slucy wang - Sun Microsystems - Beijing China uint16_t opackets = (payload / mss) + ((payload % mss) != 0); 316004b6cca3Slucy wang - Sun Microsystems - Beijing China tx->info[idx].ostat.opackets = opackets; 316104b6cca3Slucy wang - Sun Microsystems - Beijing China tx->info[idx].ostat.obytes = (opackets - 1) * hdr_size 316204b6cca3Slucy wang - Sun Microsystems - Beijing China + pkt_size; 316304b6cca3Slucy wang - Sun Microsystems - Beijing China } 316404b6cca3Slucy wang - Sun Microsystems - Beijing China hdr_size_tmp = hdr_size; 316504b6cca3Slucy wang - Sun Microsystems - Beijing China mss_resid = mss; 316604b6cca3Slucy wang - Sun Microsystems - Beijing China flags = (MXGEFW_FLAGS_TSO_HDR | MXGEFW_FLAGS_FIRST); 316704b6cca3Slucy wang - Sun Microsystems - Beijing China tx_req = tx->req; 316804b6cca3Slucy wang - Sun Microsystems - Beijing China for (bp = mp; bp != NULL; bp = bp->b_cont) { 316904b6cca3Slucy wang - Sun Microsystems - Beijing China mblen = MBLKL(bp); 317004b6cca3Slucy wang - Sun Microsystems - Beijing China rptr = (caddr_t)bp->b_rptr; 317104b6cca3Slucy wang - Sun Microsystems - Beijing China len = min(hdr_size_tmp, mblen); 317204b6cca3Slucy wang - Sun Microsystems - Beijing China if (len) { 317304b6cca3Slucy wang - Sun Microsystems - Beijing China bcopy(rptr, ptr, len); 317404b6cca3Slucy wang - Sun Microsystems - Beijing China rptr += len; 317504b6cca3Slucy wang - Sun Microsystems - Beijing China ptr += len; 317604b6cca3Slucy wang - Sun Microsystems - Beijing China resid -= len; 317704b6cca3Slucy wang - Sun Microsystems - Beijing China mblen -= len; 317804b6cca3Slucy wang - Sun Microsystems - Beijing China hdr_size_tmp -= len; 317904b6cca3Slucy wang - Sun Microsystems - Beijing China cp->len += len; 318004b6cca3Slucy wang - Sun Microsystems - Beijing China if (hdr_size_tmp) 318104b6cca3Slucy wang - Sun Microsystems - Beijing China continue; 318204b6cca3Slucy wang - Sun Microsystems - Beijing China if (resid < mss) { 318304b6cca3Slucy wang - Sun Microsystems - Beijing China tx_req++; 318404b6cca3Slucy wang - Sun Microsystems - Beijing China idx = tx->mask & tx_req; 318504b6cca3Slucy wang - Sun Microsystems - Beijing China cp = &tx->cp[idx]; 318604b6cca3Slucy wang - Sun Microsystems - Beijing China low = ntohl(cp->dma.low); 318704b6cca3Slucy wang - Sun Microsystems - Beijing China ptr = cp->va; 318804b6cca3Slucy wang - Sun Microsystems - Beijing China resid = tx_boundary; 318904b6cca3Slucy wang - Sun Microsystems - Beijing China } 319004b6cca3Slucy wang - Sun Microsystems - Beijing China } 319104b6cca3Slucy wang - Sun Microsystems - Beijing China while (mblen) { 319204b6cca3Slucy wang - Sun Microsystems - Beijing China len = min(mss_resid, mblen); 319304b6cca3Slucy wang - Sun Microsystems - Beijing China bcopy(rptr, ptr, len); 319404b6cca3Slucy wang - Sun Microsystems - Beijing China mss_resid -= len; 319504b6cca3Slucy wang - Sun Microsystems - Beijing China resid -= len; 319604b6cca3Slucy wang - Sun Microsystems - Beijing China mblen -= len; 319704b6cca3Slucy wang - Sun Microsystems - Beijing China rptr += len; 319804b6cca3Slucy wang - Sun Microsystems - Beijing China ptr += len; 319904b6cca3Slucy wang - Sun Microsystems - Beijing China cp->len += len; 320004b6cca3Slucy wang - Sun Microsystems - Beijing China if (mss_resid == 0) { 320104b6cca3Slucy wang - Sun Microsystems - Beijing China mss_resid = mss; 320204b6cca3Slucy wang - Sun Microsystems - Beijing China if (resid < mss) { 320304b6cca3Slucy wang - Sun Microsystems - Beijing China tx_req++; 320404b6cca3Slucy wang - Sun Microsystems - Beijing China idx = tx->mask & tx_req; 320504b6cca3Slucy wang - Sun Microsystems - Beijing China cp = &tx->cp[idx]; 320604b6cca3Slucy wang - Sun Microsystems - Beijing China cp->len = 0; 320704b6cca3Slucy wang - Sun Microsystems - Beijing China low = ntohl(cp->dma.low); 320804b6cca3Slucy wang - Sun Microsystems - Beijing China ptr = cp->va; 320904b6cca3Slucy wang - Sun Microsystems - Beijing China resid = tx_boundary; 321004b6cca3Slucy wang - Sun Microsystems - Beijing China } 321104b6cca3Slucy wang - Sun Microsystems - Beijing China } 321204b6cca3Slucy wang - Sun Microsystems - Beijing China } 321304b6cca3Slucy wang - Sun Microsystems - Beijing China } 321404b6cca3Slucy wang - Sun Microsystems - Beijing China 321504b6cca3Slucy wang - Sun Microsystems - Beijing China req = req_list; 321604b6cca3Slucy wang - Sun Microsystems - Beijing China pkt_size_tmp = pkt_size; 321704b6cca3Slucy wang - Sun Microsystems - Beijing China count = 0; 321804b6cca3Slucy wang - Sun Microsystems - Beijing China rdma_count = 0; 321904b6cca3Slucy wang - Sun Microsystems - Beijing China tx_req = tx->req; 322004b6cca3Slucy wang - Sun Microsystems - Beijing China while (pkt_size_tmp) { 322104b6cca3Slucy wang - Sun Microsystems - Beijing China idx = tx->mask & tx_req; 322204b6cca3Slucy wang - Sun Microsystems - Beijing China cp = &tx->cp[idx]; 322304b6cca3Slucy wang - Sun Microsystems - Beijing China high_swapped = cp->dma.high; 322404b6cca3Slucy wang - Sun Microsystems - Beijing China low = ntohl(cp->dma.low); 322504b6cca3Slucy wang - Sun Microsystems - Beijing China len = cp->len; 322604b6cca3Slucy wang - Sun Microsystems - Beijing China if (len == 0) { 322704b6cca3Slucy wang - Sun Microsystems - Beijing China printf("len=0! pkt_size_tmp=%d, pkt_size=%d\n", 322804b6cca3Slucy wang - Sun Microsystems - Beijing China pkt_size_tmp, pkt_size); 322904b6cca3Slucy wang - Sun Microsystems - Beijing China for (bp = mp; bp != NULL; bp = bp->b_cont) { 323004b6cca3Slucy wang - Sun Microsystems - Beijing China mblen = MBLKL(bp); 323104b6cca3Slucy wang - Sun Microsystems - Beijing China printf("mblen:%d\n", mblen); 323204b6cca3Slucy wang - Sun Microsystems - Beijing China } 323304b6cca3Slucy wang - Sun Microsystems - Beijing China pkt_size_tmp = pkt_size; 323404b6cca3Slucy wang - Sun Microsystems - Beijing China tx_req = tx->req; 323504b6cca3Slucy wang - Sun Microsystems - Beijing China while (pkt_size_tmp > 0) { 323604b6cca3Slucy wang - Sun Microsystems - Beijing China idx = tx->mask & tx_req; 323704b6cca3Slucy wang - Sun Microsystems - Beijing China cp = &tx->cp[idx]; 323804b6cca3Slucy wang - Sun Microsystems - Beijing China printf("cp->len = %d\n", cp->len); 323904b6cca3Slucy wang - Sun Microsystems - Beijing China pkt_size_tmp -= cp->len; 324004b6cca3Slucy wang - Sun Microsystems - Beijing China tx_req++; 324104b6cca3Slucy wang - Sun Microsystems - Beijing China } 324204b6cca3Slucy wang - Sun Microsystems - Beijing China printf("dropped\n"); 324304b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_err); 324404b6cca3Slucy wang - Sun Microsystems - Beijing China goto done; 324504b6cca3Slucy wang - Sun Microsystems - Beijing China } 324604b6cca3Slucy wang - Sun Microsystems - Beijing China pkt_size_tmp -= len; 324704b6cca3Slucy wang - Sun Microsystems - Beijing China while (len) { 324804b6cca3Slucy wang - Sun Microsystems - Beijing China while (len) { 324904b6cca3Slucy wang - Sun Microsystems - Beijing China uint8_t flags_next; 325004b6cca3Slucy wang - Sun Microsystems - Beijing China int cum_len_next; 325104b6cca3Slucy wang - Sun Microsystems - Beijing China 325204b6cca3Slucy wang - Sun Microsystems - Beijing China boundary = (low + mgp->tx_boundary) & 325304b6cca3Slucy wang - Sun Microsystems - Beijing China ~(mgp->tx_boundary - 1); 325404b6cca3Slucy wang - Sun Microsystems - Beijing China seglen = boundary - low; 325504b6cca3Slucy wang - Sun Microsystems - Beijing China if (seglen > len) 325604b6cca3Slucy wang - Sun Microsystems - Beijing China seglen = len; 325704b6cca3Slucy wang - Sun Microsystems - Beijing China 325804b6cca3Slucy wang - Sun Microsystems - Beijing China flags_next = flags & ~MXGEFW_FLAGS_FIRST; 325904b6cca3Slucy wang - Sun Microsystems - Beijing China cum_len_next = cum_len + seglen; 326004b6cca3Slucy wang - Sun Microsystems - Beijing China (req-rdma_count)->rdma_count = rdma_count + 1; 326104b6cca3Slucy wang - Sun Microsystems - Beijing China if (likely(cum_len >= 0)) { 326204b6cca3Slucy wang - Sun Microsystems - Beijing China /* payload */ 326304b6cca3Slucy wang - Sun Microsystems - Beijing China int next_is_first, chop; 326404b6cca3Slucy wang - Sun Microsystems - Beijing China 326504b6cca3Slucy wang - Sun Microsystems - Beijing China chop = (cum_len_next > mss); 326604b6cca3Slucy wang - Sun Microsystems - Beijing China cum_len_next = cum_len_next % mss; 326704b6cca3Slucy wang - Sun Microsystems - Beijing China next_is_first = (cum_len_next == 0); 326804b6cca3Slucy wang - Sun Microsystems - Beijing China flags |= chop * 326904b6cca3Slucy wang - Sun Microsystems - Beijing China MXGEFW_FLAGS_TSO_CHOP; 327004b6cca3Slucy wang - Sun Microsystems - Beijing China flags_next |= next_is_first * 327104b6cca3Slucy wang - Sun Microsystems - Beijing China MXGEFW_FLAGS_FIRST; 327204b6cca3Slucy wang - Sun Microsystems - Beijing China rdma_count |= -(chop | next_is_first); 327304b6cca3Slucy wang - Sun Microsystems - Beijing China rdma_count += chop & !next_is_first; 327404b6cca3Slucy wang - Sun Microsystems - Beijing China } else if (likely(cum_len_next >= 0)) { 327504b6cca3Slucy wang - Sun Microsystems - Beijing China /* header ends */ 327604b6cca3Slucy wang - Sun Microsystems - Beijing China int small; 327704b6cca3Slucy wang - Sun Microsystems - Beijing China 327804b6cca3Slucy wang - Sun Microsystems - Beijing China rdma_count = -1; 327904b6cca3Slucy wang - Sun Microsystems - Beijing China cum_len_next = 0; 328004b6cca3Slucy wang - Sun Microsystems - Beijing China seglen = -cum_len; 328104b6cca3Slucy wang - Sun Microsystems - Beijing China small = (mss <= MXGEFW_SEND_SMALL_SIZE); 328204b6cca3Slucy wang - Sun Microsystems - Beijing China flags_next = MXGEFW_FLAGS_TSO_PLD | 328304b6cca3Slucy wang - Sun Microsystems - Beijing China MXGEFW_FLAGS_FIRST | 328404b6cca3Slucy wang - Sun Microsystems - Beijing China (small * MXGEFW_FLAGS_SMALL); 328504b6cca3Slucy wang - Sun Microsystems - Beijing China } 328604b6cca3Slucy wang - Sun Microsystems - Beijing China req->addr_high = high_swapped; 328704b6cca3Slucy wang - Sun Microsystems - Beijing China req->addr_low = htonl(low); 328804b6cca3Slucy wang - Sun Microsystems - Beijing China req->pseudo_hdr_offset = pseudo_hdr_offset; 328904b6cca3Slucy wang - Sun Microsystems - Beijing China req->pad = 0; /* complete solid 16-byte block */ 329004b6cca3Slucy wang - Sun Microsystems - Beijing China req->rdma_count = 1; 329104b6cca3Slucy wang - Sun Microsystems - Beijing China req->cksum_offset = cksum_offset; 329204b6cca3Slucy wang - Sun Microsystems - Beijing China req->length = htons(seglen); 329304b6cca3Slucy wang - Sun Microsystems - Beijing China req->flags = flags | ((cum_len & 1) * 329404b6cca3Slucy wang - Sun Microsystems - Beijing China MXGEFW_FLAGS_ALIGN_ODD); 329504b6cca3Slucy wang - Sun Microsystems - Beijing China if (cksum_offset > seglen) 329604b6cca3Slucy wang - Sun Microsystems - Beijing China cksum_offset -= seglen; 329704b6cca3Slucy wang - Sun Microsystems - Beijing China else 329804b6cca3Slucy wang - Sun Microsystems - Beijing China cksum_offset = 0; 329904b6cca3Slucy wang - Sun Microsystems - Beijing China low += seglen; 330004b6cca3Slucy wang - Sun Microsystems - Beijing China len -= seglen; 330104b6cca3Slucy wang - Sun Microsystems - Beijing China cum_len = cum_len_next; 330204b6cca3Slucy wang - Sun Microsystems - Beijing China req++; 330304b6cca3Slucy wang - Sun Microsystems - Beijing China req->flags = 0; 330404b6cca3Slucy wang - Sun Microsystems - Beijing China flags = flags_next; 330504b6cca3Slucy wang - Sun Microsystems - Beijing China count++; 330604b6cca3Slucy wang - Sun Microsystems - Beijing China rdma_count++; 330704b6cca3Slucy wang - Sun Microsystems - Beijing China } 330804b6cca3Slucy wang - Sun Microsystems - Beijing China } 330904b6cca3Slucy wang - Sun Microsystems - Beijing China tx_req++; 331004b6cca3Slucy wang - Sun Microsystems - Beijing China } 331104b6cca3Slucy wang - Sun Microsystems - Beijing China (req-rdma_count)->rdma_count = (uint8_t)rdma_count; 331204b6cca3Slucy wang - Sun Microsystems - Beijing China do { 331304b6cca3Slucy wang - Sun Microsystems - Beijing China req--; 331404b6cca3Slucy wang - Sun Microsystems - Beijing China req->flags |= MXGEFW_FLAGS_TSO_LAST; 331504b6cca3Slucy wang - Sun Microsystems - Beijing China } while (!(req->flags & (MXGEFW_FLAGS_TSO_CHOP | 331604b6cca3Slucy wang - Sun Microsystems - Beijing China MXGEFW_FLAGS_FIRST))); 331704b6cca3Slucy wang - Sun Microsystems - Beijing China 331804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_submit_req(tx, req_list, count); 331904b6cca3Slucy wang - Sun Microsystems - Beijing China done: 332004b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&tx->lock); 332104b6cca3Slucy wang - Sun Microsystems - Beijing China freemsg(mp); 332204b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 332304b6cca3Slucy wang - Sun Microsystems - Beijing China } 332404b6cca3Slucy wang - Sun Microsystems - Beijing China 332504b6cca3Slucy wang - Sun Microsystems - Beijing China /* 332604b6cca3Slucy wang - Sun Microsystems - Beijing China * Try to send the chain of buffers described by the mp. We must not 332704b6cca3Slucy wang - Sun Microsystems - Beijing China * encapsulate more than eth->tx.req - eth->tx.done, or 332804b6cca3Slucy wang - Sun Microsystems - Beijing China * MXGEFW_MAX_SEND_DESC, whichever is more. 332904b6cca3Slucy wang - Sun Microsystems - Beijing China */ 333004b6cca3Slucy wang - Sun Microsystems - Beijing China 333104b6cca3Slucy wang - Sun Microsystems - Beijing China static int 333204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_send(struct myri10ge_slice_state *ss, mblk_t *mp, 333304b6cca3Slucy wang - Sun Microsystems - Beijing China mcp_kreq_ether_send_t *req_list, struct myri10ge_tx_buffer_state *tx_info) 333404b6cca3Slucy wang - Sun Microsystems - Beijing China { 333504b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = ss->mgp; 333604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_ring_t *tx = &ss->tx; 333704b6cca3Slucy wang - Sun Microsystems - Beijing China mcp_kreq_ether_send_t *req; 333804b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_tx_dma_handle *handles, *dma_handle = NULL; 333904b6cca3Slucy wang - Sun Microsystems - Beijing China mblk_t *bp; 334004b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_dma_cookie_t cookie; 334104b6cca3Slucy wang - Sun Microsystems - Beijing China int err, rv, count, avail, mblen, try_pullup, i, max_segs, maclen, 334204b6cca3Slucy wang - Sun Microsystems - Beijing China rdma_count, cum_len, lso_hdr_size; 334304b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t start, stuff, tx_offload_flags; 334404b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t seglen, len, mss, boundary, low, high_swapped; 334504b6cca3Slucy wang - Sun Microsystems - Beijing China uint_t ncookies; 334604b6cca3Slucy wang - Sun Microsystems - Beijing China uint16_t pseudo_hdr_offset; 334704b6cca3Slucy wang - Sun Microsystems - Beijing China uint8_t flags, cksum_offset, odd_flag; 334804b6cca3Slucy wang - Sun Microsystems - Beijing China int pkt_size; 334904b6cca3Slucy wang - Sun Microsystems - Beijing China int lso_copy = myri10ge_lso_copy; 335004b6cca3Slucy wang - Sun Microsystems - Beijing China try_pullup = 1; 335104b6cca3Slucy wang - Sun Microsystems - Beijing China 335204b6cca3Slucy wang - Sun Microsystems - Beijing China again: 335304b6cca3Slucy wang - Sun Microsystems - Beijing China /* Setup checksum offloading, if needed */ 33540dc2366fSVenugopal Iyer mac_hcksum_get(mp, &start, &stuff, NULL, NULL, &tx_offload_flags); 335504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_lso_info_get(mp, &mss, &tx_offload_flags); 335604b6cca3Slucy wang - Sun Microsystems - Beijing China if (tx_offload_flags & HW_LSO) { 335704b6cca3Slucy wang - Sun Microsystems - Beijing China max_segs = MYRI10GE_MAX_SEND_DESC_TSO; 335804b6cca3Slucy wang - Sun Microsystems - Beijing China if ((tx_offload_flags & HCK_PARTIALCKSUM) == 0) { 335904b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_lsobadflags); 336004b6cca3Slucy wang - Sun Microsystems - Beijing China freemsg(mp); 336104b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 336204b6cca3Slucy wang - Sun Microsystems - Beijing China } 336304b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 336404b6cca3Slucy wang - Sun Microsystems - Beijing China max_segs = MXGEFW_MAX_SEND_DESC; 336504b6cca3Slucy wang - Sun Microsystems - Beijing China mss = 0; 336604b6cca3Slucy wang - Sun Microsystems - Beijing China } 336704b6cca3Slucy wang - Sun Microsystems - Beijing China req = req_list; 336804b6cca3Slucy wang - Sun Microsystems - Beijing China cksum_offset = 0; 336904b6cca3Slucy wang - Sun Microsystems - Beijing China pseudo_hdr_offset = 0; 337004b6cca3Slucy wang - Sun Microsystems - Beijing China 337104b6cca3Slucy wang - Sun Microsystems - Beijing China /* leave an extra slot keep the ring from wrapping */ 337204b6cca3Slucy wang - Sun Microsystems - Beijing China avail = tx->mask - (tx->req - tx->done); 337304b6cca3Slucy wang - Sun Microsystems - Beijing China 337404b6cca3Slucy wang - Sun Microsystems - Beijing China /* 337504b6cca3Slucy wang - Sun Microsystems - Beijing China * If we have > MXGEFW_MAX_SEND_DESC, then any over-length 337604b6cca3Slucy wang - Sun Microsystems - Beijing China * message will need to be pulled up in order to fit. 337704b6cca3Slucy wang - Sun Microsystems - Beijing China * Otherwise, we are low on transmit descriptors, it is 337804b6cca3Slucy wang - Sun Microsystems - Beijing China * probably better to stall and try again rather than pullup a 337904b6cca3Slucy wang - Sun Microsystems - Beijing China * message to fit. 338004b6cca3Slucy wang - Sun Microsystems - Beijing China */ 338104b6cca3Slucy wang - Sun Microsystems - Beijing China 338204b6cca3Slucy wang - Sun Microsystems - Beijing China if (avail < max_segs) { 338304b6cca3Slucy wang - Sun Microsystems - Beijing China err = EBUSY; 33841a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&tx->stall_early); 338504b6cca3Slucy wang - Sun Microsystems - Beijing China goto stall; 338604b6cca3Slucy wang - Sun Microsystems - Beijing China } 338704b6cca3Slucy wang - Sun Microsystems - Beijing China 338804b6cca3Slucy wang - Sun Microsystems - Beijing China /* find out how long the frame is and how many segments it is */ 338904b6cca3Slucy wang - Sun Microsystems - Beijing China count = 0; 339004b6cca3Slucy wang - Sun Microsystems - Beijing China odd_flag = 0; 339104b6cca3Slucy wang - Sun Microsystems - Beijing China pkt_size = 0; 339204b6cca3Slucy wang - Sun Microsystems - Beijing China flags = (MXGEFW_FLAGS_NO_TSO | MXGEFW_FLAGS_FIRST); 339304b6cca3Slucy wang - Sun Microsystems - Beijing China for (bp = mp; bp != NULL; bp = bp->b_cont) { 339404b6cca3Slucy wang - Sun Microsystems - Beijing China dblk_t *dbp; 339504b6cca3Slucy wang - Sun Microsystems - Beijing China mblen = MBLKL(bp); 339604b6cca3Slucy wang - Sun Microsystems - Beijing China if (mblen == 0) { 339704b6cca3Slucy wang - Sun Microsystems - Beijing China /* 339804b6cca3Slucy wang - Sun Microsystems - Beijing China * we can't simply skip over 0-length mblks 339904b6cca3Slucy wang - Sun Microsystems - Beijing China * because the hardware can't deal with them, 340004b6cca3Slucy wang - Sun Microsystems - Beijing China * and we could leak them. 340104b6cca3Slucy wang - Sun Microsystems - Beijing China */ 340204b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_zero_len); 340304b6cca3Slucy wang - Sun Microsystems - Beijing China err = EIO; 340404b6cca3Slucy wang - Sun Microsystems - Beijing China goto pullup; 340504b6cca3Slucy wang - Sun Microsystems - Beijing China } 340604b6cca3Slucy wang - Sun Microsystems - Beijing China /* 340704b6cca3Slucy wang - Sun Microsystems - Beijing China * There's no advantage to copying most gesballoc 340804b6cca3Slucy wang - Sun Microsystems - Beijing China * attached blocks, so disable lso copy in that case 340904b6cca3Slucy wang - Sun Microsystems - Beijing China */ 341004b6cca3Slucy wang - Sun Microsystems - Beijing China if (mss && lso_copy == 1 && ((dbp = bp->b_datap) != NULL)) { 341104b6cca3Slucy wang - Sun Microsystems - Beijing China if ((void *)dbp->db_lastfree != myri10ge_db_lastfree) { 341204b6cca3Slucy wang - Sun Microsystems - Beijing China lso_copy = 0; 341304b6cca3Slucy wang - Sun Microsystems - Beijing China } 341404b6cca3Slucy wang - Sun Microsystems - Beijing China } 341504b6cca3Slucy wang - Sun Microsystems - Beijing China pkt_size += mblen; 341604b6cca3Slucy wang - Sun Microsystems - Beijing China count++; 341704b6cca3Slucy wang - Sun Microsystems - Beijing China } 341804b6cca3Slucy wang - Sun Microsystems - Beijing China 341904b6cca3Slucy wang - Sun Microsystems - Beijing China /* Try to pull up excessivly long chains */ 342004b6cca3Slucy wang - Sun Microsystems - Beijing China if (count >= max_segs) { 342104b6cca3Slucy wang - Sun Microsystems - Beijing China err = myri10ge_pullup(ss, mp); 342204b6cca3Slucy wang - Sun Microsystems - Beijing China if (likely(err == DDI_SUCCESS)) { 342304b6cca3Slucy wang - Sun Microsystems - Beijing China count = 1; 342404b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 342504b6cca3Slucy wang - Sun Microsystems - Beijing China if (count < MYRI10GE_MAX_SEND_DESC_TSO) { 342604b6cca3Slucy wang - Sun Microsystems - Beijing China /* 342704b6cca3Slucy wang - Sun Microsystems - Beijing China * just let the h/w send it, it will be 342804b6cca3Slucy wang - Sun Microsystems - Beijing China * inefficient, but us better than dropping 342904b6cca3Slucy wang - Sun Microsystems - Beijing China */ 343004b6cca3Slucy wang - Sun Microsystems - Beijing China max_segs = MYRI10GE_MAX_SEND_DESC_TSO; 343104b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 343204b6cca3Slucy wang - Sun Microsystems - Beijing China /* drop it */ 343304b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_err); 343404b6cca3Slucy wang - Sun Microsystems - Beijing China freemsg(mp); 343504b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 343604b6cca3Slucy wang - Sun Microsystems - Beijing China } 343704b6cca3Slucy wang - Sun Microsystems - Beijing China } 343804b6cca3Slucy wang - Sun Microsystems - Beijing China } 343904b6cca3Slucy wang - Sun Microsystems - Beijing China 344004b6cca3Slucy wang - Sun Microsystems - Beijing China cum_len = 0; 344104b6cca3Slucy wang - Sun Microsystems - Beijing China maclen = myri10ge_ether_parse_header(mp); 344204b6cca3Slucy wang - Sun Microsystems - Beijing China 344304b6cca3Slucy wang - Sun Microsystems - Beijing China if (tx_offload_flags & HCK_PARTIALCKSUM) { 344404b6cca3Slucy wang - Sun Microsystems - Beijing China 344504b6cca3Slucy wang - Sun Microsystems - Beijing China cksum_offset = start + maclen; 344604b6cca3Slucy wang - Sun Microsystems - Beijing China pseudo_hdr_offset = htons(stuff + maclen); 344704b6cca3Slucy wang - Sun Microsystems - Beijing China odd_flag = MXGEFW_FLAGS_ALIGN_ODD; 344804b6cca3Slucy wang - Sun Microsystems - Beijing China flags |= MXGEFW_FLAGS_CKSUM; 344904b6cca3Slucy wang - Sun Microsystems - Beijing China } 345004b6cca3Slucy wang - Sun Microsystems - Beijing China 345104b6cca3Slucy wang - Sun Microsystems - Beijing China lso_hdr_size = 0; /* -Wunitinialized */ 345204b6cca3Slucy wang - Sun Microsystems - Beijing China if (mss) { /* LSO */ 345304b6cca3Slucy wang - Sun Microsystems - Beijing China /* this removes any CKSUM flag from before */ 345404b6cca3Slucy wang - Sun Microsystems - Beijing China flags = (MXGEFW_FLAGS_TSO_HDR | MXGEFW_FLAGS_FIRST); 345504b6cca3Slucy wang - Sun Microsystems - Beijing China /* 345604b6cca3Slucy wang - Sun Microsystems - Beijing China * parse the headers and set cum_len to a negative 345704b6cca3Slucy wang - Sun Microsystems - Beijing China * value to reflect the offset of the TCP payload 345804b6cca3Slucy wang - Sun Microsystems - Beijing China */ 345904b6cca3Slucy wang - Sun Microsystems - Beijing China lso_hdr_size = myri10ge_lso_parse_header(mp, maclen); 346004b6cca3Slucy wang - Sun Microsystems - Beijing China cum_len = -lso_hdr_size; 346104b6cca3Slucy wang - Sun Microsystems - Beijing China if ((mss < mgp->tx_boundary) && lso_copy) { 346204b6cca3Slucy wang - Sun Microsystems - Beijing China err = myri10ge_tx_tso_copy(ss, mp, req_list, 346304b6cca3Slucy wang - Sun Microsystems - Beijing China lso_hdr_size, pkt_size, mss, cksum_offset); 346404b6cca3Slucy wang - Sun Microsystems - Beijing China return (err); 346504b6cca3Slucy wang - Sun Microsystems - Beijing China } 346604b6cca3Slucy wang - Sun Microsystems - Beijing China 346704b6cca3Slucy wang - Sun Microsystems - Beijing China /* 346804b6cca3Slucy wang - Sun Microsystems - Beijing China * for TSO, pseudo_hdr_offset holds mss. The firmware 346904b6cca3Slucy wang - Sun Microsystems - Beijing China * figures out where to put the checksum by parsing 347004b6cca3Slucy wang - Sun Microsystems - Beijing China * the header. 347104b6cca3Slucy wang - Sun Microsystems - Beijing China */ 347204b6cca3Slucy wang - Sun Microsystems - Beijing China 347304b6cca3Slucy wang - Sun Microsystems - Beijing China pseudo_hdr_offset = htons(mss); 347404b6cca3Slucy wang - Sun Microsystems - Beijing China } else if (pkt_size <= MXGEFW_SEND_SMALL_SIZE) { 347504b6cca3Slucy wang - Sun Microsystems - Beijing China flags |= MXGEFW_FLAGS_SMALL; 347604b6cca3Slucy wang - Sun Microsystems - Beijing China if (pkt_size < myri10ge_tx_copylen) { 347704b6cca3Slucy wang - Sun Microsystems - Beijing China req->cksum_offset = cksum_offset; 347804b6cca3Slucy wang - Sun Microsystems - Beijing China req->pseudo_hdr_offset = pseudo_hdr_offset; 347904b6cca3Slucy wang - Sun Microsystems - Beijing China req->flags = flags; 348004b6cca3Slucy wang - Sun Microsystems - Beijing China err = myri10ge_tx_copy(ss, mp, req); 348104b6cca3Slucy wang - Sun Microsystems - Beijing China return (err); 348204b6cca3Slucy wang - Sun Microsystems - Beijing China } 348304b6cca3Slucy wang - Sun Microsystems - Beijing China cum_len = 0; 348404b6cca3Slucy wang - Sun Microsystems - Beijing China } 348504b6cca3Slucy wang - Sun Microsystems - Beijing China 348604b6cca3Slucy wang - Sun Microsystems - Beijing China /* pull one DMA handle for each bp from our freelist */ 348704b6cca3Slucy wang - Sun Microsystems - Beijing China handles = NULL; 348804b6cca3Slucy wang - Sun Microsystems - Beijing China err = myri10ge_alloc_tx_handles(ss, count, &handles); 348904b6cca3Slucy wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 349004b6cca3Slucy wang - Sun Microsystems - Beijing China err = DDI_FAILURE; 349104b6cca3Slucy wang - Sun Microsystems - Beijing China goto stall; 349204b6cca3Slucy wang - Sun Microsystems - Beijing China } 349304b6cca3Slucy wang - Sun Microsystems - Beijing China count = 0; 349404b6cca3Slucy wang - Sun Microsystems - Beijing China rdma_count = 0; 349504b6cca3Slucy wang - Sun Microsystems - Beijing China for (bp = mp; bp != NULL; bp = bp->b_cont) { 349604b6cca3Slucy wang - Sun Microsystems - Beijing China mblen = MBLKL(bp); 349704b6cca3Slucy wang - Sun Microsystems - Beijing China dma_handle = handles; 349804b6cca3Slucy wang - Sun Microsystems - Beijing China handles = handles->next; 349904b6cca3Slucy wang - Sun Microsystems - Beijing China 350004b6cca3Slucy wang - Sun Microsystems - Beijing China rv = ddi_dma_addr_bind_handle(dma_handle->h, NULL, 350104b6cca3Slucy wang - Sun Microsystems - Beijing China (caddr_t)bp->b_rptr, mblen, 350204b6cca3Slucy wang - Sun Microsystems - Beijing China DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, 350304b6cca3Slucy wang - Sun Microsystems - Beijing China &cookie, &ncookies); 350404b6cca3Slucy wang - Sun Microsystems - Beijing China if (unlikely(rv != DDI_DMA_MAPPED)) { 350504b6cca3Slucy wang - Sun Microsystems - Beijing China err = EIO; 350604b6cca3Slucy wang - Sun Microsystems - Beijing China try_pullup = 0; 350704b6cca3Slucy wang - Sun Microsystems - Beijing China dma_handle->next = handles; 350804b6cca3Slucy wang - Sun Microsystems - Beijing China handles = dma_handle; 350904b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_handles; 351004b6cca3Slucy wang - Sun Microsystems - Beijing China } 351104b6cca3Slucy wang - Sun Microsystems - Beijing China 351204b6cca3Slucy wang - Sun Microsystems - Beijing China /* reserve the slot */ 351304b6cca3Slucy wang - Sun Microsystems - Beijing China tx_info[count].m = bp; 351404b6cca3Slucy wang - Sun Microsystems - Beijing China tx_info[count].handle = dma_handle; 351504b6cca3Slucy wang - Sun Microsystems - Beijing China 351604b6cca3Slucy wang - Sun Microsystems - Beijing China for (; ; ) { 351704b6cca3Slucy wang - Sun Microsystems - Beijing China low = MYRI10GE_LOWPART_TO_U32(cookie.dmac_laddress); 351804b6cca3Slucy wang - Sun Microsystems - Beijing China high_swapped = 351904b6cca3Slucy wang - Sun Microsystems - Beijing China htonl(MYRI10GE_HIGHPART_TO_U32( 352004b6cca3Slucy wang - Sun Microsystems - Beijing China cookie.dmac_laddress)); 352104b6cca3Slucy wang - Sun Microsystems - Beijing China len = (uint32_t)cookie.dmac_size; 352204b6cca3Slucy wang - Sun Microsystems - Beijing China while (len) { 352304b6cca3Slucy wang - Sun Microsystems - Beijing China uint8_t flags_next; 352404b6cca3Slucy wang - Sun Microsystems - Beijing China int cum_len_next; 352504b6cca3Slucy wang - Sun Microsystems - Beijing China 352604b6cca3Slucy wang - Sun Microsystems - Beijing China boundary = (low + mgp->tx_boundary) & 352704b6cca3Slucy wang - Sun Microsystems - Beijing China ~(mgp->tx_boundary - 1); 352804b6cca3Slucy wang - Sun Microsystems - Beijing China seglen = boundary - low; 352904b6cca3Slucy wang - Sun Microsystems - Beijing China if (seglen > len) 353004b6cca3Slucy wang - Sun Microsystems - Beijing China seglen = len; 353104b6cca3Slucy wang - Sun Microsystems - Beijing China 353204b6cca3Slucy wang - Sun Microsystems - Beijing China flags_next = flags & ~MXGEFW_FLAGS_FIRST; 353304b6cca3Slucy wang - Sun Microsystems - Beijing China cum_len_next = cum_len + seglen; 353404b6cca3Slucy wang - Sun Microsystems - Beijing China if (mss) { 353504b6cca3Slucy wang - Sun Microsystems - Beijing China (req-rdma_count)->rdma_count = 353604b6cca3Slucy wang - Sun Microsystems - Beijing China rdma_count + 1; 353704b6cca3Slucy wang - Sun Microsystems - Beijing China if (likely(cum_len >= 0)) { 353804b6cca3Slucy wang - Sun Microsystems - Beijing China /* payload */ 353904b6cca3Slucy wang - Sun Microsystems - Beijing China int next_is_first, chop; 354004b6cca3Slucy wang - Sun Microsystems - Beijing China 354104b6cca3Slucy wang - Sun Microsystems - Beijing China chop = (cum_len_next > mss); 354204b6cca3Slucy wang - Sun Microsystems - Beijing China cum_len_next = 354304b6cca3Slucy wang - Sun Microsystems - Beijing China cum_len_next % mss; 354404b6cca3Slucy wang - Sun Microsystems - Beijing China next_is_first = 354504b6cca3Slucy wang - Sun Microsystems - Beijing China (cum_len_next == 0); 354604b6cca3Slucy wang - Sun Microsystems - Beijing China flags |= chop * 354704b6cca3Slucy wang - Sun Microsystems - Beijing China MXGEFW_FLAGS_TSO_CHOP; 354804b6cca3Slucy wang - Sun Microsystems - Beijing China flags_next |= next_is_first * 354904b6cca3Slucy wang - Sun Microsystems - Beijing China MXGEFW_FLAGS_FIRST; 355004b6cca3Slucy wang - Sun Microsystems - Beijing China rdma_count |= 355104b6cca3Slucy wang - Sun Microsystems - Beijing China -(chop | next_is_first); 355204b6cca3Slucy wang - Sun Microsystems - Beijing China rdma_count += 355304b6cca3Slucy wang - Sun Microsystems - Beijing China chop & !next_is_first; 355404b6cca3Slucy wang - Sun Microsystems - Beijing China } else if (likely(cum_len_next >= 0)) { 355504b6cca3Slucy wang - Sun Microsystems - Beijing China /* header ends */ 355604b6cca3Slucy wang - Sun Microsystems - Beijing China int small; 355704b6cca3Slucy wang - Sun Microsystems - Beijing China 355804b6cca3Slucy wang - Sun Microsystems - Beijing China rdma_count = -1; 355904b6cca3Slucy wang - Sun Microsystems - Beijing China cum_len_next = 0; 356004b6cca3Slucy wang - Sun Microsystems - Beijing China seglen = -cum_len; 356104b6cca3Slucy wang - Sun Microsystems - Beijing China small = (mss <= 356204b6cca3Slucy wang - Sun Microsystems - Beijing China MXGEFW_SEND_SMALL_SIZE); 356304b6cca3Slucy wang - Sun Microsystems - Beijing China flags_next = 356404b6cca3Slucy wang - Sun Microsystems - Beijing China MXGEFW_FLAGS_TSO_PLD 356504b6cca3Slucy wang - Sun Microsystems - Beijing China | MXGEFW_FLAGS_FIRST 356604b6cca3Slucy wang - Sun Microsystems - Beijing China | (small * 356704b6cca3Slucy wang - Sun Microsystems - Beijing China MXGEFW_FLAGS_SMALL); 356804b6cca3Slucy wang - Sun Microsystems - Beijing China } 356904b6cca3Slucy wang - Sun Microsystems - Beijing China } 357004b6cca3Slucy wang - Sun Microsystems - Beijing China req->addr_high = high_swapped; 357104b6cca3Slucy wang - Sun Microsystems - Beijing China req->addr_low = htonl(low); 357204b6cca3Slucy wang - Sun Microsystems - Beijing China req->pseudo_hdr_offset = pseudo_hdr_offset; 357304b6cca3Slucy wang - Sun Microsystems - Beijing China req->pad = 0; /* complete solid 16-byte block */ 357404b6cca3Slucy wang - Sun Microsystems - Beijing China req->rdma_count = 1; 357504b6cca3Slucy wang - Sun Microsystems - Beijing China req->cksum_offset = cksum_offset; 357604b6cca3Slucy wang - Sun Microsystems - Beijing China req->length = htons(seglen); 357704b6cca3Slucy wang - Sun Microsystems - Beijing China req->flags = flags | ((cum_len & 1) * odd_flag); 357804b6cca3Slucy wang - Sun Microsystems - Beijing China if (cksum_offset > seglen) 357904b6cca3Slucy wang - Sun Microsystems - Beijing China cksum_offset -= seglen; 358004b6cca3Slucy wang - Sun Microsystems - Beijing China else 358104b6cca3Slucy wang - Sun Microsystems - Beijing China cksum_offset = 0; 358204b6cca3Slucy wang - Sun Microsystems - Beijing China low += seglen; 358304b6cca3Slucy wang - Sun Microsystems - Beijing China len -= seglen; 358404b6cca3Slucy wang - Sun Microsystems - Beijing China cum_len = cum_len_next; 358504b6cca3Slucy wang - Sun Microsystems - Beijing China count++; 358604b6cca3Slucy wang - Sun Microsystems - Beijing China rdma_count++; 358704b6cca3Slucy wang - Sun Microsystems - Beijing China /* make sure all the segments will fit */ 358804b6cca3Slucy wang - Sun Microsystems - Beijing China if (unlikely(count >= max_segs)) { 358904b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_ATOMIC_SLICE_STAT_INC( 359004b6cca3Slucy wang - Sun Microsystems - Beijing China xmit_lowbuf); 359104b6cca3Slucy wang - Sun Microsystems - Beijing China /* may try a pullup */ 359204b6cca3Slucy wang - Sun Microsystems - Beijing China err = EBUSY; 359304b6cca3Slucy wang - Sun Microsystems - Beijing China if (try_pullup) 359404b6cca3Slucy wang - Sun Microsystems - Beijing China try_pullup = 2; 359504b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_handles; 359604b6cca3Slucy wang - Sun Microsystems - Beijing China } 359704b6cca3Slucy wang - Sun Microsystems - Beijing China req++; 359804b6cca3Slucy wang - Sun Microsystems - Beijing China req->flags = 0; 359904b6cca3Slucy wang - Sun Microsystems - Beijing China flags = flags_next; 360004b6cca3Slucy wang - Sun Microsystems - Beijing China tx_info[count].m = 0; 360104b6cca3Slucy wang - Sun Microsystems - Beijing China } 360204b6cca3Slucy wang - Sun Microsystems - Beijing China ncookies--; 360304b6cca3Slucy wang - Sun Microsystems - Beijing China if (ncookies == 0) 360404b6cca3Slucy wang - Sun Microsystems - Beijing China break; 360504b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_dma_nextcookie(dma_handle->h, &cookie); 360604b6cca3Slucy wang - Sun Microsystems - Beijing China } 360704b6cca3Slucy wang - Sun Microsystems - Beijing China } 360804b6cca3Slucy wang - Sun Microsystems - Beijing China (req-rdma_count)->rdma_count = (uint8_t)rdma_count; 360904b6cca3Slucy wang - Sun Microsystems - Beijing China 361004b6cca3Slucy wang - Sun Microsystems - Beijing China if (mss) { 361104b6cca3Slucy wang - Sun Microsystems - Beijing China do { 361204b6cca3Slucy wang - Sun Microsystems - Beijing China req--; 361304b6cca3Slucy wang - Sun Microsystems - Beijing China req->flags |= MXGEFW_FLAGS_TSO_LAST; 361404b6cca3Slucy wang - Sun Microsystems - Beijing China } while (!(req->flags & (MXGEFW_FLAGS_TSO_CHOP | 361504b6cca3Slucy wang - Sun Microsystems - Beijing China MXGEFW_FLAGS_FIRST))); 361604b6cca3Slucy wang - Sun Microsystems - Beijing China } 361704b6cca3Slucy wang - Sun Microsystems - Beijing China 361804b6cca3Slucy wang - Sun Microsystems - Beijing China /* calculate tx stats */ 361904b6cca3Slucy wang - Sun Microsystems - Beijing China if (mss) { 362004b6cca3Slucy wang - Sun Microsystems - Beijing China uint16_t opackets; 362104b6cca3Slucy wang - Sun Microsystems - Beijing China int payload; 362204b6cca3Slucy wang - Sun Microsystems - Beijing China 362304b6cca3Slucy wang - Sun Microsystems - Beijing China payload = pkt_size - lso_hdr_size; 362404b6cca3Slucy wang - Sun Microsystems - Beijing China opackets = (payload / mss) + ((payload % mss) != 0); 362504b6cca3Slucy wang - Sun Microsystems - Beijing China tx_info[0].stat.un.all = 0; 362604b6cca3Slucy wang - Sun Microsystems - Beijing China tx_info[0].ostat.opackets = opackets; 362704b6cca3Slucy wang - Sun Microsystems - Beijing China tx_info[0].ostat.obytes = (opackets - 1) * lso_hdr_size 362804b6cca3Slucy wang - Sun Microsystems - Beijing China + pkt_size; 362904b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 363004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_stat(&tx_info[0].stat, 363104b6cca3Slucy wang - Sun Microsystems - Beijing China (struct ether_header *)(void *)mp->b_rptr, 1, pkt_size); 363204b6cca3Slucy wang - Sun Microsystems - Beijing China } 363304b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&tx->lock); 363404b6cca3Slucy wang - Sun Microsystems - Beijing China 363504b6cca3Slucy wang - Sun Microsystems - Beijing China /* check to see if the slots are really there */ 363604b6cca3Slucy wang - Sun Microsystems - Beijing China avail = tx->mask - (tx->req - tx->done); 363704b6cca3Slucy wang - Sun Microsystems - Beijing China if (unlikely(avail <= count)) { 363804b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&tx->lock); 363904b6cca3Slucy wang - Sun Microsystems - Beijing China err = 0; 364004b6cca3Slucy wang - Sun Microsystems - Beijing China goto late_stall; 364104b6cca3Slucy wang - Sun Microsystems - Beijing China } 364204b6cca3Slucy wang - Sun Microsystems - Beijing China 364304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_send_locked(tx, req_list, tx_info, count); 364404b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&tx->lock); 364504b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 364604b6cca3Slucy wang - Sun Microsystems - Beijing China 364704b6cca3Slucy wang - Sun Microsystems - Beijing China late_stall: 364804b6cca3Slucy wang - Sun Microsystems - Beijing China try_pullup = 0; 36491a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&tx->stall_late); 365004b6cca3Slucy wang - Sun Microsystems - Beijing China 365104b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_handles: 365204b6cca3Slucy wang - Sun Microsystems - Beijing China /* unbind and free handles from previous mblks */ 365304b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < count; i++) { 365404b6cca3Slucy wang - Sun Microsystems - Beijing China bp = tx_info[i].m; 365504b6cca3Slucy wang - Sun Microsystems - Beijing China tx_info[i].m = 0; 365604b6cca3Slucy wang - Sun Microsystems - Beijing China if (bp) { 365704b6cca3Slucy wang - Sun Microsystems - Beijing China dma_handle = tx_info[i].handle; 365804b6cca3Slucy wang - Sun Microsystems - Beijing China (void) ddi_dma_unbind_handle(dma_handle->h); 365904b6cca3Slucy wang - Sun Microsystems - Beijing China dma_handle->next = handles; 366004b6cca3Slucy wang - Sun Microsystems - Beijing China handles = dma_handle; 366104b6cca3Slucy wang - Sun Microsystems - Beijing China tx_info[i].handle = NULL; 366204b6cca3Slucy wang - Sun Microsystems - Beijing China tx_info[i].m = NULL; 366304b6cca3Slucy wang - Sun Microsystems - Beijing China } 366404b6cca3Slucy wang - Sun Microsystems - Beijing China } 366504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_free_tx_handle_slist(tx, handles); 366604b6cca3Slucy wang - Sun Microsystems - Beijing China pullup: 366704b6cca3Slucy wang - Sun Microsystems - Beijing China if (try_pullup) { 366804b6cca3Slucy wang - Sun Microsystems - Beijing China err = myri10ge_pullup(ss, mp); 366904b6cca3Slucy wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS && try_pullup == 2) { 367004b6cca3Slucy wang - Sun Microsystems - Beijing China /* drop */ 367104b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_err); 367204b6cca3Slucy wang - Sun Microsystems - Beijing China freemsg(mp); 367304b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 367404b6cca3Slucy wang - Sun Microsystems - Beijing China } 367504b6cca3Slucy wang - Sun Microsystems - Beijing China try_pullup = 0; 367604b6cca3Slucy wang - Sun Microsystems - Beijing China goto again; 367704b6cca3Slucy wang - Sun Microsystems - Beijing China } 367804b6cca3Slucy wang - Sun Microsystems - Beijing China 367904b6cca3Slucy wang - Sun Microsystems - Beijing China stall: 368004b6cca3Slucy wang - Sun Microsystems - Beijing China if (err != 0) { 368104b6cca3Slucy wang - Sun Microsystems - Beijing China if (err == EBUSY) { 36821a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&tx->stall); 368304b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 368404b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_err); 368504b6cca3Slucy wang - Sun Microsystems - Beijing China } 368604b6cca3Slucy wang - Sun Microsystems - Beijing China } 368704b6cca3Slucy wang - Sun Microsystems - Beijing China return (err); 368804b6cca3Slucy wang - Sun Microsystems - Beijing China } 368904b6cca3Slucy wang - Sun Microsystems - Beijing China 369004b6cca3Slucy wang - Sun Microsystems - Beijing China static mblk_t * 369104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_send_wrapper(void *arg, mblk_t *mp) 369204b6cca3Slucy wang - Sun Microsystems - Beijing China { 369304b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_slice_state *ss = arg; 369404b6cca3Slucy wang - Sun Microsystems - Beijing China int err = 0; 369504b6cca3Slucy wang - Sun Microsystems - Beijing China mcp_kreq_ether_send_t *req_list; 369604b6cca3Slucy wang - Sun Microsystems - Beijing China #if defined(__i386) 369704b6cca3Slucy wang - Sun Microsystems - Beijing China /* 369804b6cca3Slucy wang - Sun Microsystems - Beijing China * We need about 2.5KB of scratch space to handle transmits. 369904b6cca3Slucy wang - Sun Microsystems - Beijing China * i86pc has only 8KB of kernel stack space, so we malloc the 370004b6cca3Slucy wang - Sun Microsystems - Beijing China * scratch space there rather than keeping it on the stack. 370104b6cca3Slucy wang - Sun Microsystems - Beijing China */ 370204b6cca3Slucy wang - Sun Microsystems - Beijing China size_t req_size, tx_info_size; 370304b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_tx_buffer_state *tx_info; 370404b6cca3Slucy wang - Sun Microsystems - Beijing China caddr_t req_bytes; 370504b6cca3Slucy wang - Sun Microsystems - Beijing China 370604b6cca3Slucy wang - Sun Microsystems - Beijing China req_size = sizeof (*req_list) * (MYRI10GE_MAX_SEND_DESC_TSO + 4) 370704b6cca3Slucy wang - Sun Microsystems - Beijing China + 8; 370804b6cca3Slucy wang - Sun Microsystems - Beijing China req_bytes = kmem_alloc(req_size, KM_SLEEP); 370904b6cca3Slucy wang - Sun Microsystems - Beijing China tx_info_size = sizeof (*tx_info) * (MYRI10GE_MAX_SEND_DESC_TSO + 1); 371004b6cca3Slucy wang - Sun Microsystems - Beijing China tx_info = kmem_alloc(tx_info_size, KM_SLEEP); 371104b6cca3Slucy wang - Sun Microsystems - Beijing China #else 371204b6cca3Slucy wang - Sun Microsystems - Beijing China char req_bytes[sizeof (*req_list) * (MYRI10GE_MAX_SEND_DESC_TSO + 4) 371304b6cca3Slucy wang - Sun Microsystems - Beijing China + 8]; 371404b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_tx_buffer_state tx_info[MYRI10GE_MAX_SEND_DESC_TSO + 1]; 371504b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 371604b6cca3Slucy wang - Sun Microsystems - Beijing China 371704b6cca3Slucy wang - Sun Microsystems - Beijing China /* ensure req_list entries are aligned to 8 bytes */ 371804b6cca3Slucy wang - Sun Microsystems - Beijing China req_list = (struct mcp_kreq_ether_send *) 371904b6cca3Slucy wang - Sun Microsystems - Beijing China (((unsigned long)req_bytes + 7UL) & ~7UL); 372004b6cca3Slucy wang - Sun Microsystems - Beijing China 372104b6cca3Slucy wang - Sun Microsystems - Beijing China err = myri10ge_send(ss, mp, req_list, tx_info); 372204b6cca3Slucy wang - Sun Microsystems - Beijing China 372304b6cca3Slucy wang - Sun Microsystems - Beijing China #if defined(__i386) 372404b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(tx_info, tx_info_size); 372504b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(req_bytes, req_size); 372604b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 372704b6cca3Slucy wang - Sun Microsystems - Beijing China if (err) 372804b6cca3Slucy wang - Sun Microsystems - Beijing China return (mp); 372904b6cca3Slucy wang - Sun Microsystems - Beijing China else 373004b6cca3Slucy wang - Sun Microsystems - Beijing China return (NULL); 373104b6cca3Slucy wang - Sun Microsystems - Beijing China } 373204b6cca3Slucy wang - Sun Microsystems - Beijing China 373304b6cca3Slucy wang - Sun Microsystems - Beijing China static int 373404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_addmac(void *arg, const uint8_t *mac_addr) 373504b6cca3Slucy wang - Sun Microsystems - Beijing China { 373604b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = arg; 373704b6cca3Slucy wang - Sun Microsystems - Beijing China int err; 373804b6cca3Slucy wang - Sun Microsystems - Beijing China 373904b6cca3Slucy wang - Sun Microsystems - Beijing China if (mac_addr == NULL) 374004b6cca3Slucy wang - Sun Microsystems - Beijing China return (EINVAL); 374104b6cca3Slucy wang - Sun Microsystems - Beijing China 374204b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&mgp->intrlock); 374304b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->macaddr_cnt) { 374404b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->intrlock); 374504b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENOSPC); 374604b6cca3Slucy wang - Sun Microsystems - Beijing China } 374704b6cca3Slucy wang - Sun Microsystems - Beijing China err = myri10ge_m_unicst(mgp, mac_addr); 374804b6cca3Slucy wang - Sun Microsystems - Beijing China if (!err) 374904b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->macaddr_cnt++; 375004b6cca3Slucy wang - Sun Microsystems - Beijing China 375104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->intrlock); 375204b6cca3Slucy wang - Sun Microsystems - Beijing China if (err) 375304b6cca3Slucy wang - Sun Microsystems - Beijing China return (err); 375404b6cca3Slucy wang - Sun Microsystems - Beijing China 375504b6cca3Slucy wang - Sun Microsystems - Beijing China bcopy(mac_addr, mgp->mac_addr, sizeof (mgp->mac_addr)); 375604b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 375704b6cca3Slucy wang - Sun Microsystems - Beijing China } 375804b6cca3Slucy wang - Sun Microsystems - Beijing China 375904b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/ 376004b6cca3Slucy wang - Sun Microsystems - Beijing China static int 376104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_remmac(void *arg, const uint8_t *mac_addr) 376204b6cca3Slucy wang - Sun Microsystems - Beijing China { 376304b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = arg; 376404b6cca3Slucy wang - Sun Microsystems - Beijing China 376504b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&mgp->intrlock); 376604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->macaddr_cnt--; 376704b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->intrlock); 376804b6cca3Slucy wang - Sun Microsystems - Beijing China 376904b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 377004b6cca3Slucy wang - Sun Microsystems - Beijing China } 377104b6cca3Slucy wang - Sun Microsystems - Beijing China 377204b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/ 377304b6cca3Slucy wang - Sun Microsystems - Beijing China static void 377404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_fill_group(void *arg, mac_ring_type_t rtype, const int index, 377504b6cca3Slucy wang - Sun Microsystems - Beijing China mac_group_info_t *infop, mac_group_handle_t gh) 377604b6cca3Slucy wang - Sun Microsystems - Beijing China { 377704b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = arg; 377804b6cca3Slucy wang - Sun Microsystems - Beijing China 377904b6cca3Slucy wang - Sun Microsystems - Beijing China if (rtype != MAC_RING_TYPE_RX) 378004b6cca3Slucy wang - Sun Microsystems - Beijing China return; 378104b6cca3Slucy wang - Sun Microsystems - Beijing China 378204b6cca3Slucy wang - Sun Microsystems - Beijing China infop->mgi_driver = (mac_group_driver_t)mgp; 378304b6cca3Slucy wang - Sun Microsystems - Beijing China infop->mgi_start = NULL; 378404b6cca3Slucy wang - Sun Microsystems - Beijing China infop->mgi_stop = NULL; 378504b6cca3Slucy wang - Sun Microsystems - Beijing China infop->mgi_addmac = myri10ge_addmac; 378604b6cca3Slucy wang - Sun Microsystems - Beijing China infop->mgi_remmac = myri10ge_remmac; 378704b6cca3Slucy wang - Sun Microsystems - Beijing China infop->mgi_count = mgp->num_slices; 378804b6cca3Slucy wang - Sun Microsystems - Beijing China } 378904b6cca3Slucy wang - Sun Microsystems - Beijing China 379004b6cca3Slucy wang - Sun Microsystems - Beijing China static int 379104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num) 379204b6cca3Slucy wang - Sun Microsystems - Beijing China { 379304b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_slice_state *ss; 379404b6cca3Slucy wang - Sun Microsystems - Beijing China 379504b6cca3Slucy wang - Sun Microsystems - Beijing China ss = (struct myri10ge_slice_state *)rh; 379604b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&ss->rx_lock); 379704b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_gen_num = mr_gen_num; 379804b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&ss->rx_lock); 379904b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 380004b6cca3Slucy wang - Sun Microsystems - Beijing China } 380104b6cca3Slucy wang - Sun Microsystems - Beijing China 38020dc2366fSVenugopal Iyer /* 38030dc2366fSVenugopal Iyer * Retrieve a value for one of the statistics for a particular rx ring 38040dc2366fSVenugopal Iyer */ 38050dc2366fSVenugopal Iyer int 38060dc2366fSVenugopal Iyer myri10ge_rx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val) 38070dc2366fSVenugopal Iyer { 38080dc2366fSVenugopal Iyer struct myri10ge_slice_state *ss; 38090dc2366fSVenugopal Iyer 38100dc2366fSVenugopal Iyer ss = (struct myri10ge_slice_state *)rh; 38110dc2366fSVenugopal Iyer switch (stat) { 38120dc2366fSVenugopal Iyer case MAC_STAT_RBYTES: 38130dc2366fSVenugopal Iyer *val = ss->rx_stats.ibytes; 38140dc2366fSVenugopal Iyer break; 38150dc2366fSVenugopal Iyer 38160dc2366fSVenugopal Iyer case MAC_STAT_IPACKETS: 38170dc2366fSVenugopal Iyer *val = ss->rx_stats.ipackets; 38180dc2366fSVenugopal Iyer break; 38190dc2366fSVenugopal Iyer 38200dc2366fSVenugopal Iyer default: 38210dc2366fSVenugopal Iyer *val = 0; 38220dc2366fSVenugopal Iyer return (ENOTSUP); 38230dc2366fSVenugopal Iyer } 38240dc2366fSVenugopal Iyer 38250dc2366fSVenugopal Iyer return (0); 38260dc2366fSVenugopal Iyer } 38270dc2366fSVenugopal Iyer 38280dc2366fSVenugopal Iyer /* 38290dc2366fSVenugopal Iyer * Retrieve a value for one of the statistics for a particular tx ring 38300dc2366fSVenugopal Iyer */ 38310dc2366fSVenugopal Iyer int 38320dc2366fSVenugopal Iyer myri10ge_tx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val) 38330dc2366fSVenugopal Iyer { 38340dc2366fSVenugopal Iyer struct myri10ge_slice_state *ss; 38350dc2366fSVenugopal Iyer 38360dc2366fSVenugopal Iyer ss = (struct myri10ge_slice_state *)rh; 38370dc2366fSVenugopal Iyer switch (stat) { 38380dc2366fSVenugopal Iyer case MAC_STAT_OBYTES: 38390dc2366fSVenugopal Iyer *val = ss->tx.stats.obytes; 38400dc2366fSVenugopal Iyer break; 38410dc2366fSVenugopal Iyer 38420dc2366fSVenugopal Iyer case MAC_STAT_OPACKETS: 38430dc2366fSVenugopal Iyer *val = ss->tx.stats.opackets; 38440dc2366fSVenugopal Iyer break; 38450dc2366fSVenugopal Iyer 38460dc2366fSVenugopal Iyer default: 38470dc2366fSVenugopal Iyer *val = 0; 38480dc2366fSVenugopal Iyer return (ENOTSUP); 38490dc2366fSVenugopal Iyer } 38500dc2366fSVenugopal Iyer 38510dc2366fSVenugopal Iyer return (0); 38520dc2366fSVenugopal Iyer } 38530dc2366fSVenugopal Iyer 385404b6cca3Slucy wang - Sun Microsystems - Beijing China static int 385504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rx_ring_intr_disable(mac_intr_handle_t intrh) 385604b6cca3Slucy wang - Sun Microsystems - Beijing China { 385704b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_slice_state *ss; 385804b6cca3Slucy wang - Sun Microsystems - Beijing China 385904b6cca3Slucy wang - Sun Microsystems - Beijing China ss = (struct myri10ge_slice_state *)intrh; 386004b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&ss->poll_lock); 386104b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_polling = B_TRUE; 386204b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&ss->poll_lock); 386304b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 386404b6cca3Slucy wang - Sun Microsystems - Beijing China } 386504b6cca3Slucy wang - Sun Microsystems - Beijing China 386604b6cca3Slucy wang - Sun Microsystems - Beijing China static int 386704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rx_ring_intr_enable(mac_intr_handle_t intrh) 386804b6cca3Slucy wang - Sun Microsystems - Beijing China { 386904b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_slice_state *ss; 387004b6cca3Slucy wang - Sun Microsystems - Beijing China 387104b6cca3Slucy wang - Sun Microsystems - Beijing China ss = (struct myri10ge_slice_state *)intrh; 387204b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&ss->poll_lock); 387304b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_polling = B_FALSE; 387404b6cca3Slucy wang - Sun Microsystems - Beijing China if (ss->rx_token) { 387504b6cca3Slucy wang - Sun Microsystems - Beijing China *ss->irq_claim = BE_32(3); 387604b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_token = 0; 387704b6cca3Slucy wang - Sun Microsystems - Beijing China } 387804b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&ss->poll_lock); 387904b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 388004b6cca3Slucy wang - Sun Microsystems - Beijing China } 388104b6cca3Slucy wang - Sun Microsystems - Beijing China 388204b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/ 388304b6cca3Slucy wang - Sun Microsystems - Beijing China static void 388404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index, 388504b6cca3Slucy wang - Sun Microsystems - Beijing China const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh) 388604b6cca3Slucy wang - Sun Microsystems - Beijing China { 388704b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = arg; 388804b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_slice_state *ss; 388904b6cca3Slucy wang - Sun Microsystems - Beijing China mac_intr_t *mintr = &infop->mri_intr; 389004b6cca3Slucy wang - Sun Microsystems - Beijing China 389104b6cca3Slucy wang - Sun Microsystems - Beijing China ASSERT((unsigned int)ring_index < mgp->num_slices); 389204b6cca3Slucy wang - Sun Microsystems - Beijing China 389304b6cca3Slucy wang - Sun Microsystems - Beijing China ss = &mgp->ss[ring_index]; 389404b6cca3Slucy wang - Sun Microsystems - Beijing China switch (rtype) { 389504b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_RING_TYPE_RX: 389604b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_rh = rh; 389704b6cca3Slucy wang - Sun Microsystems - Beijing China infop->mri_driver = (mac_ring_driver_t)ss; 389804b6cca3Slucy wang - Sun Microsystems - Beijing China infop->mri_start = myri10ge_ring_start; 389904b6cca3Slucy wang - Sun Microsystems - Beijing China infop->mri_stop = NULL; 390004b6cca3Slucy wang - Sun Microsystems - Beijing China infop->mri_poll = myri10ge_poll_rx; 39010dc2366fSVenugopal Iyer infop->mri_stat = myri10ge_rx_ring_stat; 390204b6cca3Slucy wang - Sun Microsystems - Beijing China mintr->mi_handle = (mac_intr_handle_t)ss; 390304b6cca3Slucy wang - Sun Microsystems - Beijing China mintr->mi_enable = myri10ge_rx_ring_intr_enable; 390404b6cca3Slucy wang - Sun Microsystems - Beijing China mintr->mi_disable = myri10ge_rx_ring_intr_disable; 390504b6cca3Slucy wang - Sun Microsystems - Beijing China break; 390604b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_RING_TYPE_TX: 390704b6cca3Slucy wang - Sun Microsystems - Beijing China ss->tx.rh = rh; 390804b6cca3Slucy wang - Sun Microsystems - Beijing China infop->mri_driver = (mac_ring_driver_t)ss; 390904b6cca3Slucy wang - Sun Microsystems - Beijing China infop->mri_start = NULL; 391004b6cca3Slucy wang - Sun Microsystems - Beijing China infop->mri_stop = NULL; 391104b6cca3Slucy wang - Sun Microsystems - Beijing China infop->mri_tx = myri10ge_send_wrapper; 39120dc2366fSVenugopal Iyer infop->mri_stat = myri10ge_tx_ring_stat; 391304b6cca3Slucy wang - Sun Microsystems - Beijing China break; 391404b6cca3Slucy wang - Sun Microsystems - Beijing China default: 391504b6cca3Slucy wang - Sun Microsystems - Beijing China break; 391604b6cca3Slucy wang - Sun Microsystems - Beijing China } 391704b6cca3Slucy wang - Sun Microsystems - Beijing China } 391804b6cca3Slucy wang - Sun Microsystems - Beijing China 391904b6cca3Slucy wang - Sun Microsystems - Beijing China static void 392004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_nic_stat_destroy(struct myri10ge_priv *mgp) 392104b6cca3Slucy wang - Sun Microsystems - Beijing China { 392204b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->ksp_stat == NULL) 392304b6cca3Slucy wang - Sun Microsystems - Beijing China return; 392404b6cca3Slucy wang - Sun Microsystems - Beijing China 392504b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_delete(mgp->ksp_stat); 392604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->ksp_stat = NULL; 392704b6cca3Slucy wang - Sun Microsystems - Beijing China } 392804b6cca3Slucy wang - Sun Microsystems - Beijing China 392904b6cca3Slucy wang - Sun Microsystems - Beijing China static void 393004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_slice_stat_destroy(struct myri10ge_slice_state *ss) 393104b6cca3Slucy wang - Sun Microsystems - Beijing China { 393204b6cca3Slucy wang - Sun Microsystems - Beijing China if (ss->ksp_stat == NULL) 393304b6cca3Slucy wang - Sun Microsystems - Beijing China return; 393404b6cca3Slucy wang - Sun Microsystems - Beijing China 393504b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_delete(ss->ksp_stat); 393604b6cca3Slucy wang - Sun Microsystems - Beijing China ss->ksp_stat = NULL; 393704b6cca3Slucy wang - Sun Microsystems - Beijing China } 393804b6cca3Slucy wang - Sun Microsystems - Beijing China 393904b6cca3Slucy wang - Sun Microsystems - Beijing China static void 394004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_info_destroy(struct myri10ge_priv *mgp) 394104b6cca3Slucy wang - Sun Microsystems - Beijing China { 394204b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->ksp_info == NULL) 394304b6cca3Slucy wang - Sun Microsystems - Beijing China return; 394404b6cca3Slucy wang - Sun Microsystems - Beijing China 394504b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_delete(mgp->ksp_info); 394604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->ksp_info = NULL; 394704b6cca3Slucy wang - Sun Microsystems - Beijing China } 394804b6cca3Slucy wang - Sun Microsystems - Beijing China 394904b6cca3Slucy wang - Sun Microsystems - Beijing China static int 395004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_nic_stat_kstat_update(kstat_t *ksp, int rw) 395104b6cca3Slucy wang - Sun Microsystems - Beijing China { 395204b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_nic_stat *ethstat; 395304b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp; 395404b6cca3Slucy wang - Sun Microsystems - Beijing China mcp_irq_data_t *fw_stats; 395504b6cca3Slucy wang - Sun Microsystems - Beijing China 395604b6cca3Slucy wang - Sun Microsystems - Beijing China 395704b6cca3Slucy wang - Sun Microsystems - Beijing China if (rw == KSTAT_WRITE) 395804b6cca3Slucy wang - Sun Microsystems - Beijing China return (EACCES); 395904b6cca3Slucy wang - Sun Microsystems - Beijing China 396004b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat = (struct myri10ge_nic_stat *)ksp->ks_data; 396104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp = (struct myri10ge_priv *)ksp->ks_private; 396204b6cca3Slucy wang - Sun Microsystems - Beijing China fw_stats = mgp->ss[0].fw_stats; 396304b6cca3Slucy wang - Sun Microsystems - Beijing China 396404b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->dma_read_bw_MBs.value.ul = mgp->read_dma; 396504b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->dma_write_bw_MBs.value.ul = mgp->write_dma; 396604b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->dma_read_write_bw_MBs.value.ul = mgp->read_write_dma; 396704b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_tx_dma_attr.dma_attr_flags & DDI_DMA_FORCE_PHYSICAL) 396804b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->dma_force_physical.value.ul = 1; 396904b6cca3Slucy wang - Sun Microsystems - Beijing China else 397004b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->dma_force_physical.value.ul = 0; 397104b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->lanes.value.ul = mgp->pcie_link_width; 397204b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->dropped_bad_crc32.value.ul = 397304b6cca3Slucy wang - Sun Microsystems - Beijing China ntohl(fw_stats->dropped_bad_crc32); 397404b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->dropped_bad_phy.value.ul = 397504b6cca3Slucy wang - Sun Microsystems - Beijing China ntohl(fw_stats->dropped_bad_phy); 397604b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->dropped_link_error_or_filtered.value.ul = 397704b6cca3Slucy wang - Sun Microsystems - Beijing China ntohl(fw_stats->dropped_link_error_or_filtered); 397804b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->dropped_link_overflow.value.ul = 397904b6cca3Slucy wang - Sun Microsystems - Beijing China ntohl(fw_stats->dropped_link_overflow); 398004b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->dropped_multicast_filtered.value.ul = 398104b6cca3Slucy wang - Sun Microsystems - Beijing China ntohl(fw_stats->dropped_multicast_filtered); 398204b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->dropped_no_big_buffer.value.ul = 398304b6cca3Slucy wang - Sun Microsystems - Beijing China ntohl(fw_stats->dropped_no_big_buffer); 398404b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->dropped_no_small_buffer.value.ul = 398504b6cca3Slucy wang - Sun Microsystems - Beijing China ntohl(fw_stats->dropped_no_small_buffer); 398604b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->dropped_overrun.value.ul = 398704b6cca3Slucy wang - Sun Microsystems - Beijing China ntohl(fw_stats->dropped_overrun); 398804b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->dropped_pause.value.ul = 398904b6cca3Slucy wang - Sun Microsystems - Beijing China ntohl(fw_stats->dropped_pause); 399004b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->dropped_runt.value.ul = 399104b6cca3Slucy wang - Sun Microsystems - Beijing China ntohl(fw_stats->dropped_runt); 399204b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->link_up.value.ul = 399304b6cca3Slucy wang - Sun Microsystems - Beijing China ntohl(fw_stats->link_up); 399404b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->dropped_unicast_filtered.value.ul = 399504b6cca3Slucy wang - Sun Microsystems - Beijing China ntohl(fw_stats->dropped_unicast_filtered); 399604b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 399704b6cca3Slucy wang - Sun Microsystems - Beijing China } 399804b6cca3Slucy wang - Sun Microsystems - Beijing China 399904b6cca3Slucy wang - Sun Microsystems - Beijing China static int 400004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_slice_stat_kstat_update(kstat_t *ksp, int rw) 400104b6cca3Slucy wang - Sun Microsystems - Beijing China { 400204b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_slice_stat *ethstat; 400304b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_slice_state *ss; 400404b6cca3Slucy wang - Sun Microsystems - Beijing China 400504b6cca3Slucy wang - Sun Microsystems - Beijing China if (rw == KSTAT_WRITE) 400604b6cca3Slucy wang - Sun Microsystems - Beijing China return (EACCES); 400704b6cca3Slucy wang - Sun Microsystems - Beijing China 400804b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat = (struct myri10ge_slice_stat *)ksp->ks_data; 400904b6cca3Slucy wang - Sun Microsystems - Beijing China ss = (struct myri10ge_slice_state *)ksp->ks_private; 401004b6cca3Slucy wang - Sun Microsystems - Beijing China 401104b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->rx_big.value.ul = ss->j_rx_cnt; 401204b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->rx_bigbuf_firmware.value.ul = ss->rx_big.cnt - ss->j_rx_cnt; 401304b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->rx_bigbuf_pool.value.ul = 401404b6cca3Slucy wang - Sun Microsystems - Beijing China ss->jpool.num_alloc - ss->jbufs_for_smalls; 401504b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->rx_bigbuf_smalls.value.ul = ss->jbufs_for_smalls; 401604b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->rx_small.value.ul = ss->rx_small.cnt - 401704b6cca3Slucy wang - Sun Microsystems - Beijing China (ss->rx_small.mask + 1); 401804b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->tx_done.value.ul = ss->tx.done; 401904b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->tx_req.value.ul = ss->tx.req; 402004b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->tx_activate.value.ul = ss->tx.activate; 402104b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->xmit_sched.value.ul = ss->tx.sched; 402204b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->xmit_stall.value.ul = ss->tx.stall; 402304b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->xmit_stall_early.value.ul = ss->tx.stall_early; 402404b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->xmit_stall_late.value.ul = ss->tx.stall_late; 402504b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat->xmit_err.value.ul = MYRI10GE_SLICE_STAT(xmit_err); 402604b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 402704b6cca3Slucy wang - Sun Microsystems - Beijing China } 402804b6cca3Slucy wang - Sun Microsystems - Beijing China 402904b6cca3Slucy wang - Sun Microsystems - Beijing China static int 403004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_info_kstat_update(kstat_t *ksp, int rw) 403104b6cca3Slucy wang - Sun Microsystems - Beijing China { 403204b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_info *info; 403304b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp; 403404b6cca3Slucy wang - Sun Microsystems - Beijing China 403504b6cca3Slucy wang - Sun Microsystems - Beijing China 403604b6cca3Slucy wang - Sun Microsystems - Beijing China if (rw == KSTAT_WRITE) 403704b6cca3Slucy wang - Sun Microsystems - Beijing China return (EACCES); 403804b6cca3Slucy wang - Sun Microsystems - Beijing China 403904b6cca3Slucy wang - Sun Microsystems - Beijing China info = (struct myri10ge_info *)ksp->ks_data; 404004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp = (struct myri10ge_priv *)ksp->ks_private; 404104b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_setstr(&info->driver_version, MYRI10GE_VERSION_STR); 404204b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_setstr(&info->firmware_version, mgp->fw_version); 404304b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_setstr(&info->firmware_name, mgp->fw_name); 404404b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_setstr(&info->interrupt_type, mgp->intr_type); 404504b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_setstr(&info->product_code, mgp->pc_str); 404604b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_setstr(&info->serial_number, mgp->sn_str); 404704b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 404804b6cca3Slucy wang - Sun Microsystems - Beijing China } 404904b6cca3Slucy wang - Sun Microsystems - Beijing China 405004b6cca3Slucy wang - Sun Microsystems - Beijing China static struct myri10ge_info myri10ge_info_template = { 405104b6cca3Slucy wang - Sun Microsystems - Beijing China { "driver_version", KSTAT_DATA_STRING }, 405204b6cca3Slucy wang - Sun Microsystems - Beijing China { "firmware_version", KSTAT_DATA_STRING }, 405304b6cca3Slucy wang - Sun Microsystems - Beijing China { "firmware_name", KSTAT_DATA_STRING }, 405404b6cca3Slucy wang - Sun Microsystems - Beijing China { "interrupt_type", KSTAT_DATA_STRING }, 405504b6cca3Slucy wang - Sun Microsystems - Beijing China { "product_code", KSTAT_DATA_STRING }, 405604b6cca3Slucy wang - Sun Microsystems - Beijing China { "serial_number", KSTAT_DATA_STRING }, 405704b6cca3Slucy wang - Sun Microsystems - Beijing China }; 405804b6cca3Slucy wang - Sun Microsystems - Beijing China static kmutex_t myri10ge_info_template_lock; 405904b6cca3Slucy wang - Sun Microsystems - Beijing China 406004b6cca3Slucy wang - Sun Microsystems - Beijing China 406104b6cca3Slucy wang - Sun Microsystems - Beijing China static int 406204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_info_init(struct myri10ge_priv *mgp) 406304b6cca3Slucy wang - Sun Microsystems - Beijing China { 406404b6cca3Slucy wang - Sun Microsystems - Beijing China struct kstat *ksp; 406504b6cca3Slucy wang - Sun Microsystems - Beijing China 406604b6cca3Slucy wang - Sun Microsystems - Beijing China ksp = kstat_create("myri10ge", ddi_get_instance(mgp->dip), 406704b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_info", "net", KSTAT_TYPE_NAMED, 406804b6cca3Slucy wang - Sun Microsystems - Beijing China sizeof (myri10ge_info_template) / 406904b6cca3Slucy wang - Sun Microsystems - Beijing China sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL); 407004b6cca3Slucy wang - Sun Microsystems - Beijing China if (ksp == NULL) { 407104b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 407204b6cca3Slucy wang - Sun Microsystems - Beijing China "%s: myri10ge_info_init: kstat_create failed", mgp->name); 407304b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 407404b6cca3Slucy wang - Sun Microsystems - Beijing China } 407504b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->ksp_info = ksp; 407604b6cca3Slucy wang - Sun Microsystems - Beijing China ksp->ks_update = myri10ge_info_kstat_update; 407704b6cca3Slucy wang - Sun Microsystems - Beijing China ksp->ks_private = (void *) mgp; 407804b6cca3Slucy wang - Sun Microsystems - Beijing China ksp->ks_data = &myri10ge_info_template; 407904b6cca3Slucy wang - Sun Microsystems - Beijing China ksp->ks_lock = &myri10ge_info_template_lock; 408004b6cca3Slucy wang - Sun Microsystems - Beijing China if (MYRI10GE_VERSION_STR != NULL) 408104b6cca3Slucy wang - Sun Microsystems - Beijing China ksp->ks_data_size += strlen(MYRI10GE_VERSION_STR) + 1; 408204b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->fw_version != NULL) 408304b6cca3Slucy wang - Sun Microsystems - Beijing China ksp->ks_data_size += strlen(mgp->fw_version) + 1; 408404b6cca3Slucy wang - Sun Microsystems - Beijing China ksp->ks_data_size += strlen(mgp->fw_name) + 1; 408504b6cca3Slucy wang - Sun Microsystems - Beijing China ksp->ks_data_size += strlen(mgp->intr_type) + 1; 408604b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->pc_str != NULL) 408704b6cca3Slucy wang - Sun Microsystems - Beijing China ksp->ks_data_size += strlen(mgp->pc_str) + 1; 408804b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->sn_str != NULL) 408904b6cca3Slucy wang - Sun Microsystems - Beijing China ksp->ks_data_size += strlen(mgp->sn_str) + 1; 409004b6cca3Slucy wang - Sun Microsystems - Beijing China 409104b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_install(ksp); 409204b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 409304b6cca3Slucy wang - Sun Microsystems - Beijing China } 409404b6cca3Slucy wang - Sun Microsystems - Beijing China 409504b6cca3Slucy wang - Sun Microsystems - Beijing China 409604b6cca3Slucy wang - Sun Microsystems - Beijing China static int 409704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_nic_stat_init(struct myri10ge_priv *mgp) 409804b6cca3Slucy wang - Sun Microsystems - Beijing China { 409904b6cca3Slucy wang - Sun Microsystems - Beijing China struct kstat *ksp; 410004b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_nic_stat *ethstat; 410104b6cca3Slucy wang - Sun Microsystems - Beijing China 410204b6cca3Slucy wang - Sun Microsystems - Beijing China ksp = kstat_create("myri10ge", ddi_get_instance(mgp->dip), 410304b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_nic_stats", "net", KSTAT_TYPE_NAMED, 410404b6cca3Slucy wang - Sun Microsystems - Beijing China sizeof (*ethstat) / sizeof (kstat_named_t), 0); 410504b6cca3Slucy wang - Sun Microsystems - Beijing China if (ksp == NULL) { 410604b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 410704b6cca3Slucy wang - Sun Microsystems - Beijing China "%s: myri10ge_stat_init: kstat_create failed", mgp->name); 410804b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 410904b6cca3Slucy wang - Sun Microsystems - Beijing China } 411004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->ksp_stat = ksp; 411104b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat = (struct myri10ge_nic_stat *)(ksp->ks_data); 411204b6cca3Slucy wang - Sun Microsystems - Beijing China 411304b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->dma_read_bw_MBs, 411404b6cca3Slucy wang - Sun Microsystems - Beijing China "dma_read_bw_MBs", KSTAT_DATA_ULONG); 411504b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->dma_write_bw_MBs, 411604b6cca3Slucy wang - Sun Microsystems - Beijing China "dma_write_bw_MBs", KSTAT_DATA_ULONG); 411704b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->dma_read_write_bw_MBs, 411804b6cca3Slucy wang - Sun Microsystems - Beijing China "dma_read_write_bw_MBs", KSTAT_DATA_ULONG); 411904b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->dma_force_physical, 412004b6cca3Slucy wang - Sun Microsystems - Beijing China "dma_force_physical", KSTAT_DATA_ULONG); 412104b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->lanes, 412204b6cca3Slucy wang - Sun Microsystems - Beijing China "lanes", KSTAT_DATA_ULONG); 412304b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->dropped_bad_crc32, 412404b6cca3Slucy wang - Sun Microsystems - Beijing China "dropped_bad_crc32", KSTAT_DATA_ULONG); 412504b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->dropped_bad_phy, 412604b6cca3Slucy wang - Sun Microsystems - Beijing China "dropped_bad_phy", KSTAT_DATA_ULONG); 412704b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->dropped_link_error_or_filtered, 412804b6cca3Slucy wang - Sun Microsystems - Beijing China "dropped_link_error_or_filtered", KSTAT_DATA_ULONG); 412904b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->dropped_link_overflow, 413004b6cca3Slucy wang - Sun Microsystems - Beijing China "dropped_link_overflow", KSTAT_DATA_ULONG); 413104b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->dropped_multicast_filtered, 413204b6cca3Slucy wang - Sun Microsystems - Beijing China "dropped_multicast_filtered", KSTAT_DATA_ULONG); 413304b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->dropped_no_big_buffer, 413404b6cca3Slucy wang - Sun Microsystems - Beijing China "dropped_no_big_buffer", KSTAT_DATA_ULONG); 413504b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->dropped_no_small_buffer, 413604b6cca3Slucy wang - Sun Microsystems - Beijing China "dropped_no_small_buffer", KSTAT_DATA_ULONG); 413704b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->dropped_overrun, 413804b6cca3Slucy wang - Sun Microsystems - Beijing China "dropped_overrun", KSTAT_DATA_ULONG); 413904b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->dropped_pause, 414004b6cca3Slucy wang - Sun Microsystems - Beijing China "dropped_pause", KSTAT_DATA_ULONG); 414104b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->dropped_runt, 414204b6cca3Slucy wang - Sun Microsystems - Beijing China "dropped_runt", KSTAT_DATA_ULONG); 414304b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->dropped_unicast_filtered, 414404b6cca3Slucy wang - Sun Microsystems - Beijing China "dropped_unicast_filtered", KSTAT_DATA_ULONG); 414504b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->dropped_runt, "dropped_runt", 414604b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 414704b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->link_up, "link_up", KSTAT_DATA_ULONG); 414804b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->link_changes, "link_changes", 414904b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 415004b6cca3Slucy wang - Sun Microsystems - Beijing China ksp->ks_update = myri10ge_nic_stat_kstat_update; 415104b6cca3Slucy wang - Sun Microsystems - Beijing China ksp->ks_private = (void *) mgp; 415204b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_install(ksp); 415304b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 415404b6cca3Slucy wang - Sun Microsystems - Beijing China } 415504b6cca3Slucy wang - Sun Microsystems - Beijing China 415604b6cca3Slucy wang - Sun Microsystems - Beijing China static int 415704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_slice_stat_init(struct myri10ge_slice_state *ss) 415804b6cca3Slucy wang - Sun Microsystems - Beijing China { 415904b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = ss->mgp; 416004b6cca3Slucy wang - Sun Microsystems - Beijing China struct kstat *ksp; 416104b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_slice_stat *ethstat; 416204b6cca3Slucy wang - Sun Microsystems - Beijing China int instance; 416304b6cca3Slucy wang - Sun Microsystems - Beijing China 416404b6cca3Slucy wang - Sun Microsystems - Beijing China /* 416504b6cca3Slucy wang - Sun Microsystems - Beijing China * fake an instance so that the same slice numbers from 416604b6cca3Slucy wang - Sun Microsystems - Beijing China * different instances do not collide 416704b6cca3Slucy wang - Sun Microsystems - Beijing China */ 416804b6cca3Slucy wang - Sun Microsystems - Beijing China instance = (ddi_get_instance(mgp->dip) * 1000) + (int)(ss - mgp->ss); 416904b6cca3Slucy wang - Sun Microsystems - Beijing China ksp = kstat_create("myri10ge", instance, 417004b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_slice_stats", "net", KSTAT_TYPE_NAMED, 417104b6cca3Slucy wang - Sun Microsystems - Beijing China sizeof (*ethstat) / sizeof (kstat_named_t), 0); 417204b6cca3Slucy wang - Sun Microsystems - Beijing China if (ksp == NULL) { 417304b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 417404b6cca3Slucy wang - Sun Microsystems - Beijing China "%s: myri10ge_stat_init: kstat_create failed", mgp->name); 417504b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 417604b6cca3Slucy wang - Sun Microsystems - Beijing China } 417704b6cca3Slucy wang - Sun Microsystems - Beijing China ss->ksp_stat = ksp; 417804b6cca3Slucy wang - Sun Microsystems - Beijing China ethstat = (struct myri10ge_slice_stat *)(ksp->ks_data); 417904b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->lro_bad_csum, "lro_bad_csum", 418004b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 418104b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->lro_flushed, "lro_flushed", 418204b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 418304b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->lro_queued, "lro_queued", 418404b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 418504b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->rx_bigbuf_firmware, "rx_bigbuf_firmware", 418604b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 418704b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->rx_bigbuf_pool, "rx_bigbuf_pool", 418804b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 418904b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->rx_bigbuf_smalls, "rx_bigbuf_smalls", 419004b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 419104b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->rx_copy, "rx_copy", 419204b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 419304b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->rx_big_nobuf, "rx_big_nobuf", 419404b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 419504b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->rx_small_nobuf, "rx_small_nobuf", 419604b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 419704b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->xmit_zero_len, "xmit_zero_len", 419804b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 419904b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->xmit_pullup, "xmit_pullup", 420004b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 420104b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->xmit_pullup_first, "xmit_pullup_first", 420204b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 420304b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->xmit_lowbuf, "xmit_lowbuf", 420404b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 420504b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->xmit_lsobadflags, "xmit_lsobadflags", 420604b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 420704b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->xmit_sched, "xmit_sched", 420804b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 420904b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->xmit_stall, "xmit_stall", 421004b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 421104b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->xmit_stall_early, "xmit_stall_early", 421204b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 421304b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->xmit_stall_late, "xmit_stall_late", 421404b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 421504b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->xmit_err, "xmit_err", 421604b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 421704b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->tx_req, "tx_req", 421804b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 421904b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->tx_activate, "tx_activate", 422004b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 422104b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->tx_done, "tx_done", 422204b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 422304b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->tx_handles_alloced, "tx_handles_alloced", 422404b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 422504b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->rx_big, "rx_big", 422604b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 422704b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_named_init(ðstat->rx_small, "rx_small", 422804b6cca3Slucy wang - Sun Microsystems - Beijing China KSTAT_DATA_ULONG); 422904b6cca3Slucy wang - Sun Microsystems - Beijing China ksp->ks_update = myri10ge_slice_stat_kstat_update; 423004b6cca3Slucy wang - Sun Microsystems - Beijing China ksp->ks_private = (void *) ss; 423104b6cca3Slucy wang - Sun Microsystems - Beijing China kstat_install(ksp); 423204b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 423304b6cca3Slucy wang - Sun Microsystems - Beijing China } 423404b6cca3Slucy wang - Sun Microsystems - Beijing China 423504b6cca3Slucy wang - Sun Microsystems - Beijing China 423604b6cca3Slucy wang - Sun Microsystems - Beijing China 42375ee6ac27SRichard Lowe #if defined __i386 || defined i386 || defined __i386__ || defined __x86_64__ 423804b6cca3Slucy wang - Sun Microsystems - Beijing China 423904b6cca3Slucy wang - Sun Microsystems - Beijing China #include <vm/hat.h> 4240a56d24eaSMark Johnson #include <sys/ddi_isa.h> 424104b6cca3Slucy wang - Sun Microsystems - Beijing China void *device_arena_alloc(size_t size, int vm_flag); 424204b6cca3Slucy wang - Sun Microsystems - Beijing China void device_arena_free(void *vaddr, size_t size); 424304b6cca3Slucy wang - Sun Microsystems - Beijing China 424404b6cca3Slucy wang - Sun Microsystems - Beijing China static void 424504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_enable_nvidia_ecrc(struct myri10ge_priv *mgp) 424604b6cca3Slucy wang - Sun Microsystems - Beijing China { 424704b6cca3Slucy wang - Sun Microsystems - Beijing China dev_info_t *parent_dip; 424804b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_acc_handle_t handle; 424904b6cca3Slucy wang - Sun Microsystems - Beijing China unsigned long bus_number, dev_number, func_number; 425004b6cca3Slucy wang - Sun Microsystems - Beijing China unsigned long cfg_pa, paddr, base, pgoffset; 425104b6cca3Slucy wang - Sun Microsystems - Beijing China char *cvaddr, *ptr; 425204b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t *ptr32; 425304b6cca3Slucy wang - Sun Microsystems - Beijing China int retval = DDI_FAILURE; 425404b6cca3Slucy wang - Sun Microsystems - Beijing China int dontcare; 425504b6cca3Slucy wang - Sun Microsystems - Beijing China uint16_t read_vid, read_did, vendor_id, device_id; 425604b6cca3Slucy wang - Sun Microsystems - Beijing China 425704b6cca3Slucy wang - Sun Microsystems - Beijing China if (!myri10ge_nvidia_ecrc_enable) 425804b6cca3Slucy wang - Sun Microsystems - Beijing China return; 425904b6cca3Slucy wang - Sun Microsystems - Beijing China 426004b6cca3Slucy wang - Sun Microsystems - Beijing China parent_dip = ddi_get_parent(mgp->dip); 426104b6cca3Slucy wang - Sun Microsystems - Beijing China if (parent_dip == NULL) { 426204b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: I'm an orphan?", mgp->name); 426304b6cca3Slucy wang - Sun Microsystems - Beijing China return; 426404b6cca3Slucy wang - Sun Microsystems - Beijing China } 426504b6cca3Slucy wang - Sun Microsystems - Beijing China 426604b6cca3Slucy wang - Sun Microsystems - Beijing China if (pci_config_setup(parent_dip, &handle) != DDI_SUCCESS) { 426704b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 426804b6cca3Slucy wang - Sun Microsystems - Beijing China "%s: Could not access my parent's registers", mgp->name); 426904b6cca3Slucy wang - Sun Microsystems - Beijing China return; 427004b6cca3Slucy wang - Sun Microsystems - Beijing China } 427104b6cca3Slucy wang - Sun Microsystems - Beijing China 427204b6cca3Slucy wang - Sun Microsystems - Beijing China vendor_id = pci_config_get16(handle, PCI_CONF_VENID); 427304b6cca3Slucy wang - Sun Microsystems - Beijing China device_id = pci_config_get16(handle, PCI_CONF_DEVID); 427404b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_teardown(&handle); 427504b6cca3Slucy wang - Sun Microsystems - Beijing China 427604b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_verbose) { 427704b6cca3Slucy wang - Sun Microsystems - Beijing China unsigned long bus_number, dev_number, func_number; 427804b6cca3Slucy wang - Sun Microsystems - Beijing China int reg_set, span; 427904b6cca3Slucy wang - Sun Microsystems - Beijing China (void) myri10ge_reg_set(parent_dip, ®_set, &span, 428004b6cca3Slucy wang - Sun Microsystems - Beijing China &bus_number, &dev_number, &func_number); 428104b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_verbose) 428204b6cca3Slucy wang - Sun Microsystems - Beijing China printf("%s: parent at %ld:%ld:%ld\n", mgp->name, 428304b6cca3Slucy wang - Sun Microsystems - Beijing China bus_number, dev_number, func_number); 428404b6cca3Slucy wang - Sun Microsystems - Beijing China } 428504b6cca3Slucy wang - Sun Microsystems - Beijing China 428604b6cca3Slucy wang - Sun Microsystems - Beijing China if (vendor_id != 0x10de) 428704b6cca3Slucy wang - Sun Microsystems - Beijing China return; 428804b6cca3Slucy wang - Sun Microsystems - Beijing China 428904b6cca3Slucy wang - Sun Microsystems - Beijing China if (device_id != 0x005d /* CK804 */ && 429004b6cca3Slucy wang - Sun Microsystems - Beijing China (device_id < 0x374 || device_id > 0x378) /* MCP55 */) { 429104b6cca3Slucy wang - Sun Microsystems - Beijing China return; 429204b6cca3Slucy wang - Sun Microsystems - Beijing China } 429304b6cca3Slucy wang - Sun Microsystems - Beijing China (void) myri10ge_reg_set(parent_dip, &dontcare, &dontcare, 429404b6cca3Slucy wang - Sun Microsystems - Beijing China &bus_number, &dev_number, &func_number); 429504b6cca3Slucy wang - Sun Microsystems - Beijing China 429604b6cca3Slucy wang - Sun Microsystems - Beijing China for (cfg_pa = 0xf0000000UL; 429704b6cca3Slucy wang - Sun Microsystems - Beijing China retval != DDI_SUCCESS && cfg_pa >= 0xe0000000UL; 429804b6cca3Slucy wang - Sun Microsystems - Beijing China cfg_pa -= 0x10000000UL) { 429904b6cca3Slucy wang - Sun Microsystems - Beijing China /* find the config space address for the nvidia bridge */ 430004b6cca3Slucy wang - Sun Microsystems - Beijing China paddr = (cfg_pa + bus_number * 0x00100000UL + 430104b6cca3Slucy wang - Sun Microsystems - Beijing China (dev_number * 8 + func_number) * 0x00001000UL); 430204b6cca3Slucy wang - Sun Microsystems - Beijing China 430304b6cca3Slucy wang - Sun Microsystems - Beijing China base = paddr & (~MMU_PAGEOFFSET); 430404b6cca3Slucy wang - Sun Microsystems - Beijing China pgoffset = paddr & MMU_PAGEOFFSET; 430504b6cca3Slucy wang - Sun Microsystems - Beijing China 430604b6cca3Slucy wang - Sun Microsystems - Beijing China /* map it into the kernel */ 430704b6cca3Slucy wang - Sun Microsystems - Beijing China cvaddr = device_arena_alloc(ptob(1), VM_NOSLEEP); 430804b6cca3Slucy wang - Sun Microsystems - Beijing China if (cvaddr == NULL) 430904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: failed to map nf4: cvaddr\n", 431004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 431104b6cca3Slucy wang - Sun Microsystems - Beijing China 4312a56d24eaSMark Johnson hat_devload(kas.a_hat, cvaddr, mmu_ptob(1), 4313a56d24eaSMark Johnson i_ddi_paddr_to_pfn(base), 431404b6cca3Slucy wang - Sun Microsystems - Beijing China PROT_WRITE|HAT_STRICTORDER, HAT_LOAD_LOCK); 431504b6cca3Slucy wang - Sun Microsystems - Beijing China 431604b6cca3Slucy wang - Sun Microsystems - Beijing China ptr = cvaddr + pgoffset; 431704b6cca3Slucy wang - Sun Microsystems - Beijing China read_vid = *(uint16_t *)(void *)(ptr + PCI_CONF_VENID); 431804b6cca3Slucy wang - Sun Microsystems - Beijing China read_did = *(uint16_t *)(void *)(ptr + PCI_CONF_DEVID); 431904b6cca3Slucy wang - Sun Microsystems - Beijing China if (vendor_id == read_did || device_id == read_did) { 432004b6cca3Slucy wang - Sun Microsystems - Beijing China ptr32 = (uint32_t *)(void *)(ptr + 0x178); 432104b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_verbose) 432204b6cca3Slucy wang - Sun Microsystems - Beijing China printf("%s: Enabling ECRC on upstream " 432304b6cca3Slucy wang - Sun Microsystems - Beijing China "Nvidia bridge (0x%x:0x%x) " 432404b6cca3Slucy wang - Sun Microsystems - Beijing China "at %ld:%ld:%ld\n", mgp->name, 432504b6cca3Slucy wang - Sun Microsystems - Beijing China read_vid, read_did, bus_number, 432604b6cca3Slucy wang - Sun Microsystems - Beijing China dev_number, func_number); 432704b6cca3Slucy wang - Sun Microsystems - Beijing China *ptr32 |= 0x40; 432804b6cca3Slucy wang - Sun Microsystems - Beijing China retval = DDI_SUCCESS; 432904b6cca3Slucy wang - Sun Microsystems - Beijing China } 433004b6cca3Slucy wang - Sun Microsystems - Beijing China hat_unload(kas.a_hat, cvaddr, ptob(1), HAT_UNLOAD_UNLOCK); 433104b6cca3Slucy wang - Sun Microsystems - Beijing China device_arena_free(cvaddr, ptob(1)); 433204b6cca3Slucy wang - Sun Microsystems - Beijing China } 433304b6cca3Slucy wang - Sun Microsystems - Beijing China } 433404b6cca3Slucy wang - Sun Microsystems - Beijing China 433504b6cca3Slucy wang - Sun Microsystems - Beijing China #else 433604b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/ 433704b6cca3Slucy wang - Sun Microsystems - Beijing China static void 433804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_enable_nvidia_ecrc(struct myri10ge_priv *mgp) 433904b6cca3Slucy wang - Sun Microsystems - Beijing China { 434004b6cca3Slucy wang - Sun Microsystems - Beijing China } 434104b6cca3Slucy wang - Sun Microsystems - Beijing China #endif /* i386 */ 434204b6cca3Slucy wang - Sun Microsystems - Beijing China 434304b6cca3Slucy wang - Sun Microsystems - Beijing China 434404b6cca3Slucy wang - Sun Microsystems - Beijing China /* 434504b6cca3Slucy wang - Sun Microsystems - Beijing China * The Lanai Z8E PCI-E interface achieves higher Read-DMA throughput 434604b6cca3Slucy wang - Sun Microsystems - Beijing China * when the PCI-E Completion packets are aligned on an 8-byte 434704b6cca3Slucy wang - Sun Microsystems - Beijing China * boundary. Some PCI-E chip sets always align Completion packets; on 434804b6cca3Slucy wang - Sun Microsystems - Beijing China * the ones that do not, the alignment can be enforced by enabling 434904b6cca3Slucy wang - Sun Microsystems - Beijing China * ECRC generation (if supported). 435004b6cca3Slucy wang - Sun Microsystems - Beijing China * 435104b6cca3Slucy wang - Sun Microsystems - Beijing China * When PCI-E Completion packets are not aligned, it is actually more 435204b6cca3Slucy wang - Sun Microsystems - Beijing China * efficient to limit Read-DMA transactions to 2KB, rather than 4KB. 435304b6cca3Slucy wang - Sun Microsystems - Beijing China * 435404b6cca3Slucy wang - Sun Microsystems - Beijing China * If the driver can neither enable ECRC nor verify that it has 435504b6cca3Slucy wang - Sun Microsystems - Beijing China * already been enabled, then it must use a firmware image which works 435604b6cca3Slucy wang - Sun Microsystems - Beijing China * around unaligned completion packets (ethp_z8e.dat), and it should 435704b6cca3Slucy wang - Sun Microsystems - Beijing China * also ensure that it never gives the device a Read-DMA which is 435804b6cca3Slucy wang - Sun Microsystems - Beijing China * larger than 2KB by setting the tx.boundary to 2KB. If ECRC is 435904b6cca3Slucy wang - Sun Microsystems - Beijing China * enabled, then the driver should use the aligned (eth_z8e.dat) 436004b6cca3Slucy wang - Sun Microsystems - Beijing China * firmware image, and set tx.boundary to 4KB. 436104b6cca3Slucy wang - Sun Microsystems - Beijing China */ 436204b6cca3Slucy wang - Sun Microsystems - Beijing China 436304b6cca3Slucy wang - Sun Microsystems - Beijing China 436404b6cca3Slucy wang - Sun Microsystems - Beijing China static int 436504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_firmware_probe(struct myri10ge_priv *mgp) 436604b6cca3Slucy wang - Sun Microsystems - Beijing China { 436704b6cca3Slucy wang - Sun Microsystems - Beijing China int status; 436804b6cca3Slucy wang - Sun Microsystems - Beijing China 436904b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->tx_boundary = 4096; 437004b6cca3Slucy wang - Sun Microsystems - Beijing China /* 437104b6cca3Slucy wang - Sun Microsystems - Beijing China * Verify the max read request size was set to 4KB 437204b6cca3Slucy wang - Sun Microsystems - Beijing China * before trying the test with 4KB. 437304b6cca3Slucy wang - Sun Microsystems - Beijing China */ 437404b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->max_read_request_4k == 0) 437504b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->tx_boundary = 2048; 437604b6cca3Slucy wang - Sun Microsystems - Beijing China /* 437704b6cca3Slucy wang - Sun Microsystems - Beijing China * load the optimized firmware which assumes aligned PCIe 437804b6cca3Slucy wang - Sun Microsystems - Beijing China * completions in order to see if it works on this host. 437904b6cca3Slucy wang - Sun Microsystems - Beijing China */ 438004b6cca3Slucy wang - Sun Microsystems - Beijing China 438104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->fw_name = "rss_eth_z8e"; 438204b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->eth_z8e = (unsigned char *)rss_eth_z8e; 438304b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->eth_z8e_length = rss_eth_z8e_length; 438404b6cca3Slucy wang - Sun Microsystems - Beijing China 438504b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_load_firmware(mgp); 438604b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 438704b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 438804b6cca3Slucy wang - Sun Microsystems - Beijing China } 438904b6cca3Slucy wang - Sun Microsystems - Beijing China /* 439004b6cca3Slucy wang - Sun Microsystems - Beijing China * Enable ECRC if possible 439104b6cca3Slucy wang - Sun Microsystems - Beijing China */ 439204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_enable_nvidia_ecrc(mgp); 439304b6cca3Slucy wang - Sun Microsystems - Beijing China 439404b6cca3Slucy wang - Sun Microsystems - Beijing China /* 439504b6cca3Slucy wang - Sun Microsystems - Beijing China * Run a DMA test which watches for unaligned completions and 439604b6cca3Slucy wang - Sun Microsystems - Beijing China * aborts on the first one seen. 439704b6cca3Slucy wang - Sun Microsystems - Beijing China */ 439804b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_dma_test(mgp, MXGEFW_CMD_UNALIGNED_TEST); 439904b6cca3Slucy wang - Sun Microsystems - Beijing China if (status == 0) 440004b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); /* keep the aligned firmware */ 440104b6cca3Slucy wang - Sun Microsystems - Beijing China 440204b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != E2BIG) 440304b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: DMA test failed: %d\n", 440404b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, status); 440504b6cca3Slucy wang - Sun Microsystems - Beijing China if (status == ENOSYS) 440604b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: Falling back to ethp! " 440704b6cca3Slucy wang - Sun Microsystems - Beijing China "Please install up to date fw\n", mgp->name); 440804b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 440904b6cca3Slucy wang - Sun Microsystems - Beijing China } 441004b6cca3Slucy wang - Sun Microsystems - Beijing China 441104b6cca3Slucy wang - Sun Microsystems - Beijing China static int 441204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_select_firmware(struct myri10ge_priv *mgp) 441304b6cca3Slucy wang - Sun Microsystems - Beijing China { 441404b6cca3Slucy wang - Sun Microsystems - Beijing China int aligned; 441504b6cca3Slucy wang - Sun Microsystems - Beijing China 441604b6cca3Slucy wang - Sun Microsystems - Beijing China aligned = 0; 441704b6cca3Slucy wang - Sun Microsystems - Beijing China 441804b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_force_firmware == 1) { 441904b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_verbose) 442004b6cca3Slucy wang - Sun Microsystems - Beijing China printf("%s: Assuming aligned completions (forced)\n", 442104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 442204b6cca3Slucy wang - Sun Microsystems - Beijing China aligned = 1; 442304b6cca3Slucy wang - Sun Microsystems - Beijing China goto done; 442404b6cca3Slucy wang - Sun Microsystems - Beijing China } 442504b6cca3Slucy wang - Sun Microsystems - Beijing China 442604b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_force_firmware == 2) { 442704b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_verbose) 442804b6cca3Slucy wang - Sun Microsystems - Beijing China printf("%s: Assuming unaligned completions (forced)\n", 442904b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 443004b6cca3Slucy wang - Sun Microsystems - Beijing China aligned = 0; 443104b6cca3Slucy wang - Sun Microsystems - Beijing China goto done; 443204b6cca3Slucy wang - Sun Microsystems - Beijing China } 443304b6cca3Slucy wang - Sun Microsystems - Beijing China 443404b6cca3Slucy wang - Sun Microsystems - Beijing China /* If the width is less than 8, we may used the aligned firmware */ 443504b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->pcie_link_width != 0 && mgp->pcie_link_width < 8) { 443604b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "!%s: PCIe link running at x%d\n", 443704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, mgp->pcie_link_width); 443804b6cca3Slucy wang - Sun Microsystems - Beijing China aligned = 1; 443904b6cca3Slucy wang - Sun Microsystems - Beijing China goto done; 444004b6cca3Slucy wang - Sun Microsystems - Beijing China } 444104b6cca3Slucy wang - Sun Microsystems - Beijing China 444204b6cca3Slucy wang - Sun Microsystems - Beijing China if (0 == myri10ge_firmware_probe(mgp)) 444304b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); /* keep optimized firmware */ 444404b6cca3Slucy wang - Sun Microsystems - Beijing China 444504b6cca3Slucy wang - Sun Microsystems - Beijing China done: 444604b6cca3Slucy wang - Sun Microsystems - Beijing China if (aligned) { 444704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->fw_name = "rss_eth_z8e"; 444804b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->eth_z8e = (unsigned char *)rss_eth_z8e; 444904b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->eth_z8e_length = rss_eth_z8e_length; 445004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->tx_boundary = 4096; 445104b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 445204b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->fw_name = "rss_ethp_z8e"; 445304b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->eth_z8e = (unsigned char *)rss_ethp_z8e; 445404b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->eth_z8e_length = rss_ethp_z8e_length; 445504b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->tx_boundary = 2048; 445604b6cca3Slucy wang - Sun Microsystems - Beijing China } 445704b6cca3Slucy wang - Sun Microsystems - Beijing China 445804b6cca3Slucy wang - Sun Microsystems - Beijing China return (myri10ge_load_firmware(mgp)); 445904b6cca3Slucy wang - Sun Microsystems - Beijing China } 446004b6cca3Slucy wang - Sun Microsystems - Beijing China 446104b6cca3Slucy wang - Sun Microsystems - Beijing China static int 446204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_add_intrs(struct myri10ge_priv *mgp, int add_handler) 446304b6cca3Slucy wang - Sun Microsystems - Beijing China { 446404b6cca3Slucy wang - Sun Microsystems - Beijing China dev_info_t *devinfo = mgp->dip; 446504b6cca3Slucy wang - Sun Microsystems - Beijing China int count, avail, actual, intr_types; 446604b6cca3Slucy wang - Sun Microsystems - Beijing China int x, y, rc, inum = 0; 446704b6cca3Slucy wang - Sun Microsystems - Beijing China 446804b6cca3Slucy wang - Sun Microsystems - Beijing China 446904b6cca3Slucy wang - Sun Microsystems - Beijing China rc = ddi_intr_get_supported_types(devinfo, &intr_types); 447004b6cca3Slucy wang - Sun Microsystems - Beijing China if (rc != DDI_SUCCESS) { 447104b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 447204b6cca3Slucy wang - Sun Microsystems - Beijing China "!%s: ddi_intr_get_nintrs() failure, rc = %d\n", mgp->name, 447304b6cca3Slucy wang - Sun Microsystems - Beijing China rc); 447404b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 447504b6cca3Slucy wang - Sun Microsystems - Beijing China } 447604b6cca3Slucy wang - Sun Microsystems - Beijing China 447704b6cca3Slucy wang - Sun Microsystems - Beijing China if (!myri10ge_use_msi) 447804b6cca3Slucy wang - Sun Microsystems - Beijing China intr_types &= ~DDI_INTR_TYPE_MSI; 447904b6cca3Slucy wang - Sun Microsystems - Beijing China if (!myri10ge_use_msix) 448004b6cca3Slucy wang - Sun Microsystems - Beijing China intr_types &= ~DDI_INTR_TYPE_MSIX; 448104b6cca3Slucy wang - Sun Microsystems - Beijing China 448204b6cca3Slucy wang - Sun Microsystems - Beijing China if (intr_types & DDI_INTR_TYPE_MSIX) { 448304b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->ddi_intr_type = DDI_INTR_TYPE_MSIX; 448404b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->intr_type = "MSI-X"; 448504b6cca3Slucy wang - Sun Microsystems - Beijing China } else if (intr_types & DDI_INTR_TYPE_MSI) { 448604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->ddi_intr_type = DDI_INTR_TYPE_MSI; 448704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->intr_type = "MSI"; 448804b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 448904b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->ddi_intr_type = DDI_INTR_TYPE_FIXED; 449004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->intr_type = "Legacy"; 449104b6cca3Slucy wang - Sun Microsystems - Beijing China } 449204b6cca3Slucy wang - Sun Microsystems - Beijing China /* Get number of interrupts */ 449304b6cca3Slucy wang - Sun Microsystems - Beijing China rc = ddi_intr_get_nintrs(devinfo, mgp->ddi_intr_type, &count); 449404b6cca3Slucy wang - Sun Microsystems - Beijing China if ((rc != DDI_SUCCESS) || (count == 0)) { 449504b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: ddi_intr_get_nintrs() failure, rc: %d, " 449604b6cca3Slucy wang - Sun Microsystems - Beijing China "count: %d", mgp->name, rc, count); 449704b6cca3Slucy wang - Sun Microsystems - Beijing China 449804b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 449904b6cca3Slucy wang - Sun Microsystems - Beijing China } 450004b6cca3Slucy wang - Sun Microsystems - Beijing China 450104b6cca3Slucy wang - Sun Microsystems - Beijing China /* Get number of available interrupts */ 450204b6cca3Slucy wang - Sun Microsystems - Beijing China rc = ddi_intr_get_navail(devinfo, mgp->ddi_intr_type, &avail); 450304b6cca3Slucy wang - Sun Microsystems - Beijing China if ((rc != DDI_SUCCESS) || (avail == 0)) { 450404b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: ddi_intr_get_navail() failure, " 450504b6cca3Slucy wang - Sun Microsystems - Beijing China "rc: %d, avail: %d\n", mgp->name, rc, avail); 450604b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 450704b6cca3Slucy wang - Sun Microsystems - Beijing China } 450804b6cca3Slucy wang - Sun Microsystems - Beijing China if (avail < count) { 450904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_NOTE, 451004b6cca3Slucy wang - Sun Microsystems - Beijing China "!%s: nintrs() returned %d, navail returned %d", 451104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, count, avail); 451204b6cca3Slucy wang - Sun Microsystems - Beijing China count = avail; 451304b6cca3Slucy wang - Sun Microsystems - Beijing China } 451404b6cca3Slucy wang - Sun Microsystems - Beijing China 451504b6cca3Slucy wang - Sun Microsystems - Beijing China if (count < mgp->num_slices) 451604b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 451704b6cca3Slucy wang - Sun Microsystems - Beijing China 451804b6cca3Slucy wang - Sun Microsystems - Beijing China if (count > mgp->num_slices) 451904b6cca3Slucy wang - Sun Microsystems - Beijing China count = mgp->num_slices; 452004b6cca3Slucy wang - Sun Microsystems - Beijing China 452104b6cca3Slucy wang - Sun Microsystems - Beijing China /* Allocate memory for MSI interrupts */ 452204b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->intr_size = count * sizeof (ddi_intr_handle_t); 452304b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->htable = kmem_alloc(mgp->intr_size, KM_SLEEP); 452404b6cca3Slucy wang - Sun Microsystems - Beijing China 452504b6cca3Slucy wang - Sun Microsystems - Beijing China rc = ddi_intr_alloc(devinfo, mgp->htable, mgp->ddi_intr_type, inum, 452604b6cca3Slucy wang - Sun Microsystems - Beijing China count, &actual, DDI_INTR_ALLOC_NORMAL); 452704b6cca3Slucy wang - Sun Microsystems - Beijing China 452804b6cca3Slucy wang - Sun Microsystems - Beijing China if ((rc != DDI_SUCCESS) || (actual == 0)) { 452904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: ddi_intr_alloc() failed: %d", 453004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, rc); 453104b6cca3Slucy wang - Sun Microsystems - Beijing China 453204b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(mgp->htable, mgp->intr_size); 453304b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->htable = NULL; 453404b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 453504b6cca3Slucy wang - Sun Microsystems - Beijing China } 453604b6cca3Slucy wang - Sun Microsystems - Beijing China 453704b6cca3Slucy wang - Sun Microsystems - Beijing China if ((actual < count) && myri10ge_verbose) { 453804b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_NOTE, "%s: got %d/%d slices", 453904b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, actual, count); 454004b6cca3Slucy wang - Sun Microsystems - Beijing China } 454104b6cca3Slucy wang - Sun Microsystems - Beijing China 454204b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->intr_cnt = actual; 454304b6cca3Slucy wang - Sun Microsystems - Beijing China 454404b6cca3Slucy wang - Sun Microsystems - Beijing China /* 454504b6cca3Slucy wang - Sun Microsystems - Beijing China * Get priority for first irq, assume remaining are all the same 454604b6cca3Slucy wang - Sun Microsystems - Beijing China */ 454704b6cca3Slucy wang - Sun Microsystems - Beijing China if (ddi_intr_get_pri(mgp->htable[0], &mgp->intr_pri) 454804b6cca3Slucy wang - Sun Microsystems - Beijing China != DDI_SUCCESS) { 454904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: ddi_intr_get_pri() failed", mgp->name); 455004b6cca3Slucy wang - Sun Microsystems - Beijing China 455104b6cca3Slucy wang - Sun Microsystems - Beijing China /* Free already allocated intr */ 455204b6cca3Slucy wang - Sun Microsystems - Beijing China for (y = 0; y < actual; y++) { 455304b6cca3Slucy wang - Sun Microsystems - Beijing China (void) ddi_intr_free(mgp->htable[y]); 455404b6cca3Slucy wang - Sun Microsystems - Beijing China } 455504b6cca3Slucy wang - Sun Microsystems - Beijing China 455604b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(mgp->htable, mgp->intr_size); 455704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->htable = NULL; 455804b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 455904b6cca3Slucy wang - Sun Microsystems - Beijing China } 456004b6cca3Slucy wang - Sun Microsystems - Beijing China 456104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->icookie = (void *)(uintptr_t)mgp->intr_pri; 456204b6cca3Slucy wang - Sun Microsystems - Beijing China 456304b6cca3Slucy wang - Sun Microsystems - Beijing China if (!add_handler) 456404b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 456504b6cca3Slucy wang - Sun Microsystems - Beijing China 456604b6cca3Slucy wang - Sun Microsystems - Beijing China /* Call ddi_intr_add_handler() */ 456704b6cca3Slucy wang - Sun Microsystems - Beijing China for (x = 0; x < actual; x++) { 456804b6cca3Slucy wang - Sun Microsystems - Beijing China if (ddi_intr_add_handler(mgp->htable[x], myri10ge_intr, 456904b6cca3Slucy wang - Sun Microsystems - Beijing China (caddr_t)&mgp->ss[x], NULL) != DDI_SUCCESS) { 457004b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: ddi_intr_add_handler() failed", 457104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 457204b6cca3Slucy wang - Sun Microsystems - Beijing China 457304b6cca3Slucy wang - Sun Microsystems - Beijing China /* Free already allocated intr */ 457404b6cca3Slucy wang - Sun Microsystems - Beijing China for (y = 0; y < actual; y++) { 457504b6cca3Slucy wang - Sun Microsystems - Beijing China (void) ddi_intr_free(mgp->htable[y]); 457604b6cca3Slucy wang - Sun Microsystems - Beijing China } 457704b6cca3Slucy wang - Sun Microsystems - Beijing China 457804b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(mgp->htable, mgp->intr_size); 457904b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->htable = NULL; 458004b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 458104b6cca3Slucy wang - Sun Microsystems - Beijing China } 458204b6cca3Slucy wang - Sun Microsystems - Beijing China } 458304b6cca3Slucy wang - Sun Microsystems - Beijing China 458404b6cca3Slucy wang - Sun Microsystems - Beijing China (void) ddi_intr_get_cap(mgp->htable[0], &mgp->intr_cap); 458504b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->intr_cap & DDI_INTR_FLAG_BLOCK) { 458604b6cca3Slucy wang - Sun Microsystems - Beijing China /* Call ddi_intr_block_enable() for MSI */ 458704b6cca3Slucy wang - Sun Microsystems - Beijing China (void) ddi_intr_block_enable(mgp->htable, mgp->intr_cnt); 458804b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 458904b6cca3Slucy wang - Sun Microsystems - Beijing China /* Call ddi_intr_enable() for MSI non block enable */ 459004b6cca3Slucy wang - Sun Microsystems - Beijing China for (x = 0; x < mgp->intr_cnt; x++) { 459104b6cca3Slucy wang - Sun Microsystems - Beijing China (void) ddi_intr_enable(mgp->htable[x]); 459204b6cca3Slucy wang - Sun Microsystems - Beijing China } 459304b6cca3Slucy wang - Sun Microsystems - Beijing China } 459404b6cca3Slucy wang - Sun Microsystems - Beijing China 459504b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 459604b6cca3Slucy wang - Sun Microsystems - Beijing China } 459704b6cca3Slucy wang - Sun Microsystems - Beijing China 459804b6cca3Slucy wang - Sun Microsystems - Beijing China static void 459904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rem_intrs(struct myri10ge_priv *mgp, int handler_installed) 460004b6cca3Slucy wang - Sun Microsystems - Beijing China { 460104b6cca3Slucy wang - Sun Microsystems - Beijing China int x, err; 460204b6cca3Slucy wang - Sun Microsystems - Beijing China 460304b6cca3Slucy wang - Sun Microsystems - Beijing China /* Disable all interrupts */ 460404b6cca3Slucy wang - Sun Microsystems - Beijing China if (handler_installed) { 460504b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->intr_cap & DDI_INTR_FLAG_BLOCK) { 460604b6cca3Slucy wang - Sun Microsystems - Beijing China /* Call ddi_intr_block_disable() */ 460704b6cca3Slucy wang - Sun Microsystems - Beijing China (void) ddi_intr_block_disable(mgp->htable, 460804b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->intr_cnt); 460904b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 461004b6cca3Slucy wang - Sun Microsystems - Beijing China for (x = 0; x < mgp->intr_cnt; x++) { 461104b6cca3Slucy wang - Sun Microsystems - Beijing China (void) ddi_intr_disable(mgp->htable[x]); 461204b6cca3Slucy wang - Sun Microsystems - Beijing China } 461304b6cca3Slucy wang - Sun Microsystems - Beijing China } 461404b6cca3Slucy wang - Sun Microsystems - Beijing China } 461504b6cca3Slucy wang - Sun Microsystems - Beijing China 461604b6cca3Slucy wang - Sun Microsystems - Beijing China for (x = 0; x < mgp->intr_cnt; x++) { 461704b6cca3Slucy wang - Sun Microsystems - Beijing China if (handler_installed) { 461804b6cca3Slucy wang - Sun Microsystems - Beijing China /* Call ddi_intr_remove_handler() */ 461904b6cca3Slucy wang - Sun Microsystems - Beijing China err = ddi_intr_remove_handler(mgp->htable[x]); 462004b6cca3Slucy wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 462104b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 462204b6cca3Slucy wang - Sun Microsystems - Beijing China "%s: ddi_intr_remove_handler for" 462304b6cca3Slucy wang - Sun Microsystems - Beijing China "vec %d returned %d\n", mgp->name, 462404b6cca3Slucy wang - Sun Microsystems - Beijing China x, err); 462504b6cca3Slucy wang - Sun Microsystems - Beijing China } 462604b6cca3Slucy wang - Sun Microsystems - Beijing China } 462704b6cca3Slucy wang - Sun Microsystems - Beijing China err = ddi_intr_free(mgp->htable[x]); 462804b6cca3Slucy wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 462904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 463004b6cca3Slucy wang - Sun Microsystems - Beijing China "%s: ddi_intr_free for vec %d returned %d\n", 463104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, x, err); 463204b6cca3Slucy wang - Sun Microsystems - Beijing China } 463304b6cca3Slucy wang - Sun Microsystems - Beijing China } 463404b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(mgp->htable, mgp->intr_size); 463504b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->htable = NULL; 463604b6cca3Slucy wang - Sun Microsystems - Beijing China } 463704b6cca3Slucy wang - Sun Microsystems - Beijing China 463804b6cca3Slucy wang - Sun Microsystems - Beijing China static void 463904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_test_physical(dev_info_t *dip) 464004b6cca3Slucy wang - Sun Microsystems - Beijing China { 464104b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_dma_handle_t handle; 464204b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_dma_stuff dma; 464304b6cca3Slucy wang - Sun Microsystems - Beijing China void *addr; 464404b6cca3Slucy wang - Sun Microsystems - Beijing China int err; 464504b6cca3Slucy wang - Sun Microsystems - Beijing China 464604b6cca3Slucy wang - Sun Microsystems - Beijing China /* test #1, sufficient for older sparc systems */ 464704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL; 464804b6cca3Slucy wang - Sun Microsystems - Beijing China err = ddi_dma_alloc_handle(dip, &myri10ge_tx_dma_attr, 464904b6cca3Slucy wang - Sun Microsystems - Beijing China DDI_DMA_DONTWAIT, NULL, &handle); 465004b6cca3Slucy wang - Sun Microsystems - Beijing China if (err == DDI_DMA_BADATTR) 465104b6cca3Slucy wang - Sun Microsystems - Beijing China goto fail; 465204b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_dma_free_handle(&handle); 465304b6cca3Slucy wang - Sun Microsystems - Beijing China 465404b6cca3Slucy wang - Sun Microsystems - Beijing China /* test #2, required on Olympis where the bind is what fails */ 465504b6cca3Slucy wang - Sun Microsystems - Beijing China addr = myri10ge_dma_alloc(dip, 128, &myri10ge_tx_dma_attr, 465604b6cca3Slucy wang - Sun Microsystems - Beijing China &myri10ge_dev_access_attr, DDI_DMA_STREAMING, 465704b6cca3Slucy wang - Sun Microsystems - Beijing China DDI_DMA_WRITE|DDI_DMA_STREAMING, &dma, 0, DDI_DMA_DONTWAIT); 465804b6cca3Slucy wang - Sun Microsystems - Beijing China if (addr == NULL) 465904b6cca3Slucy wang - Sun Microsystems - Beijing China goto fail; 466004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dma_free(&dma); 466104b6cca3Slucy wang - Sun Microsystems - Beijing China return; 466204b6cca3Slucy wang - Sun Microsystems - Beijing China 466304b6cca3Slucy wang - Sun Microsystems - Beijing China fail: 466404b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_verbose) 466504b6cca3Slucy wang - Sun Microsystems - Beijing China printf("myri10ge%d: DDI_DMA_FORCE_PHYSICAL failed, " 466604b6cca3Slucy wang - Sun Microsystems - Beijing China "using IOMMU\n", ddi_get_instance(dip)); 466704b6cca3Slucy wang - Sun Microsystems - Beijing China 466804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_dma_attr.dma_attr_flags &= ~DDI_DMA_FORCE_PHYSICAL; 466904b6cca3Slucy wang - Sun Microsystems - Beijing China } 467004b6cca3Slucy wang - Sun Microsystems - Beijing China 467104b6cca3Slucy wang - Sun Microsystems - Beijing China static void 467204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_props(dev_info_t *dip) 467304b6cca3Slucy wang - Sun Microsystems - Beijing China { 467404b6cca3Slucy wang - Sun Microsystems - Beijing China 467504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_flow_control = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 467604b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_flow_control", myri10ge_flow_control); 467704b6cca3Slucy wang - Sun Microsystems - Beijing China 467804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_intr_coal_delay = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 467904b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_intr_coal_delay", myri10ge_intr_coal_delay); 468004b6cca3Slucy wang - Sun Microsystems - Beijing China 46815ee6ac27SRichard Lowe #if defined __i386 || defined i386 || defined __i386__ || defined __x86_64__ 468204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_nvidia_ecrc_enable = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 468304b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_nvidia_ecrc_enable", 1); 468404b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 468504b6cca3Slucy wang - Sun Microsystems - Beijing China 468604b6cca3Slucy wang - Sun Microsystems - Beijing China 468704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_use_msi = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 468804b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_use_msi", myri10ge_use_msi); 468904b6cca3Slucy wang - Sun Microsystems - Beijing China 469004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_deassert_wait = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 469104b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_deassert_wait", myri10ge_deassert_wait); 469204b6cca3Slucy wang - Sun Microsystems - Beijing China 469304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_verbose = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 469404b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_verbose", myri10ge_verbose); 469504b6cca3Slucy wang - Sun Microsystems - Beijing China 469604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_copylen = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 469704b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_tx_copylen", myri10ge_tx_copylen); 469804b6cca3Slucy wang - Sun Microsystems - Beijing China 469904b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_tx_copylen < 60) { 470004b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 470104b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_tx_copylen must be >= 60 bytes\n"); 470204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_copylen = 60; 470304b6cca3Slucy wang - Sun Microsystems - Beijing China } 470404b6cca3Slucy wang - Sun Microsystems - Beijing China 470504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_mtu_override = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 470604b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_mtu_override", myri10ge_mtu_override); 470704b6cca3Slucy wang - Sun Microsystems - Beijing China 4708*6d0043d8SRobert Mustacchi if (myri10ge_mtu_override >= MYRI10GE_MIN_GLD_MTU && 4709*6d0043d8SRobert Mustacchi myri10ge_mtu_override <= MYRI10GE_MAX_GLD_MTU) 471004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_mtu = myri10ge_mtu_override + 471104b6cca3Slucy wang - Sun Microsystems - Beijing China sizeof (struct ether_header) + MXGEFW_PAD + VLAN_TAGSZ; 471204b6cca3Slucy wang - Sun Microsystems - Beijing China else if (myri10ge_mtu_override != 0) { 471304b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 471404b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_mtu_override must be between 1500 and " 471504b6cca3Slucy wang - Sun Microsystems - Beijing China "9000 bytes\n"); 471604b6cca3Slucy wang - Sun Microsystems - Beijing China } 471704b6cca3Slucy wang - Sun Microsystems - Beijing China 471804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_bigbufs_initial = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 471904b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_bigbufs_initial", myri10ge_bigbufs_initial); 472004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_bigbufs_max = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 472104b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_bigbufs_max", myri10ge_bigbufs_max); 472204b6cca3Slucy wang - Sun Microsystems - Beijing China 472304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_watchdog_reset = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 472404b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_watchdog_reset", myri10ge_watchdog_reset); 472504b6cca3Slucy wang - Sun Microsystems - Beijing China 472604b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_bigbufs_initial < 128) { 472704b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 472804b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_bigbufs_initial be at least 128\n"); 472904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_bigbufs_initial = 128; 473004b6cca3Slucy wang - Sun Microsystems - Beijing China } 473104b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_bigbufs_max < 128) { 473204b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 473304b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_bigbufs_max be at least 128\n"); 473404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_bigbufs_max = 128; 473504b6cca3Slucy wang - Sun Microsystems - Beijing China } 473604b6cca3Slucy wang - Sun Microsystems - Beijing China 473704b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_bigbufs_max < myri10ge_bigbufs_initial) { 473804b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 473904b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_bigbufs_max must be >= " 474004b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_bigbufs_initial\n"); 474104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_bigbufs_max = myri10ge_bigbufs_initial; 474204b6cca3Slucy wang - Sun Microsystems - Beijing China } 474304b6cca3Slucy wang - Sun Microsystems - Beijing China 474404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_force_firmware = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 474504b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_force_firmware", myri10ge_force_firmware); 474604b6cca3Slucy wang - Sun Microsystems - Beijing China 474704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_max_slices = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 474804b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_max_slices", myri10ge_max_slices); 474904b6cca3Slucy wang - Sun Microsystems - Beijing China 475004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_use_msix = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 475104b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_use_msix", myri10ge_use_msix); 475204b6cca3Slucy wang - Sun Microsystems - Beijing China 475304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rss_hash = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 475404b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_rss_hash", myri10ge_rss_hash); 475504b6cca3Slucy wang - Sun Microsystems - Beijing China 475604b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_rss_hash > MXGEFW_RSS_HASH_TYPE_MAX || 475704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rss_hash < MXGEFW_RSS_HASH_TYPE_IPV4) { 475804b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "myri10ge: Illegal rssh hash type %d\n", 475904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rss_hash); 476004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT; 476104b6cca3Slucy wang - Sun Microsystems - Beijing China } 476204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_lro = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 476304b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_lro", myri10ge_lro); 476404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_lro_cnt = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 476504b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_lro_cnt", myri10ge_lro_cnt); 476604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_lro_max_aggr = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 476704b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_lro_max_aggr", myri10ge_lro_max_aggr); 476804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_hash = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 476904b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_tx_hash", myri10ge_tx_hash); 477004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_use_lso = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 477104b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_use_lso", myri10ge_use_lso); 477204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_lso_copy = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 477304b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_lso_copy", myri10ge_lso_copy); 477404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_handles_initial = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 477504b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_tx_handles_initial", myri10ge_tx_handles_initial); 477604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_small_bytes = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 477704b6cca3Slucy wang - Sun Microsystems - Beijing China "myri10ge_small_bytes", myri10ge_small_bytes); 477804b6cca3Slucy wang - Sun Microsystems - Beijing China if ((myri10ge_small_bytes + MXGEFW_PAD) & (128 -1)) { 477904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "myri10ge: myri10ge_small_bytes (%d)\n", 478004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_small_bytes); 478104b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "must be aligned on 128b bndry -2\n"); 478204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_small_bytes += 128; 478304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_small_bytes &= ~(128 -1); 478404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_small_bytes -= MXGEFW_PAD; 478504b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "rounded up to %d\n", 478604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_small_bytes); 478704b6cca3Slucy wang - Sun Microsystems - Beijing China 478804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT; 478904b6cca3Slucy wang - Sun Microsystems - Beijing China } 479004b6cca3Slucy wang - Sun Microsystems - Beijing China } 479104b6cca3Slucy wang - Sun Microsystems - Beijing China 479204b6cca3Slucy wang - Sun Microsystems - Beijing China #ifndef PCI_EXP_LNKSTA 479304b6cca3Slucy wang - Sun Microsystems - Beijing China #define PCI_EXP_LNKSTA 18 479404b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 479504b6cca3Slucy wang - Sun Microsystems - Beijing China 479604b6cca3Slucy wang - Sun Microsystems - Beijing China static int 479704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_find_cap(ddi_acc_handle_t handle, uint8_t *capptr, uint8_t capid) 479804b6cca3Slucy wang - Sun Microsystems - Beijing China { 479904b6cca3Slucy wang - Sun Microsystems - Beijing China uint16_t status; 480004b6cca3Slucy wang - Sun Microsystems - Beijing China uint8_t ptr; 480104b6cca3Slucy wang - Sun Microsystems - Beijing China 480204b6cca3Slucy wang - Sun Microsystems - Beijing China /* check to see if we have capabilities */ 480304b6cca3Slucy wang - Sun Microsystems - Beijing China status = pci_config_get16(handle, PCI_CONF_STAT); 480404b6cca3Slucy wang - Sun Microsystems - Beijing China if (!(status & PCI_STAT_CAP)) { 480504b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "PCI_STAT_CAP not found\n"); 480604b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENXIO); 480704b6cca3Slucy wang - Sun Microsystems - Beijing China } 480804b6cca3Slucy wang - Sun Microsystems - Beijing China 480904b6cca3Slucy wang - Sun Microsystems - Beijing China ptr = pci_config_get8(handle, PCI_CONF_CAP_PTR); 481004b6cca3Slucy wang - Sun Microsystems - Beijing China 481104b6cca3Slucy wang - Sun Microsystems - Beijing China /* Walk the capabilities list, looking for a PCI Express cap */ 481204b6cca3Slucy wang - Sun Microsystems - Beijing China while (ptr != PCI_CAP_NEXT_PTR_NULL) { 481304b6cca3Slucy wang - Sun Microsystems - Beijing China if (pci_config_get8(handle, ptr + PCI_CAP_ID) == capid) 481404b6cca3Slucy wang - Sun Microsystems - Beijing China break; 481504b6cca3Slucy wang - Sun Microsystems - Beijing China ptr = pci_config_get8(handle, ptr + PCI_CAP_NEXT_PTR); 481604b6cca3Slucy wang - Sun Microsystems - Beijing China } 481704b6cca3Slucy wang - Sun Microsystems - Beijing China if (ptr < 64) { 481804b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "Bad capability offset %d\n", ptr); 481904b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENXIO); 482004b6cca3Slucy wang - Sun Microsystems - Beijing China } 482104b6cca3Slucy wang - Sun Microsystems - Beijing China *capptr = ptr; 482204b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 482304b6cca3Slucy wang - Sun Microsystems - Beijing China } 482404b6cca3Slucy wang - Sun Microsystems - Beijing China 482504b6cca3Slucy wang - Sun Microsystems - Beijing China static int 482604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_set_max_readreq(ddi_acc_handle_t handle) 482704b6cca3Slucy wang - Sun Microsystems - Beijing China { 482804b6cca3Slucy wang - Sun Microsystems - Beijing China int err; 482904b6cca3Slucy wang - Sun Microsystems - Beijing China uint16_t val; 483004b6cca3Slucy wang - Sun Microsystems - Beijing China uint8_t ptr; 483104b6cca3Slucy wang - Sun Microsystems - Beijing China 483204b6cca3Slucy wang - Sun Microsystems - Beijing China err = myri10ge_find_cap(handle, &ptr, PCI_CAP_ID_PCI_E); 483304b6cca3Slucy wang - Sun Microsystems - Beijing China if (err != 0) { 483404b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "could not find PCIe cap\n"); 483504b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENXIO); 483604b6cca3Slucy wang - Sun Microsystems - Beijing China } 483704b6cca3Slucy wang - Sun Microsystems - Beijing China 483804b6cca3Slucy wang - Sun Microsystems - Beijing China /* set max read req to 4096 */ 483904b6cca3Slucy wang - Sun Microsystems - Beijing China val = pci_config_get16(handle, ptr + PCIE_DEVCTL); 484004b6cca3Slucy wang - Sun Microsystems - Beijing China val = (val & ~PCIE_DEVCTL_MAX_READ_REQ_MASK) | 484104b6cca3Slucy wang - Sun Microsystems - Beijing China PCIE_DEVCTL_MAX_READ_REQ_4096; 484204b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_put16(handle, ptr + PCIE_DEVCTL, val); 484304b6cca3Slucy wang - Sun Microsystems - Beijing China val = pci_config_get16(handle, ptr + PCIE_DEVCTL); 484404b6cca3Slucy wang - Sun Microsystems - Beijing China if ((val & (PCIE_DEVCTL_MAX_READ_REQ_4096)) != 484504b6cca3Slucy wang - Sun Microsystems - Beijing China PCIE_DEVCTL_MAX_READ_REQ_4096) { 484604b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "could not set max read req (%x)\n", val); 484704b6cca3Slucy wang - Sun Microsystems - Beijing China return (EINVAL); 484804b6cca3Slucy wang - Sun Microsystems - Beijing China } 484904b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 485004b6cca3Slucy wang - Sun Microsystems - Beijing China } 485104b6cca3Slucy wang - Sun Microsystems - Beijing China 485204b6cca3Slucy wang - Sun Microsystems - Beijing China static int 485304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_read_pcie_link_width(ddi_acc_handle_t handle, int *link) 485404b6cca3Slucy wang - Sun Microsystems - Beijing China { 485504b6cca3Slucy wang - Sun Microsystems - Beijing China int err; 485604b6cca3Slucy wang - Sun Microsystems - Beijing China uint16_t val; 485704b6cca3Slucy wang - Sun Microsystems - Beijing China uint8_t ptr; 485804b6cca3Slucy wang - Sun Microsystems - Beijing China 485904b6cca3Slucy wang - Sun Microsystems - Beijing China err = myri10ge_find_cap(handle, &ptr, PCI_CAP_ID_PCI_E); 486004b6cca3Slucy wang - Sun Microsystems - Beijing China if (err != 0) { 486104b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "could not set max read req\n"); 486204b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENXIO); 486304b6cca3Slucy wang - Sun Microsystems - Beijing China } 486404b6cca3Slucy wang - Sun Microsystems - Beijing China 486504b6cca3Slucy wang - Sun Microsystems - Beijing China /* read link width */ 486604b6cca3Slucy wang - Sun Microsystems - Beijing China val = pci_config_get16(handle, ptr + PCIE_LINKSTS); 486704b6cca3Slucy wang - Sun Microsystems - Beijing China val &= PCIE_LINKSTS_NEG_WIDTH_MASK; 486804b6cca3Slucy wang - Sun Microsystems - Beijing China *link = (val >> 4); 486904b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 487004b6cca3Slucy wang - Sun Microsystems - Beijing China } 487104b6cca3Slucy wang - Sun Microsystems - Beijing China 487204b6cca3Slucy wang - Sun Microsystems - Beijing China static int 487304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_reset_nic(struct myri10ge_priv *mgp) 487404b6cca3Slucy wang - Sun Microsystems - Beijing China { 487504b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_acc_handle_t handle = mgp->cfg_hdl; 487604b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t reboot; 487704b6cca3Slucy wang - Sun Microsystems - Beijing China uint16_t cmd; 487804b6cca3Slucy wang - Sun Microsystems - Beijing China int err; 487904b6cca3Slucy wang - Sun Microsystems - Beijing China 488004b6cca3Slucy wang - Sun Microsystems - Beijing China cmd = pci_config_get16(handle, PCI_CONF_COMM); 488104b6cca3Slucy wang - Sun Microsystems - Beijing China if ((cmd & PCI_COMM_ME) == 0) { 488204b6cca3Slucy wang - Sun Microsystems - Beijing China /* 488304b6cca3Slucy wang - Sun Microsystems - Beijing China * Bus master DMA disabled? Check to see if the card 488404b6cca3Slucy wang - Sun Microsystems - Beijing China * rebooted due to a parity error For now, just report 488504b6cca3Slucy wang - Sun Microsystems - Beijing China * it 488604b6cca3Slucy wang - Sun Microsystems - Beijing China */ 488704b6cca3Slucy wang - Sun Microsystems - Beijing China 488804b6cca3Slucy wang - Sun Microsystems - Beijing China /* enter read32 mode */ 488904b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_put8(handle, mgp->vso + 0x10, 0x3); 489004b6cca3Slucy wang - Sun Microsystems - Beijing China /* read REBOOT_STATUS (0xfffffff0) */ 489104b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_put32(handle, mgp->vso + 0x18, 0xfffffff0); 489204b6cca3Slucy wang - Sun Microsystems - Beijing China reboot = pci_config_get16(handle, mgp->vso + 0x14); 489304b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s NIC rebooted 0x%x\n", mgp->name, reboot); 489404b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 489504b6cca3Slucy wang - Sun Microsystems - Beijing China } 489604b6cca3Slucy wang - Sun Microsystems - Beijing China if (!myri10ge_watchdog_reset) { 489704b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: not resetting\n", mgp->name); 489804b6cca3Slucy wang - Sun Microsystems - Beijing China return (1); 489904b6cca3Slucy wang - Sun Microsystems - Beijing China } 490004b6cca3Slucy wang - Sun Microsystems - Beijing China 490104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_stop_locked(mgp); 490204b6cca3Slucy wang - Sun Microsystems - Beijing China err = myri10ge_start_locked(mgp); 490304b6cca3Slucy wang - Sun Microsystems - Beijing China if (err == DDI_FAILURE) { 490404b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 490504b6cca3Slucy wang - Sun Microsystems - Beijing China } 490604b6cca3Slucy wang - Sun Microsystems - Beijing China mac_tx_update(mgp->mh); 490704b6cca3Slucy wang - Sun Microsystems - Beijing China return (1); 490804b6cca3Slucy wang - Sun Microsystems - Beijing China } 490904b6cca3Slucy wang - Sun Microsystems - Beijing China 491004b6cca3Slucy wang - Sun Microsystems - Beijing China static inline int 491104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_ring_stalled(myri10ge_tx_ring_t *tx) 491204b6cca3Slucy wang - Sun Microsystems - Beijing China { 491304b6cca3Slucy wang - Sun Microsystems - Beijing China if (tx->sched != tx->stall && 491404b6cca3Slucy wang - Sun Microsystems - Beijing China tx->done == tx->watchdog_done && 491504b6cca3Slucy wang - Sun Microsystems - Beijing China tx->watchdog_req != tx->watchdog_done) 491604b6cca3Slucy wang - Sun Microsystems - Beijing China return (1); 491704b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 491804b6cca3Slucy wang - Sun Microsystems - Beijing China } 491904b6cca3Slucy wang - Sun Microsystems - Beijing China 492004b6cca3Slucy wang - Sun Microsystems - Beijing China static void 492104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_watchdog(void *arg) 492204b6cca3Slucy wang - Sun Microsystems - Beijing China { 492304b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp; 492404b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_slice_state *ss; 492504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_tx_ring_t *tx; 492604b6cca3Slucy wang - Sun Microsystems - Beijing China int nic_ok = 1; 492704b6cca3Slucy wang - Sun Microsystems - Beijing China int slices_stalled, rx_pause, i; 492804b6cca3Slucy wang - Sun Microsystems - Beijing China int add_rx; 492904b6cca3Slucy wang - Sun Microsystems - Beijing China 493004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp = arg; 493104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&mgp->intrlock); 493204b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->running != MYRI10GE_ETH_RUNNING) { 493304b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 493404b6cca3Slucy wang - Sun Microsystems - Beijing China "%s not running, not rearming watchdog (%d)\n", 493504b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, mgp->running); 493604b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->intrlock); 493704b6cca3Slucy wang - Sun Microsystems - Beijing China return; 493804b6cca3Slucy wang - Sun Microsystems - Beijing China } 493904b6cca3Slucy wang - Sun Microsystems - Beijing China 494004b6cca3Slucy wang - Sun Microsystems - Beijing China rx_pause = ntohl(mgp->ss[0].fw_stats->dropped_pause); 494104b6cca3Slucy wang - Sun Microsystems - Beijing China 494204b6cca3Slucy wang - Sun Microsystems - Beijing China /* 494304b6cca3Slucy wang - Sun Microsystems - Beijing China * make sure nic is stalled before we reset the nic, so as to 494404b6cca3Slucy wang - Sun Microsystems - Beijing China * ensure we don't rip the transmit data structures out from 494504b6cca3Slucy wang - Sun Microsystems - Beijing China * under a pending transmit 494604b6cca3Slucy wang - Sun Microsystems - Beijing China */ 494704b6cca3Slucy wang - Sun Microsystems - Beijing China 494804b6cca3Slucy wang - Sun Microsystems - Beijing China for (slices_stalled = 0, i = 0; i < mgp->num_slices; i++) { 494904b6cca3Slucy wang - Sun Microsystems - Beijing China tx = &mgp->ss[i].tx; 495004b6cca3Slucy wang - Sun Microsystems - Beijing China slices_stalled = myri10ge_ring_stalled(tx); 495104b6cca3Slucy wang - Sun Microsystems - Beijing China if (slices_stalled) 495204b6cca3Slucy wang - Sun Microsystems - Beijing China break; 495304b6cca3Slucy wang - Sun Microsystems - Beijing China } 495404b6cca3Slucy wang - Sun Microsystems - Beijing China 495504b6cca3Slucy wang - Sun Microsystems - Beijing China if (slices_stalled) { 495604b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->watchdog_rx_pause == rx_pause) { 495704b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 495804b6cca3Slucy wang - Sun Microsystems - Beijing China "%s slice %d stalled:(%d, %d, %d, %d, %d %d %d\n)", 495904b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, i, tx->sched, tx->stall, 496004b6cca3Slucy wang - Sun Microsystems - Beijing China tx->done, tx->watchdog_done, tx->req, tx->pkt_done, 496104b6cca3Slucy wang - Sun Microsystems - Beijing China (int)ntohl(mgp->ss[i].fw_stats->send_done_count)); 496204b6cca3Slucy wang - Sun Microsystems - Beijing China nic_ok = myri10ge_reset_nic(mgp); 496304b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 496404b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 496504b6cca3Slucy wang - Sun Microsystems - Beijing China "%s Flow controlled, check link partner\n", 496604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 496704b6cca3Slucy wang - Sun Microsystems - Beijing China } 496804b6cca3Slucy wang - Sun Microsystems - Beijing China } 496904b6cca3Slucy wang - Sun Microsystems - Beijing China 497004b6cca3Slucy wang - Sun Microsystems - Beijing China if (!nic_ok) { 497104b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, 497204b6cca3Slucy wang - Sun Microsystems - Beijing China "%s Nic dead, not rearming watchdog\n", mgp->name); 497304b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->intrlock); 497404b6cca3Slucy wang - Sun Microsystems - Beijing China return; 497504b6cca3Slucy wang - Sun Microsystems - Beijing China } 497604b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 497704b6cca3Slucy wang - Sun Microsystems - Beijing China ss = &mgp->ss[i]; 497804b6cca3Slucy wang - Sun Microsystems - Beijing China tx = &ss->tx; 497904b6cca3Slucy wang - Sun Microsystems - Beijing China tx->watchdog_done = tx->done; 498004b6cca3Slucy wang - Sun Microsystems - Beijing China tx->watchdog_req = tx->req; 498104b6cca3Slucy wang - Sun Microsystems - Beijing China if (ss->watchdog_rx_copy != MYRI10GE_SLICE_STAT(rx_copy)) { 498204b6cca3Slucy wang - Sun Microsystems - Beijing China ss->watchdog_rx_copy = MYRI10GE_SLICE_STAT(rx_copy); 498304b6cca3Slucy wang - Sun Microsystems - Beijing China add_rx = 498404b6cca3Slucy wang - Sun Microsystems - Beijing China min(ss->jpool.num_alloc, 498504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_bigbufs_max - 498604b6cca3Slucy wang - Sun Microsystems - Beijing China (ss->jpool.num_alloc - 498704b6cca3Slucy wang - Sun Microsystems - Beijing China ss->jbufs_for_smalls)); 498804b6cca3Slucy wang - Sun Microsystems - Beijing China if (add_rx != 0) { 498904b6cca3Slucy wang - Sun Microsystems - Beijing China (void) myri10ge_add_jbufs(ss, add_rx, 0); 499004b6cca3Slucy wang - Sun Microsystems - Beijing China /* now feed them to the firmware */ 499104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&ss->jpool.mtx); 499204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_restock_jumbos(ss); 499304b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&ss->jpool.mtx); 499404b6cca3Slucy wang - Sun Microsystems - Beijing China } 499504b6cca3Slucy wang - Sun Microsystems - Beijing China } 499604b6cca3Slucy wang - Sun Microsystems - Beijing China } 499704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->watchdog_rx_pause = rx_pause; 499804b6cca3Slucy wang - Sun Microsystems - Beijing China 499904b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->timer_id = timeout(myri10ge_watchdog, mgp, 500004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->timer_ticks); 500104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->intrlock); 500204b6cca3Slucy wang - Sun Microsystems - Beijing China } 500304b6cca3Slucy wang - Sun Microsystems - Beijing China 500404b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/ 500504b6cca3Slucy wang - Sun Microsystems - Beijing China static int 500604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_coalesce(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp) 500704b6cca3Slucy wang - Sun Microsystems - Beijing China 500804b6cca3Slucy wang - Sun Microsystems - Beijing China { 500904b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = (struct myri10ge_priv *)(void *)cp; 501004b6cca3Slucy wang - Sun Microsystems - Beijing China (void) mi_mpprintf(mp, "%d", mgp->intr_coal_delay); 501104b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 501204b6cca3Slucy wang - Sun Microsystems - Beijing China } 501304b6cca3Slucy wang - Sun Microsystems - Beijing China 501404b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/ 501504b6cca3Slucy wang - Sun Microsystems - Beijing China static int 501604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_set_coalesce(queue_t *q, mblk_t *mp, char *value, 501704b6cca3Slucy wang - Sun Microsystems - Beijing China caddr_t cp, cred_t *credp) 501804b6cca3Slucy wang - Sun Microsystems - Beijing China 501904b6cca3Slucy wang - Sun Microsystems - Beijing China { 502004b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = (struct myri10ge_priv *)(void *)cp; 502104b6cca3Slucy wang - Sun Microsystems - Beijing China char *end; 502204b6cca3Slucy wang - Sun Microsystems - Beijing China size_t new_value; 502304b6cca3Slucy wang - Sun Microsystems - Beijing China 502404b6cca3Slucy wang - Sun Microsystems - Beijing China new_value = mi_strtol(value, &end, 10); 502504b6cca3Slucy wang - Sun Microsystems - Beijing China if (end == value) 502604b6cca3Slucy wang - Sun Microsystems - Beijing China return (EINVAL); 502704b6cca3Slucy wang - Sun Microsystems - Beijing China 502804b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&myri10ge_param_lock); 502904b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->intr_coal_delay = (int)new_value; 503004b6cca3Slucy wang - Sun Microsystems - Beijing China *mgp->intr_coal_delay_ptr = htonl(mgp->intr_coal_delay); 503104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&myri10ge_param_lock); 503204b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 503304b6cca3Slucy wang - Sun Microsystems - Beijing China } 503404b6cca3Slucy wang - Sun Microsystems - Beijing China 503504b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/ 503604b6cca3Slucy wang - Sun Microsystems - Beijing China static int 503704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_pauseparam(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp) 503804b6cca3Slucy wang - Sun Microsystems - Beijing China 503904b6cca3Slucy wang - Sun Microsystems - Beijing China { 504004b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = (struct myri10ge_priv *)(void *)cp; 504104b6cca3Slucy wang - Sun Microsystems - Beijing China (void) mi_mpprintf(mp, "%d", mgp->pause); 504204b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 504304b6cca3Slucy wang - Sun Microsystems - Beijing China } 504404b6cca3Slucy wang - Sun Microsystems - Beijing China 504504b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/ 504604b6cca3Slucy wang - Sun Microsystems - Beijing China static int 504704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_set_pauseparam(queue_t *q, mblk_t *mp, char *value, 504804b6cca3Slucy wang - Sun Microsystems - Beijing China caddr_t cp, cred_t *credp) 504904b6cca3Slucy wang - Sun Microsystems - Beijing China 505004b6cca3Slucy wang - Sun Microsystems - Beijing China { 505104b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = (struct myri10ge_priv *)(void *)cp; 505204b6cca3Slucy wang - Sun Microsystems - Beijing China char *end; 505304b6cca3Slucy wang - Sun Microsystems - Beijing China size_t new_value; 505404b6cca3Slucy wang - Sun Microsystems - Beijing China int err = 0; 505504b6cca3Slucy wang - Sun Microsystems - Beijing China 505604b6cca3Slucy wang - Sun Microsystems - Beijing China new_value = mi_strtol(value, &end, 10); 505704b6cca3Slucy wang - Sun Microsystems - Beijing China if (end == value) 505804b6cca3Slucy wang - Sun Microsystems - Beijing China return (EINVAL); 505904b6cca3Slucy wang - Sun Microsystems - Beijing China if (new_value != 0) 506004b6cca3Slucy wang - Sun Microsystems - Beijing China new_value = 1; 506104b6cca3Slucy wang - Sun Microsystems - Beijing China 506204b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&myri10ge_param_lock); 506304b6cca3Slucy wang - Sun Microsystems - Beijing China if (new_value != mgp->pause) 506404b6cca3Slucy wang - Sun Microsystems - Beijing China err = myri10ge_change_pause(mgp, new_value); 506504b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&myri10ge_param_lock); 506604b6cca3Slucy wang - Sun Microsystems - Beijing China return (err); 506704b6cca3Slucy wang - Sun Microsystems - Beijing China } 506804b6cca3Slucy wang - Sun Microsystems - Beijing China 506904b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/ 507004b6cca3Slucy wang - Sun Microsystems - Beijing China static int 507104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_int(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp) 507204b6cca3Slucy wang - Sun Microsystems - Beijing China 507304b6cca3Slucy wang - Sun Microsystems - Beijing China { 507404b6cca3Slucy wang - Sun Microsystems - Beijing China (void) mi_mpprintf(mp, "%d", *(int *)(void *)cp); 507504b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 507604b6cca3Slucy wang - Sun Microsystems - Beijing China } 507704b6cca3Slucy wang - Sun Microsystems - Beijing China 507804b6cca3Slucy wang - Sun Microsystems - Beijing China /*ARGSUSED*/ 507904b6cca3Slucy wang - Sun Microsystems - Beijing China static int 508004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_set_int(queue_t *q, mblk_t *mp, char *value, 508104b6cca3Slucy wang - Sun Microsystems - Beijing China caddr_t cp, cred_t *credp) 508204b6cca3Slucy wang - Sun Microsystems - Beijing China 508304b6cca3Slucy wang - Sun Microsystems - Beijing China { 508404b6cca3Slucy wang - Sun Microsystems - Beijing China char *end; 508504b6cca3Slucy wang - Sun Microsystems - Beijing China size_t new_value; 508604b6cca3Slucy wang - Sun Microsystems - Beijing China 508704b6cca3Slucy wang - Sun Microsystems - Beijing China new_value = mi_strtol(value, &end, 10); 508804b6cca3Slucy wang - Sun Microsystems - Beijing China if (end == value) 508904b6cca3Slucy wang - Sun Microsystems - Beijing China return (EINVAL); 509004b6cca3Slucy wang - Sun Microsystems - Beijing China *(int *)(void *)cp = new_value; 509104b6cca3Slucy wang - Sun Microsystems - Beijing China 509204b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 509304b6cca3Slucy wang - Sun Microsystems - Beijing China } 509404b6cca3Slucy wang - Sun Microsystems - Beijing China 509504b6cca3Slucy wang - Sun Microsystems - Beijing China static void 509604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_ndd_init(struct myri10ge_priv *mgp) 509704b6cca3Slucy wang - Sun Microsystems - Beijing China { 509804b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->nd_head = NULL; 509904b6cca3Slucy wang - Sun Microsystems - Beijing China 510004b6cca3Slucy wang - Sun Microsystems - Beijing China (void) nd_load(&mgp->nd_head, "myri10ge_intr_coal_delay", 510104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_coalesce, myri10ge_set_coalesce, (caddr_t)mgp); 510204b6cca3Slucy wang - Sun Microsystems - Beijing China (void) nd_load(&mgp->nd_head, "myri10ge_flow_control", 510304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_pauseparam, myri10ge_set_pauseparam, (caddr_t)mgp); 510404b6cca3Slucy wang - Sun Microsystems - Beijing China (void) nd_load(&mgp->nd_head, "myri10ge_verbose", 510504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_int, myri10ge_set_int, (caddr_t)&myri10ge_verbose); 510604b6cca3Slucy wang - Sun Microsystems - Beijing China (void) nd_load(&mgp->nd_head, "myri10ge_deassert_wait", 510704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_int, myri10ge_set_int, 510804b6cca3Slucy wang - Sun Microsystems - Beijing China (caddr_t)&myri10ge_deassert_wait); 510904b6cca3Slucy wang - Sun Microsystems - Beijing China (void) nd_load(&mgp->nd_head, "myri10ge_bigbufs_max", 511004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_int, myri10ge_set_int, 511104b6cca3Slucy wang - Sun Microsystems - Beijing China (caddr_t)&myri10ge_bigbufs_max); 511204b6cca3Slucy wang - Sun Microsystems - Beijing China (void) nd_load(&mgp->nd_head, "myri10ge_lro", 511304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_int, myri10ge_set_int, 511404b6cca3Slucy wang - Sun Microsystems - Beijing China (caddr_t)&myri10ge_lro); 511504b6cca3Slucy wang - Sun Microsystems - Beijing China (void) nd_load(&mgp->nd_head, "myri10ge_lro_max_aggr", 511604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_int, myri10ge_set_int, 511704b6cca3Slucy wang - Sun Microsystems - Beijing China (caddr_t)&myri10ge_lro_max_aggr); 511804b6cca3Slucy wang - Sun Microsystems - Beijing China (void) nd_load(&mgp->nd_head, "myri10ge_tx_hash", 511904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_int, myri10ge_set_int, 512004b6cca3Slucy wang - Sun Microsystems - Beijing China (caddr_t)&myri10ge_tx_hash); 512104b6cca3Slucy wang - Sun Microsystems - Beijing China (void) nd_load(&mgp->nd_head, "myri10ge_lso_copy", 512204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_int, myri10ge_set_int, 512304b6cca3Slucy wang - Sun Microsystems - Beijing China (caddr_t)&myri10ge_lso_copy); 512404b6cca3Slucy wang - Sun Microsystems - Beijing China } 512504b6cca3Slucy wang - Sun Microsystems - Beijing China 512604b6cca3Slucy wang - Sun Microsystems - Beijing China static void 512704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_ndd_fini(struct myri10ge_priv *mgp) 512804b6cca3Slucy wang - Sun Microsystems - Beijing China { 512904b6cca3Slucy wang - Sun Microsystems - Beijing China nd_free(&mgp->nd_head); 513004b6cca3Slucy wang - Sun Microsystems - Beijing China } 513104b6cca3Slucy wang - Sun Microsystems - Beijing China 513204b6cca3Slucy wang - Sun Microsystems - Beijing China static void 513304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 513404b6cca3Slucy wang - Sun Microsystems - Beijing China { 513504b6cca3Slucy wang - Sun Microsystems - Beijing China struct iocblk *iocp; 513604b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = arg; 513704b6cca3Slucy wang - Sun Microsystems - Beijing China int cmd, ok, err; 513804b6cca3Slucy wang - Sun Microsystems - Beijing China 513904b6cca3Slucy wang - Sun Microsystems - Beijing China iocp = (struct iocblk *)(void *)mp->b_rptr; 514004b6cca3Slucy wang - Sun Microsystems - Beijing China cmd = iocp->ioc_cmd; 514104b6cca3Slucy wang - Sun Microsystems - Beijing China 514204b6cca3Slucy wang - Sun Microsystems - Beijing China ok = 0; 514304b6cca3Slucy wang - Sun Microsystems - Beijing China err = 0; 514404b6cca3Slucy wang - Sun Microsystems - Beijing China 514504b6cca3Slucy wang - Sun Microsystems - Beijing China switch (cmd) { 514604b6cca3Slucy wang - Sun Microsystems - Beijing China case ND_GET: 514704b6cca3Slucy wang - Sun Microsystems - Beijing China case ND_SET: 514804b6cca3Slucy wang - Sun Microsystems - Beijing China ok = nd_getset(wq, mgp->nd_head, mp); 514904b6cca3Slucy wang - Sun Microsystems - Beijing China break; 515004b6cca3Slucy wang - Sun Microsystems - Beijing China default: 515104b6cca3Slucy wang - Sun Microsystems - Beijing China break; 515204b6cca3Slucy wang - Sun Microsystems - Beijing China } 515304b6cca3Slucy wang - Sun Microsystems - Beijing China if (!ok) 515404b6cca3Slucy wang - Sun Microsystems - Beijing China err = EINVAL; 515504b6cca3Slucy wang - Sun Microsystems - Beijing China else 515604b6cca3Slucy wang - Sun Microsystems - Beijing China err = iocp->ioc_error; 515704b6cca3Slucy wang - Sun Microsystems - Beijing China 515804b6cca3Slucy wang - Sun Microsystems - Beijing China if (!err) 515904b6cca3Slucy wang - Sun Microsystems - Beijing China miocack(wq, mp, iocp->ioc_count, err); 516004b6cca3Slucy wang - Sun Microsystems - Beijing China else 516104b6cca3Slucy wang - Sun Microsystems - Beijing China miocnak(wq, mp, 0, err); 516204b6cca3Slucy wang - Sun Microsystems - Beijing China } 516304b6cca3Slucy wang - Sun Microsystems - Beijing China 516404b6cca3Slucy wang - Sun Microsystems - Beijing China static struct myri10ge_priv *mgp_list; 516504b6cca3Slucy wang - Sun Microsystems - Beijing China 516604b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv * 516704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_instance(uint_t unit) 516804b6cca3Slucy wang - Sun Microsystems - Beijing China { 516904b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp; 517004b6cca3Slucy wang - Sun Microsystems - Beijing China 517104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&myri10ge_param_lock); 517204b6cca3Slucy wang - Sun Microsystems - Beijing China for (mgp = mgp_list; mgp != NULL; mgp = mgp->next) { 517304b6cca3Slucy wang - Sun Microsystems - Beijing China if (unit == ddi_get_instance(mgp->dip)) { 517404b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->refcnt++; 517504b6cca3Slucy wang - Sun Microsystems - Beijing China break; 517604b6cca3Slucy wang - Sun Microsystems - Beijing China } 517704b6cca3Slucy wang - Sun Microsystems - Beijing China } 517804b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&myri10ge_param_lock); 517904b6cca3Slucy wang - Sun Microsystems - Beijing China return (mgp); 518004b6cca3Slucy wang - Sun Microsystems - Beijing China } 518104b6cca3Slucy wang - Sun Microsystems - Beijing China 518204b6cca3Slucy wang - Sun Microsystems - Beijing China void 518304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_put_instance(struct myri10ge_priv *mgp) 518404b6cca3Slucy wang - Sun Microsystems - Beijing China { 518504b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&myri10ge_param_lock); 518604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->refcnt--; 518704b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&myri10ge_param_lock); 518804b6cca3Slucy wang - Sun Microsystems - Beijing China } 518904b6cca3Slucy wang - Sun Microsystems - Beijing China 519004b6cca3Slucy wang - Sun Microsystems - Beijing China static boolean_t 519104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 519204b6cca3Slucy wang - Sun Microsystems - Beijing China { 519304b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = arg; 519404b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t *cap_hcksum; 519504b6cca3Slucy wang - Sun Microsystems - Beijing China mac_capab_lso_t *cap_lso; 519604b6cca3Slucy wang - Sun Microsystems - Beijing China mac_capab_rings_t *cap_rings; 519704b6cca3Slucy wang - Sun Microsystems - Beijing China 519804b6cca3Slucy wang - Sun Microsystems - Beijing China switch (cap) { 519904b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_CAPAB_HCKSUM: 520004b6cca3Slucy wang - Sun Microsystems - Beijing China cap_hcksum = cap_data; 520104b6cca3Slucy wang - Sun Microsystems - Beijing China *cap_hcksum = HCKSUM_INET_PARTIAL; 520204b6cca3Slucy wang - Sun Microsystems - Beijing China break; 520304b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_CAPAB_RINGS: 520404b6cca3Slucy wang - Sun Microsystems - Beijing China cap_rings = cap_data; 520504b6cca3Slucy wang - Sun Microsystems - Beijing China switch (cap_rings->mr_type) { 520604b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_RING_TYPE_RX: 520704b6cca3Slucy wang - Sun Microsystems - Beijing China cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 520804b6cca3Slucy wang - Sun Microsystems - Beijing China cap_rings->mr_rnum = mgp->num_slices; 520904b6cca3Slucy wang - Sun Microsystems - Beijing China cap_rings->mr_gnum = 1; 521004b6cca3Slucy wang - Sun Microsystems - Beijing China cap_rings->mr_rget = myri10ge_fill_ring; 521104b6cca3Slucy wang - Sun Microsystems - Beijing China cap_rings->mr_gget = myri10ge_fill_group; 521204b6cca3Slucy wang - Sun Microsystems - Beijing China break; 521304b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_RING_TYPE_TX: 521404b6cca3Slucy wang - Sun Microsystems - Beijing China cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 521504b6cca3Slucy wang - Sun Microsystems - Beijing China cap_rings->mr_rnum = mgp->num_slices; 521604b6cca3Slucy wang - Sun Microsystems - Beijing China cap_rings->mr_gnum = 0; 521704b6cca3Slucy wang - Sun Microsystems - Beijing China cap_rings->mr_rget = myri10ge_fill_ring; 521804b6cca3Slucy wang - Sun Microsystems - Beijing China cap_rings->mr_gget = NULL; 521904b6cca3Slucy wang - Sun Microsystems - Beijing China break; 522004b6cca3Slucy wang - Sun Microsystems - Beijing China default: 522104b6cca3Slucy wang - Sun Microsystems - Beijing China return (B_FALSE); 522204b6cca3Slucy wang - Sun Microsystems - Beijing China } 522304b6cca3Slucy wang - Sun Microsystems - Beijing China break; 522404b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_CAPAB_LSO: 522504b6cca3Slucy wang - Sun Microsystems - Beijing China cap_lso = cap_data; 522604b6cca3Slucy wang - Sun Microsystems - Beijing China if (!myri10ge_use_lso) 522704b6cca3Slucy wang - Sun Microsystems - Beijing China return (B_FALSE); 522804b6cca3Slucy wang - Sun Microsystems - Beijing China if (!(mgp->features & MYRI10GE_TSO)) 522904b6cca3Slucy wang - Sun Microsystems - Beijing China return (B_FALSE); 523004b6cca3Slucy wang - Sun Microsystems - Beijing China cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 523104b6cca3Slucy wang - Sun Microsystems - Beijing China cap_lso->lso_basic_tcp_ipv4.lso_max = (uint16_t)-1; 523204b6cca3Slucy wang - Sun Microsystems - Beijing China break; 523304b6cca3Slucy wang - Sun Microsystems - Beijing China 523404b6cca3Slucy wang - Sun Microsystems - Beijing China default: 523504b6cca3Slucy wang - Sun Microsystems - Beijing China return (B_FALSE); 523604b6cca3Slucy wang - Sun Microsystems - Beijing China } 523704b6cca3Slucy wang - Sun Microsystems - Beijing China return (B_TRUE); 523804b6cca3Slucy wang - Sun Microsystems - Beijing China } 523904b6cca3Slucy wang - Sun Microsystems - Beijing China 524004b6cca3Slucy wang - Sun Microsystems - Beijing China 524104b6cca3Slucy wang - Sun Microsystems - Beijing China static int 524204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_stat(void *arg, uint_t stat, uint64_t *val) 524304b6cca3Slucy wang - Sun Microsystems - Beijing China { 524404b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = arg; 524504b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_rx_ring_stats *rstat; 524604b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_tx_ring_stats *tstat; 524704b6cca3Slucy wang - Sun Microsystems - Beijing China mcp_irq_data_t *fw_stats = mgp->ss[0].fw_stats; 524804b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_slice_state *ss; 524904b6cca3Slucy wang - Sun Microsystems - Beijing China uint64_t tmp = 0; 525004b6cca3Slucy wang - Sun Microsystems - Beijing China int i; 525104b6cca3Slucy wang - Sun Microsystems - Beijing China 525204b6cca3Slucy wang - Sun Microsystems - Beijing China switch (stat) { 525304b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_STAT_IFSPEED: 525404b6cca3Slucy wang - Sun Microsystems - Beijing China *val = 10ull * 1000ull * 1000000ull; 525504b6cca3Slucy wang - Sun Microsystems - Beijing China break; 525604b6cca3Slucy wang - Sun Microsystems - Beijing China 525704b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_STAT_MULTIRCV: 525804b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 525904b6cca3Slucy wang - Sun Microsystems - Beijing China rstat = &mgp->ss[i].rx_stats; 526004b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += rstat->multircv; 526104b6cca3Slucy wang - Sun Microsystems - Beijing China } 526204b6cca3Slucy wang - Sun Microsystems - Beijing China *val = tmp; 526304b6cca3Slucy wang - Sun Microsystems - Beijing China break; 526404b6cca3Slucy wang - Sun Microsystems - Beijing China 526504b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_STAT_BRDCSTRCV: 526604b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 526704b6cca3Slucy wang - Sun Microsystems - Beijing China rstat = &mgp->ss[i].rx_stats; 526804b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += rstat->brdcstrcv; 526904b6cca3Slucy wang - Sun Microsystems - Beijing China } 527004b6cca3Slucy wang - Sun Microsystems - Beijing China *val = tmp; 527104b6cca3Slucy wang - Sun Microsystems - Beijing China break; 527204b6cca3Slucy wang - Sun Microsystems - Beijing China 527304b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_STAT_MULTIXMT: 527404b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 527504b6cca3Slucy wang - Sun Microsystems - Beijing China tstat = &mgp->ss[i].tx.stats; 527604b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += tstat->multixmt; 527704b6cca3Slucy wang - Sun Microsystems - Beijing China } 527804b6cca3Slucy wang - Sun Microsystems - Beijing China *val = tmp; 527904b6cca3Slucy wang - Sun Microsystems - Beijing China break; 528004b6cca3Slucy wang - Sun Microsystems - Beijing China 528104b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_STAT_BRDCSTXMT: 528204b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 528304b6cca3Slucy wang - Sun Microsystems - Beijing China tstat = &mgp->ss[i].tx.stats; 528404b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += tstat->brdcstxmt; 528504b6cca3Slucy wang - Sun Microsystems - Beijing China } 528604b6cca3Slucy wang - Sun Microsystems - Beijing China *val = tmp; 528704b6cca3Slucy wang - Sun Microsystems - Beijing China break; 528804b6cca3Slucy wang - Sun Microsystems - Beijing China 528904b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_STAT_NORCVBUF: 529004b6cca3Slucy wang - Sun Microsystems - Beijing China tmp = ntohl(fw_stats->dropped_no_big_buffer); 529104b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += ntohl(fw_stats->dropped_no_small_buffer); 529204b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += ntohl(fw_stats->dropped_link_overflow); 529304b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 529404b6cca3Slucy wang - Sun Microsystems - Beijing China ss = &mgp->ss[i]; 529504b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += MYRI10GE_SLICE_STAT(rx_big_nobuf); 529604b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += MYRI10GE_SLICE_STAT(rx_small_nobuf); 529704b6cca3Slucy wang - Sun Microsystems - Beijing China } 529804b6cca3Slucy wang - Sun Microsystems - Beijing China *val = tmp; 529904b6cca3Slucy wang - Sun Microsystems - Beijing China break; 530004b6cca3Slucy wang - Sun Microsystems - Beijing China 530104b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_STAT_IERRORS: 530204b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += ntohl(fw_stats->dropped_bad_crc32); 530304b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += ntohl(fw_stats->dropped_bad_phy); 530404b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += ntohl(fw_stats->dropped_runt); 530504b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += ntohl(fw_stats->dropped_overrun); 530604b6cca3Slucy wang - Sun Microsystems - Beijing China *val = tmp; 530704b6cca3Slucy wang - Sun Microsystems - Beijing China break; 530804b6cca3Slucy wang - Sun Microsystems - Beijing China 530904b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_STAT_OERRORS: 531004b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 531104b6cca3Slucy wang - Sun Microsystems - Beijing China ss = &mgp->ss[i]; 531204b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += MYRI10GE_SLICE_STAT(xmit_lsobadflags); 531304b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += MYRI10GE_SLICE_STAT(xmit_err); 531404b6cca3Slucy wang - Sun Microsystems - Beijing China } 531504b6cca3Slucy wang - Sun Microsystems - Beijing China *val = tmp; 531604b6cca3Slucy wang - Sun Microsystems - Beijing China break; 531704b6cca3Slucy wang - Sun Microsystems - Beijing China 531804b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_STAT_RBYTES: 531904b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 532004b6cca3Slucy wang - Sun Microsystems - Beijing China rstat = &mgp->ss[i].rx_stats; 532104b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += rstat->ibytes; 532204b6cca3Slucy wang - Sun Microsystems - Beijing China } 532304b6cca3Slucy wang - Sun Microsystems - Beijing China *val = tmp; 532404b6cca3Slucy wang - Sun Microsystems - Beijing China break; 532504b6cca3Slucy wang - Sun Microsystems - Beijing China 532604b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_STAT_IPACKETS: 532704b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 532804b6cca3Slucy wang - Sun Microsystems - Beijing China rstat = &mgp->ss[i].rx_stats; 532904b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += rstat->ipackets; 533004b6cca3Slucy wang - Sun Microsystems - Beijing China } 533104b6cca3Slucy wang - Sun Microsystems - Beijing China *val = tmp; 533204b6cca3Slucy wang - Sun Microsystems - Beijing China break; 533304b6cca3Slucy wang - Sun Microsystems - Beijing China 533404b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_STAT_OBYTES: 533504b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 533604b6cca3Slucy wang - Sun Microsystems - Beijing China tstat = &mgp->ss[i].tx.stats; 533704b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += tstat->obytes; 533804b6cca3Slucy wang - Sun Microsystems - Beijing China } 533904b6cca3Slucy wang - Sun Microsystems - Beijing China *val = tmp; 534004b6cca3Slucy wang - Sun Microsystems - Beijing China break; 534104b6cca3Slucy wang - Sun Microsystems - Beijing China 534204b6cca3Slucy wang - Sun Microsystems - Beijing China case MAC_STAT_OPACKETS: 534304b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 534404b6cca3Slucy wang - Sun Microsystems - Beijing China tstat = &mgp->ss[i].tx.stats; 534504b6cca3Slucy wang - Sun Microsystems - Beijing China tmp += tstat->opackets; 534604b6cca3Slucy wang - Sun Microsystems - Beijing China } 534704b6cca3Slucy wang - Sun Microsystems - Beijing China *val = tmp; 534804b6cca3Slucy wang - Sun Microsystems - Beijing China break; 534904b6cca3Slucy wang - Sun Microsystems - Beijing China 535004b6cca3Slucy wang - Sun Microsystems - Beijing China case ETHER_STAT_TOOLONG_ERRORS: 535104b6cca3Slucy wang - Sun Microsystems - Beijing China *val = ntohl(fw_stats->dropped_overrun); 535204b6cca3Slucy wang - Sun Microsystems - Beijing China break; 535304b6cca3Slucy wang - Sun Microsystems - Beijing China 535404b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef SOLARIS_S11 535504b6cca3Slucy wang - Sun Microsystems - Beijing China case ETHER_STAT_TOOSHORT_ERRORS: 535604b6cca3Slucy wang - Sun Microsystems - Beijing China *val = ntohl(fw_stats->dropped_runt); 535704b6cca3Slucy wang - Sun Microsystems - Beijing China break; 535804b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 535904b6cca3Slucy wang - Sun Microsystems - Beijing China 536004b6cca3Slucy wang - Sun Microsystems - Beijing China case ETHER_STAT_LINK_PAUSE: 536104b6cca3Slucy wang - Sun Microsystems - Beijing China *val = mgp->pause; 536204b6cca3Slucy wang - Sun Microsystems - Beijing China break; 536304b6cca3Slucy wang - Sun Microsystems - Beijing China 536404b6cca3Slucy wang - Sun Microsystems - Beijing China case ETHER_STAT_LINK_AUTONEG: 536504b6cca3Slucy wang - Sun Microsystems - Beijing China *val = 1; 536604b6cca3Slucy wang - Sun Microsystems - Beijing China break; 536704b6cca3Slucy wang - Sun Microsystems - Beijing China 536804b6cca3Slucy wang - Sun Microsystems - Beijing China case ETHER_STAT_LINK_DUPLEX: 536904b6cca3Slucy wang - Sun Microsystems - Beijing China *val = LINK_DUPLEX_FULL; 537004b6cca3Slucy wang - Sun Microsystems - Beijing China break; 537104b6cca3Slucy wang - Sun Microsystems - Beijing China 537204b6cca3Slucy wang - Sun Microsystems - Beijing China default: 537304b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENOTSUP); 537404b6cca3Slucy wang - Sun Microsystems - Beijing China } 537504b6cca3Slucy wang - Sun Microsystems - Beijing China 537604b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 537704b6cca3Slucy wang - Sun Microsystems - Beijing China } 537804b6cca3Slucy wang - Sun Microsystems - Beijing China 5379*6d0043d8SRobert Mustacchi /* ARGSUSED */ 5380*6d0043d8SRobert Mustacchi static void 5381*6d0043d8SRobert Mustacchi myri10ge_m_propinfo(void *arg, const char *pr_name, 5382*6d0043d8SRobert Mustacchi mac_prop_id_t pr_num, mac_prop_info_handle_t prh) 5383*6d0043d8SRobert Mustacchi { 5384*6d0043d8SRobert Mustacchi switch (pr_num) { 5385*6d0043d8SRobert Mustacchi case MAC_PROP_MTU: 5386*6d0043d8SRobert Mustacchi mac_prop_info_set_default_uint32(prh, MYRI10GE_DEFAULT_GLD_MTU); 5387*6d0043d8SRobert Mustacchi mac_prop_info_set_range_uint32(prh, MYRI10GE_MIN_GLD_MTU, 5388*6d0043d8SRobert Mustacchi MYRI10GE_MAX_GLD_MTU); 5389*6d0043d8SRobert Mustacchi break; 5390*6d0043d8SRobert Mustacchi default: 5391*6d0043d8SRobert Mustacchi break; 5392*6d0043d8SRobert Mustacchi } 5393*6d0043d8SRobert Mustacchi } 5394*6d0043d8SRobert Mustacchi 5395*6d0043d8SRobert Mustacchi /*ARGSUSED*/ 5396*6d0043d8SRobert Mustacchi static int 5397*6d0043d8SRobert Mustacchi myri10ge_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 5398*6d0043d8SRobert Mustacchi uint_t pr_valsize, const void *pr_val) 5399*6d0043d8SRobert Mustacchi { 5400*6d0043d8SRobert Mustacchi int err = 0; 5401*6d0043d8SRobert Mustacchi struct myri10ge_priv *mgp = arg; 5402*6d0043d8SRobert Mustacchi 5403*6d0043d8SRobert Mustacchi switch (pr_num) { 5404*6d0043d8SRobert Mustacchi case MAC_PROP_MTU: { 5405*6d0043d8SRobert Mustacchi uint32_t mtu; 5406*6d0043d8SRobert Mustacchi if (pr_valsize < sizeof (mtu)) { 5407*6d0043d8SRobert Mustacchi err = EINVAL; 5408*6d0043d8SRobert Mustacchi break; 5409*6d0043d8SRobert Mustacchi } 5410*6d0043d8SRobert Mustacchi bcopy(pr_val, &mtu, sizeof (mtu)); 5411*6d0043d8SRobert Mustacchi if (mtu > MYRI10GE_MAX_GLD_MTU || 5412*6d0043d8SRobert Mustacchi mtu < MYRI10GE_MIN_GLD_MTU) { 5413*6d0043d8SRobert Mustacchi err = EINVAL; 5414*6d0043d8SRobert Mustacchi break; 5415*6d0043d8SRobert Mustacchi } 5416*6d0043d8SRobert Mustacchi 5417*6d0043d8SRobert Mustacchi mutex_enter(&mgp->intrlock); 5418*6d0043d8SRobert Mustacchi if (mgp->running != MYRI10GE_ETH_STOPPED) { 5419*6d0043d8SRobert Mustacchi err = EBUSY; 5420*6d0043d8SRobert Mustacchi mutex_exit(&mgp->intrlock); 5421*6d0043d8SRobert Mustacchi break; 5422*6d0043d8SRobert Mustacchi } 5423*6d0043d8SRobert Mustacchi 5424*6d0043d8SRobert Mustacchi myri10ge_mtu = mtu + sizeof (struct ether_header) + 5425*6d0043d8SRobert Mustacchi MXGEFW_PAD + VLAN_TAGSZ; 5426*6d0043d8SRobert Mustacchi mutex_exit(&mgp->intrlock); 5427*6d0043d8SRobert Mustacchi break; 5428*6d0043d8SRobert Mustacchi } 5429*6d0043d8SRobert Mustacchi default: 5430*6d0043d8SRobert Mustacchi err = ENOTSUP; 5431*6d0043d8SRobert Mustacchi break; 5432*6d0043d8SRobert Mustacchi } 5433*6d0043d8SRobert Mustacchi 5434*6d0043d8SRobert Mustacchi return (err); 5435*6d0043d8SRobert Mustacchi } 5436*6d0043d8SRobert Mustacchi 543704b6cca3Slucy wang - Sun Microsystems - Beijing China static mac_callbacks_t myri10ge_m_callbacks = { 5438*6d0043d8SRobert Mustacchi (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_PROPINFO), 543904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_stat, 544004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_start, 544104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_stop, 544204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_promisc, 544304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_multicst, 544404b6cca3Slucy wang - Sun Microsystems - Beijing China NULL, 544504b6cca3Slucy wang - Sun Microsystems - Beijing China NULL, 54460dc2366fSVenugopal Iyer NULL, 544704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_m_ioctl, 5448*6d0043d8SRobert Mustacchi myri10ge_m_getcapab, 5449*6d0043d8SRobert Mustacchi NULL, 5450*6d0043d8SRobert Mustacchi NULL, 5451*6d0043d8SRobert Mustacchi myri10ge_m_setprop, 5452*6d0043d8SRobert Mustacchi NULL, 5453*6d0043d8SRobert Mustacchi myri10ge_m_propinfo 545404b6cca3Slucy wang - Sun Microsystems - Beijing China }; 545504b6cca3Slucy wang - Sun Microsystems - Beijing China 545604b6cca3Slucy wang - Sun Microsystems - Beijing China 545704b6cca3Slucy wang - Sun Microsystems - Beijing China static int 545804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_probe_slices(struct myri10ge_priv *mgp) 545904b6cca3Slucy wang - Sun Microsystems - Beijing China { 546004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_cmd_t cmd; 546104b6cca3Slucy wang - Sun Microsystems - Beijing China int status; 546204b6cca3Slucy wang - Sun Microsystems - Beijing China 546304b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->num_slices = 1; 546404b6cca3Slucy wang - Sun Microsystems - Beijing China 546504b6cca3Slucy wang - Sun Microsystems - Beijing China /* hit the board with a reset to ensure it is alive */ 546604b6cca3Slucy wang - Sun Microsystems - Beijing China (void) memset(&cmd, 0, sizeof (cmd)); 546704b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_RESET, &cmd); 546804b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 546904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: failed reset\n", mgp->name); 547004b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENXIO); 547104b6cca3Slucy wang - Sun Microsystems - Beijing China } 547204b6cca3Slucy wang - Sun Microsystems - Beijing China 547304b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_use_msix == 0) 547404b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 547504b6cca3Slucy wang - Sun Microsystems - Beijing China 547604b6cca3Slucy wang - Sun Microsystems - Beijing China /* tell it the size of the interrupt queues */ 547704b6cca3Slucy wang - Sun Microsystems - Beijing China cmd.data0 = mgp->max_intr_slots * sizeof (struct mcp_slot); 547804b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_SIZE, &cmd); 547904b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 548004b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: failed MXGEFW_CMD_SET_INTRQ_SIZE\n", 548104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 548204b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENXIO); 548304b6cca3Slucy wang - Sun Microsystems - Beijing China } 548404b6cca3Slucy wang - Sun Microsystems - Beijing China 548504b6cca3Slucy wang - Sun Microsystems - Beijing China /* ask the maximum number of slices it supports */ 548604b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_RSS_QUEUES, 548704b6cca3Slucy wang - Sun Microsystems - Beijing China &cmd); 548804b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) 548904b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 549004b6cca3Slucy wang - Sun Microsystems - Beijing China 549104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->num_slices = cmd.data0; 549204b6cca3Slucy wang - Sun Microsystems - Beijing China 549304b6cca3Slucy wang - Sun Microsystems - Beijing China /* 549404b6cca3Slucy wang - Sun Microsystems - Beijing China * if the admin did not specify a limit to how many 549504b6cca3Slucy wang - Sun Microsystems - Beijing China * slices we should use, cap it automatically to the 549604b6cca3Slucy wang - Sun Microsystems - Beijing China * number of CPUs currently online 549704b6cca3Slucy wang - Sun Microsystems - Beijing China */ 549804b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_max_slices == -1) 549904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_max_slices = ncpus; 550004b6cca3Slucy wang - Sun Microsystems - Beijing China 550104b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->num_slices > myri10ge_max_slices) 550204b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->num_slices = myri10ge_max_slices; 550304b6cca3Slucy wang - Sun Microsystems - Beijing China 550404b6cca3Slucy wang - Sun Microsystems - Beijing China 550504b6cca3Slucy wang - Sun Microsystems - Beijing China /* 550604b6cca3Slucy wang - Sun Microsystems - Beijing China * Now try to allocate as many MSI-X vectors as we have 550704b6cca3Slucy wang - Sun Microsystems - Beijing China * slices. We give up on MSI-X if we can only get a single 550804b6cca3Slucy wang - Sun Microsystems - Beijing China * vector. 550904b6cca3Slucy wang - Sun Microsystems - Beijing China */ 551004b6cca3Slucy wang - Sun Microsystems - Beijing China while (mgp->num_slices > 1) { 551104b6cca3Slucy wang - Sun Microsystems - Beijing China /* make sure it is a power of two */ 5512de710d24SJosef 'Jeff' Sipek while (!ISP2(mgp->num_slices)) 551304b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->num_slices--; 551404b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->num_slices == 1) 551504b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 551604b6cca3Slucy wang - Sun Microsystems - Beijing China 551704b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_add_intrs(mgp, 0); 551804b6cca3Slucy wang - Sun Microsystems - Beijing China if (status == 0) { 551904b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rem_intrs(mgp, 0); 552004b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->intr_cnt == mgp->num_slices) { 552104b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_verbose) 552204b6cca3Slucy wang - Sun Microsystems - Beijing China printf("Got %d slices!\n", 552304b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->num_slices); 552404b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 552504b6cca3Slucy wang - Sun Microsystems - Beijing China } 552604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->num_slices = mgp->intr_cnt; 552704b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 552804b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->num_slices = mgp->num_slices / 2; 552904b6cca3Slucy wang - Sun Microsystems - Beijing China } 553004b6cca3Slucy wang - Sun Microsystems - Beijing China } 553104b6cca3Slucy wang - Sun Microsystems - Beijing China 553204b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_verbose) 553304b6cca3Slucy wang - Sun Microsystems - Beijing China printf("Got %d slices\n", mgp->num_slices); 553404b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 553504b6cca3Slucy wang - Sun Microsystems - Beijing China } 553604b6cca3Slucy wang - Sun Microsystems - Beijing China 553704b6cca3Slucy wang - Sun Microsystems - Beijing China static void 553804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_lro_free(struct myri10ge_slice_state *ss) 553904b6cca3Slucy wang - Sun Microsystems - Beijing China { 554004b6cca3Slucy wang - Sun Microsystems - Beijing China struct lro_entry *lro; 554104b6cca3Slucy wang - Sun Microsystems - Beijing China 554204b6cca3Slucy wang - Sun Microsystems - Beijing China while (ss->lro_free != NULL) { 554304b6cca3Slucy wang - Sun Microsystems - Beijing China lro = ss->lro_free; 554404b6cca3Slucy wang - Sun Microsystems - Beijing China ss->lro_free = lro->next; 554504b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(lro, sizeof (*lro)); 554604b6cca3Slucy wang - Sun Microsystems - Beijing China } 554704b6cca3Slucy wang - Sun Microsystems - Beijing China } 554804b6cca3Slucy wang - Sun Microsystems - Beijing China 554904b6cca3Slucy wang - Sun Microsystems - Beijing China static void 555004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_lro_alloc(struct myri10ge_slice_state *ss) 555104b6cca3Slucy wang - Sun Microsystems - Beijing China { 555204b6cca3Slucy wang - Sun Microsystems - Beijing China struct lro_entry *lro; 555304b6cca3Slucy wang - Sun Microsystems - Beijing China int idx; 555404b6cca3Slucy wang - Sun Microsystems - Beijing China 555504b6cca3Slucy wang - Sun Microsystems - Beijing China ss->lro_free = NULL; 555604b6cca3Slucy wang - Sun Microsystems - Beijing China ss->lro_active = NULL; 555704b6cca3Slucy wang - Sun Microsystems - Beijing China 555804b6cca3Slucy wang - Sun Microsystems - Beijing China for (idx = 0; idx < myri10ge_lro_cnt; idx++) { 555904b6cca3Slucy wang - Sun Microsystems - Beijing China lro = kmem_zalloc(sizeof (*lro), KM_SLEEP); 556004b6cca3Slucy wang - Sun Microsystems - Beijing China if (lro == NULL) 556104b6cca3Slucy wang - Sun Microsystems - Beijing China continue; 556204b6cca3Slucy wang - Sun Microsystems - Beijing China lro->next = ss->lro_free; 556304b6cca3Slucy wang - Sun Microsystems - Beijing China ss->lro_free = lro; 556404b6cca3Slucy wang - Sun Microsystems - Beijing China } 556504b6cca3Slucy wang - Sun Microsystems - Beijing China } 556604b6cca3Slucy wang - Sun Microsystems - Beijing China 556704b6cca3Slucy wang - Sun Microsystems - Beijing China static void 556804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_free_slices(struct myri10ge_priv *mgp) 556904b6cca3Slucy wang - Sun Microsystems - Beijing China { 557004b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_slice_state *ss; 557104b6cca3Slucy wang - Sun Microsystems - Beijing China size_t bytes; 557204b6cca3Slucy wang - Sun Microsystems - Beijing China int i; 557304b6cca3Slucy wang - Sun Microsystems - Beijing China 557404b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->ss == NULL) 557504b6cca3Slucy wang - Sun Microsystems - Beijing China return; 557604b6cca3Slucy wang - Sun Microsystems - Beijing China 557704b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 557804b6cca3Slucy wang - Sun Microsystems - Beijing China ss = &mgp->ss[i]; 557904b6cca3Slucy wang - Sun Microsystems - Beijing China if (ss->rx_done.entry == NULL) 558004b6cca3Slucy wang - Sun Microsystems - Beijing China continue; 558104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dma_free(&ss->rx_done.dma); 558204b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_done.entry = NULL; 558304b6cca3Slucy wang - Sun Microsystems - Beijing China if (ss->fw_stats == NULL) 558404b6cca3Slucy wang - Sun Microsystems - Beijing China continue; 558504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dma_free(&ss->fw_stats_dma); 558604b6cca3Slucy wang - Sun Microsystems - Beijing China ss->fw_stats = NULL; 558704b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_destroy(&ss->rx_lock); 558804b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_destroy(&ss->tx.lock); 558904b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_destroy(&ss->tx.handle_lock); 559004b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_destroy(&ss->poll_lock); 559104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_jpool_fini(ss); 559204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_slice_stat_destroy(ss); 559304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_lro_free(ss); 559404b6cca3Slucy wang - Sun Microsystems - Beijing China } 559504b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = sizeof (*mgp->ss) * mgp->num_slices; 559604b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(mgp->ss, bytes); 559704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->ss = NULL; 559804b6cca3Slucy wang - Sun Microsystems - Beijing China } 559904b6cca3Slucy wang - Sun Microsystems - Beijing China 560004b6cca3Slucy wang - Sun Microsystems - Beijing China 560104b6cca3Slucy wang - Sun Microsystems - Beijing China static int 560204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_alloc_slices(struct myri10ge_priv *mgp) 560304b6cca3Slucy wang - Sun Microsystems - Beijing China { 560404b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_slice_state *ss; 560504b6cca3Slucy wang - Sun Microsystems - Beijing China size_t bytes; 560604b6cca3Slucy wang - Sun Microsystems - Beijing China int i; 560704b6cca3Slucy wang - Sun Microsystems - Beijing China 560804b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = sizeof (*mgp->ss) * mgp->num_slices; 560904b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->ss = kmem_zalloc(bytes, KM_SLEEP); 561004b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->ss == NULL) 561104b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENOMEM); 561204b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 561304b6cca3Slucy wang - Sun Microsystems - Beijing China ss = &mgp->ss[i]; 561404b6cca3Slucy wang - Sun Microsystems - Beijing China 561504b6cca3Slucy wang - Sun Microsystems - Beijing China ss->mgp = mgp; 561604b6cca3Slucy wang - Sun Microsystems - Beijing China 561704b6cca3Slucy wang - Sun Microsystems - Beijing China /* allocate the per-slice firmware stats */ 561804b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = sizeof (*ss->fw_stats); 561904b6cca3Slucy wang - Sun Microsystems - Beijing China ss->fw_stats = (mcp_irq_data_t *)(void *) 562004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dma_alloc(mgp->dip, bytes, 562104b6cca3Slucy wang - Sun Microsystems - Beijing China &myri10ge_misc_dma_attr, &myri10ge_dev_access_attr, 562204b6cca3Slucy wang - Sun Microsystems - Beijing China DDI_DMA_CONSISTENT, DDI_DMA_READ|DDI_DMA_CONSISTENT, 562304b6cca3Slucy wang - Sun Microsystems - Beijing China &ss->fw_stats_dma, 1, DDI_DMA_DONTWAIT); 562404b6cca3Slucy wang - Sun Microsystems - Beijing China if (ss->fw_stats == NULL) 562504b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort; 562604b6cca3Slucy wang - Sun Microsystems - Beijing China (void) memset(ss->fw_stats, 0, bytes); 562704b6cca3Slucy wang - Sun Microsystems - Beijing China 562804b6cca3Slucy wang - Sun Microsystems - Beijing China /* allocate rx done ring */ 562904b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = mgp->max_intr_slots * 563004b6cca3Slucy wang - Sun Microsystems - Beijing China sizeof (*ss->rx_done.entry); 563104b6cca3Slucy wang - Sun Microsystems - Beijing China ss->rx_done.entry = (mcp_slot_t *)(void *) 563204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dma_alloc(mgp->dip, bytes, 563304b6cca3Slucy wang - Sun Microsystems - Beijing China &myri10ge_misc_dma_attr, &myri10ge_dev_access_attr, 563404b6cca3Slucy wang - Sun Microsystems - Beijing China DDI_DMA_CONSISTENT, DDI_DMA_READ|DDI_DMA_CONSISTENT, 563504b6cca3Slucy wang - Sun Microsystems - Beijing China &ss->rx_done.dma, 1, DDI_DMA_DONTWAIT); 563604b6cca3Slucy wang - Sun Microsystems - Beijing China if (ss->rx_done.entry == NULL) { 563704b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort; 563804b6cca3Slucy wang - Sun Microsystems - Beijing China } 563904b6cca3Slucy wang - Sun Microsystems - Beijing China (void) memset(ss->rx_done.entry, 0, bytes); 564004b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_init(&ss->rx_lock, NULL, MUTEX_DEFAULT, mgp->icookie); 564104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_init(&ss->tx.lock, NULL, MUTEX_DEFAULT, NULL); 564204b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_init(&ss->tx.handle_lock, NULL, MUTEX_DEFAULT, NULL); 564304b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_init(&ss->poll_lock, NULL, MUTEX_DEFAULT, NULL); 564404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_jpool_init(ss); 564504b6cca3Slucy wang - Sun Microsystems - Beijing China (void) myri10ge_slice_stat_init(ss); 564604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_lro_alloc(ss); 564704b6cca3Slucy wang - Sun Microsystems - Beijing China } 564804b6cca3Slucy wang - Sun Microsystems - Beijing China 564904b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 565004b6cca3Slucy wang - Sun Microsystems - Beijing China 565104b6cca3Slucy wang - Sun Microsystems - Beijing China abort: 565204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_free_slices(mgp); 565304b6cca3Slucy wang - Sun Microsystems - Beijing China return (ENOMEM); 565404b6cca3Slucy wang - Sun Microsystems - Beijing China } 565504b6cca3Slucy wang - Sun Microsystems - Beijing China 565604b6cca3Slucy wang - Sun Microsystems - Beijing China static int 565704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_save_msi_state(struct myri10ge_priv *mgp, 565804b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_acc_handle_t handle) 565904b6cca3Slucy wang - Sun Microsystems - Beijing China { 566004b6cca3Slucy wang - Sun Microsystems - Beijing China uint8_t ptr; 566104b6cca3Slucy wang - Sun Microsystems - Beijing China int err; 566204b6cca3Slucy wang - Sun Microsystems - Beijing China 566304b6cca3Slucy wang - Sun Microsystems - Beijing China err = myri10ge_find_cap(handle, &ptr, PCI_CAP_ID_MSI); 566404b6cca3Slucy wang - Sun Microsystems - Beijing China if (err != 0) { 566504b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: could not find MSI cap\n", 566604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 566704b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 566804b6cca3Slucy wang - Sun Microsystems - Beijing China } 566904b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->pci_saved_state.msi_ctrl = 567004b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_get16(handle, ptr + PCI_MSI_CTRL); 567104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->pci_saved_state.msi_addr_low = 567204b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_get32(handle, ptr + PCI_MSI_ADDR_OFFSET); 567304b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->pci_saved_state.msi_addr_high = 567404b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_get32(handle, ptr + PCI_MSI_ADDR_OFFSET + 4); 567504b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->pci_saved_state.msi_data_32 = 567604b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_get16(handle, ptr + PCI_MSI_32BIT_DATA); 567704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->pci_saved_state.msi_data_64 = 567804b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_get16(handle, ptr + PCI_MSI_64BIT_DATA); 567904b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 568004b6cca3Slucy wang - Sun Microsystems - Beijing China } 568104b6cca3Slucy wang - Sun Microsystems - Beijing China 568204b6cca3Slucy wang - Sun Microsystems - Beijing China static int 568304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_restore_msi_state(struct myri10ge_priv *mgp, 568404b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_acc_handle_t handle) 568504b6cca3Slucy wang - Sun Microsystems - Beijing China { 568604b6cca3Slucy wang - Sun Microsystems - Beijing China uint8_t ptr; 568704b6cca3Slucy wang - Sun Microsystems - Beijing China int err; 568804b6cca3Slucy wang - Sun Microsystems - Beijing China 568904b6cca3Slucy wang - Sun Microsystems - Beijing China err = myri10ge_find_cap(handle, &ptr, PCI_CAP_ID_MSI); 569004b6cca3Slucy wang - Sun Microsystems - Beijing China if (err != 0) { 569104b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: could not find MSI cap\n", 569204b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 569304b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 569404b6cca3Slucy wang - Sun Microsystems - Beijing China } 569504b6cca3Slucy wang - Sun Microsystems - Beijing China 569604b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_put16(handle, ptr + PCI_MSI_CTRL, 569704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->pci_saved_state.msi_ctrl); 569804b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_put32(handle, ptr + PCI_MSI_ADDR_OFFSET, 569904b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->pci_saved_state.msi_addr_low); 570004b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_put32(handle, ptr + PCI_MSI_ADDR_OFFSET + 4, 570104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->pci_saved_state.msi_addr_high); 570204b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_put16(handle, ptr + PCI_MSI_32BIT_DATA, 570304b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->pci_saved_state.msi_data_32); 570404b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_put16(handle, ptr + PCI_MSI_64BIT_DATA, 570504b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->pci_saved_state.msi_data_64); 570604b6cca3Slucy wang - Sun Microsystems - Beijing China 570704b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 570804b6cca3Slucy wang - Sun Microsystems - Beijing China } 570904b6cca3Slucy wang - Sun Microsystems - Beijing China 571004b6cca3Slucy wang - Sun Microsystems - Beijing China static int 571104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_save_pci_state(struct myri10ge_priv *mgp) 571204b6cca3Slucy wang - Sun Microsystems - Beijing China { 571304b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_acc_handle_t handle = mgp->cfg_hdl; 571404b6cca3Slucy wang - Sun Microsystems - Beijing China int i; 571504b6cca3Slucy wang - Sun Microsystems - Beijing China int err = DDI_SUCCESS; 571604b6cca3Slucy wang - Sun Microsystems - Beijing China 571704b6cca3Slucy wang - Sun Microsystems - Beijing China 571804b6cca3Slucy wang - Sun Microsystems - Beijing China /* Save the non-extended PCI config space 32-bits at a time */ 571904b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < 16; i++) 572004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->pci_saved_state.base[i] = 572104b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_get32(handle, i*4); 572204b6cca3Slucy wang - Sun Microsystems - Beijing China 572304b6cca3Slucy wang - Sun Microsystems - Beijing China /* now save MSI interrupt state *, if needed */ 572404b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->ddi_intr_type == DDI_INTR_TYPE_MSI) 572504b6cca3Slucy wang - Sun Microsystems - Beijing China err = myri10ge_save_msi_state(mgp, handle); 572604b6cca3Slucy wang - Sun Microsystems - Beijing China 572704b6cca3Slucy wang - Sun Microsystems - Beijing China return (err); 572804b6cca3Slucy wang - Sun Microsystems - Beijing China } 572904b6cca3Slucy wang - Sun Microsystems - Beijing China 573004b6cca3Slucy wang - Sun Microsystems - Beijing China static int 573104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_restore_pci_state(struct myri10ge_priv *mgp) 573204b6cca3Slucy wang - Sun Microsystems - Beijing China { 573304b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_acc_handle_t handle = mgp->cfg_hdl; 573404b6cca3Slucy wang - Sun Microsystems - Beijing China int i; 573504b6cca3Slucy wang - Sun Microsystems - Beijing China int err = DDI_SUCCESS; 573604b6cca3Slucy wang - Sun Microsystems - Beijing China 573704b6cca3Slucy wang - Sun Microsystems - Beijing China 573804b6cca3Slucy wang - Sun Microsystems - Beijing China /* Restore the non-extended PCI config space 32-bits at a time */ 573904b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 15; i >= 0; i--) 574004b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_put32(handle, i*4, mgp->pci_saved_state.base[i]); 574104b6cca3Slucy wang - Sun Microsystems - Beijing China 574204b6cca3Slucy wang - Sun Microsystems - Beijing China /* now restore MSI interrupt state *, if needed */ 574304b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->ddi_intr_type == DDI_INTR_TYPE_MSI) 574404b6cca3Slucy wang - Sun Microsystems - Beijing China err = myri10ge_restore_msi_state(mgp, handle); 574504b6cca3Slucy wang - Sun Microsystems - Beijing China 574604b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->max_read_request_4k) 574704b6cca3Slucy wang - Sun Microsystems - Beijing China (void) myri10ge_set_max_readreq(handle); 574804b6cca3Slucy wang - Sun Microsystems - Beijing China return (err); 574904b6cca3Slucy wang - Sun Microsystems - Beijing China } 575004b6cca3Slucy wang - Sun Microsystems - Beijing China 575104b6cca3Slucy wang - Sun Microsystems - Beijing China 575204b6cca3Slucy wang - Sun Microsystems - Beijing China static int 575304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_suspend(dev_info_t *dip) 575404b6cca3Slucy wang - Sun Microsystems - Beijing China { 575504b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = ddi_get_driver_private(dip); 575604b6cca3Slucy wang - Sun Microsystems - Beijing China int status; 575704b6cca3Slucy wang - Sun Microsystems - Beijing China 575804b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp == NULL) { 575904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "null dip in myri10ge_suspend\n"); 576004b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 576104b6cca3Slucy wang - Sun Microsystems - Beijing China } 576204b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->dip != dip) { 576304b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "bad dip in myri10ge_suspend\n"); 576404b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 576504b6cca3Slucy wang - Sun Microsystems - Beijing China } 576604b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&mgp->intrlock); 576704b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->running == MYRI10GE_ETH_RUNNING) { 576804b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->running = MYRI10GE_ETH_STOPPING; 576904b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->intrlock); 577004b6cca3Slucy wang - Sun Microsystems - Beijing China (void) untimeout(mgp->timer_id); 577104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&mgp->intrlock); 577204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_stop_locked(mgp); 577304b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->running = MYRI10GE_ETH_SUSPENDED_RUNNING; 577404b6cca3Slucy wang - Sun Microsystems - Beijing China } 577504b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_save_pci_state(mgp); 577604b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->intrlock); 577704b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 577804b6cca3Slucy wang - Sun Microsystems - Beijing China } 577904b6cca3Slucy wang - Sun Microsystems - Beijing China 578004b6cca3Slucy wang - Sun Microsystems - Beijing China static int 578104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_resume(dev_info_t *dip) 578204b6cca3Slucy wang - Sun Microsystems - Beijing China { 578304b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp = ddi_get_driver_private(dip); 578404b6cca3Slucy wang - Sun Microsystems - Beijing China int status = DDI_SUCCESS; 578504b6cca3Slucy wang - Sun Microsystems - Beijing China 578604b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp == NULL) { 578704b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "null dip in myri10ge_resume\n"); 578804b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 578904b6cca3Slucy wang - Sun Microsystems - Beijing China } 579004b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->dip != dip) { 579104b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "bad dip in myri10ge_resume\n"); 579204b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 579304b6cca3Slucy wang - Sun Microsystems - Beijing China } 579404b6cca3Slucy wang - Sun Microsystems - Beijing China 579504b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&mgp->intrlock); 579604b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_restore_pci_state(mgp); 579704b6cca3Slucy wang - Sun Microsystems - Beijing China if (status == DDI_SUCCESS && 579804b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->running == MYRI10GE_ETH_SUSPENDED_RUNNING) { 579904b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_start_locked(mgp); 580004b6cca3Slucy wang - Sun Microsystems - Beijing China } 580104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->intrlock); 580204b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != DDI_SUCCESS) 580304b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 580404b6cca3Slucy wang - Sun Microsystems - Beijing China 580504b6cca3Slucy wang - Sun Microsystems - Beijing China /* start the watchdog timer */ 580604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->timer_id = timeout(myri10ge_watchdog, mgp, 580704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->timer_ticks); 580804b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 580904b6cca3Slucy wang - Sun Microsystems - Beijing China } 581004b6cca3Slucy wang - Sun Microsystems - Beijing China 581104b6cca3Slucy wang - Sun Microsystems - Beijing China static int 581204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 581304b6cca3Slucy wang - Sun Microsystems - Beijing China { 581404b6cca3Slucy wang - Sun Microsystems - Beijing China 581504b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp; 581604b6cca3Slucy wang - Sun Microsystems - Beijing China mac_register_t *macp, *omacp; 581704b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_acc_handle_t handle; 581804b6cca3Slucy wang - Sun Microsystems - Beijing China uint32_t csr, hdr_offset; 581904b6cca3Slucy wang - Sun Microsystems - Beijing China int status, span, link_width, max_read_request_4k; 582004b6cca3Slucy wang - Sun Microsystems - Beijing China unsigned long bus_number, dev_number, func_number; 582104b6cca3Slucy wang - Sun Microsystems - Beijing China size_t bytes; 582204b6cca3Slucy wang - Sun Microsystems - Beijing China offset_t ss_offset; 582304b6cca3Slucy wang - Sun Microsystems - Beijing China uint8_t vso; 582404b6cca3Slucy wang - Sun Microsystems - Beijing China 582504b6cca3Slucy wang - Sun Microsystems - Beijing China if (cmd == DDI_RESUME) { 582604b6cca3Slucy wang - Sun Microsystems - Beijing China return (myri10ge_resume(dip)); 582704b6cca3Slucy wang - Sun Microsystems - Beijing China } 582804b6cca3Slucy wang - Sun Microsystems - Beijing China 582904b6cca3Slucy wang - Sun Microsystems - Beijing China if (cmd != DDI_ATTACH) 583004b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 583104b6cca3Slucy wang - Sun Microsystems - Beijing China if (pci_config_setup(dip, &handle) != DDI_SUCCESS) 583204b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 583304b6cca3Slucy wang - Sun Microsystems - Beijing China 583404b6cca3Slucy wang - Sun Microsystems - Beijing China /* enable busmater and io space access */ 583504b6cca3Slucy wang - Sun Microsystems - Beijing China csr = pci_config_get32(handle, PCI_CONF_COMM); 583604b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_put32(handle, PCI_CONF_COMM, 583704b6cca3Slucy wang - Sun Microsystems - Beijing China (csr |PCI_COMM_ME|PCI_COMM_MAE)); 583804b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_read_pcie_link_width(handle, &link_width); 583904b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 584004b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "could not read link width!\n"); 584104b6cca3Slucy wang - Sun Microsystems - Beijing China link_width = 0; 584204b6cca3Slucy wang - Sun Microsystems - Beijing China } 584304b6cca3Slucy wang - Sun Microsystems - Beijing China max_read_request_4k = !myri10ge_set_max_readreq(handle); 584404b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_find_cap(handle, &vso, PCI_CAP_ID_VS); 584504b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) 584604b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_cfg_hdl; 584704b6cca3Slucy wang - Sun Microsystems - Beijing China if ((omacp = mac_alloc(MAC_VERSION)) == NULL) 584804b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_cfg_hdl; 584904b6cca3Slucy wang - Sun Microsystems - Beijing China /* 585004b6cca3Slucy wang - Sun Microsystems - Beijing China * XXXX Hack: mac_register_t grows in newer kernels. To be 585104b6cca3Slucy wang - Sun Microsystems - Beijing China * able to write newer fields, such as m_margin, without 585204b6cca3Slucy wang - Sun Microsystems - Beijing China * writing outside allocated memory, we allocate our own macp 585304b6cca3Slucy wang - Sun Microsystems - Beijing China * and pass that to mac_register() 585404b6cca3Slucy wang - Sun Microsystems - Beijing China */ 585504b6cca3Slucy wang - Sun Microsystems - Beijing China macp = kmem_zalloc(sizeof (*macp) * 8, KM_SLEEP); 585604b6cca3Slucy wang - Sun Microsystems - Beijing China macp->m_version = omacp->m_version; 585704b6cca3Slucy wang - Sun Microsystems - Beijing China 585804b6cca3Slucy wang - Sun Microsystems - Beijing China if ((mgp = (struct myri10ge_priv *) 585904b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_zalloc(sizeof (*mgp), KM_SLEEP)) == NULL) { 586004b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_macinfo; 586104b6cca3Slucy wang - Sun Microsystems - Beijing China } 586204b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_set_driver_private(dip, mgp); 586304b6cca3Slucy wang - Sun Microsystems - Beijing China 586404b6cca3Slucy wang - Sun Microsystems - Beijing China /* setup device name for log messages */ 586504b6cca3Slucy wang - Sun Microsystems - Beijing China (void) sprintf(mgp->name, "myri10ge%d", ddi_get_instance(dip)); 586604b6cca3Slucy wang - Sun Microsystems - Beijing China 586704b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&myri10ge_param_lock); 586804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_get_props(dip); 586904b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->intr_coal_delay = myri10ge_intr_coal_delay; 587004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->pause = myri10ge_flow_control; 587104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&myri10ge_param_lock); 587204b6cca3Slucy wang - Sun Microsystems - Beijing China 587304b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->max_read_request_4k = max_read_request_4k; 587404b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->pcie_link_width = link_width; 587504b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->running = MYRI10GE_ETH_STOPPED; 587604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->vso = vso; 587704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->dip = dip; 587804b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->cfg_hdl = handle; 587904b6cca3Slucy wang - Sun Microsystems - Beijing China 588004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->timer_ticks = 5 * drv_usectohz(1000000); /* 5 seconds */ 588104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_test_physical(dip); 588204b6cca3Slucy wang - Sun Microsystems - Beijing China 588304b6cca3Slucy wang - Sun Microsystems - Beijing China /* allocate command page */ 588404b6cca3Slucy wang - Sun Microsystems - Beijing China bytes = sizeof (*mgp->cmd); 588504b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->cmd = (mcp_cmd_response_t *) 588604b6cca3Slucy wang - Sun Microsystems - Beijing China (void *)myri10ge_dma_alloc(dip, bytes, 588704b6cca3Slucy wang - Sun Microsystems - Beijing China &myri10ge_misc_dma_attr, &myri10ge_dev_access_attr, 588804b6cca3Slucy wang - Sun Microsystems - Beijing China DDI_DMA_CONSISTENT, DDI_DMA_RDWR|DDI_DMA_CONSISTENT, 588904b6cca3Slucy wang - Sun Microsystems - Beijing China &mgp->cmd_dma, 1, DDI_DMA_DONTWAIT); 589004b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->cmd == NULL) 589104b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_mgp; 589204b6cca3Slucy wang - Sun Microsystems - Beijing China 589304b6cca3Slucy wang - Sun Microsystems - Beijing China (void) myri10ge_reg_set(dip, &mgp->reg_set, &span, &bus_number, 589404b6cca3Slucy wang - Sun Microsystems - Beijing China &dev_number, &func_number); 589504b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_verbose) 589604b6cca3Slucy wang - Sun Microsystems - Beijing China printf("%s at %ld:%ld:%ld attaching\n", mgp->name, 589704b6cca3Slucy wang - Sun Microsystems - Beijing China bus_number, dev_number, func_number); 589804b6cca3Slucy wang - Sun Microsystems - Beijing China status = ddi_regs_map_setup(dip, mgp->reg_set, (caddr_t *)&mgp->sram, 589904b6cca3Slucy wang - Sun Microsystems - Beijing China (offset_t)0, (offset_t)span, &myri10ge_dev_access_attr, 590004b6cca3Slucy wang - Sun Microsystems - Beijing China &mgp->io_handle); 590104b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != DDI_SUCCESS) { 590204b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: couldn't map memory space", mgp->name); 590304b6cca3Slucy wang - Sun Microsystems - Beijing China printf("%s: reg_set = %d, span = %d, status = %d", 590404b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, mgp->reg_set, span, status); 590504b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_mgp; 590604b6cca3Slucy wang - Sun Microsystems - Beijing China } 590704b6cca3Slucy wang - Sun Microsystems - Beijing China 590804b6cca3Slucy wang - Sun Microsystems - Beijing China hdr_offset = *(uint32_t *)(void*)(mgp->sram + MCP_HEADER_PTR_OFFSET); 590904b6cca3Slucy wang - Sun Microsystems - Beijing China hdr_offset = ntohl(hdr_offset) & 0xffffc; 591004b6cca3Slucy wang - Sun Microsystems - Beijing China ss_offset = hdr_offset + 591104b6cca3Slucy wang - Sun Microsystems - Beijing China offsetof(struct mcp_gen_header, string_specs); 591204b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->sram_size = ntohl(*(uint32_t *)(void*)(mgp->sram + ss_offset)); 591304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_pio_copy32(mgp->eeprom_strings, 591404b6cca3Slucy wang - Sun Microsystems - Beijing China (uint32_t *)(void*)((char *)mgp->sram + mgp->sram_size), 591504b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_EEPROM_STRINGS_SIZE); 591604b6cca3Slucy wang - Sun Microsystems - Beijing China (void) memset(mgp->eeprom_strings + 591704b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_EEPROM_STRINGS_SIZE - 2, 0, 2); 591804b6cca3Slucy wang - Sun Microsystems - Beijing China 591904b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_read_mac_addr(mgp); 592004b6cca3Slucy wang - Sun Microsystems - Beijing China if (status) { 592104b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_mapped; 592204b6cca3Slucy wang - Sun Microsystems - Beijing China } 592304b6cca3Slucy wang - Sun Microsystems - Beijing China 592404b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_select_firmware(mgp); 592504b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 592604b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: failed to load firmware\n", mgp->name); 592704b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_mapped; 592804b6cca3Slucy wang - Sun Microsystems - Beijing China } 592904b6cca3Slucy wang - Sun Microsystems - Beijing China 593004b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_probe_slices(mgp); 593104b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 593204b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: failed to probe slices\n", mgp->name); 593304b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_dummy_rdma; 593404b6cca3Slucy wang - Sun Microsystems - Beijing China } 593504b6cca3Slucy wang - Sun Microsystems - Beijing China 593604b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_alloc_slices(mgp); 593704b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 593804b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: failed to alloc slices\n", mgp->name); 593904b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_dummy_rdma; 594004b6cca3Slucy wang - Sun Microsystems - Beijing China } 594104b6cca3Slucy wang - Sun Microsystems - Beijing China 594204b6cca3Slucy wang - Sun Microsystems - Beijing China /* add the interrupt handler */ 594304b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_add_intrs(mgp, 1); 594404b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 594504b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: Failed to add interrupt\n", 594604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name); 594704b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_slices; 594804b6cca3Slucy wang - Sun Microsystems - Beijing China } 594904b6cca3Slucy wang - Sun Microsystems - Beijing China 595004b6cca3Slucy wang - Sun Microsystems - Beijing China /* now that we have an iblock_cookie, init the mutexes */ 595104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_init(&mgp->cmd_lock, NULL, MUTEX_DRIVER, mgp->icookie); 595204b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_init(&mgp->intrlock, NULL, MUTEX_DRIVER, mgp->icookie); 595304b6cca3Slucy wang - Sun Microsystems - Beijing China 595404b6cca3Slucy wang - Sun Microsystems - Beijing China 595504b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_nic_stat_init(mgp); 595604b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != DDI_SUCCESS) 595704b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_interrupts; 595804b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_info_init(mgp); 595904b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != DDI_SUCCESS) 596004b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_stats; 596104b6cca3Slucy wang - Sun Microsystems - Beijing China 596204b6cca3Slucy wang - Sun Microsystems - Beijing China /* 596304b6cca3Slucy wang - Sun Microsystems - Beijing China * Initialize GLD state 596404b6cca3Slucy wang - Sun Microsystems - Beijing China */ 596504b6cca3Slucy wang - Sun Microsystems - Beijing China 596604b6cca3Slucy wang - Sun Microsystems - Beijing China macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 596704b6cca3Slucy wang - Sun Microsystems - Beijing China macp->m_driver = mgp; 596804b6cca3Slucy wang - Sun Microsystems - Beijing China macp->m_dip = dip; 596904b6cca3Slucy wang - Sun Microsystems - Beijing China macp->m_src_addr = mgp->mac_addr; 597004b6cca3Slucy wang - Sun Microsystems - Beijing China macp->m_callbacks = &myri10ge_m_callbacks; 597104b6cca3Slucy wang - Sun Microsystems - Beijing China macp->m_min_sdu = 0; 597204b6cca3Slucy wang - Sun Microsystems - Beijing China macp->m_max_sdu = myri10ge_mtu - 597304b6cca3Slucy wang - Sun Microsystems - Beijing China (sizeof (struct ether_header) + MXGEFW_PAD + VLAN_TAGSZ); 597404b6cca3Slucy wang - Sun Microsystems - Beijing China #ifdef SOLARIS_S11 597504b6cca3Slucy wang - Sun Microsystems - Beijing China macp->m_margin = VLAN_TAGSZ; 597604b6cca3Slucy wang - Sun Microsystems - Beijing China #endif 597704b6cca3Slucy wang - Sun Microsystems - Beijing China macp->m_v12n = MAC_VIRT_LEVEL1; 597804b6cca3Slucy wang - Sun Microsystems - Beijing China status = mac_register(macp, &mgp->mh); 597904b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != 0) { 598004b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: mac_register failed with %d\n", 598104b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, status); 598204b6cca3Slucy wang - Sun Microsystems - Beijing China goto abort_with_info; 598304b6cca3Slucy wang - Sun Microsystems - Beijing China } 598404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_ndd_init(mgp); 598504b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_verbose) 598604b6cca3Slucy wang - Sun Microsystems - Beijing China printf("%s: %s, tx bndry %d, fw %s\n", mgp->name, 598704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->intr_type, mgp->tx_boundary, mgp->fw_name); 598804b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&myri10ge_param_lock); 598904b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->next = mgp_list; 599004b6cca3Slucy wang - Sun Microsystems - Beijing China mgp_list = mgp; 599104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&myri10ge_param_lock); 599204b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(macp, sizeof (*macp) * 8); 599304b6cca3Slucy wang - Sun Microsystems - Beijing China mac_free(omacp); 599404b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 599504b6cca3Slucy wang - Sun Microsystems - Beijing China 599604b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_info: 599704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_info_destroy(mgp); 599804b6cca3Slucy wang - Sun Microsystems - Beijing China 599904b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_stats: 600004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_nic_stat_destroy(mgp); 600104b6cca3Slucy wang - Sun Microsystems - Beijing China 600204b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_interrupts: 600304b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_destroy(&mgp->cmd_lock); 600404b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_destroy(&mgp->intrlock); 600504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rem_intrs(mgp, 1); 600604b6cca3Slucy wang - Sun Microsystems - Beijing China 600704b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_slices: 600804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_free_slices(mgp); 600904b6cca3Slucy wang - Sun Microsystems - Beijing China 601004b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_dummy_rdma: 601104b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dummy_rdma(mgp, 0); 601204b6cca3Slucy wang - Sun Microsystems - Beijing China 601304b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_mapped: 601404b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_regs_map_free(&mgp->io_handle); 601504b6cca3Slucy wang - Sun Microsystems - Beijing China 601604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dma_free(&mgp->cmd_dma); 601704b6cca3Slucy wang - Sun Microsystems - Beijing China 601804b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_mgp: 601904b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(mgp, sizeof (*mgp)); 602004b6cca3Slucy wang - Sun Microsystems - Beijing China 602104b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_macinfo: 602204b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(macp, sizeof (*macp) * 8); 602304b6cca3Slucy wang - Sun Microsystems - Beijing China mac_free(omacp); 602404b6cca3Slucy wang - Sun Microsystems - Beijing China 602504b6cca3Slucy wang - Sun Microsystems - Beijing China abort_with_cfg_hdl: 602604b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_teardown(&handle); 602704b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 602804b6cca3Slucy wang - Sun Microsystems - Beijing China 602904b6cca3Slucy wang - Sun Microsystems - Beijing China } 603004b6cca3Slucy wang - Sun Microsystems - Beijing China 603104b6cca3Slucy wang - Sun Microsystems - Beijing China 603204b6cca3Slucy wang - Sun Microsystems - Beijing China static int 603304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 603404b6cca3Slucy wang - Sun Microsystems - Beijing China { 603504b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp, *tmp; 603604b6cca3Slucy wang - Sun Microsystems - Beijing China int status, i, jbufs_alloced; 603704b6cca3Slucy wang - Sun Microsystems - Beijing China 603804b6cca3Slucy wang - Sun Microsystems - Beijing China if (cmd == DDI_SUSPEND) { 603904b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_suspend(dip); 604004b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 604104b6cca3Slucy wang - Sun Microsystems - Beijing China } 604204b6cca3Slucy wang - Sun Microsystems - Beijing China 604304b6cca3Slucy wang - Sun Microsystems - Beijing China if (cmd != DDI_DETACH) { 604404b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 604504b6cca3Slucy wang - Sun Microsystems - Beijing China } 604604b6cca3Slucy wang - Sun Microsystems - Beijing China /* Get the driver private (gld_mac_info_t) structure */ 604704b6cca3Slucy wang - Sun Microsystems - Beijing China mgp = ddi_get_driver_private(dip); 604804b6cca3Slucy wang - Sun Microsystems - Beijing China 604904b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&mgp->intrlock); 605004b6cca3Slucy wang - Sun Microsystems - Beijing China jbufs_alloced = 0; 605104b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < mgp->num_slices; i++) { 605204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_remove_jbufs(&mgp->ss[i]); 605304b6cca3Slucy wang - Sun Microsystems - Beijing China jbufs_alloced += mgp->ss[i].jpool.num_alloc; 605404b6cca3Slucy wang - Sun Microsystems - Beijing China } 605504b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&mgp->intrlock); 605604b6cca3Slucy wang - Sun Microsystems - Beijing China if (jbufs_alloced != 0) { 605704b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_NOTE, "%s: %d loaned rx buffers remain\n", 605804b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, jbufs_alloced); 605904b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 606004b6cca3Slucy wang - Sun Microsystems - Beijing China } 606104b6cca3Slucy wang - Sun Microsystems - Beijing China 606204b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&myri10ge_param_lock); 606304b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->refcnt != 0) { 606404b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&myri10ge_param_lock); 606504b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_NOTE, "%s: %d external refs remain\n", 606604b6cca3Slucy wang - Sun Microsystems - Beijing China mgp->name, mgp->refcnt); 606704b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 606804b6cca3Slucy wang - Sun Microsystems - Beijing China } 606904b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&myri10ge_param_lock); 607004b6cca3Slucy wang - Sun Microsystems - Beijing China 607104b6cca3Slucy wang - Sun Microsystems - Beijing China status = mac_unregister(mgp->mh); 607204b6cca3Slucy wang - Sun Microsystems - Beijing China if (status != DDI_SUCCESS) 607304b6cca3Slucy wang - Sun Microsystems - Beijing China return (status); 607404b6cca3Slucy wang - Sun Microsystems - Beijing China 607504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_ndd_fini(mgp); 607604b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dummy_rdma(mgp, 0); 607704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_nic_stat_destroy(mgp); 607804b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_info_destroy(mgp); 607904b6cca3Slucy wang - Sun Microsystems - Beijing China 608004b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_destroy(&mgp->cmd_lock); 608104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_destroy(&mgp->intrlock); 608204b6cca3Slucy wang - Sun Microsystems - Beijing China 608304b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_rem_intrs(mgp, 1); 608404b6cca3Slucy wang - Sun Microsystems - Beijing China 608504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_free_slices(mgp); 608604b6cca3Slucy wang - Sun Microsystems - Beijing China ddi_regs_map_free(&mgp->io_handle); 608704b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_dma_free(&mgp->cmd_dma); 608804b6cca3Slucy wang - Sun Microsystems - Beijing China pci_config_teardown(&mgp->cfg_hdl); 608904b6cca3Slucy wang - Sun Microsystems - Beijing China 609004b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_enter(&myri10ge_param_lock); 609104b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp_list == mgp) { 609204b6cca3Slucy wang - Sun Microsystems - Beijing China mgp_list = mgp->next; 609304b6cca3Slucy wang - Sun Microsystems - Beijing China } else { 609404b6cca3Slucy wang - Sun Microsystems - Beijing China tmp = mgp_list; 609504b6cca3Slucy wang - Sun Microsystems - Beijing China while (tmp->next != mgp && tmp->next != NULL) 609604b6cca3Slucy wang - Sun Microsystems - Beijing China tmp = tmp->next; 609704b6cca3Slucy wang - Sun Microsystems - Beijing China if (tmp->next != NULL) 609804b6cca3Slucy wang - Sun Microsystems - Beijing China tmp->next = tmp->next->next; 609904b6cca3Slucy wang - Sun Microsystems - Beijing China } 610004b6cca3Slucy wang - Sun Microsystems - Beijing China kmem_free(mgp, sizeof (*mgp)); 610104b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_exit(&myri10ge_param_lock); 610204b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 610304b6cca3Slucy wang - Sun Microsystems - Beijing China } 610404b6cca3Slucy wang - Sun Microsystems - Beijing China 610504b6cca3Slucy wang - Sun Microsystems - Beijing China /* 610604b6cca3Slucy wang - Sun Microsystems - Beijing China * Helper for quiesce entry point: Interrupt threads are not being 610704b6cca3Slucy wang - Sun Microsystems - Beijing China * scheduled, so we must poll for the confirmation DMA to arrive in 610804b6cca3Slucy wang - Sun Microsystems - Beijing China * the firmware stats block for slice 0. We're essentially running 610904b6cca3Slucy wang - Sun Microsystems - Beijing China * the guts of the interrupt handler, and just cherry picking the 611004b6cca3Slucy wang - Sun Microsystems - Beijing China * confirmation that the NIC is queuesced (stats->link_down) 611104b6cca3Slucy wang - Sun Microsystems - Beijing China */ 611204b6cca3Slucy wang - Sun Microsystems - Beijing China 611304b6cca3Slucy wang - Sun Microsystems - Beijing China static int 611404b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_poll_down(struct myri10ge_priv *mgp) 611504b6cca3Slucy wang - Sun Microsystems - Beijing China { 611604b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_slice_state *ss = mgp->ss; 611704b6cca3Slucy wang - Sun Microsystems - Beijing China mcp_irq_data_t *stats = ss->fw_stats; 611804b6cca3Slucy wang - Sun Microsystems - Beijing China int valid; 611904b6cca3Slucy wang - Sun Microsystems - Beijing China int found_down = 0; 612004b6cca3Slucy wang - Sun Microsystems - Beijing China 612104b6cca3Slucy wang - Sun Microsystems - Beijing China 612204b6cca3Slucy wang - Sun Microsystems - Beijing China /* check for a pending IRQ */ 612304b6cca3Slucy wang - Sun Microsystems - Beijing China 612404b6cca3Slucy wang - Sun Microsystems - Beijing China if (! *((volatile uint8_t *)& stats->valid)) 612504b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 612604b6cca3Slucy wang - Sun Microsystems - Beijing China valid = stats->valid; 612704b6cca3Slucy wang - Sun Microsystems - Beijing China 612804b6cca3Slucy wang - Sun Microsystems - Beijing China /* 612904b6cca3Slucy wang - Sun Microsystems - Beijing China * Make sure to tell the NIC to lower a legacy IRQ, else 613004b6cca3Slucy wang - Sun Microsystems - Beijing China * it may have corrupt state after restarting 613104b6cca3Slucy wang - Sun Microsystems - Beijing China */ 613204b6cca3Slucy wang - Sun Microsystems - Beijing China 613304b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->ddi_intr_type == DDI_INTR_TYPE_FIXED) { 613404b6cca3Slucy wang - Sun Microsystems - Beijing China /* lower legacy IRQ */ 613504b6cca3Slucy wang - Sun Microsystems - Beijing China *mgp->irq_deassert = 0; 613604b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 613704b6cca3Slucy wang - Sun Microsystems - Beijing China /* wait for irq conf DMA */ 613804b6cca3Slucy wang - Sun Microsystems - Beijing China while (*((volatile uint8_t *)& stats->valid)) 613904b6cca3Slucy wang - Sun Microsystems - Beijing China ; 614004b6cca3Slucy wang - Sun Microsystems - Beijing China } 614104b6cca3Slucy wang - Sun Microsystems - Beijing China if (stats->stats_updated && stats->link_down) 614204b6cca3Slucy wang - Sun Microsystems - Beijing China found_down = 1; 614304b6cca3Slucy wang - Sun Microsystems - Beijing China 614404b6cca3Slucy wang - Sun Microsystems - Beijing China if (valid & 0x1) 614504b6cca3Slucy wang - Sun Microsystems - Beijing China *ss->irq_claim = BE_32(3); 614604b6cca3Slucy wang - Sun Microsystems - Beijing China *(ss->irq_claim + 1) = BE_32(3); 614704b6cca3Slucy wang - Sun Microsystems - Beijing China 614804b6cca3Slucy wang - Sun Microsystems - Beijing China return (found_down); 614904b6cca3Slucy wang - Sun Microsystems - Beijing China } 615004b6cca3Slucy wang - Sun Microsystems - Beijing China 615104b6cca3Slucy wang - Sun Microsystems - Beijing China static int 615204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_quiesce(dev_info_t *dip) 615304b6cca3Slucy wang - Sun Microsystems - Beijing China { 615404b6cca3Slucy wang - Sun Microsystems - Beijing China struct myri10ge_priv *mgp; 615504b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_cmd_t cmd; 615604b6cca3Slucy wang - Sun Microsystems - Beijing China int status, down, i; 615704b6cca3Slucy wang - Sun Microsystems - Beijing China 615804b6cca3Slucy wang - Sun Microsystems - Beijing China mgp = ddi_get_driver_private(dip); 615904b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp == NULL) 616004b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 616104b6cca3Slucy wang - Sun Microsystems - Beijing China 616204b6cca3Slucy wang - Sun Microsystems - Beijing China /* if devices was unplumbed, it is guaranteed to be quiescent */ 616304b6cca3Slucy wang - Sun Microsystems - Beijing China if (mgp->running == MYRI10GE_ETH_STOPPED) 616404b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 616504b6cca3Slucy wang - Sun Microsystems - Beijing China 616604b6cca3Slucy wang - Sun Microsystems - Beijing China /* send a down CMD to queuesce NIC */ 616704b6cca3Slucy wang - Sun Microsystems - Beijing China status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd); 616804b6cca3Slucy wang - Sun Microsystems - Beijing China if (status) { 616904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: Couldn't bring down link\n", mgp->name); 617004b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 617104b6cca3Slucy wang - Sun Microsystems - Beijing China } 617204b6cca3Slucy wang - Sun Microsystems - Beijing China 617304b6cca3Slucy wang - Sun Microsystems - Beijing China for (i = 0; i < 20; i++) { 617404b6cca3Slucy wang - Sun Microsystems - Beijing China down = myri10ge_poll_down(mgp); 617504b6cca3Slucy wang - Sun Microsystems - Beijing China if (down) 617604b6cca3Slucy wang - Sun Microsystems - Beijing China break; 617704b6cca3Slucy wang - Sun Microsystems - Beijing China delay(drv_usectohz(100000)); 617804b6cca3Slucy wang - Sun Microsystems - Beijing China mb(); 617904b6cca3Slucy wang - Sun Microsystems - Beijing China } 618004b6cca3Slucy wang - Sun Microsystems - Beijing China if (down) 618104b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 618204b6cca3Slucy wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 618304b6cca3Slucy wang - Sun Microsystems - Beijing China } 618404b6cca3Slucy wang - Sun Microsystems - Beijing China 618504b6cca3Slucy wang - Sun Microsystems - Beijing China /* 618604b6cca3Slucy wang - Sun Microsystems - Beijing China * Distinguish between allocb'ed blocks, and gesballoc'ed attached 618704b6cca3Slucy wang - Sun Microsystems - Beijing China * storage. 618804b6cca3Slucy wang - Sun Microsystems - Beijing China */ 618904b6cca3Slucy wang - Sun Microsystems - Beijing China static void 619004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_find_lastfree(void) 619104b6cca3Slucy wang - Sun Microsystems - Beijing China { 619204b6cca3Slucy wang - Sun Microsystems - Beijing China mblk_t *mp = allocb(1024, 0); 619304b6cca3Slucy wang - Sun Microsystems - Beijing China dblk_t *dbp; 619404b6cca3Slucy wang - Sun Microsystems - Beijing China 619504b6cca3Slucy wang - Sun Microsystems - Beijing China if (mp == NULL) { 619604b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "myri10ge_find_lastfree failed\n"); 619704b6cca3Slucy wang - Sun Microsystems - Beijing China return; 619804b6cca3Slucy wang - Sun Microsystems - Beijing China } 619904b6cca3Slucy wang - Sun Microsystems - Beijing China dbp = mp->b_datap; 620004b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_db_lastfree = (void *)dbp->db_lastfree; 620104b6cca3Slucy wang - Sun Microsystems - Beijing China } 620204b6cca3Slucy wang - Sun Microsystems - Beijing China 620304b6cca3Slucy wang - Sun Microsystems - Beijing China int 620404b6cca3Slucy wang - Sun Microsystems - Beijing China _init(void) 620504b6cca3Slucy wang - Sun Microsystems - Beijing China { 620604b6cca3Slucy wang - Sun Microsystems - Beijing China int i; 620704b6cca3Slucy wang - Sun Microsystems - Beijing China 620804b6cca3Slucy wang - Sun Microsystems - Beijing China if (myri10ge_verbose) 620904b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_NOTE, 621004b6cca3Slucy wang - Sun Microsystems - Beijing China "Myricom 10G driver (10GbE) version %s loading\n", 621104b6cca3Slucy wang - Sun Microsystems - Beijing China MYRI10GE_VERSION_STR); 621204b6cca3Slucy wang - Sun Microsystems - Beijing China myri10ge_find_lastfree(); 621304b6cca3Slucy wang - Sun Microsystems - Beijing China mac_init_ops(&myri10ge_ops, "myri10ge"); 621404b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_init(&myri10ge_param_lock, NULL, MUTEX_DEFAULT, NULL); 621504b6cca3Slucy wang - Sun Microsystems - Beijing China if ((i = mod_install(&modlinkage)) != 0) { 621604b6cca3Slucy wang - Sun Microsystems - Beijing China cmn_err(CE_WARN, "mod_install returned %d\n", i); 621704b6cca3Slucy wang - Sun Microsystems - Beijing China mac_fini_ops(&myri10ge_ops); 621804b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_destroy(&myri10ge_param_lock); 621904b6cca3Slucy wang - Sun Microsystems - Beijing China } 622004b6cca3Slucy wang - Sun Microsystems - Beijing China return (i); 622104b6cca3Slucy wang - Sun Microsystems - Beijing China } 622204b6cca3Slucy wang - Sun Microsystems - Beijing China 622304b6cca3Slucy wang - Sun Microsystems - Beijing China int 622404b6cca3Slucy wang - Sun Microsystems - Beijing China _fini(void) 622504b6cca3Slucy wang - Sun Microsystems - Beijing China { 622604b6cca3Slucy wang - Sun Microsystems - Beijing China int i; 622704b6cca3Slucy wang - Sun Microsystems - Beijing China i = mod_remove(&modlinkage); 622804b6cca3Slucy wang - Sun Microsystems - Beijing China if (i != 0) { 622904b6cca3Slucy wang - Sun Microsystems - Beijing China return (i); 623004b6cca3Slucy wang - Sun Microsystems - Beijing China } 623104b6cca3Slucy wang - Sun Microsystems - Beijing China mac_fini_ops(&myri10ge_ops); 623204b6cca3Slucy wang - Sun Microsystems - Beijing China mutex_destroy(&myri10ge_param_lock); 623304b6cca3Slucy wang - Sun Microsystems - Beijing China return (0); 623404b6cca3Slucy wang - Sun Microsystems - Beijing China } 623504b6cca3Slucy wang - Sun Microsystems - Beijing China 623604b6cca3Slucy wang - Sun Microsystems - Beijing China int 623704b6cca3Slucy wang - Sun Microsystems - Beijing China _info(struct modinfo *modinfop) 623804b6cca3Slucy wang - Sun Microsystems - Beijing China { 623904b6cca3Slucy wang - Sun Microsystems - Beijing China return (mod_info(&modlinkage, modinfop)); 624004b6cca3Slucy wang - Sun Microsystems - Beijing China } 624104b6cca3Slucy wang - Sun Microsystems - Beijing China 624204b6cca3Slucy wang - Sun Microsystems - Beijing China 624304b6cca3Slucy wang - Sun Microsystems - Beijing China /* 624404b6cca3Slucy wang - Sun Microsystems - Beijing China * This file uses MyriGE driver indentation. 624504b6cca3Slucy wang - Sun Microsystems - Beijing China * 624604b6cca3Slucy wang - Sun Microsystems - Beijing China * Local Variables: 624704b6cca3Slucy wang - Sun Microsystems - Beijing China * c-file-style:"sun" 624804b6cca3Slucy wang - Sun Microsystems - Beijing China * tab-width:8 624904b6cca3Slucy wang - Sun Microsystems - Beijing China * End: 625004b6cca3Slucy wang - Sun Microsystems - Beijing China */ 6251