144961713Sgirish /* 244961713Sgirish * CDDL HEADER START 344961713Sgirish * 444961713Sgirish * The contents of this file are subject to the terms of the 544961713Sgirish * Common Development and Distribution License (the "License"). 644961713Sgirish * You may not use this file except in compliance with the License. 744961713Sgirish * 844961713Sgirish * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 944961713Sgirish * or http://www.opensolaris.org/os/licensing. 1044961713Sgirish * See the License for the specific language governing permissions 1144961713Sgirish * and limitations under the License. 1244961713Sgirish * 1344961713Sgirish * When distributing Covered Code, include this CDDL HEADER in each 1444961713Sgirish * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1544961713Sgirish * If applicable, add the following below this CDDL HEADER, with the 1644961713Sgirish * fields enclosed by brackets "[]" replaced with your own identifying 1744961713Sgirish * information: Portions Copyright [yyyy] [name of copyright owner] 1844961713Sgirish * 1944961713Sgirish * CDDL HEADER END 2044961713Sgirish */ 2148056c53SMichael Speer 2244961713Sgirish /* 237b26d9ffSSantwona Behera * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2444961713Sgirish * Use is subject to license terms. 2544961713Sgirish */ 2644961713Sgirish 2744961713Sgirish /* 2844961713Sgirish * SunOs MT STREAMS NIU/Neptune 10Gb Ethernet Device Driver. 2944961713Sgirish */ 3044961713Sgirish #include <sys/nxge/nxge_impl.h> 31678453a8Sspeer #include <sys/nxge/nxge_hio.h> 32678453a8Sspeer #include <sys/nxge/nxge_rxdma.h> 3314ea4bb7Ssd #include <sys/pcie.h> 3444961713Sgirish 3544961713Sgirish uint32_t nxge_use_partition = 0; /* debug partition flag */ 3644961713Sgirish uint32_t nxge_dma_obp_props_only = 1; /* use obp published props */ 3744961713Sgirish uint32_t nxge_use_rdc_intr = 1; /* debug to assign rdc intr */ 3844961713Sgirish /* 39ec090658Sml * PSARC/2007/453 MSI-X interrupt limit override 4044961713Sgirish */ 41ec090658Sml uint32_t nxge_msi_enable = 2; 4244961713Sgirish 436f157acbSml /* 446f157acbSml * Software workaround for a Neptune (PCI-E) 456f157acbSml * hardware interrupt bug which the hardware 466f157acbSml * may generate spurious interrupts after the 476f157acbSml * device interrupt handler was removed. If this flag 486f157acbSml * is enabled, the driver will reset the 496f157acbSml * hardware when devices are being detached. 506f157acbSml */ 516f157acbSml uint32_t nxge_peu_reset_enable = 0; 526f157acbSml 53b4d05839Sml /* 54b4d05839Sml * Software workaround for the hardware 55b4d05839Sml * checksum bugs that affect packet transmission 56b4d05839Sml * and receive: 57b4d05839Sml * 58b4d05839Sml * Usage of nxge_cksum_offload: 59b4d05839Sml * 60b4d05839Sml * (1) nxge_cksum_offload = 0 (default): 61b4d05839Sml * - transmits packets: 62b4d05839Sml * TCP: uses the hardware checksum feature. 63b4d05839Sml * UDP: driver will compute the software checksum 64b4d05839Sml * based on the partial checksum computed 65b4d05839Sml * by the IP layer. 66b4d05839Sml * - receives packets 67b4d05839Sml * TCP: marks packets checksum flags based on hardware result. 68b4d05839Sml * UDP: will not mark checksum flags. 69b4d05839Sml * 70b4d05839Sml * (2) nxge_cksum_offload = 1: 71b4d05839Sml * - transmit packets: 72b4d05839Sml * TCP/UDP: uses the hardware checksum feature. 73b4d05839Sml * - receives packets 74b4d05839Sml * TCP/UDP: marks packet checksum flags based on hardware result. 75b4d05839Sml * 76b4d05839Sml * (3) nxge_cksum_offload = 2: 77b4d05839Sml * - The driver will not register its checksum capability. 78b4d05839Sml * Checksum for both TCP and UDP will be computed 79b4d05839Sml * by the stack. 80b4d05839Sml * - The software LSO is not allowed in this case. 81b4d05839Sml * 82b4d05839Sml * (4) nxge_cksum_offload > 2: 83b4d05839Sml * - Will be treated as it is set to 2 84b4d05839Sml * (stack will compute the checksum). 85b4d05839Sml * 86b4d05839Sml * (5) If the hardware bug is fixed, this workaround 87b4d05839Sml * needs to be updated accordingly to reflect 88b4d05839Sml * the new hardware revision. 89b4d05839Sml */ 90b4d05839Sml uint32_t nxge_cksum_offload = 0; 91678453a8Sspeer 9244961713Sgirish /* 9344961713Sgirish * Globals: tunable parameters (/etc/system or adb) 9444961713Sgirish * 9544961713Sgirish */ 9644961713Sgirish uint32_t nxge_rbr_size = NXGE_RBR_RBB_DEFAULT; 9744961713Sgirish uint32_t nxge_rbr_spare_size = 0; 9844961713Sgirish uint32_t nxge_rcr_size = NXGE_RCR_DEFAULT; 9944961713Sgirish uint32_t nxge_tx_ring_size = NXGE_TX_RING_DEFAULT; 100b3a0105bSspeer boolean_t nxge_no_msg = B_TRUE; /* control message display */ 10144961713Sgirish uint32_t nxge_no_link_notify = 0; /* control DL_NOTIFY */ 10244961713Sgirish uint32_t nxge_bcopy_thresh = TX_BCOPY_MAX; 10344961713Sgirish uint32_t nxge_dvma_thresh = TX_FASTDVMA_MIN; 10444961713Sgirish uint32_t nxge_dma_stream_thresh = TX_STREAM_MIN; 10544961713Sgirish uint32_t nxge_jumbo_mtu = TX_JUMBO_MTU; 1061f8914d5Sml nxge_tx_mode_t nxge_tx_scheme = NXGE_USE_SERIAL; 10744961713Sgirish 10830ac2e7bSml /* MAX LSO size */ 10930ac2e7bSml #define NXGE_LSO_MAXLEN 65535 11030ac2e7bSml uint32_t nxge_lso_max = NXGE_LSO_MAXLEN; 11130ac2e7bSml 11244961713Sgirish 11344961713Sgirish /* 11444961713Sgirish * Add tunable to reduce the amount of time spent in the 11544961713Sgirish * ISR doing Rx Processing. 11644961713Sgirish */ 11744961713Sgirish uint32_t nxge_max_rx_pkts = 1024; 11844961713Sgirish 11944961713Sgirish /* 12044961713Sgirish * Tunables to manage the receive buffer blocks. 12144961713Sgirish * 12244961713Sgirish * nxge_rx_threshold_hi: copy all buffers. 12344961713Sgirish * nxge_rx_bcopy_size_type: receive buffer block size type. 12444961713Sgirish * nxge_rx_threshold_lo: copy only up to tunable block size type. 12544961713Sgirish */ 12644961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_hi = NXGE_RX_COPY_6; 12744961713Sgirish nxge_rxbuf_type_t nxge_rx_buf_size_type = RCR_PKTBUFSZ_0; 12844961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_lo = NXGE_RX_COPY_3; 12944961713Sgirish 130678453a8Sspeer /* Use kmem_alloc() to allocate data buffers. */ 131*ef523517SMichael Speer #if defined(__sparc) 132d00f30bbSspeer uint32_t nxge_use_kmem_alloc = 1; 133*ef523517SMichael Speer #elif defined(__i386) 134d00f30bbSspeer uint32_t nxge_use_kmem_alloc = 0; 135*ef523517SMichael Speer #else 136*ef523517SMichael Speer uint32_t nxge_use_kmem_alloc = 1; 137678453a8Sspeer #endif 138678453a8Sspeer 13944961713Sgirish rtrace_t npi_rtracebuf; 14044961713Sgirish 141d6d3405fSml /* 142d6d3405fSml * The hardware sometimes fails to allow enough time for the link partner 143d6d3405fSml * to send an acknowledgement for packets that the hardware sent to it. The 144d6d3405fSml * hardware resends the packets earlier than it should be in those instances. 145d6d3405fSml * This behavior caused some switches to acknowledge the wrong packets 146d6d3405fSml * and it triggered the fatal error. 147d6d3405fSml * This software workaround is to set the replay timer to a value 148d6d3405fSml * suggested by the hardware team. 149d6d3405fSml * 150d6d3405fSml * PCI config space replay timer register: 151d6d3405fSml * The following replay timeout value is 0xc 152d6d3405fSml * for bit 14:18. 153d6d3405fSml */ 154d6d3405fSml #define PCI_REPLAY_TIMEOUT_CFG_OFFSET 0xb8 155d6d3405fSml #define PCI_REPLAY_TIMEOUT_SHIFT 14 156d6d3405fSml 157d6d3405fSml uint32_t nxge_set_replay_timer = 1; 158d6d3405fSml uint32_t nxge_replay_timeout = 0xc; 159d6d3405fSml 160cf020df9Sml /* 161cf020df9Sml * The transmit serialization sometimes causes 162cf020df9Sml * longer sleep before calling the driver transmit 163cf020df9Sml * function as it sleeps longer than it should. 164cf020df9Sml * The performace group suggests that a time wait tunable 165cf020df9Sml * can be used to set the maximum wait time when needed 166cf020df9Sml * and the default is set to 1 tick. 167cf020df9Sml */ 168cf020df9Sml uint32_t nxge_tx_serial_maxsleep = 1; 169cf020df9Sml 17044961713Sgirish #if defined(sun4v) 17144961713Sgirish /* 17244961713Sgirish * Hypervisor N2/NIU services information. 17344961713Sgirish */ 17444961713Sgirish static hsvc_info_t niu_hsvc = { 17544961713Sgirish HSVC_REV_1, NULL, HSVC_GROUP_NIU, NIU_MAJOR_VER, 17644961713Sgirish NIU_MINOR_VER, "nxge" 17744961713Sgirish }; 178678453a8Sspeer 179678453a8Sspeer static int nxge_hsvc_register(p_nxge_t); 18044961713Sgirish #endif 18144961713Sgirish 18244961713Sgirish /* 18344961713Sgirish * Function Prototypes 18444961713Sgirish */ 18544961713Sgirish static int nxge_attach(dev_info_t *, ddi_attach_cmd_t); 18644961713Sgirish static int nxge_detach(dev_info_t *, ddi_detach_cmd_t); 18744961713Sgirish static void nxge_unattach(p_nxge_t); 18819397407SSherry Moore static int nxge_quiesce(dev_info_t *); 18944961713Sgirish 19044961713Sgirish #if NXGE_PROPERTY 19144961713Sgirish static void nxge_remove_hard_properties(p_nxge_t); 19244961713Sgirish #endif 19344961713Sgirish 194678453a8Sspeer /* 195678453a8Sspeer * These two functions are required by nxge_hio.c 196678453a8Sspeer */ 197da14cebeSEric Cheng extern int nxge_m_mmac_remove(void *arg, int slot); 198651ce697SMichael Speer extern void nxge_grp_cleanup(p_nxge_t nxge); 199678453a8Sspeer 20044961713Sgirish static nxge_status_t nxge_setup_system_dma_pages(p_nxge_t); 20144961713Sgirish 20244961713Sgirish static nxge_status_t nxge_setup_mutexes(p_nxge_t); 20344961713Sgirish static void nxge_destroy_mutexes(p_nxge_t); 20444961713Sgirish 20544961713Sgirish static nxge_status_t nxge_map_regs(p_nxge_t nxgep); 20644961713Sgirish static void nxge_unmap_regs(p_nxge_t nxgep); 20744961713Sgirish #ifdef NXGE_DEBUG 20844961713Sgirish static void nxge_test_map_regs(p_nxge_t nxgep); 20944961713Sgirish #endif 21044961713Sgirish 21144961713Sgirish static nxge_status_t nxge_add_intrs(p_nxge_t nxgep); 21244961713Sgirish static void nxge_remove_intrs(p_nxge_t nxgep); 21344961713Sgirish 21444961713Sgirish static nxge_status_t nxge_add_intrs_adv(p_nxge_t nxgep); 21544961713Sgirish static nxge_status_t nxge_add_intrs_adv_type(p_nxge_t, uint32_t); 21644961713Sgirish static nxge_status_t nxge_add_intrs_adv_type_fix(p_nxge_t, uint32_t); 21744961713Sgirish static void nxge_intrs_enable(p_nxge_t nxgep); 21844961713Sgirish static void nxge_intrs_disable(p_nxge_t nxgep); 21944961713Sgirish 22044961713Sgirish static void nxge_suspend(p_nxge_t); 22144961713Sgirish static nxge_status_t nxge_resume(p_nxge_t); 22244961713Sgirish 22344961713Sgirish static nxge_status_t nxge_setup_dev(p_nxge_t); 22444961713Sgirish static void nxge_destroy_dev(p_nxge_t); 22544961713Sgirish 22644961713Sgirish static nxge_status_t nxge_alloc_mem_pool(p_nxge_t); 22744961713Sgirish static void nxge_free_mem_pool(p_nxge_t); 22844961713Sgirish 229678453a8Sspeer nxge_status_t nxge_alloc_rx_mem_pool(p_nxge_t); 23044961713Sgirish static void nxge_free_rx_mem_pool(p_nxge_t); 23144961713Sgirish 232678453a8Sspeer nxge_status_t nxge_alloc_tx_mem_pool(p_nxge_t); 23344961713Sgirish static void nxge_free_tx_mem_pool(p_nxge_t); 23444961713Sgirish 23544961713Sgirish static nxge_status_t nxge_dma_mem_alloc(p_nxge_t, dma_method_t, 23644961713Sgirish struct ddi_dma_attr *, 23744961713Sgirish size_t, ddi_device_acc_attr_t *, uint_t, 23844961713Sgirish p_nxge_dma_common_t); 23944961713Sgirish 24044961713Sgirish static void nxge_dma_mem_free(p_nxge_dma_common_t); 241678453a8Sspeer static void nxge_dma_free_rx_data_buf(p_nxge_dma_common_t); 24244961713Sgirish 24344961713Sgirish static nxge_status_t nxge_alloc_rx_buf_dma(p_nxge_t, uint16_t, 24444961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 24544961713Sgirish static void nxge_free_rx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 24644961713Sgirish 24744961713Sgirish static nxge_status_t nxge_alloc_rx_cntl_dma(p_nxge_t, uint16_t, 24844961713Sgirish p_nxge_dma_common_t *, size_t); 24944961713Sgirish static void nxge_free_rx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 25044961713Sgirish 251678453a8Sspeer extern nxge_status_t nxge_alloc_tx_buf_dma(p_nxge_t, uint16_t, 25244961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 25344961713Sgirish static void nxge_free_tx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 25444961713Sgirish 255678453a8Sspeer extern nxge_status_t nxge_alloc_tx_cntl_dma(p_nxge_t, uint16_t, 25644961713Sgirish p_nxge_dma_common_t *, 25744961713Sgirish size_t); 25844961713Sgirish static void nxge_free_tx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 25944961713Sgirish 26044961713Sgirish static int nxge_init_common_dev(p_nxge_t); 26144961713Sgirish static void nxge_uninit_common_dev(p_nxge_t); 2624045d941Ssowmini extern int nxge_param_set_mac(p_nxge_t, queue_t *, mblk_t *, 2634045d941Ssowmini char *, caddr_t); 264e759c33aSMichael Speer #if defined(sun4v) 265e759c33aSMichael Speer extern nxge_status_t nxge_hio_rdc_enable(p_nxge_t nxgep); 266e759c33aSMichael Speer extern nxge_status_t nxge_hio_rdc_intr_arm(p_nxge_t nxge, boolean_t arm); 267e759c33aSMichael Speer #endif 26844961713Sgirish 26944961713Sgirish /* 27044961713Sgirish * The next declarations are for the GLDv3 interface. 27144961713Sgirish */ 27244961713Sgirish static int nxge_m_start(void *); 27344961713Sgirish static void nxge_m_stop(void *); 27444961713Sgirish static int nxge_m_multicst(void *, boolean_t, const uint8_t *); 27544961713Sgirish static int nxge_m_promisc(void *, boolean_t); 27644961713Sgirish static void nxge_m_ioctl(void *, queue_t *, mblk_t *); 27763f531d1SSriharsha Basavapatna nxge_status_t nxge_mac_register(p_nxge_t); 278da14cebeSEric Cheng static int nxge_altmac_set(p_nxge_t nxgep, uint8_t *mac_addr, 279da14cebeSEric Cheng int slot, int rdctbl, boolean_t usetbl); 280da14cebeSEric Cheng void nxge_mmac_kstat_update(p_nxge_t nxgep, int slot, 28158324dfcSspeer boolean_t factory); 282da14cebeSEric Cheng 283da14cebeSEric Cheng static void nxge_m_getfactaddr(void *, uint_t, uint8_t *); 2841bd6825cSml static boolean_t nxge_m_getcapab(void *, mac_capab_t, void *); 2851bd6825cSml static int nxge_m_setprop(void *, const char *, mac_prop_id_t, 2861bd6825cSml uint_t, const void *); 2871bd6825cSml static int nxge_m_getprop(void *, const char *, mac_prop_id_t, 288afdda45fSVasumathi Sundaram - Sun Microsystems uint_t, uint_t, void *, uint_t *); 2891bd6825cSml static int nxge_set_priv_prop(nxge_t *, const char *, uint_t, 2901bd6825cSml const void *); 2914045d941Ssowmini static int nxge_get_priv_prop(nxge_t *, const char *, uint_t, uint_t, 292afdda45fSVasumathi Sundaram - Sun Microsystems void *, uint_t *); 2934045d941Ssowmini static int nxge_get_def_val(nxge_t *, mac_prop_id_t, uint_t, void *); 294da14cebeSEric Cheng static void nxge_fill_ring(void *, mac_ring_type_t, const int, const int, 295da14cebeSEric Cheng mac_ring_info_t *, mac_ring_handle_t); 296da14cebeSEric Cheng static void nxge_group_add_ring(mac_group_driver_t, mac_ring_driver_t, 297da14cebeSEric Cheng mac_ring_type_t); 298da14cebeSEric Cheng static void nxge_group_rem_ring(mac_group_driver_t, mac_ring_driver_t, 299da14cebeSEric Cheng mac_ring_type_t); 3004045d941Ssowmini 3016f157acbSml static void nxge_niu_peu_reset(p_nxge_t nxgep); 302d6d3405fSml static void nxge_set_pci_replay_timeout(nxge_t *); 3034045d941Ssowmini 3044045d941Ssowmini mac_priv_prop_t nxge_priv_props[] = { 3054045d941Ssowmini {"_adv_10gfdx_cap", MAC_PROP_PERM_RW}, 3064045d941Ssowmini {"_adv_pause_cap", MAC_PROP_PERM_RW}, 3074045d941Ssowmini {"_function_number", MAC_PROP_PERM_READ}, 3084045d941Ssowmini {"_fw_version", MAC_PROP_PERM_READ}, 3094045d941Ssowmini {"_port_mode", MAC_PROP_PERM_READ}, 3104045d941Ssowmini {"_hot_swap_phy", MAC_PROP_PERM_READ}, 3114045d941Ssowmini {"_rxdma_intr_time", MAC_PROP_PERM_RW}, 3124045d941Ssowmini {"_rxdma_intr_pkts", MAC_PROP_PERM_RW}, 3134045d941Ssowmini {"_class_opt_ipv4_tcp", MAC_PROP_PERM_RW}, 3144045d941Ssowmini {"_class_opt_ipv4_udp", MAC_PROP_PERM_RW}, 3154045d941Ssowmini {"_class_opt_ipv4_ah", MAC_PROP_PERM_RW}, 3164045d941Ssowmini {"_class_opt_ipv4_sctp", MAC_PROP_PERM_RW}, 3174045d941Ssowmini {"_class_opt_ipv6_tcp", MAC_PROP_PERM_RW}, 3184045d941Ssowmini {"_class_opt_ipv6_udp", MAC_PROP_PERM_RW}, 3194045d941Ssowmini {"_class_opt_ipv6_ah", MAC_PROP_PERM_RW}, 3204045d941Ssowmini {"_class_opt_ipv6_sctp", MAC_PROP_PERM_RW}, 3214045d941Ssowmini {"_soft_lso_enable", MAC_PROP_PERM_RW} 3224045d941Ssowmini }; 3234045d941Ssowmini 3244045d941Ssowmini #define NXGE_MAX_PRIV_PROPS \ 3254045d941Ssowmini (sizeof (nxge_priv_props)/sizeof (mac_priv_prop_t)) 3261bd6825cSml 32744961713Sgirish #define NXGE_NEPTUNE_MAGIC 0x4E584745UL 32844961713Sgirish #define MAX_DUMP_SZ 256 32944961713Sgirish 3301bd6825cSml #define NXGE_M_CALLBACK_FLAGS \ 331da14cebeSEric Cheng (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP) 33244961713Sgirish 333678453a8Sspeer mac_callbacks_t nxge_m_callbacks = { 33444961713Sgirish NXGE_M_CALLBACK_FLAGS, 33544961713Sgirish nxge_m_stat, 33644961713Sgirish nxge_m_start, 33744961713Sgirish nxge_m_stop, 33844961713Sgirish nxge_m_promisc, 33944961713Sgirish nxge_m_multicst, 340da14cebeSEric Cheng NULL, 341da14cebeSEric Cheng NULL, 34244961713Sgirish nxge_m_ioctl, 3431bd6825cSml nxge_m_getcapab, 3441bd6825cSml NULL, 3451bd6825cSml NULL, 3461bd6825cSml nxge_m_setprop, 3471bd6825cSml nxge_m_getprop 34844961713Sgirish }; 34944961713Sgirish 35044961713Sgirish void 35144961713Sgirish nxge_err_inject(p_nxge_t, queue_t *, mblk_t *); 35244961713Sgirish 353ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override. */ 354ec090658Sml #define NXGE_MSIX_REQUEST_10G 8 355ec090658Sml #define NXGE_MSIX_REQUEST_1G 2 356ec090658Sml static int nxge_create_msi_property(p_nxge_t); 357ef755e7aStc /* 358ef755e7aStc * For applications that care about the 359ef755e7aStc * latency, it was requested by PAE and the 360ef755e7aStc * customers that the driver has tunables that 361ef755e7aStc * allow the user to tune it to a higher number 362ef755e7aStc * interrupts to spread the interrupts among 363ef755e7aStc * multiple channels. The DDI framework limits 364ef755e7aStc * the maximum number of MSI-X resources to allocate 365ef755e7aStc * to 8 (ddi_msix_alloc_limit). If more than 8 366ef755e7aStc * is set, ddi_msix_alloc_limit must be set accordingly. 367ef755e7aStc * The default number of MSI interrupts are set to 368ef755e7aStc * 8 for 10G and 2 for 1G link. 369ef755e7aStc */ 370ef755e7aStc #define NXGE_MSIX_MAX_ALLOWED 32 371ef755e7aStc uint32_t nxge_msix_10g_intrs = NXGE_MSIX_REQUEST_10G; 372ef755e7aStc uint32_t nxge_msix_1g_intrs = NXGE_MSIX_REQUEST_1G; 373ec090658Sml 37444961713Sgirish /* 37544961713Sgirish * These global variables control the message 37644961713Sgirish * output. 37744961713Sgirish */ 37844961713Sgirish out_dbgmsg_t nxge_dbgmsg_out = DBG_CONSOLE | STR_LOG; 379678453a8Sspeer uint64_t nxge_debug_level; 38044961713Sgirish 38144961713Sgirish /* 38244961713Sgirish * This list contains the instance structures for the Neptune 38344961713Sgirish * devices present in the system. The lock exists to guarantee 38444961713Sgirish * mutually exclusive access to the list. 38544961713Sgirish */ 38644961713Sgirish void *nxge_list = NULL; 38744961713Sgirish void *nxge_hw_list = NULL; 38844961713Sgirish nxge_os_mutex_t nxge_common_lock; 3893b2d9860SMichael Speer nxge_os_mutex_t nxgedebuglock; 39044961713Sgirish 39144961713Sgirish extern uint64_t npi_debug_level; 39244961713Sgirish 39344961713Sgirish extern nxge_status_t nxge_ldgv_init(p_nxge_t, int *, int *); 39444961713Sgirish extern nxge_status_t nxge_ldgv_init_n2(p_nxge_t, int *, int *); 39544961713Sgirish extern nxge_status_t nxge_ldgv_uninit(p_nxge_t); 39644961713Sgirish extern nxge_status_t nxge_intr_ldgv_init(p_nxge_t); 39744961713Sgirish extern void nxge_fm_init(p_nxge_t, 39844961713Sgirish ddi_device_acc_attr_t *, 39944961713Sgirish ddi_device_acc_attr_t *, 40044961713Sgirish ddi_dma_attr_t *); 40144961713Sgirish extern void nxge_fm_fini(p_nxge_t); 40258324dfcSspeer extern npi_status_t npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t); 40344961713Sgirish 40444961713Sgirish /* 40544961713Sgirish * Count used to maintain the number of buffers being used 40644961713Sgirish * by Neptune instances and loaned up to the upper layers. 40744961713Sgirish */ 40844961713Sgirish uint32_t nxge_mblks_pending = 0; 40944961713Sgirish 41044961713Sgirish /* 41144961713Sgirish * Device register access attributes for PIO. 41244961713Sgirish */ 41344961713Sgirish static ddi_device_acc_attr_t nxge_dev_reg_acc_attr = { 41444961713Sgirish DDI_DEVICE_ATTR_V0, 41544961713Sgirish DDI_STRUCTURE_LE_ACC, 41644961713Sgirish DDI_STRICTORDER_ACC, 41744961713Sgirish }; 41844961713Sgirish 41944961713Sgirish /* 42044961713Sgirish * Device descriptor access attributes for DMA. 42144961713Sgirish */ 42244961713Sgirish static ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr = { 42344961713Sgirish DDI_DEVICE_ATTR_V0, 42444961713Sgirish DDI_STRUCTURE_LE_ACC, 42544961713Sgirish DDI_STRICTORDER_ACC 42644961713Sgirish }; 42744961713Sgirish 42844961713Sgirish /* 42944961713Sgirish * Device buffer access attributes for DMA. 43044961713Sgirish */ 43144961713Sgirish static ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr = { 43244961713Sgirish DDI_DEVICE_ATTR_V0, 43344961713Sgirish DDI_STRUCTURE_BE_ACC, 43444961713Sgirish DDI_STRICTORDER_ACC 43544961713Sgirish }; 43644961713Sgirish 43744961713Sgirish ddi_dma_attr_t nxge_desc_dma_attr = { 43844961713Sgirish DMA_ATTR_V0, /* version number. */ 43944961713Sgirish 0, /* low address */ 44044961713Sgirish 0xffffffffffffffff, /* high address */ 44144961713Sgirish 0xffffffffffffffff, /* address counter max */ 44244961713Sgirish #ifndef NIU_PA_WORKAROUND 44344961713Sgirish 0x100000, /* alignment */ 44444961713Sgirish #else 44544961713Sgirish 0x2000, 44644961713Sgirish #endif 44744961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 44844961713Sgirish 0x1, /* minimum transfer size */ 44944961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 45044961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 45144961713Sgirish 1, /* scatter/gather list length */ 45244961713Sgirish (unsigned int) 1, /* granularity */ 45344961713Sgirish 0 /* attribute flags */ 45444961713Sgirish }; 45544961713Sgirish 45644961713Sgirish ddi_dma_attr_t nxge_tx_dma_attr = { 45744961713Sgirish DMA_ATTR_V0, /* version number. */ 45844961713Sgirish 0, /* low address */ 45944961713Sgirish 0xffffffffffffffff, /* high address */ 46044961713Sgirish 0xffffffffffffffff, /* address counter max */ 46144961713Sgirish #if defined(_BIG_ENDIAN) 46244961713Sgirish 0x2000, /* alignment */ 46344961713Sgirish #else 46444961713Sgirish 0x1000, /* alignment */ 46544961713Sgirish #endif 46644961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 46744961713Sgirish 0x1, /* minimum transfer size */ 46844961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 46944961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 47044961713Sgirish 5, /* scatter/gather list length */ 47144961713Sgirish (unsigned int) 1, /* granularity */ 47244961713Sgirish 0 /* attribute flags */ 47344961713Sgirish }; 47444961713Sgirish 47544961713Sgirish ddi_dma_attr_t nxge_rx_dma_attr = { 47644961713Sgirish DMA_ATTR_V0, /* version number. */ 47744961713Sgirish 0, /* low address */ 47844961713Sgirish 0xffffffffffffffff, /* high address */ 47944961713Sgirish 0xffffffffffffffff, /* address counter max */ 48044961713Sgirish 0x2000, /* alignment */ 48144961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 48244961713Sgirish 0x1, /* minimum transfer size */ 48344961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 48444961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 48544961713Sgirish 1, /* scatter/gather list length */ 48644961713Sgirish (unsigned int) 1, /* granularity */ 4870e2bd521Ssbehera DDI_DMA_RELAXED_ORDERING /* attribute flags */ 48844961713Sgirish }; 48944961713Sgirish 49044961713Sgirish ddi_dma_lim_t nxge_dma_limits = { 49144961713Sgirish (uint_t)0, /* dlim_addr_lo */ 49244961713Sgirish (uint_t)0xffffffff, /* dlim_addr_hi */ 49344961713Sgirish (uint_t)0xffffffff, /* dlim_cntr_max */ 49444961713Sgirish (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */ 49544961713Sgirish 0x1, /* dlim_minxfer */ 49644961713Sgirish 1024 /* dlim_speed */ 49744961713Sgirish }; 49844961713Sgirish 49944961713Sgirish dma_method_t nxge_force_dma = DVMA; 50044961713Sgirish 50144961713Sgirish /* 50244961713Sgirish * dma chunk sizes. 50344961713Sgirish * 50444961713Sgirish * Try to allocate the largest possible size 50544961713Sgirish * so that fewer number of dma chunks would be managed 50644961713Sgirish */ 50744961713Sgirish #ifdef NIU_PA_WORKAROUND 50844961713Sgirish size_t alloc_sizes [] = {0x2000}; 50944961713Sgirish #else 51044961713Sgirish size_t alloc_sizes [] = {0x1000, 0x2000, 0x4000, 0x8000, 51144961713Sgirish 0x10000, 0x20000, 0x40000, 0x80000, 51230ac2e7bSml 0x100000, 0x200000, 0x400000, 0x800000, 51330ac2e7bSml 0x1000000, 0x2000000, 0x4000000}; 51444961713Sgirish #endif 51544961713Sgirish 51644961713Sgirish /* 51744961713Sgirish * Translate "dev_t" to a pointer to the associated "dev_info_t". 51844961713Sgirish */ 51944961713Sgirish 520678453a8Sspeer extern void nxge_get_environs(nxge_t *); 521678453a8Sspeer 52244961713Sgirish static int 52344961713Sgirish nxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 52444961713Sgirish { 52544961713Sgirish p_nxge_t nxgep = NULL; 52644961713Sgirish int instance; 52744961713Sgirish int status = DDI_SUCCESS; 52844961713Sgirish uint8_t portn; 52958324dfcSspeer nxge_mmac_t *mmac_info; 53044961713Sgirish 53144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_attach")); 53244961713Sgirish 53344961713Sgirish /* 53444961713Sgirish * Get the device instance since we'll need to setup 53544961713Sgirish * or retrieve a soft state for this instance. 53644961713Sgirish */ 53744961713Sgirish instance = ddi_get_instance(dip); 53844961713Sgirish 53944961713Sgirish switch (cmd) { 54044961713Sgirish case DDI_ATTACH: 54144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_ATTACH")); 54244961713Sgirish break; 54344961713Sgirish 54444961713Sgirish case DDI_RESUME: 54544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_RESUME")); 54644961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 54744961713Sgirish if (nxgep == NULL) { 54844961713Sgirish status = DDI_FAILURE; 54944961713Sgirish break; 55044961713Sgirish } 55144961713Sgirish if (nxgep->dip != dip) { 55244961713Sgirish status = DDI_FAILURE; 55344961713Sgirish break; 55444961713Sgirish } 55544961713Sgirish if (nxgep->suspended == DDI_PM_SUSPEND) { 55644961713Sgirish status = ddi_dev_is_needed(nxgep->dip, 0, 1); 55744961713Sgirish } else { 55856d930aeSspeer status = nxge_resume(nxgep); 55944961713Sgirish } 56044961713Sgirish goto nxge_attach_exit; 56144961713Sgirish 56244961713Sgirish case DDI_PM_RESUME: 56344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_RESUME")); 56444961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 56544961713Sgirish if (nxgep == NULL) { 56644961713Sgirish status = DDI_FAILURE; 56744961713Sgirish break; 56844961713Sgirish } 56944961713Sgirish if (nxgep->dip != dip) { 57044961713Sgirish status = DDI_FAILURE; 57144961713Sgirish break; 57244961713Sgirish } 57356d930aeSspeer status = nxge_resume(nxgep); 57444961713Sgirish goto nxge_attach_exit; 57544961713Sgirish 57644961713Sgirish default: 57744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing unknown")); 57844961713Sgirish status = DDI_FAILURE; 57944961713Sgirish goto nxge_attach_exit; 58044961713Sgirish } 58144961713Sgirish 58244961713Sgirish 58344961713Sgirish if (ddi_soft_state_zalloc(nxge_list, instance) == DDI_FAILURE) { 58444961713Sgirish status = DDI_FAILURE; 58544961713Sgirish goto nxge_attach_exit; 58644961713Sgirish } 58744961713Sgirish 58844961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance); 58944961713Sgirish if (nxgep == NULL) { 5902e59129aSraghus status = NXGE_ERROR; 5912e59129aSraghus goto nxge_attach_fail2; 59244961713Sgirish } 59344961713Sgirish 59498ecde52Stm nxgep->nxge_magic = NXGE_MAGIC; 59598ecde52Stm 59644961713Sgirish nxgep->drv_state = 0; 59744961713Sgirish nxgep->dip = dip; 59844961713Sgirish nxgep->instance = instance; 59944961713Sgirish nxgep->p_dip = ddi_get_parent(dip); 60044961713Sgirish nxgep->nxge_debug_level = nxge_debug_level; 60144961713Sgirish npi_debug_level = nxge_debug_level; 60244961713Sgirish 603678453a8Sspeer /* Are we a guest running in a Hybrid I/O environment? */ 604678453a8Sspeer nxge_get_environs(nxgep); 60544961713Sgirish 60644961713Sgirish status = nxge_map_regs(nxgep); 607678453a8Sspeer 60844961713Sgirish if (status != NXGE_OK) { 60944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_map_regs failed")); 6102e59129aSraghus goto nxge_attach_fail3; 61144961713Sgirish } 61244961713Sgirish 613678453a8Sspeer nxge_fm_init(nxgep, &nxge_dev_reg_acc_attr, 614678453a8Sspeer &nxge_dev_desc_dma_acc_attr, 615678453a8Sspeer &nxge_rx_dma_attr); 616678453a8Sspeer 617678453a8Sspeer /* Create & initialize the per-Neptune data structure */ 618678453a8Sspeer /* (even if we're a guest). */ 61944961713Sgirish status = nxge_init_common_dev(nxgep); 62044961713Sgirish if (status != NXGE_OK) { 62144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6224045d941Ssowmini "nxge_init_common_dev failed")); 6232e59129aSraghus goto nxge_attach_fail4; 62444961713Sgirish } 62544961713Sgirish 626d6d3405fSml /* 627d6d3405fSml * Software workaround: set the replay timer. 628d6d3405fSml */ 629d6d3405fSml if (nxgep->niu_type != N2_NIU) { 630d6d3405fSml nxge_set_pci_replay_timeout(nxgep); 631d6d3405fSml } 632d6d3405fSml 633678453a8Sspeer #if defined(sun4v) 634678453a8Sspeer /* This is required by nxge_hio_init(), which follows. */ 635678453a8Sspeer if ((status = nxge_hsvc_register(nxgep)) != DDI_SUCCESS) 6369d5b8bc5SMichael Speer goto nxge_attach_fail4; 637678453a8Sspeer #endif 638678453a8Sspeer 639678453a8Sspeer if ((status = nxge_hio_init(nxgep)) != NXGE_OK) { 640678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6414045d941Ssowmini "nxge_hio_init failed")); 642678453a8Sspeer goto nxge_attach_fail4; 643678453a8Sspeer } 644678453a8Sspeer 64559ac0c16Sdavemq if (nxgep->niu_type == NEPTUNE_2_10GF) { 64659ac0c16Sdavemq if (nxgep->function_num > 1) { 6474202ea4bSsbehera NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Unsupported" 64859ac0c16Sdavemq " function %d. Only functions 0 and 1 are " 64959ac0c16Sdavemq "supported for this card.", nxgep->function_num)); 65059ac0c16Sdavemq status = NXGE_ERROR; 6512e59129aSraghus goto nxge_attach_fail4; 65259ac0c16Sdavemq } 65359ac0c16Sdavemq } 65459ac0c16Sdavemq 655678453a8Sspeer if (isLDOMguest(nxgep)) { 656678453a8Sspeer /* 657678453a8Sspeer * Use the function number here. 658678453a8Sspeer */ 659678453a8Sspeer nxgep->mac.portnum = nxgep->function_num; 660678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_LOGICAL; 661678453a8Sspeer 662678453a8Sspeer /* XXX We'll set the MAC address counts to 1 for now. */ 663678453a8Sspeer mmac_info = &nxgep->nxge_mmac_info; 664678453a8Sspeer mmac_info->num_mmac = 1; 665678453a8Sspeer mmac_info->naddrfree = 1; 66658324dfcSspeer } else { 667678453a8Sspeer portn = NXGE_GET_PORT_NUM(nxgep->function_num); 668678453a8Sspeer nxgep->mac.portnum = portn; 669678453a8Sspeer if ((portn == 0) || (portn == 1)) 670678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_XMAC; 671678453a8Sspeer else 672678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_BMAC; 673678453a8Sspeer /* 674678453a8Sspeer * Neptune has 4 ports, the first 2 ports use XMAC (10G MAC) 675678453a8Sspeer * internally, the rest 2 ports use BMAC (1G "Big" MAC). 676678453a8Sspeer * The two types of MACs have different characterizations. 677678453a8Sspeer */ 678678453a8Sspeer mmac_info = &nxgep->nxge_mmac_info; 679678453a8Sspeer if (nxgep->function_num < 2) { 680678453a8Sspeer mmac_info->num_mmac = XMAC_MAX_ALT_ADDR_ENTRY; 681678453a8Sspeer mmac_info->naddrfree = XMAC_MAX_ALT_ADDR_ENTRY; 682678453a8Sspeer } else { 683678453a8Sspeer mmac_info->num_mmac = BMAC_MAX_ALT_ADDR_ENTRY; 684678453a8Sspeer mmac_info->naddrfree = BMAC_MAX_ALT_ADDR_ENTRY; 685678453a8Sspeer } 68658324dfcSspeer } 68744961713Sgirish /* 68844961713Sgirish * Setup the Ndd parameters for the this instance. 68944961713Sgirish */ 69044961713Sgirish nxge_init_param(nxgep); 69144961713Sgirish 69244961713Sgirish /* 69344961713Sgirish * Setup Register Tracing Buffer. 69444961713Sgirish */ 69544961713Sgirish npi_rtrace_buf_init((rtrace_t *)&npi_rtracebuf); 69644961713Sgirish 69744961713Sgirish /* init stats ptr */ 69844961713Sgirish nxge_init_statsp(nxgep); 69956d930aeSspeer 7002e59129aSraghus /* 701678453a8Sspeer * Copy the vpd info from eeprom to a local data 702678453a8Sspeer * structure, and then check its validity. 7032e59129aSraghus */ 704678453a8Sspeer if (!isLDOMguest(nxgep)) { 705678453a8Sspeer int *regp; 706678453a8Sspeer uint_t reglen; 707678453a8Sspeer int rv; 70856d930aeSspeer 709678453a8Sspeer nxge_vpd_info_get(nxgep); 71044961713Sgirish 711678453a8Sspeer /* Find the NIU config handle. */ 712678453a8Sspeer rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, 713678453a8Sspeer ddi_get_parent(nxgep->dip), DDI_PROP_DONTPASS, 714678453a8Sspeer "reg", ®p, ®len); 715678453a8Sspeer 716678453a8Sspeer if (rv != DDI_PROP_SUCCESS) { 717678453a8Sspeer goto nxge_attach_fail5; 718678453a8Sspeer } 719678453a8Sspeer /* 720678453a8Sspeer * The address_hi, that is the first int, in the reg 721678453a8Sspeer * property consists of config handle, but need to remove 722678453a8Sspeer * the bits 28-31 which are OBP specific info. 723678453a8Sspeer */ 724678453a8Sspeer nxgep->niu_cfg_hdl = (*regp) & 0xFFFFFFF; 725678453a8Sspeer ddi_prop_free(regp); 72644961713Sgirish } 72744961713Sgirish 72848056c53SMichael Speer /* 72948056c53SMichael Speer * Set the defaults for the MTU size. 73048056c53SMichael Speer */ 73148056c53SMichael Speer nxge_hw_id_init(nxgep); 73248056c53SMichael Speer 733678453a8Sspeer if (isLDOMguest(nxgep)) { 734678453a8Sspeer uchar_t *prop_val; 735678453a8Sspeer uint_t prop_len; 7367b1f684aSSriharsha Basavapatna uint32_t max_frame_size; 73744961713Sgirish 738678453a8Sspeer extern void nxge_get_logical_props(p_nxge_t); 739678453a8Sspeer 740678453a8Sspeer nxgep->statsp->mac_stats.xcvr_inuse = LOGICAL_XCVR; 741678453a8Sspeer nxgep->mac.portmode = PORT_LOGICAL; 742678453a8Sspeer (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 743678453a8Sspeer "phy-type", "virtual transceiver"); 744678453a8Sspeer 745678453a8Sspeer nxgep->nports = 1; 746678453a8Sspeer nxgep->board_ver = 0; /* XXX What? */ 747678453a8Sspeer 748678453a8Sspeer /* 749678453a8Sspeer * local-mac-address property gives us info on which 750678453a8Sspeer * specific MAC address the Hybrid resource is associated 751678453a8Sspeer * with. 752678453a8Sspeer */ 753678453a8Sspeer if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0, 754678453a8Sspeer "local-mac-address", &prop_val, 755678453a8Sspeer &prop_len) != DDI_PROP_SUCCESS) { 756678453a8Sspeer goto nxge_attach_fail5; 757678453a8Sspeer } 758678453a8Sspeer if (prop_len != ETHERADDRL) { 759678453a8Sspeer ddi_prop_free(prop_val); 760678453a8Sspeer goto nxge_attach_fail5; 761678453a8Sspeer } 762678453a8Sspeer ether_copy(prop_val, nxgep->hio_mac_addr); 763678453a8Sspeer ddi_prop_free(prop_val); 764678453a8Sspeer nxge_get_logical_props(nxgep); 765678453a8Sspeer 7667b1f684aSSriharsha Basavapatna /* 7677b1f684aSSriharsha Basavapatna * Enable Jumbo property based on the "max-frame-size" 7687b1f684aSSriharsha Basavapatna * property value. 7697b1f684aSSriharsha Basavapatna */ 7707b1f684aSSriharsha Basavapatna max_frame_size = ddi_prop_get_int(DDI_DEV_T_ANY, 7717b1f684aSSriharsha Basavapatna nxgep->dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 7727b1f684aSSriharsha Basavapatna "max-frame-size", NXGE_MTU_DEFAULT_MAX); 7737b1f684aSSriharsha Basavapatna if ((max_frame_size > NXGE_MTU_DEFAULT_MAX) && 7747b1f684aSSriharsha Basavapatna (max_frame_size <= TX_JUMBO_MTU)) { 7757b1f684aSSriharsha Basavapatna nxgep->mac.is_jumbo = B_TRUE; 7767b1f684aSSriharsha Basavapatna nxgep->mac.maxframesize = (uint16_t)max_frame_size; 7777b1f684aSSriharsha Basavapatna nxgep->mac.default_mtu = nxgep->mac.maxframesize - 7787b1f684aSSriharsha Basavapatna NXGE_EHEADER_VLAN_CRC; 7797b1f684aSSriharsha Basavapatna } 780678453a8Sspeer } else { 781678453a8Sspeer status = nxge_xcvr_find(nxgep); 782678453a8Sspeer 783678453a8Sspeer if (status != NXGE_OK) { 784678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_attach: " 7854045d941Ssowmini " Couldn't determine card type" 7864045d941Ssowmini " .... exit ")); 787678453a8Sspeer goto nxge_attach_fail5; 788678453a8Sspeer } 789678453a8Sspeer 790678453a8Sspeer status = nxge_get_config_properties(nxgep); 791678453a8Sspeer 792678453a8Sspeer if (status != NXGE_OK) { 793678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7944045d941Ssowmini "get_hw create failed")); 795678453a8Sspeer goto nxge_attach_fail; 796678453a8Sspeer } 79744961713Sgirish } 79844961713Sgirish 79944961713Sgirish /* 80044961713Sgirish * Setup the Kstats for the driver. 80144961713Sgirish */ 80244961713Sgirish nxge_setup_kstats(nxgep); 80344961713Sgirish 804678453a8Sspeer if (!isLDOMguest(nxgep)) 805678453a8Sspeer nxge_setup_param(nxgep); 80644961713Sgirish 80744961713Sgirish status = nxge_setup_system_dma_pages(nxgep); 80844961713Sgirish if (status != NXGE_OK) { 80944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "set dma page failed")); 81044961713Sgirish goto nxge_attach_fail; 81144961713Sgirish } 81244961713Sgirish 813678453a8Sspeer 814678453a8Sspeer if (!isLDOMguest(nxgep)) 815678453a8Sspeer nxge_hw_init_niu_common(nxgep); 81644961713Sgirish 81744961713Sgirish status = nxge_setup_mutexes(nxgep); 81844961713Sgirish if (status != NXGE_OK) { 81944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set mutex failed")); 82044961713Sgirish goto nxge_attach_fail; 82144961713Sgirish } 82244961713Sgirish 823678453a8Sspeer #if defined(sun4v) 824678453a8Sspeer if (isLDOMguest(nxgep)) { 825678453a8Sspeer /* Find our VR & channel sets. */ 826678453a8Sspeer status = nxge_hio_vr_add(nxgep); 827*ef523517SMichael Speer if (status != DDI_SUCCESS) { 828*ef523517SMichael Speer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 829330cd344SMichael Speer "nxge_hio_vr_add failed")); 830330cd344SMichael Speer (void) hsvc_unregister(&nxgep->niu_hsvc); 831330cd344SMichael Speer nxgep->niu_hsvc_available = B_FALSE; 832*ef523517SMichael Speer goto nxge_attach_fail; 833330cd344SMichael Speer } 834678453a8Sspeer goto nxge_attach_exit; 835678453a8Sspeer } 836678453a8Sspeer #endif 837678453a8Sspeer 83844961713Sgirish status = nxge_setup_dev(nxgep); 83944961713Sgirish if (status != DDI_SUCCESS) { 84044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set dev failed")); 84144961713Sgirish goto nxge_attach_fail; 84244961713Sgirish } 84344961713Sgirish 84444961713Sgirish status = nxge_add_intrs(nxgep); 84544961713Sgirish if (status != DDI_SUCCESS) { 84644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "add_intr failed")); 84744961713Sgirish goto nxge_attach_fail; 84844961713Sgirish } 849330cd344SMichael Speer 85000161856Syc /* If a guest, register with vio_net instead. */ 8512e59129aSraghus if ((status = nxge_mac_register(nxgep)) != NXGE_OK) { 85244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 853678453a8Sspeer "unable to register to mac layer (%d)", status)); 85444961713Sgirish goto nxge_attach_fail; 85544961713Sgirish } 85644961713Sgirish 85744961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_UNKNOWN); 85844961713Sgirish 859678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DDI_CTL, 860678453a8Sspeer "registered to mac (instance %d)", instance)); 86144961713Sgirish 86200161856Syc /* nxge_link_monitor calls xcvr.check_link recursively */ 86344961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 86444961713Sgirish 86544961713Sgirish goto nxge_attach_exit; 86644961713Sgirish 86744961713Sgirish nxge_attach_fail: 86844961713Sgirish nxge_unattach(nxgep); 8692e59129aSraghus goto nxge_attach_fail1; 8702e59129aSraghus 8712e59129aSraghus nxge_attach_fail5: 8722e59129aSraghus /* 8732e59129aSraghus * Tear down the ndd parameters setup. 8742e59129aSraghus */ 8752e59129aSraghus nxge_destroy_param(nxgep); 8762e59129aSraghus 8772e59129aSraghus /* 8782e59129aSraghus * Tear down the kstat setup. 8792e59129aSraghus */ 8802e59129aSraghus nxge_destroy_kstats(nxgep); 8812e59129aSraghus 8822e59129aSraghus nxge_attach_fail4: 8832e59129aSraghus if (nxgep->nxge_hw_p) { 8842e59129aSraghus nxge_uninit_common_dev(nxgep); 8852e59129aSraghus nxgep->nxge_hw_p = NULL; 8862e59129aSraghus } 8872e59129aSraghus 8882e59129aSraghus nxge_attach_fail3: 8892e59129aSraghus /* 8902e59129aSraghus * Unmap the register setup. 8912e59129aSraghus */ 8922e59129aSraghus nxge_unmap_regs(nxgep); 8932e59129aSraghus 8942e59129aSraghus nxge_fm_fini(nxgep); 8952e59129aSraghus 8962e59129aSraghus nxge_attach_fail2: 8972e59129aSraghus ddi_soft_state_free(nxge_list, nxgep->instance); 8982e59129aSraghus 8992e59129aSraghus nxge_attach_fail1: 90056d930aeSspeer if (status != NXGE_OK) 90156d930aeSspeer status = (NXGE_ERROR | NXGE_DDI_FAILED); 90244961713Sgirish nxgep = NULL; 90344961713Sgirish 90444961713Sgirish nxge_attach_exit: 90544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_attach status = 0x%08x", 9064045d941Ssowmini status)); 90744961713Sgirish 90844961713Sgirish return (status); 90944961713Sgirish } 91044961713Sgirish 91144961713Sgirish static int 91244961713Sgirish nxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 91344961713Sgirish { 91444961713Sgirish int status = DDI_SUCCESS; 91544961713Sgirish int instance; 91644961713Sgirish p_nxge_t nxgep = NULL; 91744961713Sgirish 91844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_detach")); 91944961713Sgirish instance = ddi_get_instance(dip); 92044961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance); 92144961713Sgirish if (nxgep == NULL) { 92244961713Sgirish status = DDI_FAILURE; 92344961713Sgirish goto nxge_detach_exit; 92444961713Sgirish } 92544961713Sgirish 92644961713Sgirish switch (cmd) { 92744961713Sgirish case DDI_DETACH: 92844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_DETACH")); 92944961713Sgirish break; 93044961713Sgirish 93144961713Sgirish case DDI_PM_SUSPEND: 93244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_SUSPEND")); 93344961713Sgirish nxgep->suspended = DDI_PM_SUSPEND; 93444961713Sgirish nxge_suspend(nxgep); 93544961713Sgirish break; 93644961713Sgirish 93744961713Sgirish case DDI_SUSPEND: 93844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_SUSPEND")); 93944961713Sgirish if (nxgep->suspended != DDI_PM_SUSPEND) { 94044961713Sgirish nxgep->suspended = DDI_SUSPEND; 94144961713Sgirish nxge_suspend(nxgep); 94244961713Sgirish } 94344961713Sgirish break; 94444961713Sgirish 94544961713Sgirish default: 94644961713Sgirish status = DDI_FAILURE; 94744961713Sgirish } 94844961713Sgirish 94944961713Sgirish if (cmd != DDI_DETACH) 95044961713Sgirish goto nxge_detach_exit; 95144961713Sgirish 95244961713Sgirish /* 95344961713Sgirish * Stop the xcvr polling. 95444961713Sgirish */ 95544961713Sgirish nxgep->suspended = cmd; 95644961713Sgirish 95744961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 95844961713Sgirish 95963f531d1SSriharsha Basavapatna if (nxgep->mach && (status = mac_unregister(nxgep->mach)) != 0) { 96044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 9614045d941Ssowmini "<== nxge_detach status = 0x%08X", status)); 96244961713Sgirish return (DDI_FAILURE); 96344961713Sgirish } 96444961713Sgirish 96544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 9664045d941Ssowmini "<== nxge_detach (mac_unregister) status = 0x%08X", status)); 96744961713Sgirish 96844961713Sgirish nxge_unattach(nxgep); 96944961713Sgirish nxgep = NULL; 97044961713Sgirish 97144961713Sgirish nxge_detach_exit: 97244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_detach status = 0x%08X", 9734045d941Ssowmini status)); 97444961713Sgirish 97544961713Sgirish return (status); 97644961713Sgirish } 97744961713Sgirish 97844961713Sgirish static void 97944961713Sgirish nxge_unattach(p_nxge_t nxgep) 98044961713Sgirish { 98144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unattach")); 98244961713Sgirish 98344961713Sgirish if (nxgep == NULL || nxgep->dev_regs == NULL) { 98444961713Sgirish return; 98544961713Sgirish } 98644961713Sgirish 98798ecde52Stm nxgep->nxge_magic = 0; 98898ecde52Stm 98944961713Sgirish if (nxgep->nxge_timerid) { 99044961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 99144961713Sgirish nxgep->nxge_timerid = 0; 99244961713Sgirish } 99344961713Sgirish 9946f157acbSml /* 9956f157acbSml * If this flag is set, it will affect the Neptune 9966f157acbSml * only. 9976f157acbSml */ 9986f157acbSml if ((nxgep->niu_type != N2_NIU) && nxge_peu_reset_enable) { 9996f157acbSml nxge_niu_peu_reset(nxgep); 10006f157acbSml } 10016f157acbSml 1002678453a8Sspeer #if defined(sun4v) 1003678453a8Sspeer if (isLDOMguest(nxgep)) { 1004d00f30bbSspeer (void) nxge_hio_vr_release(nxgep); 1005678453a8Sspeer } 1006678453a8Sspeer #endif 1007678453a8Sspeer 100853560810Ssbehera if (nxgep->nxge_hw_p) { 100953560810Ssbehera nxge_uninit_common_dev(nxgep); 101053560810Ssbehera nxgep->nxge_hw_p = NULL; 101153560810Ssbehera } 101253560810Ssbehera 101344961713Sgirish #if defined(sun4v) 101444961713Sgirish if (nxgep->niu_type == N2_NIU && nxgep->niu_hsvc_available == B_TRUE) { 101544961713Sgirish (void) hsvc_unregister(&nxgep->niu_hsvc); 101644961713Sgirish nxgep->niu_hsvc_available = B_FALSE; 101744961713Sgirish } 101844961713Sgirish #endif 101944961713Sgirish /* 102044961713Sgirish * Stop any further interrupts. 102144961713Sgirish */ 102244961713Sgirish nxge_remove_intrs(nxgep); 102344961713Sgirish 102444961713Sgirish /* 102544961713Sgirish * Stop the device and free resources. 102644961713Sgirish */ 1027678453a8Sspeer if (!isLDOMguest(nxgep)) { 1028678453a8Sspeer nxge_destroy_dev(nxgep); 1029678453a8Sspeer } 103044961713Sgirish 103144961713Sgirish /* 103244961713Sgirish * Tear down the ndd parameters setup. 103344961713Sgirish */ 103444961713Sgirish nxge_destroy_param(nxgep); 103544961713Sgirish 103644961713Sgirish /* 103744961713Sgirish * Tear down the kstat setup. 103844961713Sgirish */ 103944961713Sgirish nxge_destroy_kstats(nxgep); 104044961713Sgirish 104144961713Sgirish /* 104244961713Sgirish * Destroy all mutexes. 104344961713Sgirish */ 104444961713Sgirish nxge_destroy_mutexes(nxgep); 104544961713Sgirish 104644961713Sgirish /* 104744961713Sgirish * Remove the list of ndd parameters which 104844961713Sgirish * were setup during attach. 104944961713Sgirish */ 105044961713Sgirish if (nxgep->dip) { 105144961713Sgirish NXGE_DEBUG_MSG((nxgep, OBP_CTL, 10524045d941Ssowmini " nxge_unattach: remove all properties")); 105344961713Sgirish 105444961713Sgirish (void) ddi_prop_remove_all(nxgep->dip); 105544961713Sgirish } 105644961713Sgirish 105744961713Sgirish #if NXGE_PROPERTY 105844961713Sgirish nxge_remove_hard_properties(nxgep); 105944961713Sgirish #endif 106044961713Sgirish 106144961713Sgirish /* 106244961713Sgirish * Unmap the register setup. 106344961713Sgirish */ 106444961713Sgirish nxge_unmap_regs(nxgep); 106544961713Sgirish 106644961713Sgirish nxge_fm_fini(nxgep); 106744961713Sgirish 106844961713Sgirish ddi_soft_state_free(nxge_list, nxgep->instance); 106944961713Sgirish 107044961713Sgirish NXGE_DEBUG_MSG((NULL, DDI_CTL, "<== nxge_unattach")); 107144961713Sgirish } 107244961713Sgirish 1073678453a8Sspeer #if defined(sun4v) 1074678453a8Sspeer int 10759d5b8bc5SMichael Speer nxge_hsvc_register(nxge_t *nxgep) 1076678453a8Sspeer { 1077678453a8Sspeer nxge_status_t status; 1078678453a8Sspeer 1079678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 1080678453a8Sspeer nxgep->niu_hsvc_available = B_FALSE; 1081678453a8Sspeer bcopy(&niu_hsvc, &nxgep->niu_hsvc, sizeof (hsvc_info_t)); 1082678453a8Sspeer if ((status = hsvc_register(&nxgep->niu_hsvc, 1083678453a8Sspeer &nxgep->niu_min_ver)) != 0) { 1084678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1085678453a8Sspeer "nxge_attach: %s: cannot negotiate " 1086678453a8Sspeer "hypervisor services revision %d group: 0x%lx " 1087678453a8Sspeer "major: 0x%lx minor: 0x%lx errno: %d", 1088678453a8Sspeer niu_hsvc.hsvc_modname, niu_hsvc.hsvc_rev, 1089678453a8Sspeer niu_hsvc.hsvc_group, niu_hsvc.hsvc_major, 1090678453a8Sspeer niu_hsvc.hsvc_minor, status)); 1091678453a8Sspeer return (DDI_FAILURE); 1092678453a8Sspeer } 1093678453a8Sspeer nxgep->niu_hsvc_available = B_TRUE; 1094678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DDI_CTL, 10954045d941Ssowmini "NIU Hypervisor service enabled")); 1096678453a8Sspeer } 1097678453a8Sspeer 1098678453a8Sspeer return (DDI_SUCCESS); 1099678453a8Sspeer } 1100678453a8Sspeer #endif 1101678453a8Sspeer 110244961713Sgirish static char n2_siu_name[] = "niu"; 110344961713Sgirish 110444961713Sgirish static nxge_status_t 110544961713Sgirish nxge_map_regs(p_nxge_t nxgep) 110644961713Sgirish { 110744961713Sgirish int ddi_status = DDI_SUCCESS; 110844961713Sgirish p_dev_regs_t dev_regs; 110944961713Sgirish char buf[MAXPATHLEN + 1]; 111044961713Sgirish char *devname; 111144961713Sgirish #ifdef NXGE_DEBUG 111244961713Sgirish char *sysname; 111344961713Sgirish #endif 111444961713Sgirish off_t regsize; 111544961713Sgirish nxge_status_t status = NXGE_OK; 111614ea4bb7Ssd #if !defined(_BIG_ENDIAN) 111714ea4bb7Ssd off_t pci_offset; 111814ea4bb7Ssd uint16_t pcie_devctl; 111914ea4bb7Ssd #endif 112044961713Sgirish 1121678453a8Sspeer if (isLDOMguest(nxgep)) { 1122678453a8Sspeer return (nxge_guest_regs_map(nxgep)); 1123678453a8Sspeer } 1124678453a8Sspeer 112544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_map_regs")); 112644961713Sgirish nxgep->dev_regs = NULL; 112744961713Sgirish dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP); 112844961713Sgirish dev_regs->nxge_regh = NULL; 112944961713Sgirish dev_regs->nxge_pciregh = NULL; 113044961713Sgirish dev_regs->nxge_msix_regh = NULL; 113144961713Sgirish dev_regs->nxge_vir_regh = NULL; 113244961713Sgirish dev_regs->nxge_vir2_regh = NULL; 113359ac0c16Sdavemq nxgep->niu_type = NIU_TYPE_NONE; 113444961713Sgirish 113544961713Sgirish devname = ddi_pathname(nxgep->dip, buf); 113644961713Sgirish ASSERT(strlen(devname) > 0); 113744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11384045d941Ssowmini "nxge_map_regs: pathname devname %s", devname)); 113944961713Sgirish 114000161856Syc /* 114100161856Syc * The driver is running on a N2-NIU system if devname is something 114200161856Syc * like "/niu@80/network@0" 114300161856Syc */ 114444961713Sgirish if (strstr(devname, n2_siu_name)) { 114544961713Sgirish /* N2/NIU */ 114644961713Sgirish nxgep->niu_type = N2_NIU; 114744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11484045d941Ssowmini "nxge_map_regs: N2/NIU devname %s", devname)); 114944961713Sgirish /* get function number */ 115044961713Sgirish nxgep->function_num = 11514045d941Ssowmini (devname[strlen(devname) -1] == '1' ? 1 : 0); 115244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11534045d941Ssowmini "nxge_map_regs: N2/NIU function number %d", 11544045d941Ssowmini nxgep->function_num)); 115544961713Sgirish } else { 115644961713Sgirish int *prop_val; 115744961713Sgirish uint_t prop_len; 115844961713Sgirish uint8_t func_num; 115944961713Sgirish 116044961713Sgirish if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 11614045d941Ssowmini 0, "reg", 11624045d941Ssowmini &prop_val, &prop_len) != DDI_PROP_SUCCESS) { 116344961713Sgirish NXGE_DEBUG_MSG((nxgep, VPD_CTL, 11644045d941Ssowmini "Reg property not found")); 116544961713Sgirish ddi_status = DDI_FAILURE; 116644961713Sgirish goto nxge_map_regs_fail0; 116744961713Sgirish 116844961713Sgirish } else { 116944961713Sgirish func_num = (prop_val[0] >> 8) & 0x7; 117044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11714045d941Ssowmini "Reg property found: fun # %d", 11724045d941Ssowmini func_num)); 117344961713Sgirish nxgep->function_num = func_num; 1174678453a8Sspeer if (isLDOMguest(nxgep)) { 1175678453a8Sspeer nxgep->function_num /= 2; 1176678453a8Sspeer return (NXGE_OK); 1177678453a8Sspeer } 117844961713Sgirish ddi_prop_free(prop_val); 117944961713Sgirish } 118044961713Sgirish } 118144961713Sgirish 118244961713Sgirish switch (nxgep->niu_type) { 118344961713Sgirish default: 118444961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 0, ®size); 118544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11864045d941Ssowmini "nxge_map_regs: pci config size 0x%x", regsize)); 118744961713Sgirish 118844961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 0, 11894045d941Ssowmini (caddr_t *)&(dev_regs->nxge_pciregp), 0, 0, 11904045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_pciregh); 119144961713Sgirish if (ddi_status != DDI_SUCCESS) { 119244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 11934045d941Ssowmini "ddi_map_regs, nxge bus config regs failed")); 119444961713Sgirish goto nxge_map_regs_fail0; 119544961713Sgirish } 119644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11974045d941Ssowmini "nxge_map_reg: PCI config addr 0x%0llx " 11984045d941Ssowmini " handle 0x%0llx", dev_regs->nxge_pciregp, 11994045d941Ssowmini dev_regs->nxge_pciregh)); 120044961713Sgirish /* 120144961713Sgirish * IMP IMP 120244961713Sgirish * workaround for bit swapping bug in HW 120344961713Sgirish * which ends up in no-snoop = yes 120444961713Sgirish * resulting, in DMA not synched properly 120544961713Sgirish */ 120644961713Sgirish #if !defined(_BIG_ENDIAN) 120714ea4bb7Ssd /* workarounds for x86 systems */ 120814ea4bb7Ssd pci_offset = 0x80 + PCIE_DEVCTL; 120948056c53SMichael Speer pcie_devctl = pci_config_get16(dev_regs->nxge_pciregh, 121048056c53SMichael Speer pci_offset); 121148056c53SMichael Speer pcie_devctl &= ~PCIE_DEVCTL_ENABLE_NO_SNOOP; 121214ea4bb7Ssd pcie_devctl |= PCIE_DEVCTL_RO_EN; 121314ea4bb7Ssd pci_config_put16(dev_regs->nxge_pciregh, pci_offset, 12144045d941Ssowmini pcie_devctl); 121544961713Sgirish #endif 121614ea4bb7Ssd 121744961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 121844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12194045d941Ssowmini "nxge_map_regs: pio size 0x%x", regsize)); 122044961713Sgirish /* set up the device mapped register */ 122144961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 12224045d941Ssowmini (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 12234045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 122444961713Sgirish if (ddi_status != DDI_SUCCESS) { 122544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12264045d941Ssowmini "ddi_map_regs for Neptune global reg failed")); 122744961713Sgirish goto nxge_map_regs_fail1; 122844961713Sgirish } 122944961713Sgirish 123044961713Sgirish /* set up the msi/msi-x mapped register */ 123144961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 123244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12334045d941Ssowmini "nxge_map_regs: msix size 0x%x", regsize)); 123444961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 12354045d941Ssowmini (caddr_t *)&(dev_regs->nxge_msix_regp), 0, 0, 12364045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_msix_regh); 123744961713Sgirish if (ddi_status != DDI_SUCCESS) { 123844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12394045d941Ssowmini "ddi_map_regs for msi reg failed")); 124044961713Sgirish goto nxge_map_regs_fail2; 124144961713Sgirish } 124244961713Sgirish 124344961713Sgirish /* set up the vio region mapped register */ 124444961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 124544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12464045d941Ssowmini "nxge_map_regs: vio size 0x%x", regsize)); 124744961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 12484045d941Ssowmini (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 12494045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 125044961713Sgirish 125144961713Sgirish if (ddi_status != DDI_SUCCESS) { 125244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12534045d941Ssowmini "ddi_map_regs for nxge vio reg failed")); 125444961713Sgirish goto nxge_map_regs_fail3; 125544961713Sgirish } 125644961713Sgirish nxgep->dev_regs = dev_regs; 125744961713Sgirish 125844961713Sgirish NPI_PCI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_pciregh); 125944961713Sgirish NPI_PCI_ADD_HANDLE_SET(nxgep, 12604045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_pciregp); 126144961713Sgirish NPI_MSI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_msix_regh); 126244961713Sgirish NPI_MSI_ADD_HANDLE_SET(nxgep, 12634045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_msix_regp); 126444961713Sgirish 126544961713Sgirish NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 126644961713Sgirish NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 126744961713Sgirish 126844961713Sgirish NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 126944961713Sgirish NPI_REG_ADD_HANDLE_SET(nxgep, 12704045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_regp); 127144961713Sgirish 127244961713Sgirish NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 127344961713Sgirish NPI_VREG_ADD_HANDLE_SET(nxgep, 12744045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 127544961713Sgirish 127644961713Sgirish break; 127744961713Sgirish 127844961713Sgirish case N2_NIU: 127944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "ddi_map_regs, NIU")); 128044961713Sgirish /* 128144961713Sgirish * Set up the device mapped register (FWARC 2006/556) 128244961713Sgirish * (changed back to 1: reg starts at 1!) 128344961713Sgirish */ 128444961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 128544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12864045d941Ssowmini "nxge_map_regs: dev size 0x%x", regsize)); 128744961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 12884045d941Ssowmini (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 12894045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 129044961713Sgirish 129144961713Sgirish if (ddi_status != DDI_SUCCESS) { 129244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12934045d941Ssowmini "ddi_map_regs for N2/NIU, global reg failed ")); 129444961713Sgirish goto nxge_map_regs_fail1; 129544961713Sgirish } 129644961713Sgirish 1297678453a8Sspeer /* set up the first vio region mapped register */ 129844961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 129944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13004045d941Ssowmini "nxge_map_regs: vio (1) size 0x%x", regsize)); 130144961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 13024045d941Ssowmini (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 13034045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 130444961713Sgirish 130544961713Sgirish if (ddi_status != DDI_SUCCESS) { 130644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13074045d941Ssowmini "ddi_map_regs for nxge vio reg failed")); 130844961713Sgirish goto nxge_map_regs_fail2; 130944961713Sgirish } 1310678453a8Sspeer /* set up the second vio region mapped register */ 131144961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 131244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13134045d941Ssowmini "nxge_map_regs: vio (3) size 0x%x", regsize)); 131444961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 13154045d941Ssowmini (caddr_t *)&(dev_regs->nxge_vir2_regp), 0, 0, 13164045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir2_regh); 131744961713Sgirish 131844961713Sgirish if (ddi_status != DDI_SUCCESS) { 131944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13204045d941Ssowmini "ddi_map_regs for nxge vio2 reg failed")); 132144961713Sgirish goto nxge_map_regs_fail3; 132244961713Sgirish } 132344961713Sgirish nxgep->dev_regs = dev_regs; 132444961713Sgirish 132544961713Sgirish NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 132644961713Sgirish NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 132744961713Sgirish 132844961713Sgirish NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 132944961713Sgirish NPI_REG_ADD_HANDLE_SET(nxgep, 13304045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_regp); 133144961713Sgirish 133244961713Sgirish NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 133344961713Sgirish NPI_VREG_ADD_HANDLE_SET(nxgep, 13344045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 133544961713Sgirish 133644961713Sgirish NPI_V2REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir2_regh); 133744961713Sgirish NPI_V2REG_ADD_HANDLE_SET(nxgep, 13384045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_vir2_regp); 133944961713Sgirish 134044961713Sgirish break; 134144961713Sgirish } 134244961713Sgirish 134344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "nxge_map_reg: hardware addr 0x%0llx " 13444045d941Ssowmini " handle 0x%0llx", dev_regs->nxge_regp, dev_regs->nxge_regh)); 134544961713Sgirish 134644961713Sgirish goto nxge_map_regs_exit; 134744961713Sgirish nxge_map_regs_fail3: 134844961713Sgirish if (dev_regs->nxge_msix_regh) { 134944961713Sgirish ddi_regs_map_free(&dev_regs->nxge_msix_regh); 135044961713Sgirish } 135144961713Sgirish if (dev_regs->nxge_vir_regh) { 135244961713Sgirish ddi_regs_map_free(&dev_regs->nxge_regh); 135344961713Sgirish } 135444961713Sgirish nxge_map_regs_fail2: 135544961713Sgirish if (dev_regs->nxge_regh) { 135644961713Sgirish ddi_regs_map_free(&dev_regs->nxge_regh); 135744961713Sgirish } 135844961713Sgirish nxge_map_regs_fail1: 135944961713Sgirish if (dev_regs->nxge_pciregh) { 136044961713Sgirish ddi_regs_map_free(&dev_regs->nxge_pciregh); 136144961713Sgirish } 136244961713Sgirish nxge_map_regs_fail0: 136344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Freeing register set memory")); 136444961713Sgirish kmem_free(dev_regs, sizeof (dev_regs_t)); 136544961713Sgirish 136644961713Sgirish nxge_map_regs_exit: 136744961713Sgirish if (ddi_status != DDI_SUCCESS) 136844961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 136944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_map_regs")); 137044961713Sgirish return (status); 137144961713Sgirish } 137244961713Sgirish 137344961713Sgirish static void 137444961713Sgirish nxge_unmap_regs(p_nxge_t nxgep) 137544961713Sgirish { 137644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unmap_regs")); 1377678453a8Sspeer 1378678453a8Sspeer if (isLDOMguest(nxgep)) { 1379678453a8Sspeer nxge_guest_regs_map_free(nxgep); 1380678453a8Sspeer return; 1381678453a8Sspeer } 1382678453a8Sspeer 138344961713Sgirish if (nxgep->dev_regs) { 138444961713Sgirish if (nxgep->dev_regs->nxge_pciregh) { 138544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13864045d941Ssowmini "==> nxge_unmap_regs: bus")); 138744961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_pciregh); 138844961713Sgirish nxgep->dev_regs->nxge_pciregh = NULL; 138944961713Sgirish } 139044961713Sgirish if (nxgep->dev_regs->nxge_regh) { 139144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13924045d941Ssowmini "==> nxge_unmap_regs: device registers")); 139344961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_regh); 139444961713Sgirish nxgep->dev_regs->nxge_regh = NULL; 139544961713Sgirish } 139644961713Sgirish if (nxgep->dev_regs->nxge_msix_regh) { 139744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13984045d941Ssowmini "==> nxge_unmap_regs: device interrupts")); 139944961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_msix_regh); 140044961713Sgirish nxgep->dev_regs->nxge_msix_regh = NULL; 140144961713Sgirish } 140244961713Sgirish if (nxgep->dev_regs->nxge_vir_regh) { 140344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 14044045d941Ssowmini "==> nxge_unmap_regs: vio region")); 140544961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_vir_regh); 140644961713Sgirish nxgep->dev_regs->nxge_vir_regh = NULL; 140744961713Sgirish } 140844961713Sgirish if (nxgep->dev_regs->nxge_vir2_regh) { 140944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 14104045d941Ssowmini "==> nxge_unmap_regs: vio2 region")); 141144961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_vir2_regh); 141244961713Sgirish nxgep->dev_regs->nxge_vir2_regh = NULL; 141344961713Sgirish } 141444961713Sgirish 141544961713Sgirish kmem_free(nxgep->dev_regs, sizeof (dev_regs_t)); 141644961713Sgirish nxgep->dev_regs = NULL; 141744961713Sgirish } 141844961713Sgirish 141944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_unmap_regs")); 142044961713Sgirish } 142144961713Sgirish 142244961713Sgirish static nxge_status_t 142344961713Sgirish nxge_setup_mutexes(p_nxge_t nxgep) 142444961713Sgirish { 142544961713Sgirish int ddi_status = DDI_SUCCESS; 142644961713Sgirish nxge_status_t status = NXGE_OK; 142744961713Sgirish nxge_classify_t *classify_ptr; 142844961713Sgirish int partition; 142944961713Sgirish 143044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_mutexes")); 143144961713Sgirish 143244961713Sgirish /* 143344961713Sgirish * Get the interrupt cookie so the mutexes can be 143458324dfcSspeer * Initialized. 143544961713Sgirish */ 1436678453a8Sspeer if (isLDOMguest(nxgep)) { 1437678453a8Sspeer nxgep->interrupt_cookie = 0; 1438678453a8Sspeer } else { 1439678453a8Sspeer ddi_status = ddi_get_iblock_cookie(nxgep->dip, 0, 1440678453a8Sspeer &nxgep->interrupt_cookie); 1441678453a8Sspeer 1442678453a8Sspeer if (ddi_status != DDI_SUCCESS) { 1443678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1444678453a8Sspeer "<== nxge_setup_mutexes: failed 0x%x", 1445678453a8Sspeer ddi_status)); 1446678453a8Sspeer goto nxge_setup_mutexes_exit; 1447678453a8Sspeer } 144844961713Sgirish } 144944961713Sgirish 145098ecde52Stm cv_init(&nxgep->poll_cv, NULL, CV_DRIVER, NULL); 145198ecde52Stm MUTEX_INIT(&nxgep->poll_lock, NULL, 145298ecde52Stm MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 145398ecde52Stm 145444961713Sgirish /* 145598ecde52Stm * Initialize mutexes for this device. 145644961713Sgirish */ 145744961713Sgirish MUTEX_INIT(nxgep->genlock, NULL, 14584045d941Ssowmini MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 145944961713Sgirish MUTEX_INIT(&nxgep->ouraddr_lock, NULL, 14604045d941Ssowmini MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 146144961713Sgirish MUTEX_INIT(&nxgep->mif_lock, NULL, 14624045d941Ssowmini MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 1463678453a8Sspeer MUTEX_INIT(&nxgep->group_lock, NULL, 1464678453a8Sspeer MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 146544961713Sgirish RW_INIT(&nxgep->filter_lock, NULL, 14664045d941Ssowmini RW_DRIVER, (void *)nxgep->interrupt_cookie); 146744961713Sgirish 146844961713Sgirish classify_ptr = &nxgep->classifier; 146944961713Sgirish /* 147044961713Sgirish * FFLP Mutexes are never used in interrupt context 147144961713Sgirish * as fflp operation can take very long time to 147244961713Sgirish * complete and hence not suitable to invoke from interrupt 147344961713Sgirish * handlers. 147444961713Sgirish */ 147544961713Sgirish MUTEX_INIT(&classify_ptr->tcam_lock, NULL, 147659ac0c16Sdavemq NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 14772e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 147844961713Sgirish MUTEX_INIT(&classify_ptr->fcram_lock, NULL, 147959ac0c16Sdavemq NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 148044961713Sgirish for (partition = 0; partition < MAX_PARTITION; partition++) { 148144961713Sgirish MUTEX_INIT(&classify_ptr->hash_lock[partition], NULL, 148244961713Sgirish NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 148344961713Sgirish } 148444961713Sgirish } 148544961713Sgirish 148644961713Sgirish nxge_setup_mutexes_exit: 148744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 148859ac0c16Sdavemq "<== nxge_setup_mutexes status = %x", status)); 148944961713Sgirish 149044961713Sgirish if (ddi_status != DDI_SUCCESS) 149144961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 149244961713Sgirish 149344961713Sgirish return (status); 149444961713Sgirish } 149544961713Sgirish 149644961713Sgirish static void 149744961713Sgirish nxge_destroy_mutexes(p_nxge_t nxgep) 149844961713Sgirish { 149944961713Sgirish int partition; 150044961713Sgirish nxge_classify_t *classify_ptr; 150144961713Sgirish 150244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_mutexes")); 150344961713Sgirish RW_DESTROY(&nxgep->filter_lock); 1504678453a8Sspeer MUTEX_DESTROY(&nxgep->group_lock); 150544961713Sgirish MUTEX_DESTROY(&nxgep->mif_lock); 150644961713Sgirish MUTEX_DESTROY(&nxgep->ouraddr_lock); 150744961713Sgirish MUTEX_DESTROY(nxgep->genlock); 150844961713Sgirish 150944961713Sgirish classify_ptr = &nxgep->classifier; 151044961713Sgirish MUTEX_DESTROY(&classify_ptr->tcam_lock); 151144961713Sgirish 151298ecde52Stm /* Destroy all polling resources. */ 151398ecde52Stm MUTEX_DESTROY(&nxgep->poll_lock); 151498ecde52Stm cv_destroy(&nxgep->poll_cv); 151598ecde52Stm 151698ecde52Stm /* free data structures, based on HW type */ 15172e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 151844961713Sgirish MUTEX_DESTROY(&classify_ptr->fcram_lock); 151944961713Sgirish for (partition = 0; partition < MAX_PARTITION; partition++) { 152044961713Sgirish MUTEX_DESTROY(&classify_ptr->hash_lock[partition]); 152144961713Sgirish } 152244961713Sgirish } 152344961713Sgirish 152444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_mutexes")); 152544961713Sgirish } 152644961713Sgirish 152744961713Sgirish nxge_status_t 152844961713Sgirish nxge_init(p_nxge_t nxgep) 152944961713Sgirish { 1530678453a8Sspeer nxge_status_t status = NXGE_OK; 153144961713Sgirish 153244961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_init")); 153344961713Sgirish 153414ea4bb7Ssd if (nxgep->drv_state & STATE_HW_INITIALIZED) { 153514ea4bb7Ssd return (status); 153614ea4bb7Ssd } 153714ea4bb7Ssd 153844961713Sgirish /* 153944961713Sgirish * Allocate system memory for the receive/transmit buffer blocks 154044961713Sgirish * and receive/transmit descriptor rings. 154144961713Sgirish */ 154244961713Sgirish status = nxge_alloc_mem_pool(nxgep); 154344961713Sgirish if (status != NXGE_OK) { 154444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "alloc mem failed\n")); 154544961713Sgirish goto nxge_init_fail1; 154644961713Sgirish } 154744961713Sgirish 1548678453a8Sspeer if (!isLDOMguest(nxgep)) { 1549678453a8Sspeer /* 1550678453a8Sspeer * Initialize and enable the TXC registers. 1551678453a8Sspeer * (Globally enable the Tx controller, 1552678453a8Sspeer * enable the port, configure the dma channel bitmap, 1553678453a8Sspeer * configure the max burst size). 1554678453a8Sspeer */ 1555678453a8Sspeer status = nxge_txc_init(nxgep); 1556678453a8Sspeer if (status != NXGE_OK) { 1557678453a8Sspeer NXGE_ERROR_MSG((nxgep, 1558678453a8Sspeer NXGE_ERR_CTL, "init txc failed\n")); 1559678453a8Sspeer goto nxge_init_fail2; 1560678453a8Sspeer } 156144961713Sgirish } 156244961713Sgirish 156344961713Sgirish /* 156444961713Sgirish * Initialize and enable TXDMA channels. 156544961713Sgirish */ 156644961713Sgirish status = nxge_init_txdma_channels(nxgep); 156744961713Sgirish if (status != NXGE_OK) { 156844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txdma failed\n")); 156944961713Sgirish goto nxge_init_fail3; 157044961713Sgirish } 157144961713Sgirish 157244961713Sgirish /* 157344961713Sgirish * Initialize and enable RXDMA channels. 157444961713Sgirish */ 157544961713Sgirish status = nxge_init_rxdma_channels(nxgep); 157644961713Sgirish if (status != NXGE_OK) { 157744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init rxdma failed\n")); 157844961713Sgirish goto nxge_init_fail4; 157944961713Sgirish } 158044961713Sgirish 1581678453a8Sspeer /* 1582678453a8Sspeer * The guest domain is now done. 1583678453a8Sspeer */ 1584678453a8Sspeer if (isLDOMguest(nxgep)) { 1585678453a8Sspeer nxgep->drv_state |= STATE_HW_INITIALIZED; 1586678453a8Sspeer goto nxge_init_exit; 1587678453a8Sspeer } 1588678453a8Sspeer 158944961713Sgirish /* 159044961713Sgirish * Initialize TCAM and FCRAM (Neptune). 159144961713Sgirish */ 159244961713Sgirish status = nxge_classify_init(nxgep); 159344961713Sgirish if (status != NXGE_OK) { 159444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init classify failed\n")); 159544961713Sgirish goto nxge_init_fail5; 159644961713Sgirish } 159744961713Sgirish 159844961713Sgirish /* 159944961713Sgirish * Initialize ZCP 160044961713Sgirish */ 160144961713Sgirish status = nxge_zcp_init(nxgep); 160244961713Sgirish if (status != NXGE_OK) { 160344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init ZCP failed\n")); 160444961713Sgirish goto nxge_init_fail5; 160544961713Sgirish } 160644961713Sgirish 160744961713Sgirish /* 160844961713Sgirish * Initialize IPP. 160944961713Sgirish */ 161044961713Sgirish status = nxge_ipp_init(nxgep); 161144961713Sgirish if (status != NXGE_OK) { 161244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init IPP failed\n")); 161344961713Sgirish goto nxge_init_fail5; 161444961713Sgirish } 161544961713Sgirish 161644961713Sgirish /* 161744961713Sgirish * Initialize the MAC block. 161844961713Sgirish */ 161944961713Sgirish status = nxge_mac_init(nxgep); 162044961713Sgirish if (status != NXGE_OK) { 162144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init MAC failed\n")); 162244961713Sgirish goto nxge_init_fail5; 162344961713Sgirish } 162444961713Sgirish 162544961713Sgirish /* 1626e759c33aSMichael Speer * Enable the interrrupts for DDI. 162744961713Sgirish */ 1628e759c33aSMichael Speer nxge_intrs_enable(nxgep); 1629e759c33aSMichael Speer 163044961713Sgirish nxgep->drv_state |= STATE_HW_INITIALIZED; 163144961713Sgirish 163244961713Sgirish goto nxge_init_exit; 163344961713Sgirish 163444961713Sgirish nxge_init_fail5: 163544961713Sgirish nxge_uninit_rxdma_channels(nxgep); 163644961713Sgirish nxge_init_fail4: 163744961713Sgirish nxge_uninit_txdma_channels(nxgep); 163844961713Sgirish nxge_init_fail3: 1639678453a8Sspeer if (!isLDOMguest(nxgep)) { 1640678453a8Sspeer (void) nxge_txc_uninit(nxgep); 1641678453a8Sspeer } 164244961713Sgirish nxge_init_fail2: 164344961713Sgirish nxge_free_mem_pool(nxgep); 164444961713Sgirish nxge_init_fail1: 164544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16464045d941Ssowmini "<== nxge_init status (failed) = 0x%08x", status)); 164744961713Sgirish return (status); 164844961713Sgirish 164944961713Sgirish nxge_init_exit: 165044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_init status = 0x%08x", 16514045d941Ssowmini status)); 165244961713Sgirish return (status); 165344961713Sgirish } 165444961713Sgirish 165544961713Sgirish 165644961713Sgirish timeout_id_t 165744961713Sgirish nxge_start_timer(p_nxge_t nxgep, fptrv_t func, int msec) 165844961713Sgirish { 16594045d941Ssowmini if ((nxgep->suspended == 0) || (nxgep->suspended == DDI_RESUME)) { 166044961713Sgirish return (timeout(func, (caddr_t)nxgep, 16614045d941Ssowmini drv_usectohz(1000 * msec))); 166244961713Sgirish } 166344961713Sgirish return (NULL); 166444961713Sgirish } 166544961713Sgirish 166644961713Sgirish /*ARGSUSED*/ 166744961713Sgirish void 166844961713Sgirish nxge_stop_timer(p_nxge_t nxgep, timeout_id_t timerid) 166944961713Sgirish { 167044961713Sgirish if (timerid) { 167144961713Sgirish (void) untimeout(timerid); 167244961713Sgirish } 167344961713Sgirish } 167444961713Sgirish 167544961713Sgirish void 167644961713Sgirish nxge_uninit(p_nxge_t nxgep) 167744961713Sgirish { 167844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_uninit")); 167944961713Sgirish 168044961713Sgirish if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 168144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 16824045d941Ssowmini "==> nxge_uninit: not initialized")); 168344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 16844045d941Ssowmini "<== nxge_uninit")); 168544961713Sgirish return; 168644961713Sgirish } 168744961713Sgirish 1688e759c33aSMichael Speer if (!isLDOMguest(nxgep)) { 1689e759c33aSMichael Speer /* 1690e759c33aSMichael Speer * Reset the receive MAC side. 1691e759c33aSMichael Speer */ 1692e759c33aSMichael Speer (void) nxge_rx_mac_disable(nxgep); 1693e759c33aSMichael Speer 1694e759c33aSMichael Speer /* 1695e759c33aSMichael Speer * Drain the IPP. 1696e759c33aSMichael Speer */ 1697e759c33aSMichael Speer (void) nxge_ipp_drain(nxgep); 1698e759c33aSMichael Speer } 1699e759c33aSMichael Speer 170044961713Sgirish /* stop timer */ 170144961713Sgirish if (nxgep->nxge_timerid) { 170244961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 170344961713Sgirish nxgep->nxge_timerid = 0; 170444961713Sgirish } 170544961713Sgirish 170644961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 170744961713Sgirish (void) nxge_intr_hw_disable(nxgep); 170844961713Sgirish 170944961713Sgirish 171044961713Sgirish /* Disable and soft reset the IPP */ 1711678453a8Sspeer if (!isLDOMguest(nxgep)) 1712678453a8Sspeer (void) nxge_ipp_disable(nxgep); 171344961713Sgirish 1714a3c5bd6dSspeer /* Free classification resources */ 1715a3c5bd6dSspeer (void) nxge_classify_uninit(nxgep); 1716a3c5bd6dSspeer 171744961713Sgirish /* 171844961713Sgirish * Reset the transmit/receive DMA side. 171944961713Sgirish */ 172044961713Sgirish (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 172144961713Sgirish (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 172244961713Sgirish 172344961713Sgirish nxge_uninit_txdma_channels(nxgep); 172444961713Sgirish nxge_uninit_rxdma_channels(nxgep); 172544961713Sgirish 172644961713Sgirish /* 172744961713Sgirish * Reset the transmit MAC side. 172844961713Sgirish */ 172944961713Sgirish (void) nxge_tx_mac_disable(nxgep); 173044961713Sgirish 173144961713Sgirish nxge_free_mem_pool(nxgep); 173244961713Sgirish 17336f157acbSml /* 17346f157acbSml * Start the timer if the reset flag is not set. 17356f157acbSml * If this reset flag is set, the link monitor 17366f157acbSml * will not be started in order to stop furthur bus 17376f157acbSml * activities coming from this interface. 17386f157acbSml * The driver will start the monitor function 17396f157acbSml * if the interface was initialized again later. 17406f157acbSml */ 17416f157acbSml if (!nxge_peu_reset_enable) { 17426f157acbSml (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 17436f157acbSml } 174444961713Sgirish 174544961713Sgirish nxgep->drv_state &= ~STATE_HW_INITIALIZED; 174644961713Sgirish 174744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_uninit: " 17484045d941Ssowmini "nxge_mblks_pending %d", nxge_mblks_pending)); 174944961713Sgirish } 175044961713Sgirish 175144961713Sgirish void 175244961713Sgirish nxge_get64(p_nxge_t nxgep, p_mblk_t mp) 175344961713Sgirish { 175444961713Sgirish uint64_t reg; 175544961713Sgirish uint64_t regdata; 175644961713Sgirish int i, retry; 175744961713Sgirish 175844961713Sgirish bcopy((char *)mp->b_rptr, (char *)®, sizeof (uint64_t)); 175944961713Sgirish regdata = 0; 176044961713Sgirish retry = 1; 176144961713Sgirish 176244961713Sgirish for (i = 0; i < retry; i++) { 176344961713Sgirish NXGE_REG_RD64(nxgep->npi_handle, reg, ®data); 176444961713Sgirish } 176544961713Sgirish bcopy((char *)®data, (char *)mp->b_rptr, sizeof (uint64_t)); 176644961713Sgirish } 176744961713Sgirish 176844961713Sgirish void 176944961713Sgirish nxge_put64(p_nxge_t nxgep, p_mblk_t mp) 177044961713Sgirish { 177144961713Sgirish uint64_t reg; 177244961713Sgirish uint64_t buf[2]; 177344961713Sgirish 177444961713Sgirish bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t)); 177544961713Sgirish reg = buf[0]; 177644961713Sgirish 177744961713Sgirish NXGE_NPI_PIO_WRITE64(nxgep->npi_handle, reg, buf[1]); 177844961713Sgirish } 177944961713Sgirish 178044961713Sgirish /*ARGSUSED*/ 178144961713Sgirish /*VARARGS*/ 178244961713Sgirish void 178344961713Sgirish nxge_debug_msg(p_nxge_t nxgep, uint64_t level, char *fmt, ...) 178444961713Sgirish { 178544961713Sgirish char msg_buffer[1048]; 178644961713Sgirish char prefix_buffer[32]; 178744961713Sgirish int instance; 178844961713Sgirish uint64_t debug_level; 178944961713Sgirish int cmn_level = CE_CONT; 179044961713Sgirish va_list ap; 179144961713Sgirish 1792678453a8Sspeer if (nxgep && nxgep->nxge_debug_level != nxge_debug_level) { 1793678453a8Sspeer /* In case a developer has changed nxge_debug_level. */ 1794678453a8Sspeer if (nxgep->nxge_debug_level != nxge_debug_level) 1795678453a8Sspeer nxgep->nxge_debug_level = nxge_debug_level; 1796678453a8Sspeer } 1797678453a8Sspeer 179844961713Sgirish debug_level = (nxgep == NULL) ? nxge_debug_level : 17994045d941Ssowmini nxgep->nxge_debug_level; 180044961713Sgirish 180144961713Sgirish if ((level & debug_level) || 18024045d941Ssowmini (level == NXGE_NOTE) || 18034045d941Ssowmini (level == NXGE_ERR_CTL)) { 180444961713Sgirish /* do the msg processing */ 180544961713Sgirish MUTEX_ENTER(&nxgedebuglock); 180644961713Sgirish 180744961713Sgirish if ((level & NXGE_NOTE)) { 180844961713Sgirish cmn_level = CE_NOTE; 180944961713Sgirish } 181044961713Sgirish 181144961713Sgirish if (level & NXGE_ERR_CTL) { 181244961713Sgirish cmn_level = CE_WARN; 181344961713Sgirish } 181444961713Sgirish 181544961713Sgirish va_start(ap, fmt); 181644961713Sgirish (void) vsprintf(msg_buffer, fmt, ap); 181744961713Sgirish va_end(ap); 181844961713Sgirish if (nxgep == NULL) { 181944961713Sgirish instance = -1; 182044961713Sgirish (void) sprintf(prefix_buffer, "%s :", "nxge"); 182144961713Sgirish } else { 182244961713Sgirish instance = nxgep->instance; 182344961713Sgirish (void) sprintf(prefix_buffer, 18244045d941Ssowmini "%s%d :", "nxge", instance); 182544961713Sgirish } 182644961713Sgirish 182744961713Sgirish MUTEX_EXIT(&nxgedebuglock); 182844961713Sgirish cmn_err(cmn_level, "!%s %s\n", 18294045d941Ssowmini prefix_buffer, msg_buffer); 183044961713Sgirish 183144961713Sgirish } 183244961713Sgirish } 183344961713Sgirish 183444961713Sgirish char * 183544961713Sgirish nxge_dump_packet(char *addr, int size) 183644961713Sgirish { 183744961713Sgirish uchar_t *ap = (uchar_t *)addr; 183844961713Sgirish int i; 183944961713Sgirish static char etherbuf[1024]; 184044961713Sgirish char *cp = etherbuf; 184144961713Sgirish char digits[] = "0123456789abcdef"; 184244961713Sgirish 184344961713Sgirish if (!size) 184444961713Sgirish size = 60; 184544961713Sgirish 184644961713Sgirish if (size > MAX_DUMP_SZ) { 184744961713Sgirish /* Dump the leading bytes */ 184844961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 184944961713Sgirish if (*ap > 0x0f) 185044961713Sgirish *cp++ = digits[*ap >> 4]; 185144961713Sgirish *cp++ = digits[*ap++ & 0xf]; 185244961713Sgirish *cp++ = ':'; 185344961713Sgirish } 185444961713Sgirish for (i = 0; i < 20; i++) 185544961713Sgirish *cp++ = '.'; 185644961713Sgirish /* Dump the last MAX_DUMP_SZ/2 bytes */ 185744961713Sgirish ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ/2)); 185844961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 185944961713Sgirish if (*ap > 0x0f) 186044961713Sgirish *cp++ = digits[*ap >> 4]; 186144961713Sgirish *cp++ = digits[*ap++ & 0xf]; 186244961713Sgirish *cp++ = ':'; 186344961713Sgirish } 186444961713Sgirish } else { 186544961713Sgirish for (i = 0; i < size; i++) { 186644961713Sgirish if (*ap > 0x0f) 186744961713Sgirish *cp++ = digits[*ap >> 4]; 186844961713Sgirish *cp++ = digits[*ap++ & 0xf]; 186944961713Sgirish *cp++ = ':'; 187044961713Sgirish } 187144961713Sgirish } 187244961713Sgirish *--cp = 0; 187344961713Sgirish return (etherbuf); 187444961713Sgirish } 187544961713Sgirish 187644961713Sgirish #ifdef NXGE_DEBUG 187744961713Sgirish static void 187844961713Sgirish nxge_test_map_regs(p_nxge_t nxgep) 187944961713Sgirish { 188044961713Sgirish ddi_acc_handle_t cfg_handle; 188144961713Sgirish p_pci_cfg_t cfg_ptr; 188244961713Sgirish ddi_acc_handle_t dev_handle; 188344961713Sgirish char *dev_ptr; 188444961713Sgirish ddi_acc_handle_t pci_config_handle; 188544961713Sgirish uint32_t regval; 188644961713Sgirish int i; 188744961713Sgirish 188844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_test_map_regs")); 188944961713Sgirish 189044961713Sgirish dev_handle = nxgep->dev_regs->nxge_regh; 189144961713Sgirish dev_ptr = (char *)nxgep->dev_regs->nxge_regp; 189244961713Sgirish 18932e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 189444961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 189544961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 189644961713Sgirish 189744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 189859ac0c16Sdavemq "Neptune PCI regp cfg_ptr 0x%llx", (char *)cfg_ptr)); 189944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 190059ac0c16Sdavemq "Neptune PCI cfg_ptr vendor id ptr 0x%llx", 190159ac0c16Sdavemq &cfg_ptr->vendorid)); 190244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 190359ac0c16Sdavemq "\tvendorid 0x%x devid 0x%x", 190459ac0c16Sdavemq NXGE_PIO_READ16(cfg_handle, &cfg_ptr->vendorid, 0), 190559ac0c16Sdavemq NXGE_PIO_READ16(cfg_handle, &cfg_ptr->devid, 0))); 190644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 190759ac0c16Sdavemq "PCI BAR: base 0x%x base14 0x%x base 18 0x%x " 190859ac0c16Sdavemq "bar1c 0x%x", 190959ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base, 0), 191059ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base14, 0), 191159ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base18, 0), 191259ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base1c, 0))); 191344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 191459ac0c16Sdavemq "\nNeptune PCI BAR: base20 0x%x base24 0x%x " 191559ac0c16Sdavemq "base 28 0x%x bar2c 0x%x\n", 191659ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base20, 0), 191759ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base24, 0), 191859ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base28, 0), 191959ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base2c, 0))); 192044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 192159ac0c16Sdavemq "\nNeptune PCI BAR: base30 0x%x\n", 192259ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base30, 0))); 192344961713Sgirish 192444961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 192544961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 192644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 192759ac0c16Sdavemq "first 0x%llx second 0x%llx third 0x%llx " 192859ac0c16Sdavemq "last 0x%llx ", 192959ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 193059ac0c16Sdavemq (uint64_t *)(dev_ptr + 0), 0), 193159ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 193259ac0c16Sdavemq (uint64_t *)(dev_ptr + 8), 0), 193359ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 193459ac0c16Sdavemq (uint64_t *)(dev_ptr + 16), 0), 193559ac0c16Sdavemq NXGE_PIO_READ64(cfg_handle, 193659ac0c16Sdavemq (uint64_t *)(dev_ptr + 24), 0))); 193744961713Sgirish } 193844961713Sgirish } 193944961713Sgirish 194044961713Sgirish #endif 194144961713Sgirish 194244961713Sgirish static void 194344961713Sgirish nxge_suspend(p_nxge_t nxgep) 194444961713Sgirish { 194544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_suspend")); 194644961713Sgirish 194744961713Sgirish nxge_intrs_disable(nxgep); 194844961713Sgirish nxge_destroy_dev(nxgep); 194944961713Sgirish 195044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_suspend")); 195144961713Sgirish } 195244961713Sgirish 195344961713Sgirish static nxge_status_t 195444961713Sgirish nxge_resume(p_nxge_t nxgep) 195544961713Sgirish { 195644961713Sgirish nxge_status_t status = NXGE_OK; 195744961713Sgirish 195844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_resume")); 195944961713Sgirish 196091c98b31Sjoycey nxgep->suspended = DDI_RESUME; 196191c98b31Sjoycey (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 196291c98b31Sjoycey (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_START); 196391c98b31Sjoycey (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START); 196491c98b31Sjoycey (void) nxge_rx_mac_enable(nxgep); 196591c98b31Sjoycey (void) nxge_tx_mac_enable(nxgep); 196691c98b31Sjoycey nxge_intrs_enable(nxgep); 196744961713Sgirish nxgep->suspended = 0; 196844961713Sgirish 196944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 19704045d941Ssowmini "<== nxge_resume status = 0x%x", status)); 197144961713Sgirish return (status); 197244961713Sgirish } 197344961713Sgirish 197444961713Sgirish static nxge_status_t 197544961713Sgirish nxge_setup_dev(p_nxge_t nxgep) 197644961713Sgirish { 197744961713Sgirish nxge_status_t status = NXGE_OK; 197844961713Sgirish 197944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_dev port %d", 198059ac0c16Sdavemq nxgep->mac.portnum)); 198144961713Sgirish 198244961713Sgirish status = nxge_link_init(nxgep); 198314ea4bb7Ssd 198414ea4bb7Ssd if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) { 198514ea4bb7Ssd NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 19864045d941Ssowmini "port%d Bad register acc handle", nxgep->mac.portnum)); 198714ea4bb7Ssd status = NXGE_ERROR; 198814ea4bb7Ssd } 198914ea4bb7Ssd 199044961713Sgirish if (status != NXGE_OK) { 199144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 19924045d941Ssowmini " nxge_setup_dev status " 19934045d941Ssowmini "(xcvr init 0x%08x)", status)); 199444961713Sgirish goto nxge_setup_dev_exit; 199544961713Sgirish } 199644961713Sgirish 199744961713Sgirish nxge_setup_dev_exit: 199844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 19994045d941Ssowmini "<== nxge_setup_dev port %d status = 0x%08x", 20004045d941Ssowmini nxgep->mac.portnum, status)); 200144961713Sgirish 200244961713Sgirish return (status); 200344961713Sgirish } 200444961713Sgirish 200544961713Sgirish static void 200644961713Sgirish nxge_destroy_dev(p_nxge_t nxgep) 200744961713Sgirish { 200844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_dev")); 200944961713Sgirish 201044961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 201144961713Sgirish 201244961713Sgirish (void) nxge_hw_stop(nxgep); 201344961713Sgirish 201444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_dev")); 201544961713Sgirish } 201644961713Sgirish 201744961713Sgirish static nxge_status_t 201844961713Sgirish nxge_setup_system_dma_pages(p_nxge_t nxgep) 201944961713Sgirish { 202044961713Sgirish int ddi_status = DDI_SUCCESS; 202144961713Sgirish uint_t count; 202244961713Sgirish ddi_dma_cookie_t cookie; 202344961713Sgirish uint_t iommu_pagesize; 202444961713Sgirish nxge_status_t status = NXGE_OK; 202544961713Sgirish 2026678453a8Sspeer NXGE_ERROR_MSG((nxgep, DDI_CTL, "==> nxge_setup_system_dma_pages")); 202744961713Sgirish nxgep->sys_page_sz = ddi_ptob(nxgep->dip, (ulong_t)1); 202844961713Sgirish if (nxgep->niu_type != N2_NIU) { 202944961713Sgirish iommu_pagesize = dvma_pagesize(nxgep->dip); 203044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20314045d941Ssowmini " nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 20324045d941Ssowmini " default_block_size %d iommu_pagesize %d", 20334045d941Ssowmini nxgep->sys_page_sz, 20344045d941Ssowmini ddi_ptob(nxgep->dip, (ulong_t)1), 20354045d941Ssowmini nxgep->rx_default_block_size, 20364045d941Ssowmini iommu_pagesize)); 203744961713Sgirish 203844961713Sgirish if (iommu_pagesize != 0) { 203944961713Sgirish if (nxgep->sys_page_sz == iommu_pagesize) { 204044961713Sgirish if (iommu_pagesize > 0x4000) 204144961713Sgirish nxgep->sys_page_sz = 0x4000; 204244961713Sgirish } else { 204344961713Sgirish if (nxgep->sys_page_sz > iommu_pagesize) 204444961713Sgirish nxgep->sys_page_sz = iommu_pagesize; 204544961713Sgirish } 204644961713Sgirish } 204744961713Sgirish } 204844961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 204944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20504045d941Ssowmini "==> nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 20514045d941Ssowmini "default_block_size %d page mask %d", 20524045d941Ssowmini nxgep->sys_page_sz, 20534045d941Ssowmini ddi_ptob(nxgep->dip, (ulong_t)1), 20544045d941Ssowmini nxgep->rx_default_block_size, 20554045d941Ssowmini nxgep->sys_page_mask)); 205644961713Sgirish 205744961713Sgirish 205844961713Sgirish switch (nxgep->sys_page_sz) { 205944961713Sgirish default: 206044961713Sgirish nxgep->sys_page_sz = 0x1000; 206144961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 206244961713Sgirish nxgep->rx_default_block_size = 0x1000; 206344961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 206444961713Sgirish break; 206544961713Sgirish case 0x1000: 206644961713Sgirish nxgep->rx_default_block_size = 0x1000; 206744961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 206844961713Sgirish break; 206944961713Sgirish case 0x2000: 207044961713Sgirish nxgep->rx_default_block_size = 0x2000; 207144961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 207244961713Sgirish break; 207344961713Sgirish case 0x4000: 207444961713Sgirish nxgep->rx_default_block_size = 0x4000; 207544961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_16K; 207644961713Sgirish break; 207744961713Sgirish case 0x8000: 207844961713Sgirish nxgep->rx_default_block_size = 0x8000; 207944961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_32K; 208044961713Sgirish break; 208144961713Sgirish } 208244961713Sgirish 208344961713Sgirish #ifndef USE_RX_BIG_BUF 208444961713Sgirish nxge_rx_dma_attr.dma_attr_align = nxgep->sys_page_sz; 208544961713Sgirish #else 208644961713Sgirish nxgep->rx_default_block_size = 0x2000; 208744961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 208844961713Sgirish #endif 208944961713Sgirish /* 209044961713Sgirish * Get the system DMA burst size. 209144961713Sgirish */ 209244961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr, 20934045d941Ssowmini DDI_DMA_DONTWAIT, 0, 20944045d941Ssowmini &nxgep->dmasparehandle); 209544961713Sgirish if (ddi_status != DDI_SUCCESS) { 209644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20974045d941Ssowmini "ddi_dma_alloc_handle: failed " 20984045d941Ssowmini " status 0x%x", ddi_status)); 209944961713Sgirish goto nxge_get_soft_properties_exit; 210044961713Sgirish } 210144961713Sgirish 210244961713Sgirish ddi_status = ddi_dma_addr_bind_handle(nxgep->dmasparehandle, NULL, 21034045d941Ssowmini (caddr_t)nxgep->dmasparehandle, 21044045d941Ssowmini sizeof (nxgep->dmasparehandle), 21054045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 21064045d941Ssowmini DDI_DMA_DONTWAIT, 0, 21074045d941Ssowmini &cookie, &count); 210844961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 210944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 21104045d941Ssowmini "Binding spare handle to find system" 21114045d941Ssowmini " burstsize failed.")); 211244961713Sgirish ddi_status = DDI_FAILURE; 211344961713Sgirish goto nxge_get_soft_properties_fail1; 211444961713Sgirish } 211544961713Sgirish 211644961713Sgirish nxgep->sys_burst_sz = ddi_dma_burstsizes(nxgep->dmasparehandle); 211744961713Sgirish (void) ddi_dma_unbind_handle(nxgep->dmasparehandle); 211844961713Sgirish 211944961713Sgirish nxge_get_soft_properties_fail1: 212044961713Sgirish ddi_dma_free_handle(&nxgep->dmasparehandle); 212144961713Sgirish 212244961713Sgirish nxge_get_soft_properties_exit: 212344961713Sgirish 212444961713Sgirish if (ddi_status != DDI_SUCCESS) 212544961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 212644961713Sgirish 212744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 21284045d941Ssowmini "<== nxge_setup_system_dma_pages status = 0x%08x", status)); 212944961713Sgirish return (status); 213044961713Sgirish } 213144961713Sgirish 213244961713Sgirish static nxge_status_t 213344961713Sgirish nxge_alloc_mem_pool(p_nxge_t nxgep) 213444961713Sgirish { 213544961713Sgirish nxge_status_t status = NXGE_OK; 213644961713Sgirish 213744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_alloc_mem_pool")); 213844961713Sgirish 213944961713Sgirish status = nxge_alloc_rx_mem_pool(nxgep); 214044961713Sgirish if (status != NXGE_OK) { 214144961713Sgirish return (NXGE_ERROR); 214244961713Sgirish } 214344961713Sgirish 214444961713Sgirish status = nxge_alloc_tx_mem_pool(nxgep); 214544961713Sgirish if (status != NXGE_OK) { 214644961713Sgirish nxge_free_rx_mem_pool(nxgep); 214744961713Sgirish return (NXGE_ERROR); 214844961713Sgirish } 214944961713Sgirish 215044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_alloc_mem_pool")); 215144961713Sgirish return (NXGE_OK); 215244961713Sgirish } 215344961713Sgirish 215444961713Sgirish static void 215544961713Sgirish nxge_free_mem_pool(p_nxge_t nxgep) 215644961713Sgirish { 215744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_mem_pool")); 215844961713Sgirish 215944961713Sgirish nxge_free_rx_mem_pool(nxgep); 216044961713Sgirish nxge_free_tx_mem_pool(nxgep); 216144961713Sgirish 216244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_mem_pool")); 216344961713Sgirish } 216444961713Sgirish 2165678453a8Sspeer nxge_status_t 216644961713Sgirish nxge_alloc_rx_mem_pool(p_nxge_t nxgep) 216744961713Sgirish { 2168678453a8Sspeer uint32_t rdc_max; 216944961713Sgirish p_nxge_dma_pt_cfg_t p_all_cfgp; 217044961713Sgirish p_nxge_hw_pt_cfg_t p_cfgp; 217144961713Sgirish p_nxge_dma_pool_t dma_poolp; 217244961713Sgirish p_nxge_dma_common_t *dma_buf_p; 217344961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 217444961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 217544961713Sgirish uint32_t *num_chunks; /* per dma */ 217644961713Sgirish nxge_status_t status = NXGE_OK; 217744961713Sgirish 217844961713Sgirish uint32_t nxge_port_rbr_size; 217944961713Sgirish uint32_t nxge_port_rbr_spare_size; 218044961713Sgirish uint32_t nxge_port_rcr_size; 2181678453a8Sspeer uint32_t rx_cntl_alloc_size; 218244961713Sgirish 218344961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_mem_pool")); 218444961713Sgirish 218544961713Sgirish p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 218644961713Sgirish p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 2187678453a8Sspeer rdc_max = NXGE_MAX_RDCS; 218844961713Sgirish 218944961713Sgirish /* 2190678453a8Sspeer * Allocate memory for the common DMA data structures. 219144961713Sgirish */ 219244961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 21934045d941Ssowmini KM_SLEEP); 219444961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 21954045d941Ssowmini sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP); 219644961713Sgirish 219744961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 21984045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 219944961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 22004045d941Ssowmini sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP); 220144961713Sgirish 220244961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 22034045d941Ssowmini sizeof (uint32_t) * rdc_max, KM_SLEEP); 220444961713Sgirish 220544961713Sgirish /* 2206678453a8Sspeer * Assume that each DMA channel will be configured with 2207678453a8Sspeer * the default block size. 2208678453a8Sspeer * rbr block counts are modulo the batch count (16). 220944961713Sgirish */ 221044961713Sgirish nxge_port_rbr_size = p_all_cfgp->rbr_size; 221144961713Sgirish nxge_port_rcr_size = p_all_cfgp->rcr_size; 221244961713Sgirish 221344961713Sgirish if (!nxge_port_rbr_size) { 221444961713Sgirish nxge_port_rbr_size = NXGE_RBR_RBB_DEFAULT; 221544961713Sgirish } 221644961713Sgirish if (nxge_port_rbr_size % NXGE_RXDMA_POST_BATCH) { 221744961713Sgirish nxge_port_rbr_size = (NXGE_RXDMA_POST_BATCH * 22184045d941Ssowmini (nxge_port_rbr_size / NXGE_RXDMA_POST_BATCH + 1)); 221944961713Sgirish } 222044961713Sgirish 222144961713Sgirish p_all_cfgp->rbr_size = nxge_port_rbr_size; 222244961713Sgirish nxge_port_rbr_spare_size = nxge_rbr_spare_size; 222344961713Sgirish 222444961713Sgirish if (nxge_port_rbr_spare_size % NXGE_RXDMA_POST_BATCH) { 222544961713Sgirish nxge_port_rbr_spare_size = (NXGE_RXDMA_POST_BATCH * 22264045d941Ssowmini (nxge_port_rbr_spare_size / NXGE_RXDMA_POST_BATCH + 1)); 222744961713Sgirish } 222830ac2e7bSml if (nxge_port_rbr_size > RBR_DEFAULT_MAX_BLKS) { 222930ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 223030ac2e7bSml "nxge_alloc_rx_mem_pool: RBR size too high %d, " 223130ac2e7bSml "set to default %d", 223230ac2e7bSml nxge_port_rbr_size, RBR_DEFAULT_MAX_BLKS)); 223330ac2e7bSml nxge_port_rbr_size = RBR_DEFAULT_MAX_BLKS; 223430ac2e7bSml } 223530ac2e7bSml if (nxge_port_rcr_size > RCR_DEFAULT_MAX) { 223630ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 223730ac2e7bSml "nxge_alloc_rx_mem_pool: RCR too high %d, " 223830ac2e7bSml "set to default %d", 223930ac2e7bSml nxge_port_rcr_size, RCR_DEFAULT_MAX)); 224030ac2e7bSml nxge_port_rcr_size = RCR_DEFAULT_MAX; 224130ac2e7bSml } 224244961713Sgirish 224344961713Sgirish /* 224444961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 224544961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 224644961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 224744961713Sgirish * function). 224844961713Sgirish */ 224944961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 225044961713Sgirish if (nxgep->niu_type == N2_NIU) { 225144961713Sgirish nxge_port_rbr_spare_size = 0; 225244961713Sgirish if ((nxge_port_rbr_size > NXGE_NIU_CONTIG_RBR_MAX) || 22534045d941Ssowmini (!ISP2(nxge_port_rbr_size))) { 225444961713Sgirish nxge_port_rbr_size = NXGE_NIU_CONTIG_RBR_MAX; 225544961713Sgirish } 225644961713Sgirish if ((nxge_port_rcr_size > NXGE_NIU_CONTIG_RCR_MAX) || 22574045d941Ssowmini (!ISP2(nxge_port_rcr_size))) { 225844961713Sgirish nxge_port_rcr_size = NXGE_NIU_CONTIG_RCR_MAX; 225944961713Sgirish } 226044961713Sgirish } 226144961713Sgirish #endif 226244961713Sgirish 226344961713Sgirish /* 226444961713Sgirish * Addresses of receive block ring, receive completion ring and the 226544961713Sgirish * mailbox must be all cache-aligned (64 bytes). 226644961713Sgirish */ 226744961713Sgirish rx_cntl_alloc_size = nxge_port_rbr_size + nxge_port_rbr_spare_size; 226844961713Sgirish rx_cntl_alloc_size *= (sizeof (rx_desc_t)); 226944961713Sgirish rx_cntl_alloc_size += (sizeof (rcr_entry_t) * nxge_port_rcr_size); 227044961713Sgirish rx_cntl_alloc_size += sizeof (rxdma_mailbox_t); 227144961713Sgirish 227244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_alloc_rx_mem_pool: " 22734045d941Ssowmini "nxge_port_rbr_size = %d nxge_port_rbr_spare_size = %d " 22744045d941Ssowmini "nxge_port_rcr_size = %d " 22754045d941Ssowmini "rx_cntl_alloc_size = %d", 22764045d941Ssowmini nxge_port_rbr_size, nxge_port_rbr_spare_size, 22774045d941Ssowmini nxge_port_rcr_size, 22784045d941Ssowmini rx_cntl_alloc_size)); 227944961713Sgirish 228044961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 228144961713Sgirish if (nxgep->niu_type == N2_NIU) { 2282678453a8Sspeer uint32_t rx_buf_alloc_size = (nxgep->rx_default_block_size * 2283678453a8Sspeer (nxge_port_rbr_size + nxge_port_rbr_spare_size)); 2284678453a8Sspeer 228544961713Sgirish if (!ISP2(rx_buf_alloc_size)) { 228644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 22874045d941Ssowmini "==> nxge_alloc_rx_mem_pool: " 22884045d941Ssowmini " must be power of 2")); 228944961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 229044961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 229144961713Sgirish } 229244961713Sgirish 229344961713Sgirish if (rx_buf_alloc_size > (1 << 22)) { 229444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 22954045d941Ssowmini "==> nxge_alloc_rx_mem_pool: " 22964045d941Ssowmini " limit size to 4M")); 229744961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 229844961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 229944961713Sgirish } 230044961713Sgirish 230144961713Sgirish if (rx_cntl_alloc_size < 0x2000) { 230244961713Sgirish rx_cntl_alloc_size = 0x2000; 230344961713Sgirish } 230444961713Sgirish } 230544961713Sgirish #endif 230644961713Sgirish nxgep->nxge_port_rbr_size = nxge_port_rbr_size; 230744961713Sgirish nxgep->nxge_port_rcr_size = nxge_port_rcr_size; 2308678453a8Sspeer nxgep->nxge_port_rbr_spare_size = nxge_port_rbr_spare_size; 2309678453a8Sspeer nxgep->nxge_port_rx_cntl_alloc_size = rx_cntl_alloc_size; 231044961713Sgirish 2311678453a8Sspeer dma_poolp->ndmas = p_cfgp->max_rdcs; 231244961713Sgirish dma_poolp->num_chunks = num_chunks; 231344961713Sgirish dma_poolp->buf_allocated = B_TRUE; 231444961713Sgirish nxgep->rx_buf_pool_p = dma_poolp; 231544961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 231644961713Sgirish 2317678453a8Sspeer dma_cntl_poolp->ndmas = p_cfgp->max_rdcs; 231844961713Sgirish dma_cntl_poolp->buf_allocated = B_TRUE; 231944961713Sgirish nxgep->rx_cntl_pool_p = dma_cntl_poolp; 232044961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 232144961713Sgirish 2322678453a8Sspeer /* Allocate the receive rings, too. */ 2323678453a8Sspeer nxgep->rx_rbr_rings = 23244045d941Ssowmini KMEM_ZALLOC(sizeof (rx_rbr_rings_t), KM_SLEEP); 2325678453a8Sspeer nxgep->rx_rbr_rings->rbr_rings = 23264045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_rbr_ring_t) * rdc_max, KM_SLEEP); 2327678453a8Sspeer nxgep->rx_rcr_rings = 23284045d941Ssowmini KMEM_ZALLOC(sizeof (rx_rcr_rings_t), KM_SLEEP); 2329678453a8Sspeer nxgep->rx_rcr_rings->rcr_rings = 23304045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_rcr_ring_t) * rdc_max, KM_SLEEP); 2331678453a8Sspeer nxgep->rx_mbox_areas_p = 23324045d941Ssowmini KMEM_ZALLOC(sizeof (rx_mbox_areas_t), KM_SLEEP); 2333678453a8Sspeer nxgep->rx_mbox_areas_p->rxmbox_areas = 23344045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_mbox_t) * rdc_max, KM_SLEEP); 2335678453a8Sspeer 2336678453a8Sspeer nxgep->rx_rbr_rings->ndmas = nxgep->rx_rcr_rings->ndmas = 2337678453a8Sspeer p_cfgp->max_rdcs; 233844961713Sgirish 233944961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 23404045d941Ssowmini "<== nxge_alloc_rx_mem_pool:status 0x%08x", status)); 234144961713Sgirish 2342678453a8Sspeer nxge_alloc_rx_mem_pool_exit: 2343678453a8Sspeer return (status); 2344678453a8Sspeer } 2345678453a8Sspeer 2346678453a8Sspeer /* 2347678453a8Sspeer * nxge_alloc_rxb 2348678453a8Sspeer * 2349678453a8Sspeer * Allocate buffers for an RDC. 2350678453a8Sspeer * 2351678453a8Sspeer * Arguments: 2352678453a8Sspeer * nxgep 2353678453a8Sspeer * channel The channel to map into our kernel space. 2354678453a8Sspeer * 2355678453a8Sspeer * Notes: 2356678453a8Sspeer * 2357678453a8Sspeer * NPI function calls: 2358678453a8Sspeer * 2359678453a8Sspeer * NXGE function calls: 2360678453a8Sspeer * 2361678453a8Sspeer * Registers accessed: 2362678453a8Sspeer * 2363678453a8Sspeer * Context: 2364678453a8Sspeer * 2365678453a8Sspeer * Taking apart: 2366678453a8Sspeer * 2367678453a8Sspeer * Open questions: 2368678453a8Sspeer * 2369678453a8Sspeer */ 2370678453a8Sspeer nxge_status_t 2371678453a8Sspeer nxge_alloc_rxb( 2372678453a8Sspeer p_nxge_t nxgep, 2373678453a8Sspeer int channel) 2374678453a8Sspeer { 2375678453a8Sspeer size_t rx_buf_alloc_size; 2376678453a8Sspeer nxge_status_t status = NXGE_OK; 2377678453a8Sspeer 2378678453a8Sspeer nxge_dma_common_t **data; 2379678453a8Sspeer nxge_dma_common_t **control; 2380678453a8Sspeer uint32_t *num_chunks; 2381678453a8Sspeer 2382678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb")); 2383678453a8Sspeer 2384678453a8Sspeer /* 2385678453a8Sspeer * Allocate memory for the receive buffers and descriptor rings. 2386678453a8Sspeer * Replace these allocation functions with the interface functions 2387678453a8Sspeer * provided by the partition manager if/when they are available. 2388678453a8Sspeer */ 2389678453a8Sspeer 2390678453a8Sspeer /* 2391678453a8Sspeer * Allocate memory for the receive buffer blocks. 2392678453a8Sspeer */ 2393678453a8Sspeer rx_buf_alloc_size = (nxgep->rx_default_block_size * 23944045d941Ssowmini (nxgep->nxge_port_rbr_size + nxgep->nxge_port_rbr_spare_size)); 2395678453a8Sspeer 2396678453a8Sspeer data = &nxgep->rx_buf_pool_p->dma_buf_pool_p[channel]; 2397678453a8Sspeer num_chunks = &nxgep->rx_buf_pool_p->num_chunks[channel]; 2398678453a8Sspeer 2399678453a8Sspeer if ((status = nxge_alloc_rx_buf_dma( 2400678453a8Sspeer nxgep, channel, data, rx_buf_alloc_size, 2401678453a8Sspeer nxgep->rx_default_block_size, num_chunks)) != NXGE_OK) { 2402678453a8Sspeer return (status); 240344961713Sgirish } 240444961713Sgirish 2405678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_alloc_rxb(): " 2406678453a8Sspeer "dma %d dma_buf_p %llx &dma_buf_p %llx", channel, *data, data)); 2407678453a8Sspeer 2408678453a8Sspeer /* 2409678453a8Sspeer * Allocate memory for descriptor rings and mailbox. 2410678453a8Sspeer */ 2411678453a8Sspeer control = &nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel]; 2412678453a8Sspeer 2413678453a8Sspeer if ((status = nxge_alloc_rx_cntl_dma( 2414678453a8Sspeer nxgep, channel, control, nxgep->nxge_port_rx_cntl_alloc_size)) 2415678453a8Sspeer != NXGE_OK) { 2416678453a8Sspeer nxge_free_rx_cntl_dma(nxgep, *control); 2417678453a8Sspeer (*data)->buf_alloc_state |= BUF_ALLOCATED_WAIT_FREE; 2418678453a8Sspeer nxge_free_rx_buf_dma(nxgep, *data, *num_chunks); 2419678453a8Sspeer return (status); 2420678453a8Sspeer } 242144961713Sgirish 242244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 2423678453a8Sspeer "<== nxge_alloc_rx_mem_pool:status 0x%08x", status)); 242444961713Sgirish 242544961713Sgirish return (status); 242644961713Sgirish } 242744961713Sgirish 2428678453a8Sspeer void 2429678453a8Sspeer nxge_free_rxb( 2430678453a8Sspeer p_nxge_t nxgep, 2431678453a8Sspeer int channel) 2432678453a8Sspeer { 2433678453a8Sspeer nxge_dma_common_t *data; 2434678453a8Sspeer nxge_dma_common_t *control; 2435678453a8Sspeer uint32_t num_chunks; 2436678453a8Sspeer 2437678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb")); 2438678453a8Sspeer 2439678453a8Sspeer data = nxgep->rx_buf_pool_p->dma_buf_pool_p[channel]; 2440678453a8Sspeer num_chunks = nxgep->rx_buf_pool_p->num_chunks[channel]; 2441678453a8Sspeer nxge_free_rx_buf_dma(nxgep, data, num_chunks); 2442678453a8Sspeer 2443678453a8Sspeer nxgep->rx_buf_pool_p->dma_buf_pool_p[channel] = 0; 2444678453a8Sspeer nxgep->rx_buf_pool_p->num_chunks[channel] = 0; 2445678453a8Sspeer 2446678453a8Sspeer control = nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel]; 2447678453a8Sspeer nxge_free_rx_cntl_dma(nxgep, control); 2448678453a8Sspeer 2449678453a8Sspeer nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel] = 0; 2450678453a8Sspeer 2451678453a8Sspeer KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 2452678453a8Sspeer KMEM_FREE(control, sizeof (nxge_dma_common_t)); 2453678453a8Sspeer 2454678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_alloc_rbb")); 2455678453a8Sspeer } 2456678453a8Sspeer 245744961713Sgirish static void 245844961713Sgirish nxge_free_rx_mem_pool(p_nxge_t nxgep) 245944961713Sgirish { 2460678453a8Sspeer int rdc_max = NXGE_MAX_RDCS; 246144961713Sgirish 246244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_mem_pool")); 246344961713Sgirish 2464678453a8Sspeer if (!nxgep->rx_buf_pool_p || !nxgep->rx_buf_pool_p->buf_allocated) { 246544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 24664045d941Ssowmini "<== nxge_free_rx_mem_pool " 24674045d941Ssowmini "(null rx buf pool or buf not allocated")); 246844961713Sgirish return; 246944961713Sgirish } 2470678453a8Sspeer if (!nxgep->rx_cntl_pool_p || !nxgep->rx_cntl_pool_p->buf_allocated) { 247144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 24724045d941Ssowmini "<== nxge_free_rx_mem_pool " 24734045d941Ssowmini "(null rx cntl buf pool or cntl buf not allocated")); 247444961713Sgirish return; 247544961713Sgirish } 247644961713Sgirish 2477678453a8Sspeer KMEM_FREE(nxgep->rx_cntl_pool_p->dma_buf_pool_p, 2478678453a8Sspeer sizeof (p_nxge_dma_common_t) * rdc_max); 2479678453a8Sspeer KMEM_FREE(nxgep->rx_cntl_pool_p, sizeof (nxge_dma_pool_t)); 248044961713Sgirish 2481678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p->num_chunks, 2482678453a8Sspeer sizeof (uint32_t) * rdc_max); 2483678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p->dma_buf_pool_p, 2484678453a8Sspeer sizeof (p_nxge_dma_common_t) * rdc_max); 2485678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p, sizeof (nxge_dma_pool_t)); 248644961713Sgirish 2487678453a8Sspeer nxgep->rx_buf_pool_p = 0; 2488678453a8Sspeer nxgep->rx_cntl_pool_p = 0; 248944961713Sgirish 2490678453a8Sspeer KMEM_FREE(nxgep->rx_rbr_rings->rbr_rings, 2491678453a8Sspeer sizeof (p_rx_rbr_ring_t) * rdc_max); 2492678453a8Sspeer KMEM_FREE(nxgep->rx_rbr_rings, sizeof (rx_rbr_rings_t)); 2493678453a8Sspeer KMEM_FREE(nxgep->rx_rcr_rings->rcr_rings, 2494678453a8Sspeer sizeof (p_rx_rcr_ring_t) * rdc_max); 2495678453a8Sspeer KMEM_FREE(nxgep->rx_rcr_rings, sizeof (rx_rcr_rings_t)); 2496678453a8Sspeer KMEM_FREE(nxgep->rx_mbox_areas_p->rxmbox_areas, 2497678453a8Sspeer sizeof (p_rx_mbox_t) * rdc_max); 2498678453a8Sspeer KMEM_FREE(nxgep->rx_mbox_areas_p, sizeof (rx_mbox_areas_t)); 249944961713Sgirish 2500678453a8Sspeer nxgep->rx_rbr_rings = 0; 2501678453a8Sspeer nxgep->rx_rcr_rings = 0; 2502678453a8Sspeer nxgep->rx_mbox_areas_p = 0; 250344961713Sgirish 250444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_rx_mem_pool")); 250544961713Sgirish } 250644961713Sgirish 250744961713Sgirish 250844961713Sgirish static nxge_status_t 250944961713Sgirish nxge_alloc_rx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 251044961713Sgirish p_nxge_dma_common_t *dmap, 251144961713Sgirish size_t alloc_size, size_t block_size, uint32_t *num_chunks) 251244961713Sgirish { 251344961713Sgirish p_nxge_dma_common_t rx_dmap; 251444961713Sgirish nxge_status_t status = NXGE_OK; 251544961713Sgirish size_t total_alloc_size; 251644961713Sgirish size_t allocated = 0; 251744961713Sgirish int i, size_index, array_size; 2518678453a8Sspeer boolean_t use_kmem_alloc = B_FALSE; 251944961713Sgirish 252044961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_buf_dma")); 252144961713Sgirish 252244961713Sgirish rx_dmap = (p_nxge_dma_common_t) 25234045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 25244045d941Ssowmini KM_SLEEP); 252544961713Sgirish 252644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 25274045d941Ssowmini " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ", 25284045d941Ssowmini dma_channel, alloc_size, block_size, dmap)); 252944961713Sgirish 253044961713Sgirish total_alloc_size = alloc_size; 253144961713Sgirish 253244961713Sgirish #if defined(RX_USE_RECLAIM_POST) 253344961713Sgirish total_alloc_size = alloc_size + alloc_size/4; 253444961713Sgirish #endif 253544961713Sgirish 253644961713Sgirish i = 0; 253744961713Sgirish size_index = 0; 253844961713Sgirish array_size = sizeof (alloc_sizes)/sizeof (size_t); 25397b26d9ffSSantwona Behera while ((size_index < array_size) && 25407b26d9ffSSantwona Behera (alloc_sizes[size_index] < alloc_size)) 25414045d941Ssowmini size_index++; 254244961713Sgirish if (size_index >= array_size) { 254344961713Sgirish size_index = array_size - 1; 254444961713Sgirish } 254544961713Sgirish 2546678453a8Sspeer /* For Neptune, use kmem_alloc if the kmem flag is set. */ 2547678453a8Sspeer if (nxgep->niu_type != N2_NIU && nxge_use_kmem_alloc) { 2548678453a8Sspeer use_kmem_alloc = B_TRUE; 2549678453a8Sspeer #if defined(__i386) || defined(__amd64) 2550678453a8Sspeer size_index = 0; 2551678453a8Sspeer #endif 2552678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2553678453a8Sspeer "==> nxge_alloc_rx_buf_dma: " 2554678453a8Sspeer "Neptune use kmem_alloc() - size_index %d", 2555678453a8Sspeer size_index)); 2556678453a8Sspeer } 2557678453a8Sspeer 255844961713Sgirish while ((allocated < total_alloc_size) && 25594045d941Ssowmini (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 256044961713Sgirish rx_dmap[i].dma_chunk_index = i; 256144961713Sgirish rx_dmap[i].block_size = block_size; 256244961713Sgirish rx_dmap[i].alength = alloc_sizes[size_index]; 256344961713Sgirish rx_dmap[i].orig_alength = rx_dmap[i].alength; 256444961713Sgirish rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 256544961713Sgirish rx_dmap[i].dma_channel = dma_channel; 256644961713Sgirish rx_dmap[i].contig_alloc_type = B_FALSE; 2567678453a8Sspeer rx_dmap[i].kmem_alloc_type = B_FALSE; 2568678453a8Sspeer rx_dmap[i].buf_alloc_type = DDI_MEM_ALLOC; 256944961713Sgirish 257044961713Sgirish /* 257144961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 257244961713Sgirish * needs to call Hypervisor api to set up 257344961713Sgirish * logical pages. 257444961713Sgirish */ 257544961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 257644961713Sgirish rx_dmap[i].contig_alloc_type = B_TRUE; 2577678453a8Sspeer rx_dmap[i].buf_alloc_type = CONTIG_MEM_ALLOC; 2578678453a8Sspeer } else if (use_kmem_alloc) { 2579678453a8Sspeer /* For Neptune, use kmem_alloc */ 2580678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2581678453a8Sspeer "==> nxge_alloc_rx_buf_dma: " 2582678453a8Sspeer "Neptune use kmem_alloc()")); 2583678453a8Sspeer rx_dmap[i].kmem_alloc_type = B_TRUE; 2584678453a8Sspeer rx_dmap[i].buf_alloc_type = KMEM_ALLOC; 258544961713Sgirish } 258644961713Sgirish 258744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 25884045d941Ssowmini "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x " 25894045d941Ssowmini "i %d nblocks %d alength %d", 25904045d941Ssowmini dma_channel, i, &rx_dmap[i], block_size, 25914045d941Ssowmini i, rx_dmap[i].nblocks, 25924045d941Ssowmini rx_dmap[i].alength)); 259344961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 25944045d941Ssowmini &nxge_rx_dma_attr, 25954045d941Ssowmini rx_dmap[i].alength, 25964045d941Ssowmini &nxge_dev_buf_dma_acc_attr, 25974045d941Ssowmini DDI_DMA_READ | DDI_DMA_STREAMING, 25984045d941Ssowmini (p_nxge_dma_common_t)(&rx_dmap[i])); 259944961713Sgirish if (status != NXGE_OK) { 260044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2601678453a8Sspeer "nxge_alloc_rx_buf_dma: Alloc Failed: " 2602678453a8Sspeer "dma %d size_index %d size requested %d", 2603678453a8Sspeer dma_channel, 2604678453a8Sspeer size_index, 2605678453a8Sspeer rx_dmap[i].alength)); 260644961713Sgirish size_index--; 260744961713Sgirish } else { 2608678453a8Sspeer rx_dmap[i].buf_alloc_state = BUF_ALLOCATED; 2609678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2610678453a8Sspeer " nxge_alloc_rx_buf_dma DONE alloc mem: " 2611678453a8Sspeer "dma %d dma_buf_p $%p kaddrp $%p alength %d " 2612678453a8Sspeer "buf_alloc_state %d alloc_type %d", 2613678453a8Sspeer dma_channel, 2614678453a8Sspeer &rx_dmap[i], 2615678453a8Sspeer rx_dmap[i].kaddrp, 2616678453a8Sspeer rx_dmap[i].alength, 2617678453a8Sspeer rx_dmap[i].buf_alloc_state, 2618678453a8Sspeer rx_dmap[i].buf_alloc_type)); 2619678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2620678453a8Sspeer " alloc_rx_buf_dma allocated rdc %d " 2621678453a8Sspeer "chunk %d size %x dvma %x bufp %llx kaddrp $%p", 2622678453a8Sspeer dma_channel, i, rx_dmap[i].alength, 2623678453a8Sspeer rx_dmap[i].ioaddr_pp, &rx_dmap[i], 2624678453a8Sspeer rx_dmap[i].kaddrp)); 262544961713Sgirish i++; 262644961713Sgirish allocated += alloc_sizes[size_index]; 262744961713Sgirish } 262844961713Sgirish } 262944961713Sgirish 263044961713Sgirish if (allocated < total_alloc_size) { 263130ac2e7bSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2632678453a8Sspeer "==> nxge_alloc_rx_buf_dma: not enough for channel %d " 263330ac2e7bSml "allocated 0x%x requested 0x%x", 263430ac2e7bSml dma_channel, 263530ac2e7bSml allocated, total_alloc_size)); 263630ac2e7bSml status = NXGE_ERROR; 263744961713Sgirish goto nxge_alloc_rx_mem_fail1; 263844961713Sgirish } 263944961713Sgirish 264030ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2641678453a8Sspeer "==> nxge_alloc_rx_buf_dma: Allocated for channel %d " 264230ac2e7bSml "allocated 0x%x requested 0x%x", 264330ac2e7bSml dma_channel, 264430ac2e7bSml allocated, total_alloc_size)); 264530ac2e7bSml 264644961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 26474045d941Ssowmini " alloc_rx_buf_dma rdc %d allocated %d chunks", 26484045d941Ssowmini dma_channel, i)); 264944961713Sgirish *num_chunks = i; 265044961713Sgirish *dmap = rx_dmap; 265144961713Sgirish 265244961713Sgirish goto nxge_alloc_rx_mem_exit; 265344961713Sgirish 265444961713Sgirish nxge_alloc_rx_mem_fail1: 265544961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 265644961713Sgirish 265744961713Sgirish nxge_alloc_rx_mem_exit: 265844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 26594045d941Ssowmini "<== nxge_alloc_rx_buf_dma status 0x%08x", status)); 266044961713Sgirish 266144961713Sgirish return (status); 266244961713Sgirish } 266344961713Sgirish 266444961713Sgirish /*ARGSUSED*/ 266544961713Sgirish static void 266644961713Sgirish nxge_free_rx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 266744961713Sgirish uint32_t num_chunks) 266844961713Sgirish { 266944961713Sgirish int i; 267044961713Sgirish 267144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 26724045d941Ssowmini "==> nxge_free_rx_buf_dma: # of chunks %d", num_chunks)); 267344961713Sgirish 2674678453a8Sspeer if (dmap == 0) 2675678453a8Sspeer return; 2676678453a8Sspeer 267744961713Sgirish for (i = 0; i < num_chunks; i++) { 267844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 26794045d941Ssowmini "==> nxge_free_rx_buf_dma: chunk %d dmap 0x%llx", 26804045d941Ssowmini i, dmap)); 2681678453a8Sspeer nxge_dma_free_rx_data_buf(dmap++); 268244961713Sgirish } 268344961713Sgirish 268444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_buf_dma")); 268544961713Sgirish } 268644961713Sgirish 268744961713Sgirish /*ARGSUSED*/ 268844961713Sgirish static nxge_status_t 268944961713Sgirish nxge_alloc_rx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 269044961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 269144961713Sgirish { 269244961713Sgirish p_nxge_dma_common_t rx_dmap; 269344961713Sgirish nxge_status_t status = NXGE_OK; 269444961713Sgirish 269544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_cntl_dma")); 269644961713Sgirish 269744961713Sgirish rx_dmap = (p_nxge_dma_common_t) 26984045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 269944961713Sgirish 270044961713Sgirish rx_dmap->contig_alloc_type = B_FALSE; 2701678453a8Sspeer rx_dmap->kmem_alloc_type = B_FALSE; 270244961713Sgirish 270344961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 27044045d941Ssowmini &nxge_desc_dma_attr, 27054045d941Ssowmini size, 27064045d941Ssowmini &nxge_dev_desc_dma_acc_attr, 27074045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 27084045d941Ssowmini rx_dmap); 270944961713Sgirish if (status != NXGE_OK) { 271044961713Sgirish goto nxge_alloc_rx_cntl_dma_fail1; 271144961713Sgirish } 271244961713Sgirish 271344961713Sgirish *dmap = rx_dmap; 271444961713Sgirish goto nxge_alloc_rx_cntl_dma_exit; 271544961713Sgirish 271644961713Sgirish nxge_alloc_rx_cntl_dma_fail1: 271744961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t)); 271844961713Sgirish 271944961713Sgirish nxge_alloc_rx_cntl_dma_exit: 272044961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 27214045d941Ssowmini "<== nxge_alloc_rx_cntl_dma status 0x%08x", status)); 272244961713Sgirish 2723678453a8Sspeer return (status); 2724678453a8Sspeer } 2725678453a8Sspeer 2726678453a8Sspeer /*ARGSUSED*/ 2727678453a8Sspeer static void 2728678453a8Sspeer nxge_free_rx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 2729678453a8Sspeer { 2730678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_rx_cntl_dma")); 2731678453a8Sspeer 2732678453a8Sspeer if (dmap == 0) 2733678453a8Sspeer return; 2734678453a8Sspeer 2735678453a8Sspeer nxge_dma_mem_free(dmap); 2736678453a8Sspeer 2737678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_rx_cntl_dma")); 2738678453a8Sspeer } 2739678453a8Sspeer 2740678453a8Sspeer typedef struct { 2741678453a8Sspeer size_t tx_size; 2742678453a8Sspeer size_t cr_size; 2743678453a8Sspeer size_t threshhold; 2744678453a8Sspeer } nxge_tdc_sizes_t; 2745678453a8Sspeer 2746678453a8Sspeer static 2747678453a8Sspeer nxge_status_t 2748678453a8Sspeer nxge_tdc_sizes( 2749678453a8Sspeer nxge_t *nxgep, 2750678453a8Sspeer nxge_tdc_sizes_t *sizes) 2751678453a8Sspeer { 2752678453a8Sspeer uint32_t threshhold; /* The bcopy() threshhold */ 2753678453a8Sspeer size_t tx_size; /* Transmit buffer size */ 2754678453a8Sspeer size_t cr_size; /* Completion ring size */ 2755678453a8Sspeer 2756678453a8Sspeer /* 2757678453a8Sspeer * Assume that each DMA channel will be configured with the 2758678453a8Sspeer * default transmit buffer size for copying transmit data. 2759678453a8Sspeer * (If a packet is bigger than this, it will not be copied.) 2760678453a8Sspeer */ 2761678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 2762678453a8Sspeer threshhold = TX_BCOPY_SIZE; 2763678453a8Sspeer } else { 2764678453a8Sspeer threshhold = nxge_bcopy_thresh; 2765678453a8Sspeer } 2766678453a8Sspeer tx_size = nxge_tx_ring_size * threshhold; 2767678453a8Sspeer 2768678453a8Sspeer cr_size = nxge_tx_ring_size * sizeof (tx_desc_t); 2769678453a8Sspeer cr_size += sizeof (txdma_mailbox_t); 2770678453a8Sspeer 2771678453a8Sspeer #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 2772678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 2773678453a8Sspeer if (!ISP2(tx_size)) { 2774678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27754045d941Ssowmini "==> nxge_tdc_sizes: Tx size" 27764045d941Ssowmini " must be power of 2")); 2777678453a8Sspeer return (NXGE_ERROR); 2778678453a8Sspeer } 2779678453a8Sspeer 2780678453a8Sspeer if (tx_size > (1 << 22)) { 2781678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27824045d941Ssowmini "==> nxge_tdc_sizes: Tx size" 27834045d941Ssowmini " limited to 4M")); 2784678453a8Sspeer return (NXGE_ERROR); 2785678453a8Sspeer } 2786678453a8Sspeer 2787678453a8Sspeer if (cr_size < 0x2000) 2788678453a8Sspeer cr_size = 0x2000; 2789678453a8Sspeer } 2790678453a8Sspeer #endif 2791678453a8Sspeer 2792678453a8Sspeer sizes->threshhold = threshhold; 2793678453a8Sspeer sizes->tx_size = tx_size; 2794678453a8Sspeer sizes->cr_size = cr_size; 2795678453a8Sspeer 2796678453a8Sspeer return (NXGE_OK); 2797678453a8Sspeer } 2798678453a8Sspeer /* 2799678453a8Sspeer * nxge_alloc_txb 2800678453a8Sspeer * 2801678453a8Sspeer * Allocate buffers for an TDC. 2802678453a8Sspeer * 2803678453a8Sspeer * Arguments: 2804678453a8Sspeer * nxgep 2805678453a8Sspeer * channel The channel to map into our kernel space. 2806678453a8Sspeer * 2807678453a8Sspeer * Notes: 2808678453a8Sspeer * 2809678453a8Sspeer * NPI function calls: 2810678453a8Sspeer * 2811678453a8Sspeer * NXGE function calls: 2812678453a8Sspeer * 2813678453a8Sspeer * Registers accessed: 2814678453a8Sspeer * 2815678453a8Sspeer * Context: 2816678453a8Sspeer * 2817678453a8Sspeer * Taking apart: 2818678453a8Sspeer * 2819678453a8Sspeer * Open questions: 2820678453a8Sspeer * 2821678453a8Sspeer */ 2822678453a8Sspeer nxge_status_t 2823678453a8Sspeer nxge_alloc_txb( 2824678453a8Sspeer p_nxge_t nxgep, 2825678453a8Sspeer int channel) 2826678453a8Sspeer { 2827678453a8Sspeer nxge_dma_common_t **dma_buf_p; 2828678453a8Sspeer nxge_dma_common_t **dma_cntl_p; 2829678453a8Sspeer uint32_t *num_chunks; 2830678453a8Sspeer nxge_status_t status = NXGE_OK; 2831678453a8Sspeer 2832678453a8Sspeer nxge_tdc_sizes_t sizes; 2833678453a8Sspeer 2834678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tbb")); 2835678453a8Sspeer 2836678453a8Sspeer if (nxge_tdc_sizes(nxgep, &sizes) != NXGE_OK) 2837678453a8Sspeer return (NXGE_ERROR); 2838678453a8Sspeer 2839678453a8Sspeer /* 2840678453a8Sspeer * Allocate memory for transmit buffers and descriptor rings. 2841678453a8Sspeer * Replace these allocation functions with the interface functions 2842678453a8Sspeer * provided by the partition manager Real Soon Now. 2843678453a8Sspeer */ 2844678453a8Sspeer dma_buf_p = &nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2845678453a8Sspeer num_chunks = &nxgep->tx_buf_pool_p->num_chunks[channel]; 2846678453a8Sspeer 2847678453a8Sspeer dma_cntl_p = &nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2848678453a8Sspeer 2849678453a8Sspeer /* 2850678453a8Sspeer * Allocate memory for transmit buffers and descriptor rings. 2851678453a8Sspeer * Replace allocation functions with interface functions provided 2852678453a8Sspeer * by the partition manager when it is available. 2853678453a8Sspeer * 2854678453a8Sspeer * Allocate memory for the transmit buffer pool. 2855678453a8Sspeer */ 2856678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 28574045d941Ssowmini "sizes: tx: %ld, cr:%ld, th:%ld", 28584045d941Ssowmini sizes.tx_size, sizes.cr_size, sizes.threshhold)); 2859678453a8Sspeer 2860678453a8Sspeer *num_chunks = 0; 2861678453a8Sspeer status = nxge_alloc_tx_buf_dma(nxgep, channel, dma_buf_p, 2862678453a8Sspeer sizes.tx_size, sizes.threshhold, num_chunks); 2863678453a8Sspeer if (status != NXGE_OK) { 2864678453a8Sspeer cmn_err(CE_NOTE, "nxge_alloc_tx_buf_dma failed!"); 2865678453a8Sspeer return (status); 2866678453a8Sspeer } 2867678453a8Sspeer 2868678453a8Sspeer /* 2869678453a8Sspeer * Allocate memory for descriptor rings and mailbox. 2870678453a8Sspeer */ 2871678453a8Sspeer status = nxge_alloc_tx_cntl_dma(nxgep, channel, dma_cntl_p, 2872678453a8Sspeer sizes.cr_size); 2873678453a8Sspeer if (status != NXGE_OK) { 2874678453a8Sspeer nxge_free_tx_buf_dma(nxgep, *dma_buf_p, *num_chunks); 2875678453a8Sspeer cmn_err(CE_NOTE, "nxge_alloc_tx_cntl_dma failed!"); 2876678453a8Sspeer return (status); 2877678453a8Sspeer } 2878678453a8Sspeer 2879678453a8Sspeer return (NXGE_OK); 2880678453a8Sspeer } 2881678453a8Sspeer 2882678453a8Sspeer void 2883678453a8Sspeer nxge_free_txb( 2884678453a8Sspeer p_nxge_t nxgep, 2885678453a8Sspeer int channel) 2886678453a8Sspeer { 2887678453a8Sspeer nxge_dma_common_t *data; 2888678453a8Sspeer nxge_dma_common_t *control; 2889678453a8Sspeer uint32_t num_chunks; 2890678453a8Sspeer 2891678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_txb")); 2892678453a8Sspeer 2893678453a8Sspeer data = nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2894678453a8Sspeer num_chunks = nxgep->tx_buf_pool_p->num_chunks[channel]; 2895678453a8Sspeer nxge_free_tx_buf_dma(nxgep, data, num_chunks); 2896678453a8Sspeer 2897678453a8Sspeer nxgep->tx_buf_pool_p->dma_buf_pool_p[channel] = 0; 2898678453a8Sspeer nxgep->tx_buf_pool_p->num_chunks[channel] = 0; 2899678453a8Sspeer 2900678453a8Sspeer control = nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2901678453a8Sspeer nxge_free_tx_cntl_dma(nxgep, control); 290244961713Sgirish 2903678453a8Sspeer nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel] = 0; 290444961713Sgirish 2905678453a8Sspeer KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 2906678453a8Sspeer KMEM_FREE(control, sizeof (nxge_dma_common_t)); 290744961713Sgirish 2908678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_txb")); 290944961713Sgirish } 291044961713Sgirish 2911678453a8Sspeer /* 2912678453a8Sspeer * nxge_alloc_tx_mem_pool 2913678453a8Sspeer * 2914678453a8Sspeer * This function allocates all of the per-port TDC control data structures. 2915678453a8Sspeer * The per-channel (TDC) data structures are allocated when needed. 2916678453a8Sspeer * 2917678453a8Sspeer * Arguments: 2918678453a8Sspeer * nxgep 2919678453a8Sspeer * 2920678453a8Sspeer * Notes: 2921678453a8Sspeer * 2922678453a8Sspeer * Context: 2923678453a8Sspeer * Any domain 2924678453a8Sspeer */ 2925678453a8Sspeer nxge_status_t 292644961713Sgirish nxge_alloc_tx_mem_pool(p_nxge_t nxgep) 292744961713Sgirish { 2928678453a8Sspeer nxge_hw_pt_cfg_t *p_cfgp; 2929678453a8Sspeer nxge_dma_pool_t *dma_poolp; 2930678453a8Sspeer nxge_dma_common_t **dma_buf_p; 2931678453a8Sspeer nxge_dma_pool_t *dma_cntl_poolp; 2932678453a8Sspeer nxge_dma_common_t **dma_cntl_p; 293344961713Sgirish uint32_t *num_chunks; /* per dma */ 2934678453a8Sspeer int tdc_max; 293544961713Sgirish 293644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool")); 293744961713Sgirish 2938678453a8Sspeer p_cfgp = &nxgep->pt_config.hw_config; 2939678453a8Sspeer tdc_max = NXGE_MAX_TDCS; 294044961713Sgirish 294144961713Sgirish /* 294244961713Sgirish * Allocate memory for each transmit DMA channel. 294344961713Sgirish */ 294444961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 29454045d941Ssowmini KM_SLEEP); 294644961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 29474045d941Ssowmini sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP); 294844961713Sgirish 294944961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 29504045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 295144961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 29524045d941Ssowmini sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP); 295344961713Sgirish 295430ac2e7bSml if (nxge_tx_ring_size > TDC_DEFAULT_MAX) { 295530ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 295630ac2e7bSml "nxge_alloc_tx_mem_pool: TDC too high %d, " 295730ac2e7bSml "set to default %d", 295830ac2e7bSml nxge_tx_ring_size, TDC_DEFAULT_MAX)); 295930ac2e7bSml nxge_tx_ring_size = TDC_DEFAULT_MAX; 296030ac2e7bSml } 296130ac2e7bSml 296244961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 296344961713Sgirish /* 296444961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 296544961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 296644961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 296744961713Sgirish * function). The transmit ring is limited to 8K (includes the 296844961713Sgirish * mailbox). 296944961713Sgirish */ 297044961713Sgirish if (nxgep->niu_type == N2_NIU) { 297144961713Sgirish if ((nxge_tx_ring_size > NXGE_NIU_CONTIG_TX_MAX) || 29724045d941Ssowmini (!ISP2(nxge_tx_ring_size))) { 297344961713Sgirish nxge_tx_ring_size = NXGE_NIU_CONTIG_TX_MAX; 297444961713Sgirish } 297544961713Sgirish } 297644961713Sgirish #endif 297744961713Sgirish 297844961713Sgirish nxgep->nxge_port_tx_ring_size = nxge_tx_ring_size; 297944961713Sgirish 298044961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 29814045d941Ssowmini sizeof (uint32_t) * tdc_max, KM_SLEEP); 298244961713Sgirish 2983678453a8Sspeer dma_poolp->ndmas = p_cfgp->tdc.owned; 298444961713Sgirish dma_poolp->num_chunks = num_chunks; 298544961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 298644961713Sgirish nxgep->tx_buf_pool_p = dma_poolp; 298744961713Sgirish 2988678453a8Sspeer dma_poolp->buf_allocated = B_TRUE; 2989678453a8Sspeer 2990678453a8Sspeer dma_cntl_poolp->ndmas = p_cfgp->tdc.owned; 299144961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 299244961713Sgirish nxgep->tx_cntl_pool_p = dma_cntl_poolp; 299344961713Sgirish 2994678453a8Sspeer dma_cntl_poolp->buf_allocated = B_TRUE; 299544961713Sgirish 2996678453a8Sspeer nxgep->tx_rings = 2997678453a8Sspeer KMEM_ZALLOC(sizeof (tx_rings_t), KM_SLEEP); 2998678453a8Sspeer nxgep->tx_rings->rings = 2999678453a8Sspeer KMEM_ZALLOC(sizeof (p_tx_ring_t) * tdc_max, KM_SLEEP); 3000678453a8Sspeer nxgep->tx_mbox_areas_p = 3001678453a8Sspeer KMEM_ZALLOC(sizeof (tx_mbox_areas_t), KM_SLEEP); 3002678453a8Sspeer nxgep->tx_mbox_areas_p->txmbox_areas_p = 3003678453a8Sspeer KMEM_ZALLOC(sizeof (p_tx_mbox_t) * tdc_max, KM_SLEEP); 300444961713Sgirish 3005678453a8Sspeer nxgep->tx_rings->ndmas = p_cfgp->tdc.owned; 300644961713Sgirish 300744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, 30084045d941Ssowmini "==> nxge_alloc_tx_mem_pool: ndmas %d poolp->ndmas %d", 30094045d941Ssowmini tdc_max, dma_poolp->ndmas)); 301044961713Sgirish 3011678453a8Sspeer return (NXGE_OK); 301244961713Sgirish } 301344961713Sgirish 3014678453a8Sspeer nxge_status_t 301544961713Sgirish nxge_alloc_tx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 301644961713Sgirish p_nxge_dma_common_t *dmap, size_t alloc_size, 301744961713Sgirish size_t block_size, uint32_t *num_chunks) 301844961713Sgirish { 301944961713Sgirish p_nxge_dma_common_t tx_dmap; 302044961713Sgirish nxge_status_t status = NXGE_OK; 302144961713Sgirish size_t total_alloc_size; 302244961713Sgirish size_t allocated = 0; 302344961713Sgirish int i, size_index, array_size; 302444961713Sgirish 302544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_buf_dma")); 302644961713Sgirish 302744961713Sgirish tx_dmap = (p_nxge_dma_common_t) 30284045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 30294045d941Ssowmini KM_SLEEP); 303044961713Sgirish 303144961713Sgirish total_alloc_size = alloc_size; 303244961713Sgirish i = 0; 303344961713Sgirish size_index = 0; 303444961713Sgirish array_size = sizeof (alloc_sizes) / sizeof (size_t); 30357b26d9ffSSantwona Behera while ((size_index < array_size) && 30367b26d9ffSSantwona Behera (alloc_sizes[size_index] < alloc_size)) 303744961713Sgirish size_index++; 303844961713Sgirish if (size_index >= array_size) { 303944961713Sgirish size_index = array_size - 1; 304044961713Sgirish } 304144961713Sgirish 304244961713Sgirish while ((allocated < total_alloc_size) && 30434045d941Ssowmini (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 304444961713Sgirish 304544961713Sgirish tx_dmap[i].dma_chunk_index = i; 304644961713Sgirish tx_dmap[i].block_size = block_size; 304744961713Sgirish tx_dmap[i].alength = alloc_sizes[size_index]; 304844961713Sgirish tx_dmap[i].orig_alength = tx_dmap[i].alength; 304944961713Sgirish tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 305044961713Sgirish tx_dmap[i].dma_channel = dma_channel; 305144961713Sgirish tx_dmap[i].contig_alloc_type = B_FALSE; 3052678453a8Sspeer tx_dmap[i].kmem_alloc_type = B_FALSE; 305344961713Sgirish 305444961713Sgirish /* 305544961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 305644961713Sgirish * needs to call Hypervisor api to set up 305744961713Sgirish * logical pages. 305844961713Sgirish */ 305944961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 306044961713Sgirish tx_dmap[i].contig_alloc_type = B_TRUE; 306144961713Sgirish } 306244961713Sgirish 306344961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 30644045d941Ssowmini &nxge_tx_dma_attr, 30654045d941Ssowmini tx_dmap[i].alength, 30664045d941Ssowmini &nxge_dev_buf_dma_acc_attr, 30674045d941Ssowmini DDI_DMA_WRITE | DDI_DMA_STREAMING, 30684045d941Ssowmini (p_nxge_dma_common_t)(&tx_dmap[i])); 306944961713Sgirish if (status != NXGE_OK) { 307044961713Sgirish size_index--; 307144961713Sgirish } else { 307244961713Sgirish i++; 307344961713Sgirish allocated += alloc_sizes[size_index]; 307444961713Sgirish } 307544961713Sgirish } 307644961713Sgirish 307744961713Sgirish if (allocated < total_alloc_size) { 307830ac2e7bSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 307930ac2e7bSml "==> nxge_alloc_tx_buf_dma: not enough channel %d: " 308030ac2e7bSml "allocated 0x%x requested 0x%x", 308130ac2e7bSml dma_channel, 308230ac2e7bSml allocated, total_alloc_size)); 308330ac2e7bSml status = NXGE_ERROR; 308444961713Sgirish goto nxge_alloc_tx_mem_fail1; 308544961713Sgirish } 308644961713Sgirish 308730ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 308830ac2e7bSml "==> nxge_alloc_tx_buf_dma: Allocated for channel %d: " 308930ac2e7bSml "allocated 0x%x requested 0x%x", 309030ac2e7bSml dma_channel, 309130ac2e7bSml allocated, total_alloc_size)); 309230ac2e7bSml 309344961713Sgirish *num_chunks = i; 309444961713Sgirish *dmap = tx_dmap; 309544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 30964045d941Ssowmini "==> nxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d", 30974045d941Ssowmini *dmap, i)); 309844961713Sgirish goto nxge_alloc_tx_mem_exit; 309944961713Sgirish 310044961713Sgirish nxge_alloc_tx_mem_fail1: 310144961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 310244961713Sgirish 310344961713Sgirish nxge_alloc_tx_mem_exit: 310444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 31054045d941Ssowmini "<== nxge_alloc_tx_buf_dma status 0x%08x", status)); 310644961713Sgirish 310744961713Sgirish return (status); 310844961713Sgirish } 310944961713Sgirish 311044961713Sgirish /*ARGSUSED*/ 311144961713Sgirish static void 311244961713Sgirish nxge_free_tx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 311344961713Sgirish uint32_t num_chunks) 311444961713Sgirish { 311544961713Sgirish int i; 311644961713Sgirish 311744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_tx_buf_dma")); 311844961713Sgirish 3119678453a8Sspeer if (dmap == 0) 3120678453a8Sspeer return; 3121678453a8Sspeer 312244961713Sgirish for (i = 0; i < num_chunks; i++) { 312344961713Sgirish nxge_dma_mem_free(dmap++); 312444961713Sgirish } 312544961713Sgirish 312644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_tx_buf_dma")); 312744961713Sgirish } 312844961713Sgirish 312944961713Sgirish /*ARGSUSED*/ 3130678453a8Sspeer nxge_status_t 313144961713Sgirish nxge_alloc_tx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 313244961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 313344961713Sgirish { 313444961713Sgirish p_nxge_dma_common_t tx_dmap; 313544961713Sgirish nxge_status_t status = NXGE_OK; 313644961713Sgirish 313744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_cntl_dma")); 313844961713Sgirish tx_dmap = (p_nxge_dma_common_t) 31394045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 314044961713Sgirish 314144961713Sgirish tx_dmap->contig_alloc_type = B_FALSE; 3142678453a8Sspeer tx_dmap->kmem_alloc_type = B_FALSE; 314344961713Sgirish 314444961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 31454045d941Ssowmini &nxge_desc_dma_attr, 31464045d941Ssowmini size, 31474045d941Ssowmini &nxge_dev_desc_dma_acc_attr, 31484045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 31494045d941Ssowmini tx_dmap); 315044961713Sgirish if (status != NXGE_OK) { 315144961713Sgirish goto nxge_alloc_tx_cntl_dma_fail1; 315244961713Sgirish } 315344961713Sgirish 315444961713Sgirish *dmap = tx_dmap; 315544961713Sgirish goto nxge_alloc_tx_cntl_dma_exit; 315644961713Sgirish 315744961713Sgirish nxge_alloc_tx_cntl_dma_fail1: 315844961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t)); 315944961713Sgirish 316044961713Sgirish nxge_alloc_tx_cntl_dma_exit: 316144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 31624045d941Ssowmini "<== nxge_alloc_tx_cntl_dma status 0x%08x", status)); 316344961713Sgirish 316444961713Sgirish return (status); 316544961713Sgirish } 316644961713Sgirish 316744961713Sgirish /*ARGSUSED*/ 316844961713Sgirish static void 316944961713Sgirish nxge_free_tx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 317044961713Sgirish { 317144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_tx_cntl_dma")); 317244961713Sgirish 3173678453a8Sspeer if (dmap == 0) 3174678453a8Sspeer return; 3175678453a8Sspeer 317644961713Sgirish nxge_dma_mem_free(dmap); 317744961713Sgirish 317844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_tx_cntl_dma")); 317944961713Sgirish } 318044961713Sgirish 3181678453a8Sspeer /* 3182678453a8Sspeer * nxge_free_tx_mem_pool 3183678453a8Sspeer * 3184678453a8Sspeer * This function frees all of the per-port TDC control data structures. 3185678453a8Sspeer * The per-channel (TDC) data structures are freed when the channel 3186678453a8Sspeer * is stopped. 3187678453a8Sspeer * 3188678453a8Sspeer * Arguments: 3189678453a8Sspeer * nxgep 3190678453a8Sspeer * 3191678453a8Sspeer * Notes: 3192678453a8Sspeer * 3193678453a8Sspeer * Context: 3194678453a8Sspeer * Any domain 3195678453a8Sspeer */ 319644961713Sgirish static void 319744961713Sgirish nxge_free_tx_mem_pool(p_nxge_t nxgep) 319844961713Sgirish { 3199678453a8Sspeer int tdc_max = NXGE_MAX_TDCS; 320044961713Sgirish 3201678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_tx_mem_pool")); 320244961713Sgirish 3203678453a8Sspeer if (!nxgep->tx_buf_pool_p || !nxgep->tx_buf_pool_p->buf_allocated) { 3204678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 32054045d941Ssowmini "<== nxge_free_tx_mem_pool " 32064045d941Ssowmini "(null tx buf pool or buf not allocated")); 320744961713Sgirish return; 320844961713Sgirish } 3209678453a8Sspeer if (!nxgep->tx_cntl_pool_p || !nxgep->tx_cntl_pool_p->buf_allocated) { 3210678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 32114045d941Ssowmini "<== nxge_free_tx_mem_pool " 32124045d941Ssowmini "(null tx cntl buf pool or cntl buf not allocated")); 321344961713Sgirish return; 321444961713Sgirish } 321544961713Sgirish 3216678453a8Sspeer /* 1. Free the mailboxes. */ 3217678453a8Sspeer KMEM_FREE(nxgep->tx_mbox_areas_p->txmbox_areas_p, 3218678453a8Sspeer sizeof (p_tx_mbox_t) * tdc_max); 3219678453a8Sspeer KMEM_FREE(nxgep->tx_mbox_areas_p, sizeof (tx_mbox_areas_t)); 322044961713Sgirish 3221678453a8Sspeer nxgep->tx_mbox_areas_p = 0; 322244961713Sgirish 3223678453a8Sspeer /* 2. Free the transmit ring arrays. */ 3224678453a8Sspeer KMEM_FREE(nxgep->tx_rings->rings, 3225678453a8Sspeer sizeof (p_tx_ring_t) * tdc_max); 3226678453a8Sspeer KMEM_FREE(nxgep->tx_rings, sizeof (tx_rings_t)); 322744961713Sgirish 3228678453a8Sspeer nxgep->tx_rings = 0; 322944961713Sgirish 3230678453a8Sspeer /* 3. Free the completion ring data structures. */ 3231678453a8Sspeer KMEM_FREE(nxgep->tx_cntl_pool_p->dma_buf_pool_p, 3232678453a8Sspeer sizeof (p_nxge_dma_common_t) * tdc_max); 3233678453a8Sspeer KMEM_FREE(nxgep->tx_cntl_pool_p, sizeof (nxge_dma_pool_t)); 323444961713Sgirish 3235678453a8Sspeer nxgep->tx_cntl_pool_p = 0; 323644961713Sgirish 3237678453a8Sspeer /* 4. Free the data ring data structures. */ 3238678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p->num_chunks, 3239678453a8Sspeer sizeof (uint32_t) * tdc_max); 3240678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p->dma_buf_pool_p, 3241678453a8Sspeer sizeof (p_nxge_dma_common_t) * tdc_max); 3242678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p, sizeof (nxge_dma_pool_t)); 324344961713Sgirish 3244678453a8Sspeer nxgep->tx_buf_pool_p = 0; 3245678453a8Sspeer 3246678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_tx_mem_pool")); 324744961713Sgirish } 324844961713Sgirish 324944961713Sgirish /*ARGSUSED*/ 325044961713Sgirish static nxge_status_t 325144961713Sgirish nxge_dma_mem_alloc(p_nxge_t nxgep, dma_method_t method, 325244961713Sgirish struct ddi_dma_attr *dma_attrp, 325344961713Sgirish size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags, 325444961713Sgirish p_nxge_dma_common_t dma_p) 325544961713Sgirish { 325644961713Sgirish caddr_t kaddrp; 325744961713Sgirish int ddi_status = DDI_SUCCESS; 325844961713Sgirish boolean_t contig_alloc_type; 3259678453a8Sspeer boolean_t kmem_alloc_type; 326044961713Sgirish 326144961713Sgirish contig_alloc_type = dma_p->contig_alloc_type; 326244961713Sgirish 326344961713Sgirish if (contig_alloc_type && (nxgep->niu_type != N2_NIU)) { 326444961713Sgirish /* 326544961713Sgirish * contig_alloc_type for contiguous memory only allowed 326644961713Sgirish * for N2/NIU. 326744961713Sgirish */ 326844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 32694045d941Ssowmini "nxge_dma_mem_alloc: alloc type not allowed (%d)", 32704045d941Ssowmini dma_p->contig_alloc_type)); 327144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 327244961713Sgirish } 327344961713Sgirish 327444961713Sgirish dma_p->dma_handle = NULL; 327544961713Sgirish dma_p->acc_handle = NULL; 327644961713Sgirish dma_p->kaddrp = dma_p->last_kaddrp = NULL; 327744961713Sgirish dma_p->first_ioaddr_pp = dma_p->last_ioaddr_pp = NULL; 327844961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, dma_attrp, 32794045d941Ssowmini DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle); 328044961713Sgirish if (ddi_status != DDI_SUCCESS) { 328144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 32824045d941Ssowmini "nxge_dma_mem_alloc:ddi_dma_alloc_handle failed.")); 328344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 328444961713Sgirish } 328544961713Sgirish 3286678453a8Sspeer kmem_alloc_type = dma_p->kmem_alloc_type; 3287678453a8Sspeer 328844961713Sgirish switch (contig_alloc_type) { 328944961713Sgirish case B_FALSE: 3290678453a8Sspeer switch (kmem_alloc_type) { 3291678453a8Sspeer case B_FALSE: 3292678453a8Sspeer ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, 32934045d941Ssowmini length, 32944045d941Ssowmini acc_attr_p, 32954045d941Ssowmini xfer_flags, 32964045d941Ssowmini DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength, 32974045d941Ssowmini &dma_p->acc_handle); 3298678453a8Sspeer if (ddi_status != DDI_SUCCESS) { 3299678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3300678453a8Sspeer "nxge_dma_mem_alloc: " 3301678453a8Sspeer "ddi_dma_mem_alloc failed")); 3302678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3303678453a8Sspeer dma_p->dma_handle = NULL; 3304678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3305678453a8Sspeer } 3306678453a8Sspeer if (dma_p->alength < length) { 3307678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3308678453a8Sspeer "nxge_dma_mem_alloc:di_dma_mem_alloc " 3309678453a8Sspeer "< length.")); 331044961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 3311678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 331244961713Sgirish dma_p->acc_handle = NULL; 3313678453a8Sspeer dma_p->dma_handle = NULL; 3314678453a8Sspeer return (NXGE_ERROR); 331544961713Sgirish } 331644961713Sgirish 3317678453a8Sspeer ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, 3318678453a8Sspeer NULL, 3319678453a8Sspeer kaddrp, dma_p->alength, xfer_flags, 3320678453a8Sspeer DDI_DMA_DONTWAIT, 3321678453a8Sspeer 0, &dma_p->dma_cookie, &dma_p->ncookies); 3322678453a8Sspeer if (ddi_status != DDI_DMA_MAPPED) { 3323678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3324678453a8Sspeer "nxge_dma_mem_alloc: ddi_dma_addr_bind " 3325678453a8Sspeer "failed " 3326678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 3327678453a8Sspeer dma_p->ncookies)); 3328678453a8Sspeer if (dma_p->acc_handle) { 3329678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3330678453a8Sspeer dma_p->acc_handle = NULL; 3331678453a8Sspeer } 3332678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3333678453a8Sspeer dma_p->dma_handle = NULL; 3334678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3335678453a8Sspeer } 3336678453a8Sspeer 3337678453a8Sspeer if (dma_p->ncookies != 1) { 3338678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 3339678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind " 3340678453a8Sspeer "> 1 cookie" 3341678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 3342678453a8Sspeer dma_p->ncookies)); 3343330cd344SMichael Speer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3344678453a8Sspeer if (dma_p->acc_handle) { 3345678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3346678453a8Sspeer dma_p->acc_handle = NULL; 3347678453a8Sspeer } 3348678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3349678453a8Sspeer dma_p->dma_handle = NULL; 3350330cd344SMichael Speer dma_p->acc_handle = NULL; 3351678453a8Sspeer return (NXGE_ERROR); 3352678453a8Sspeer } 3353678453a8Sspeer break; 3354678453a8Sspeer 3355678453a8Sspeer case B_TRUE: 3356678453a8Sspeer kaddrp = KMEM_ALLOC(length, KM_NOSLEEP); 3357678453a8Sspeer if (kaddrp == NULL) { 3358678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3359678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_mem_alloc " 3360678453a8Sspeer "kmem alloc failed")); 3361678453a8Sspeer return (NXGE_ERROR); 3362678453a8Sspeer } 3363678453a8Sspeer 3364678453a8Sspeer dma_p->alength = length; 3365678453a8Sspeer ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, 3366678453a8Sspeer NULL, kaddrp, dma_p->alength, xfer_flags, 3367678453a8Sspeer DDI_DMA_DONTWAIT, 0, 3368678453a8Sspeer &dma_p->dma_cookie, &dma_p->ncookies); 3369678453a8Sspeer if (ddi_status != DDI_DMA_MAPPED) { 3370678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3371678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind: " 3372678453a8Sspeer "(kmem_alloc) failed kaddrp $%p length %d " 3373678453a8Sspeer "(staus 0x%x (%d) ncookies %d.)", 3374678453a8Sspeer kaddrp, length, 3375678453a8Sspeer ddi_status, ddi_status, dma_p->ncookies)); 3376678453a8Sspeer KMEM_FREE(kaddrp, length); 3377678453a8Sspeer dma_p->acc_handle = NULL; 3378678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3379678453a8Sspeer dma_p->dma_handle = NULL; 3380678453a8Sspeer dma_p->kaddrp = NULL; 3381678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3382678453a8Sspeer } 3383678453a8Sspeer 3384678453a8Sspeer if (dma_p->ncookies != 1) { 3385678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 3386678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind " 3387678453a8Sspeer "(kmem_alloc) > 1 cookie" 3388678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 33894045d941Ssowmini dma_p->ncookies)); 3390678453a8Sspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3391330cd344SMichael Speer KMEM_FREE(kaddrp, length); 3392678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3393678453a8Sspeer dma_p->dma_handle = NULL; 3394330cd344SMichael Speer dma_p->acc_handle = NULL; 3395678453a8Sspeer dma_p->kaddrp = NULL; 3396678453a8Sspeer return (NXGE_ERROR); 339744961713Sgirish } 3398678453a8Sspeer 3399678453a8Sspeer dma_p->kaddrp = kaddrp; 3400678453a8Sspeer 3401678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 34024045d941Ssowmini "nxge_dma_mem_alloc: kmem_alloc dmap $%p " 34034045d941Ssowmini "kaddr $%p alength %d", 34044045d941Ssowmini dma_p, 34054045d941Ssowmini kaddrp, 34064045d941Ssowmini dma_p->alength)); 3407678453a8Sspeer break; 340844961713Sgirish } 340944961713Sgirish break; 341044961713Sgirish 341144961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 341244961713Sgirish case B_TRUE: 341344961713Sgirish kaddrp = (caddr_t)contig_mem_alloc(length); 341444961713Sgirish if (kaddrp == NULL) { 341544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34164045d941Ssowmini "nxge_dma_mem_alloc:contig_mem_alloc failed.")); 341744961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 341844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 341944961713Sgirish } 342044961713Sgirish 342144961713Sgirish dma_p->alength = length; 342244961713Sgirish ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL, 34234045d941Ssowmini kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0, 34244045d941Ssowmini &dma_p->dma_cookie, &dma_p->ncookies); 342544961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 342644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34274045d941Ssowmini "nxge_dma_mem_alloc:di_dma_addr_bind failed " 34284045d941Ssowmini "(status 0x%x ncookies %d.)", ddi_status, 34294045d941Ssowmini dma_p->ncookies)); 343044961713Sgirish 343144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 34324045d941Ssowmini "==> nxge_dma_mem_alloc: (not mapped)" 34334045d941Ssowmini "length %lu (0x%x) " 34344045d941Ssowmini "free contig kaddrp $%p " 34354045d941Ssowmini "va_to_pa $%p", 34364045d941Ssowmini length, length, 34374045d941Ssowmini kaddrp, 34384045d941Ssowmini va_to_pa(kaddrp))); 343944961713Sgirish 344044961713Sgirish 344144961713Sgirish contig_mem_free((void *)kaddrp, length); 344244961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 344344961713Sgirish 344444961713Sgirish dma_p->dma_handle = NULL; 344544961713Sgirish dma_p->acc_handle = NULL; 344644961713Sgirish dma_p->alength = NULL; 344744961713Sgirish dma_p->kaddrp = NULL; 344844961713Sgirish 344944961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 345044961713Sgirish } 345144961713Sgirish 345244961713Sgirish if (dma_p->ncookies != 1 || 34534045d941Ssowmini (dma_p->dma_cookie.dmac_laddress == NULL)) { 345444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34554045d941Ssowmini "nxge_dma_mem_alloc:di_dma_addr_bind > 1 " 34564045d941Ssowmini "cookie or " 34574045d941Ssowmini "dmac_laddress is NULL $%p size %d " 34584045d941Ssowmini " (status 0x%x ncookies %d.)", 34594045d941Ssowmini ddi_status, 34604045d941Ssowmini dma_p->dma_cookie.dmac_laddress, 34614045d941Ssowmini dma_p->dma_cookie.dmac_size, 34624045d941Ssowmini dma_p->ncookies)); 346344961713Sgirish 346444961713Sgirish contig_mem_free((void *)kaddrp, length); 346556d930aeSspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 346644961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 346744961713Sgirish 346844961713Sgirish dma_p->alength = 0; 346944961713Sgirish dma_p->dma_handle = NULL; 347044961713Sgirish dma_p->acc_handle = NULL; 347144961713Sgirish dma_p->kaddrp = NULL; 347244961713Sgirish 347344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 347444961713Sgirish } 347544961713Sgirish break; 347644961713Sgirish 347744961713Sgirish #else 347844961713Sgirish case B_TRUE: 347944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34804045d941Ssowmini "nxge_dma_mem_alloc: invalid alloc type for !sun4v")); 348144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 348244961713Sgirish #endif 348344961713Sgirish } 348444961713Sgirish 348544961713Sgirish dma_p->kaddrp = kaddrp; 348644961713Sgirish dma_p->last_kaddrp = (unsigned char *)kaddrp + 34874045d941Ssowmini dma_p->alength - RXBUF_64B_ALIGNED; 3488adfcba55Sjoycey #if defined(__i386) 3489adfcba55Sjoycey dma_p->ioaddr_pp = 34904045d941Ssowmini (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress; 3491adfcba55Sjoycey #else 349244961713Sgirish dma_p->ioaddr_pp = (unsigned char *)dma_p->dma_cookie.dmac_laddress; 3493adfcba55Sjoycey #endif 349444961713Sgirish dma_p->last_ioaddr_pp = 3495adfcba55Sjoycey #if defined(__i386) 34964045d941Ssowmini (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress + 3497adfcba55Sjoycey #else 34984045d941Ssowmini (unsigned char *)dma_p->dma_cookie.dmac_laddress + 3499adfcba55Sjoycey #endif 35004045d941Ssowmini dma_p->alength - RXBUF_64B_ALIGNED; 350144961713Sgirish 350244961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle); 350344961713Sgirish 350444961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 350544961713Sgirish dma_p->orig_ioaddr_pp = 35064045d941Ssowmini (unsigned char *)dma_p->dma_cookie.dmac_laddress; 350744961713Sgirish dma_p->orig_alength = length; 350844961713Sgirish dma_p->orig_kaddrp = kaddrp; 350944961713Sgirish dma_p->orig_vatopa = (uint64_t)va_to_pa(kaddrp); 351044961713Sgirish #endif 351144961713Sgirish 351244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_dma_mem_alloc: " 35134045d941Ssowmini "dma buffer allocated: dma_p $%p " 35144045d941Ssowmini "return dmac_ladress from cookie $%p cookie dmac_size %d " 35154045d941Ssowmini "dma_p->ioaddr_p $%p " 35164045d941Ssowmini "dma_p->orig_ioaddr_p $%p " 35174045d941Ssowmini "orig_vatopa $%p " 35184045d941Ssowmini "alength %d (0x%x) " 35194045d941Ssowmini "kaddrp $%p " 35204045d941Ssowmini "length %d (0x%x)", 35214045d941Ssowmini dma_p, 35224045d941Ssowmini dma_p->dma_cookie.dmac_laddress, dma_p->dma_cookie.dmac_size, 35234045d941Ssowmini dma_p->ioaddr_pp, 35244045d941Ssowmini dma_p->orig_ioaddr_pp, 35254045d941Ssowmini dma_p->orig_vatopa, 35264045d941Ssowmini dma_p->alength, dma_p->alength, 35274045d941Ssowmini kaddrp, 35284045d941Ssowmini length, length)); 352944961713Sgirish 353044961713Sgirish return (NXGE_OK); 353144961713Sgirish } 353244961713Sgirish 353344961713Sgirish static void 353444961713Sgirish nxge_dma_mem_free(p_nxge_dma_common_t dma_p) 353544961713Sgirish { 353644961713Sgirish if (dma_p->dma_handle != NULL) { 353744961713Sgirish if (dma_p->ncookies) { 353844961713Sgirish (void) ddi_dma_unbind_handle(dma_p->dma_handle); 353944961713Sgirish dma_p->ncookies = 0; 354044961713Sgirish } 354144961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 354244961713Sgirish dma_p->dma_handle = NULL; 354344961713Sgirish } 354444961713Sgirish 354544961713Sgirish if (dma_p->acc_handle != NULL) { 354644961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 354744961713Sgirish dma_p->acc_handle = NULL; 354844961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 354944961713Sgirish } 355044961713Sgirish 355144961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 355244961713Sgirish if (dma_p->contig_alloc_type && 35534045d941Ssowmini dma_p->orig_kaddrp && dma_p->orig_alength) { 355444961713Sgirish NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_mem_free: " 35554045d941Ssowmini "kaddrp $%p (orig_kaddrp $%p)" 35564045d941Ssowmini "mem type %d ", 35574045d941Ssowmini "orig_alength %d " 35584045d941Ssowmini "alength 0x%x (%d)", 35594045d941Ssowmini dma_p->kaddrp, 35604045d941Ssowmini dma_p->orig_kaddrp, 35614045d941Ssowmini dma_p->contig_alloc_type, 35624045d941Ssowmini dma_p->orig_alength, 35634045d941Ssowmini dma_p->alength, dma_p->alength)); 356444961713Sgirish 356544961713Sgirish contig_mem_free(dma_p->orig_kaddrp, dma_p->orig_alength); 356644961713Sgirish dma_p->orig_alength = NULL; 356744961713Sgirish dma_p->orig_kaddrp = NULL; 356844961713Sgirish dma_p->contig_alloc_type = B_FALSE; 356944961713Sgirish } 357044961713Sgirish #endif 357144961713Sgirish dma_p->kaddrp = NULL; 357244961713Sgirish dma_p->alength = NULL; 357344961713Sgirish } 357444961713Sgirish 3575678453a8Sspeer static void 3576678453a8Sspeer nxge_dma_free_rx_data_buf(p_nxge_dma_common_t dma_p) 3577678453a8Sspeer { 3578678453a8Sspeer uint64_t kaddr; 3579678453a8Sspeer uint32_t buf_size; 3580678453a8Sspeer 3581678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "==> nxge_dma_free_rx_data_buf")); 3582678453a8Sspeer 3583678453a8Sspeer if (dma_p->dma_handle != NULL) { 3584678453a8Sspeer if (dma_p->ncookies) { 3585678453a8Sspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3586678453a8Sspeer dma_p->ncookies = 0; 3587678453a8Sspeer } 3588678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3589678453a8Sspeer dma_p->dma_handle = NULL; 3590678453a8Sspeer } 3591678453a8Sspeer 3592678453a8Sspeer if (dma_p->acc_handle != NULL) { 3593678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3594678453a8Sspeer dma_p->acc_handle = NULL; 3595678453a8Sspeer NPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 3596678453a8Sspeer } 3597678453a8Sspeer 3598678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3599678453a8Sspeer "==> nxge_dma_free_rx_data_buf: dmap $%p buf_alloc_state %d", 3600678453a8Sspeer dma_p, 3601678453a8Sspeer dma_p->buf_alloc_state)); 3602678453a8Sspeer 3603678453a8Sspeer if (!(dma_p->buf_alloc_state & BUF_ALLOCATED_WAIT_FREE)) { 3604678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3605678453a8Sspeer "<== nxge_dma_free_rx_data_buf: " 3606678453a8Sspeer "outstanding data buffers")); 3607678453a8Sspeer return; 3608678453a8Sspeer } 3609678453a8Sspeer 3610678453a8Sspeer #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 3611678453a8Sspeer if (dma_p->contig_alloc_type && 36124045d941Ssowmini dma_p->orig_kaddrp && dma_p->orig_alength) { 3613678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_free_rx_data_buf: " 3614678453a8Sspeer "kaddrp $%p (orig_kaddrp $%p)" 3615678453a8Sspeer "mem type %d ", 3616678453a8Sspeer "orig_alength %d " 3617678453a8Sspeer "alength 0x%x (%d)", 3618678453a8Sspeer dma_p->kaddrp, 3619678453a8Sspeer dma_p->orig_kaddrp, 3620678453a8Sspeer dma_p->contig_alloc_type, 3621678453a8Sspeer dma_p->orig_alength, 3622678453a8Sspeer dma_p->alength, dma_p->alength)); 3623678453a8Sspeer 3624678453a8Sspeer kaddr = (uint64_t)dma_p->orig_kaddrp; 3625678453a8Sspeer buf_size = dma_p->orig_alength; 3626678453a8Sspeer nxge_free_buf(CONTIG_MEM_ALLOC, kaddr, buf_size); 3627678453a8Sspeer dma_p->orig_alength = NULL; 3628678453a8Sspeer dma_p->orig_kaddrp = NULL; 3629678453a8Sspeer dma_p->contig_alloc_type = B_FALSE; 3630678453a8Sspeer dma_p->kaddrp = NULL; 3631678453a8Sspeer dma_p->alength = NULL; 3632678453a8Sspeer return; 3633678453a8Sspeer } 3634678453a8Sspeer #endif 3635678453a8Sspeer 3636678453a8Sspeer if (dma_p->kmem_alloc_type) { 3637678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3638678453a8Sspeer "nxge_dma_free_rx_data_buf: free kmem " 36394045d941Ssowmini "kaddrp $%p (orig_kaddrp $%p)" 36404045d941Ssowmini "alloc type %d " 36414045d941Ssowmini "orig_alength %d " 36424045d941Ssowmini "alength 0x%x (%d)", 36434045d941Ssowmini dma_p->kaddrp, 36444045d941Ssowmini dma_p->orig_kaddrp, 36454045d941Ssowmini dma_p->kmem_alloc_type, 36464045d941Ssowmini dma_p->orig_alength, 36474045d941Ssowmini dma_p->alength, dma_p->alength)); 3648678453a8Sspeer #if defined(__i386) 3649678453a8Sspeer kaddr = (uint64_t)(uint32_t)dma_p->kaddrp; 3650678453a8Sspeer #else 3651678453a8Sspeer kaddr = (uint64_t)dma_p->kaddrp; 3652678453a8Sspeer #endif 3653678453a8Sspeer buf_size = dma_p->orig_alength; 3654678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3655678453a8Sspeer "nxge_dma_free_rx_data_buf: free dmap $%p " 3656678453a8Sspeer "kaddr $%p buf_size %d", 3657678453a8Sspeer dma_p, 3658678453a8Sspeer kaddr, buf_size)); 3659678453a8Sspeer nxge_free_buf(KMEM_ALLOC, kaddr, buf_size); 3660678453a8Sspeer dma_p->alength = 0; 3661678453a8Sspeer dma_p->orig_alength = 0; 3662678453a8Sspeer dma_p->kaddrp = NULL; 3663678453a8Sspeer dma_p->kmem_alloc_type = B_FALSE; 3664678453a8Sspeer } 3665678453a8Sspeer 3666678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_dma_free_rx_data_buf")); 3667678453a8Sspeer } 3668678453a8Sspeer 366944961713Sgirish /* 367044961713Sgirish * nxge_m_start() -- start transmitting and receiving. 367144961713Sgirish * 367244961713Sgirish * This function is called by the MAC layer when the first 367344961713Sgirish * stream is open to prepare the hardware ready for sending 367444961713Sgirish * and transmitting packets. 367544961713Sgirish */ 367644961713Sgirish static int 367744961713Sgirish nxge_m_start(void *arg) 367844961713Sgirish { 367944961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 368044961713Sgirish 368144961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_start")); 368244961713Sgirish 3683e759c33aSMichael Speer /* 3684e759c33aSMichael Speer * Are we already started? 3685e759c33aSMichael Speer */ 3686e759c33aSMichael Speer if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 3687e759c33aSMichael Speer return (0); 3688e759c33aSMichael Speer } 3689e759c33aSMichael Speer 36906f157acbSml if (nxge_peu_reset_enable && !nxgep->nxge_link_poll_timerid) { 36916f157acbSml (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 36926f157acbSml } 36936f157acbSml 3694e759c33aSMichael Speer /* 3695e759c33aSMichael Speer * Make sure RX MAC is disabled while we initialize. 3696e759c33aSMichael Speer */ 3697e759c33aSMichael Speer if (!isLDOMguest(nxgep)) { 3698e759c33aSMichael Speer (void) nxge_rx_mac_disable(nxgep); 3699e759c33aSMichael Speer } 3700e759c33aSMichael Speer 3701e759c33aSMichael Speer /* 3702e759c33aSMichael Speer * Grab the global lock. 3703e759c33aSMichael Speer */ 370444961713Sgirish MUTEX_ENTER(nxgep->genlock); 3705e759c33aSMichael Speer 3706e759c33aSMichael Speer /* 3707e759c33aSMichael Speer * Initialize the driver and hardware. 3708e759c33aSMichael Speer */ 370914ea4bb7Ssd if (nxge_init(nxgep) != NXGE_OK) { 371044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 37114045d941Ssowmini "<== nxge_m_start: initialization failed")); 371244961713Sgirish MUTEX_EXIT(nxgep->genlock); 371344961713Sgirish return (EIO); 371444961713Sgirish } 371544961713Sgirish 371644961713Sgirish /* 371744961713Sgirish * Start timer to check the system error and tx hangs 371844961713Sgirish */ 3719678453a8Sspeer if (!isLDOMguest(nxgep)) 3720678453a8Sspeer nxgep->nxge_timerid = nxge_start_timer(nxgep, 3721678453a8Sspeer nxge_check_hw_state, NXGE_CHECK_TIMER); 3722e759c33aSMichael Speer #if defined(sun4v) 3723678453a8Sspeer else 3724678453a8Sspeer nxge_hio_start_timer(nxgep); 3725678453a8Sspeer #endif 372644961713Sgirish 3727a3c5bd6dSspeer nxgep->link_notify = B_TRUE; 372844961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STARTED; 372944961713Sgirish 3730e759c33aSMichael Speer /* 3731e759c33aSMichael Speer * Let the global lock go, since we are intialized. 3732e759c33aSMichael Speer */ 373344961713Sgirish MUTEX_EXIT(nxgep->genlock); 3734e759c33aSMichael Speer 3735e759c33aSMichael Speer /* 3736e759c33aSMichael Speer * Let the MAC start receiving packets, now that 3737e759c33aSMichael Speer * we are initialized. 3738e759c33aSMichael Speer */ 3739e759c33aSMichael Speer if (!isLDOMguest(nxgep)) { 3740e759c33aSMichael Speer if (nxge_rx_mac_enable(nxgep) != NXGE_OK) { 3741e759c33aSMichael Speer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3742e759c33aSMichael Speer "<== nxge_m_start: enable of RX mac failed")); 3743e759c33aSMichael Speer return (EIO); 3744e759c33aSMichael Speer } 3745e759c33aSMichael Speer 3746e759c33aSMichael Speer /* 3747e759c33aSMichael Speer * Enable hardware interrupts. 3748e759c33aSMichael Speer */ 3749e759c33aSMichael Speer nxge_intr_hw_enable(nxgep); 3750e759c33aSMichael Speer } 3751e759c33aSMichael Speer #if defined(sun4v) 3752e759c33aSMichael Speer else { 3753e759c33aSMichael Speer /* 3754e759c33aSMichael Speer * In guest domain we enable RDCs and their interrupts as 3755e759c33aSMichael Speer * the last step. 3756e759c33aSMichael Speer */ 3757e759c33aSMichael Speer if (nxge_hio_rdc_enable(nxgep) != NXGE_OK) { 3758e759c33aSMichael Speer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3759e759c33aSMichael Speer "<== nxge_m_start: enable of RDCs failed")); 3760e759c33aSMichael Speer return (EIO); 3761e759c33aSMichael Speer } 3762e759c33aSMichael Speer 3763e759c33aSMichael Speer if (nxge_hio_rdc_intr_arm(nxgep, B_TRUE) != NXGE_OK) { 3764e759c33aSMichael Speer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3765e759c33aSMichael Speer "<== nxge_m_start: intrs enable for RDCs failed")); 3766e759c33aSMichael Speer return (EIO); 3767e759c33aSMichael Speer } 3768e759c33aSMichael Speer } 3769e759c33aSMichael Speer #endif 377044961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_start")); 377144961713Sgirish return (0); 377244961713Sgirish } 377344961713Sgirish 3774da14cebeSEric Cheng static boolean_t 3775da14cebeSEric Cheng nxge_check_groups_stopped(p_nxge_t nxgep) 3776da14cebeSEric Cheng { 3777da14cebeSEric Cheng int i; 3778da14cebeSEric Cheng 3779da14cebeSEric Cheng for (i = 0; i < NXGE_MAX_RDC_GROUPS; i++) { 3780da14cebeSEric Cheng if (nxgep->rx_hio_groups[i].started) 3781da14cebeSEric Cheng return (B_FALSE); 3782da14cebeSEric Cheng } 3783da14cebeSEric Cheng 3784da14cebeSEric Cheng return (B_TRUE); 3785da14cebeSEric Cheng } 3786da14cebeSEric Cheng 378744961713Sgirish /* 378844961713Sgirish * nxge_m_stop(): stop transmitting and receiving. 378944961713Sgirish */ 379044961713Sgirish static void 379144961713Sgirish nxge_m_stop(void *arg) 379244961713Sgirish { 379344961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 3794da14cebeSEric Cheng boolean_t groups_stopped; 379544961713Sgirish 379644961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_stop")); 379744961713Sgirish 3798e759c33aSMichael Speer /* 3799e759c33aSMichael Speer * Are the groups stopped? 3800e759c33aSMichael Speer */ 3801da14cebeSEric Cheng groups_stopped = nxge_check_groups_stopped(nxgep); 3802e759c33aSMichael Speer ASSERT(groups_stopped == B_TRUE); 3803da14cebeSEric Cheng if (!groups_stopped) { 3804da14cebeSEric Cheng cmn_err(CE_WARN, "nxge(%d): groups are not stopped!\n", 3805da14cebeSEric Cheng nxgep->instance); 3806da14cebeSEric Cheng return; 3807da14cebeSEric Cheng } 3808da14cebeSEric Cheng 3809e759c33aSMichael Speer if (!isLDOMguest(nxgep)) { 3810e759c33aSMichael Speer /* 3811e759c33aSMichael Speer * Disable the RX mac. 3812e759c33aSMichael Speer */ 3813e759c33aSMichael Speer (void) nxge_rx_mac_disable(nxgep); 3814e759c33aSMichael Speer 3815e759c33aSMichael Speer /* 3816e759c33aSMichael Speer * Wait for the IPP to drain. 3817e759c33aSMichael Speer */ 3818e759c33aSMichael Speer (void) nxge_ipp_drain(nxgep); 3819e759c33aSMichael Speer 3820e759c33aSMichael Speer /* 3821e759c33aSMichael Speer * Disable hardware interrupts. 3822e759c33aSMichael Speer */ 3823e759c33aSMichael Speer nxge_intr_hw_disable(nxgep); 3824e759c33aSMichael Speer } 3825e759c33aSMichael Speer #if defined(sun4v) 3826e759c33aSMichael Speer else { 3827e759c33aSMichael Speer (void) nxge_hio_rdc_intr_arm(nxgep, B_FALSE); 3828e759c33aSMichael Speer } 3829e759c33aSMichael Speer #endif 3830e759c33aSMichael Speer 3831e759c33aSMichael Speer /* 3832e759c33aSMichael Speer * Grab the global lock. 3833e759c33aSMichael Speer */ 3834d7cf53fcSmisaki Miyashita MUTEX_ENTER(nxgep->genlock); 3835d7cf53fcSmisaki Miyashita 3836e759c33aSMichael Speer nxgep->nxge_mac_state = NXGE_MAC_STOPPING; 383744961713Sgirish if (nxgep->nxge_timerid) { 383844961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 383944961713Sgirish nxgep->nxge_timerid = 0; 384044961713Sgirish } 3841a3c5bd6dSspeer 3842e759c33aSMichael Speer /* 3843e759c33aSMichael Speer * Clean up. 3844e759c33aSMichael Speer */ 384544961713Sgirish nxge_uninit(nxgep); 384644961713Sgirish 384744961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STOPPED; 384844961713Sgirish 3849e759c33aSMichael Speer /* 3850e759c33aSMichael Speer * Let go of the global lock. 3851e759c33aSMichael Speer */ 385244961713Sgirish MUTEX_EXIT(nxgep->genlock); 385344961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_stop")); 385444961713Sgirish } 385544961713Sgirish 385644961713Sgirish static int 385744961713Sgirish nxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 385844961713Sgirish { 385944961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 386044961713Sgirish struct ether_addr addrp; 386144961713Sgirish 386244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38634045d941Ssowmini "==> nxge_m_multicst: add %d", add)); 386444961713Sgirish 386544961713Sgirish bcopy(mca, (uint8_t *)&addrp, ETHERADDRL); 386644961713Sgirish if (add) { 386744961713Sgirish if (nxge_add_mcast_addr(nxgep, &addrp)) { 386844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 38694045d941Ssowmini "<== nxge_m_multicst: add multicast failed")); 387044961713Sgirish return (EINVAL); 387144961713Sgirish } 387244961713Sgirish } else { 387344961713Sgirish if (nxge_del_mcast_addr(nxgep, &addrp)) { 387444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 38754045d941Ssowmini "<== nxge_m_multicst: del multicast failed")); 387644961713Sgirish return (EINVAL); 387744961713Sgirish } 387844961713Sgirish } 387944961713Sgirish 388044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_multicst")); 388144961713Sgirish 388244961713Sgirish return (0); 388344961713Sgirish } 388444961713Sgirish 388544961713Sgirish static int 388644961713Sgirish nxge_m_promisc(void *arg, boolean_t on) 388744961713Sgirish { 388844961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 388944961713Sgirish 389044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38914045d941Ssowmini "==> nxge_m_promisc: on %d", on)); 389244961713Sgirish 389344961713Sgirish if (nxge_set_promisc(nxgep, on)) { 389444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 38954045d941Ssowmini "<== nxge_m_promisc: set promisc failed")); 389644961713Sgirish return (EINVAL); 389744961713Sgirish } 389844961713Sgirish 389944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 39004045d941Ssowmini "<== nxge_m_promisc: on %d", on)); 390144961713Sgirish 390244961713Sgirish return (0); 390344961713Sgirish } 390444961713Sgirish 390544961713Sgirish static void 390644961713Sgirish nxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 390744961713Sgirish { 390844961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 390956d930aeSspeer struct iocblk *iocp; 391044961713Sgirish boolean_t need_privilege; 391144961713Sgirish int err; 391244961713Sgirish int cmd; 391344961713Sgirish 391444961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl")); 391544961713Sgirish 391644961713Sgirish iocp = (struct iocblk *)mp->b_rptr; 391744961713Sgirish iocp->ioc_error = 0; 391844961713Sgirish need_privilege = B_TRUE; 391944961713Sgirish cmd = iocp->ioc_cmd; 392044961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl: cmd 0x%08x", cmd)); 392144961713Sgirish switch (cmd) { 392244961713Sgirish default: 392344961713Sgirish miocnak(wq, mp, 0, EINVAL); 392444961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl: invalid")); 392544961713Sgirish return; 392644961713Sgirish 392744961713Sgirish case LB_GET_INFO_SIZE: 392844961713Sgirish case LB_GET_INFO: 392944961713Sgirish case LB_GET_MODE: 393044961713Sgirish need_privilege = B_FALSE; 393144961713Sgirish break; 393244961713Sgirish case LB_SET_MODE: 393344961713Sgirish break; 393444961713Sgirish 393544961713Sgirish 393644961713Sgirish case NXGE_GET_MII: 393744961713Sgirish case NXGE_PUT_MII: 393844961713Sgirish case NXGE_GET64: 393944961713Sgirish case NXGE_PUT64: 394044961713Sgirish case NXGE_GET_TX_RING_SZ: 394144961713Sgirish case NXGE_GET_TX_DESC: 394244961713Sgirish case NXGE_TX_SIDE_RESET: 394344961713Sgirish case NXGE_RX_SIDE_RESET: 394444961713Sgirish case NXGE_GLOBAL_RESET: 394544961713Sgirish case NXGE_RESET_MAC: 394644961713Sgirish case NXGE_TX_REGS_DUMP: 394744961713Sgirish case NXGE_RX_REGS_DUMP: 394844961713Sgirish case NXGE_INT_REGS_DUMP: 394944961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 395044961713Sgirish case NXGE_PUT_TCAM: 395144961713Sgirish case NXGE_GET_TCAM: 395244961713Sgirish case NXGE_RTRACE: 395344961713Sgirish case NXGE_RDUMP: 395444961713Sgirish 395544961713Sgirish need_privilege = B_FALSE; 395644961713Sgirish break; 395744961713Sgirish case NXGE_INJECT_ERR: 395844961713Sgirish cmn_err(CE_NOTE, "!nxge_m_ioctl: Inject error\n"); 395944961713Sgirish nxge_err_inject(nxgep, wq, mp); 396044961713Sgirish break; 396144961713Sgirish } 396244961713Sgirish 396344961713Sgirish if (need_privilege) { 396456d930aeSspeer err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 396544961713Sgirish if (err != 0) { 396644961713Sgirish miocnak(wq, mp, 0, err); 396744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 39684045d941Ssowmini "<== nxge_m_ioctl: no priv")); 396944961713Sgirish return; 397044961713Sgirish } 397144961713Sgirish } 397244961713Sgirish 397344961713Sgirish switch (cmd) { 397444961713Sgirish 397544961713Sgirish case LB_GET_MODE: 397644961713Sgirish case LB_SET_MODE: 397744961713Sgirish case LB_GET_INFO_SIZE: 397844961713Sgirish case LB_GET_INFO: 397944961713Sgirish nxge_loopback_ioctl(nxgep, wq, mp, iocp); 398044961713Sgirish break; 398144961713Sgirish 398244961713Sgirish case NXGE_GET_MII: 398344961713Sgirish case NXGE_PUT_MII: 398444961713Sgirish case NXGE_PUT_TCAM: 398544961713Sgirish case NXGE_GET_TCAM: 398644961713Sgirish case NXGE_GET64: 398744961713Sgirish case NXGE_PUT64: 398844961713Sgirish case NXGE_GET_TX_RING_SZ: 398944961713Sgirish case NXGE_GET_TX_DESC: 399044961713Sgirish case NXGE_TX_SIDE_RESET: 399144961713Sgirish case NXGE_RX_SIDE_RESET: 399244961713Sgirish case NXGE_GLOBAL_RESET: 399344961713Sgirish case NXGE_RESET_MAC: 399444961713Sgirish case NXGE_TX_REGS_DUMP: 399544961713Sgirish case NXGE_RX_REGS_DUMP: 399644961713Sgirish case NXGE_INT_REGS_DUMP: 399744961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 399844961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 39994045d941Ssowmini "==> nxge_m_ioctl: cmd 0x%x", cmd)); 400044961713Sgirish nxge_hw_ioctl(nxgep, wq, mp, iocp); 400144961713Sgirish break; 400244961713Sgirish } 400344961713Sgirish 400444961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl")); 400544961713Sgirish } 400644961713Sgirish 400744961713Sgirish extern void nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count); 400844961713Sgirish 4009678453a8Sspeer void 4010da14cebeSEric Cheng nxge_mmac_kstat_update(p_nxge_t nxgep, int slot, boolean_t factory) 401158324dfcSspeer { 401258324dfcSspeer p_nxge_mmac_stats_t mmac_stats; 401358324dfcSspeer int i; 401458324dfcSspeer nxge_mmac_t *mmac_info; 401558324dfcSspeer 401658324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 401758324dfcSspeer 401858324dfcSspeer mmac_stats = &nxgep->statsp->mmac_stats; 401958324dfcSspeer mmac_stats->mmac_max_cnt = mmac_info->num_mmac; 402058324dfcSspeer mmac_stats->mmac_avail_cnt = mmac_info->naddrfree; 402158324dfcSspeer 402258324dfcSspeer for (i = 0; i < ETHERADDRL; i++) { 402358324dfcSspeer if (factory) { 402458324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 40254045d941Ssowmini = mmac_info->factory_mac_pool[slot][ 40264045d941Ssowmini (ETHERADDRL-1) - i]; 402758324dfcSspeer } else { 402858324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 40294045d941Ssowmini = mmac_info->mac_pool[slot].addr[ 40304045d941Ssowmini (ETHERADDRL - 1) - i]; 403158324dfcSspeer } 403258324dfcSspeer } 403358324dfcSspeer } 403458324dfcSspeer 403558324dfcSspeer /* 403658324dfcSspeer * nxge_altmac_set() -- Set an alternate MAC address 403758324dfcSspeer */ 4038da14cebeSEric Cheng static int 4039da14cebeSEric Cheng nxge_altmac_set(p_nxge_t nxgep, uint8_t *maddr, int slot, 4040da14cebeSEric Cheng int rdctbl, boolean_t usetbl) 404158324dfcSspeer { 404258324dfcSspeer uint8_t addrn; 404358324dfcSspeer uint8_t portn; 404458324dfcSspeer npi_mac_addr_t altmac; 40457b9fa28bSspeer hostinfo_t mac_rdc; 40467b9fa28bSspeer p_nxge_class_pt_cfg_t clscfgp; 404758324dfcSspeer 4048da14cebeSEric Cheng 404958324dfcSspeer altmac.w2 = ((uint16_t)maddr[0] << 8) | ((uint16_t)maddr[1] & 0x0ff); 405058324dfcSspeer altmac.w1 = ((uint16_t)maddr[2] << 8) | ((uint16_t)maddr[3] & 0x0ff); 405158324dfcSspeer altmac.w0 = ((uint16_t)maddr[4] << 8) | ((uint16_t)maddr[5] & 0x0ff); 405258324dfcSspeer 405358324dfcSspeer portn = nxgep->mac.portnum; 405458324dfcSspeer addrn = (uint8_t)slot - 1; 405558324dfcSspeer 4056da14cebeSEric Cheng if (npi_mac_altaddr_entry(nxgep->npi_handle, OP_SET, 4057da14cebeSEric Cheng nxgep->function_num, addrn, &altmac) != NPI_SUCCESS) 405858324dfcSspeer return (EIO); 40597b9fa28bSspeer 40607b9fa28bSspeer /* 40617b9fa28bSspeer * Set the rdc table number for the host info entry 40627b9fa28bSspeer * for this mac address slot. 40637b9fa28bSspeer */ 40647b9fa28bSspeer clscfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config; 40657b9fa28bSspeer mac_rdc.value = 0; 4066da14cebeSEric Cheng if (usetbl) 4067da14cebeSEric Cheng mac_rdc.bits.w0.rdc_tbl_num = rdctbl; 4068da14cebeSEric Cheng else 4069da14cebeSEric Cheng mac_rdc.bits.w0.rdc_tbl_num = 4070da14cebeSEric Cheng clscfgp->mac_host_info[addrn].rdctbl; 40717b9fa28bSspeer mac_rdc.bits.w0.mac_pref = clscfgp->mac_host_info[addrn].mpr_npr; 40727b9fa28bSspeer 40737b9fa28bSspeer if (npi_mac_hostinfo_entry(nxgep->npi_handle, OP_SET, 40747b9fa28bSspeer nxgep->function_num, addrn, &mac_rdc) != NPI_SUCCESS) { 40757b9fa28bSspeer return (EIO); 40767b9fa28bSspeer } 40777b9fa28bSspeer 407858324dfcSspeer /* 407958324dfcSspeer * Enable comparison with the alternate MAC address. 408058324dfcSspeer * While the first alternate addr is enabled by bit 1 of register 408158324dfcSspeer * BMAC_ALTAD_CMPEN, it is enabled by bit 0 of register 408258324dfcSspeer * XMAC_ADDR_CMPEN, so slot needs to be converted to addrn 408358324dfcSspeer * accordingly before calling npi_mac_altaddr_entry. 408458324dfcSspeer */ 408558324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 408658324dfcSspeer addrn = (uint8_t)slot - 1; 408758324dfcSspeer else 408858324dfcSspeer addrn = (uint8_t)slot; 408958324dfcSspeer 4090da14cebeSEric Cheng if (npi_mac_altaddr_enable(nxgep->npi_handle, 4091da14cebeSEric Cheng nxgep->function_num, addrn) != NPI_SUCCESS) { 409258324dfcSspeer return (EIO); 4093da14cebeSEric Cheng } 4094da14cebeSEric Cheng 409558324dfcSspeer return (0); 409658324dfcSspeer } 409758324dfcSspeer 409858324dfcSspeer /* 4099da14cebeSEric Cheng * nxeg_m_mmac_add_g() - find an unused address slot, set the address 410058324dfcSspeer * value to the one specified, enable the port to start filtering on 410158324dfcSspeer * the new MAC address. Returns 0 on success. 410258324dfcSspeer */ 4103678453a8Sspeer int 4104da14cebeSEric Cheng nxge_m_mmac_add_g(void *arg, const uint8_t *maddr, int rdctbl, 4105da14cebeSEric Cheng boolean_t usetbl) 410658324dfcSspeer { 410758324dfcSspeer p_nxge_t nxgep = arg; 4108da14cebeSEric Cheng int slot; 410958324dfcSspeer nxge_mmac_t *mmac_info; 411058324dfcSspeer int err; 411158324dfcSspeer nxge_status_t status; 411258324dfcSspeer 411358324dfcSspeer mutex_enter(nxgep->genlock); 411458324dfcSspeer 411558324dfcSspeer /* 411658324dfcSspeer * Make sure that nxge is initialized, if _start() has 411758324dfcSspeer * not been called. 411858324dfcSspeer */ 411958324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 412058324dfcSspeer status = nxge_init(nxgep); 412158324dfcSspeer if (status != NXGE_OK) { 412258324dfcSspeer mutex_exit(nxgep->genlock); 412358324dfcSspeer return (ENXIO); 412458324dfcSspeer } 412558324dfcSspeer } 412658324dfcSspeer 412758324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 412858324dfcSspeer if (mmac_info->naddrfree == 0) { 412958324dfcSspeer mutex_exit(nxgep->genlock); 413058324dfcSspeer return (ENOSPC); 413158324dfcSspeer } 4132da14cebeSEric Cheng 413358324dfcSspeer /* 413458324dfcSspeer * Search for the first available slot. Because naddrfree 413558324dfcSspeer * is not zero, we are guaranteed to find one. 413658324dfcSspeer * Each of the first two ports of Neptune has 16 alternate 4137678453a8Sspeer * MAC slots but only the first 7 (of 15) slots have assigned factory 413858324dfcSspeer * MAC addresses. We first search among the slots without bundled 413958324dfcSspeer * factory MACs. If we fail to find one in that range, then we 414058324dfcSspeer * search the slots with bundled factory MACs. A factory MAC 414158324dfcSspeer * will be wasted while the slot is used with a user MAC address. 414258324dfcSspeer * But the slot could be used by factory MAC again after calling 414358324dfcSspeer * nxge_m_mmac_remove and nxge_m_mmac_reserve. 414458324dfcSspeer */ 4145da14cebeSEric Cheng for (slot = 0; slot <= mmac_info->num_mmac; slot++) { 4146da14cebeSEric Cheng if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 4147da14cebeSEric Cheng break; 414858324dfcSspeer } 4149da14cebeSEric Cheng 415058324dfcSspeer ASSERT(slot <= mmac_info->num_mmac); 4151e857d0f3SMichael Speer 4152da14cebeSEric Cheng if ((err = nxge_altmac_set(nxgep, (uint8_t *)maddr, slot, rdctbl, 4153da14cebeSEric Cheng usetbl)) != 0) { 415458324dfcSspeer mutex_exit(nxgep->genlock); 415558324dfcSspeer return (err); 415658324dfcSspeer } 4157e857d0f3SMichael Speer 4158da14cebeSEric Cheng bcopy(maddr, mmac_info->mac_pool[slot].addr, ETHERADDRL); 415958324dfcSspeer mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED; 416058324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR; 416158324dfcSspeer mmac_info->naddrfree--; 416258324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 416358324dfcSspeer 416458324dfcSspeer mutex_exit(nxgep->genlock); 416558324dfcSspeer return (0); 416658324dfcSspeer } 416758324dfcSspeer 416858324dfcSspeer /* 416958324dfcSspeer * Remove the specified mac address and update the HW not to filter 417058324dfcSspeer * the mac address anymore. 417158324dfcSspeer */ 4172678453a8Sspeer int 4173da14cebeSEric Cheng nxge_m_mmac_remove(void *arg, int slot) 417458324dfcSspeer { 417558324dfcSspeer p_nxge_t nxgep = arg; 417658324dfcSspeer nxge_mmac_t *mmac_info; 417758324dfcSspeer uint8_t addrn; 417858324dfcSspeer uint8_t portn; 417958324dfcSspeer int err = 0; 418058324dfcSspeer nxge_status_t status; 418158324dfcSspeer 418258324dfcSspeer mutex_enter(nxgep->genlock); 418358324dfcSspeer 418458324dfcSspeer /* 418558324dfcSspeer * Make sure that nxge is initialized, if _start() has 418658324dfcSspeer * not been called. 418758324dfcSspeer */ 418858324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 418958324dfcSspeer status = nxge_init(nxgep); 419058324dfcSspeer if (status != NXGE_OK) { 419158324dfcSspeer mutex_exit(nxgep->genlock); 419258324dfcSspeer return (ENXIO); 419358324dfcSspeer } 419458324dfcSspeer } 419558324dfcSspeer 419658324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 419758324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 419858324dfcSspeer mutex_exit(nxgep->genlock); 419958324dfcSspeer return (EINVAL); 420058324dfcSspeer } 420158324dfcSspeer 420258324dfcSspeer portn = nxgep->mac.portnum; 420358324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 420458324dfcSspeer addrn = (uint8_t)slot - 1; 420558324dfcSspeer else 420658324dfcSspeer addrn = (uint8_t)slot; 420758324dfcSspeer 420858324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 420958324dfcSspeer if (npi_mac_altaddr_disable(nxgep->npi_handle, portn, addrn) 42104045d941Ssowmini == NPI_SUCCESS) { 421158324dfcSspeer mmac_info->naddrfree++; 421258324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_SLOT_USED; 421358324dfcSspeer /* 421458324dfcSspeer * Regardless if the MAC we just stopped filtering 421558324dfcSspeer * is a user addr or a facory addr, we must set 421658324dfcSspeer * the MMAC_VENDOR_ADDR flag if this slot has an 421758324dfcSspeer * associated factory MAC to indicate that a factory 421858324dfcSspeer * MAC is available. 421958324dfcSspeer */ 422058324dfcSspeer if (slot <= mmac_info->num_factory_mmac) { 422158324dfcSspeer mmac_info->mac_pool[slot].flags 42224045d941Ssowmini |= MMAC_VENDOR_ADDR; 422358324dfcSspeer } 422458324dfcSspeer /* 422558324dfcSspeer * Clear mac_pool[slot].addr so that kstat shows 0 422658324dfcSspeer * alternate MAC address if the slot is not used. 422758324dfcSspeer * (But nxge_m_mmac_get returns the factory MAC even 422858324dfcSspeer * when the slot is not used!) 422958324dfcSspeer */ 423058324dfcSspeer bzero(mmac_info->mac_pool[slot].addr, ETHERADDRL); 423158324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 423258324dfcSspeer } else { 423358324dfcSspeer err = EIO; 423458324dfcSspeer } 423558324dfcSspeer } else { 423658324dfcSspeer err = EINVAL; 423758324dfcSspeer } 423858324dfcSspeer 423958324dfcSspeer mutex_exit(nxgep->genlock); 424058324dfcSspeer return (err); 424158324dfcSspeer } 424258324dfcSspeer 424358324dfcSspeer /* 4244da14cebeSEric Cheng * The callback to query all the factory addresses. naddr must be the same as 4245da14cebeSEric Cheng * the number of factory addresses (returned by MAC_CAPAB_MULTIFACTADDR), and 4246da14cebeSEric Cheng * mcm_addr is the space allocated for keep all the addresses, whose size is 4247da14cebeSEric Cheng * naddr * MAXMACADDRLEN. 424858324dfcSspeer */ 4249da14cebeSEric Cheng static void 4250da14cebeSEric Cheng nxge_m_getfactaddr(void *arg, uint_t naddr, uint8_t *addr) 425158324dfcSspeer { 4252da14cebeSEric Cheng nxge_t *nxgep = arg; 4253da14cebeSEric Cheng nxge_mmac_t *mmac_info; 4254da14cebeSEric Cheng int i; 425558324dfcSspeer 425658324dfcSspeer mutex_enter(nxgep->genlock); 425758324dfcSspeer 425858324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 4259da14cebeSEric Cheng ASSERT(naddr == mmac_info->num_factory_mmac); 426058324dfcSspeer 4261da14cebeSEric Cheng for (i = 0; i < naddr; i++) { 4262da14cebeSEric Cheng bcopy(mmac_info->factory_mac_pool[i + 1], 4263da14cebeSEric Cheng addr + i * MAXMACADDRLEN, ETHERADDRL); 426458324dfcSspeer } 426558324dfcSspeer 426658324dfcSspeer mutex_exit(nxgep->genlock); 426758324dfcSspeer } 426858324dfcSspeer 4269da14cebeSEric Cheng 427044961713Sgirish static boolean_t 427144961713Sgirish nxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 427244961713Sgirish { 427358324dfcSspeer nxge_t *nxgep = arg; 427458324dfcSspeer uint32_t *txflags = cap_data; 427544961713Sgirish 427658324dfcSspeer switch (cap) { 427758324dfcSspeer case MAC_CAPAB_HCKSUM: 4278678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4279b4d05839Sml "==> nxge_m_getcapab: checksum %d", nxge_cksum_offload)); 4280b4d05839Sml if (nxge_cksum_offload <= 1) { 4281678453a8Sspeer *txflags = HCKSUM_INET_PARTIAL; 4282678453a8Sspeer } 428344961713Sgirish break; 4284678453a8Sspeer 4285da14cebeSEric Cheng case MAC_CAPAB_MULTIFACTADDR: { 4286da14cebeSEric Cheng mac_capab_multifactaddr_t *mfacp = cap_data; 428744961713Sgirish 428863f531d1SSriharsha Basavapatna if (!isLDOMguest(nxgep)) { 428963f531d1SSriharsha Basavapatna mutex_enter(nxgep->genlock); 429063f531d1SSriharsha Basavapatna mfacp->mcm_naddr = 429163f531d1SSriharsha Basavapatna nxgep->nxge_mmac_info.num_factory_mmac; 429263f531d1SSriharsha Basavapatna mfacp->mcm_getaddr = nxge_m_getfactaddr; 429363f531d1SSriharsha Basavapatna mutex_exit(nxgep->genlock); 429463f531d1SSriharsha Basavapatna } 429558324dfcSspeer break; 4296da14cebeSEric Cheng } 4297678453a8Sspeer 429830ac2e7bSml case MAC_CAPAB_LSO: { 429930ac2e7bSml mac_capab_lso_t *cap_lso = cap_data; 430030ac2e7bSml 43013d16f8e7Sml if (nxgep->soft_lso_enable) { 4302b4d05839Sml if (nxge_cksum_offload <= 1) { 4303b4d05839Sml cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 4304b4d05839Sml if (nxge_lso_max > NXGE_LSO_MAXLEN) { 4305b4d05839Sml nxge_lso_max = NXGE_LSO_MAXLEN; 4306b4d05839Sml } 4307b4d05839Sml cap_lso->lso_basic_tcp_ipv4.lso_max = 4308b4d05839Sml nxge_lso_max; 430930ac2e7bSml } 431030ac2e7bSml break; 431130ac2e7bSml } else { 431230ac2e7bSml return (B_FALSE); 431330ac2e7bSml } 431430ac2e7bSml } 431530ac2e7bSml 4316678453a8Sspeer case MAC_CAPAB_RINGS: { 4317da14cebeSEric Cheng mac_capab_rings_t *cap_rings = cap_data; 4318da14cebeSEric Cheng p_nxge_hw_pt_cfg_t p_cfgp = &nxgep->pt_config.hw_config; 4319678453a8Sspeer 4320da14cebeSEric Cheng mutex_enter(nxgep->genlock); 4321da14cebeSEric Cheng if (cap_rings->mr_type == MAC_RING_TYPE_RX) { 432263f531d1SSriharsha Basavapatna if (isLDOMguest(nxgep)) { 432363f531d1SSriharsha Basavapatna cap_rings->mr_group_type = 432463f531d1SSriharsha Basavapatna MAC_GROUP_TYPE_STATIC; 432563f531d1SSriharsha Basavapatna cap_rings->mr_rnum = 432663f531d1SSriharsha Basavapatna NXGE_HIO_SHARE_MAX_CHANNELS; 432763f531d1SSriharsha Basavapatna cap_rings->mr_rget = nxge_fill_ring; 432863f531d1SSriharsha Basavapatna cap_rings->mr_gnum = 1; 432963f531d1SSriharsha Basavapatna cap_rings->mr_gget = nxge_hio_group_get; 433063f531d1SSriharsha Basavapatna cap_rings->mr_gaddring = NULL; 433163f531d1SSriharsha Basavapatna cap_rings->mr_gremring = NULL; 433263f531d1SSriharsha Basavapatna } else { 433363f531d1SSriharsha Basavapatna /* 433463f531d1SSriharsha Basavapatna * Service Domain. 433563f531d1SSriharsha Basavapatna */ 433663f531d1SSriharsha Basavapatna cap_rings->mr_group_type = 433763f531d1SSriharsha Basavapatna MAC_GROUP_TYPE_DYNAMIC; 433863f531d1SSriharsha Basavapatna cap_rings->mr_rnum = p_cfgp->max_rdcs; 433963f531d1SSriharsha Basavapatna cap_rings->mr_rget = nxge_fill_ring; 434063f531d1SSriharsha Basavapatna cap_rings->mr_gnum = p_cfgp->max_rdc_grpids; 434163f531d1SSriharsha Basavapatna cap_rings->mr_gget = nxge_hio_group_get; 434263f531d1SSriharsha Basavapatna cap_rings->mr_gaddring = nxge_group_add_ring; 434363f531d1SSriharsha Basavapatna cap_rings->mr_gremring = nxge_group_rem_ring; 434463f531d1SSriharsha Basavapatna } 4345da14cebeSEric Cheng 4346da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, RX_CTL, 4347da14cebeSEric Cheng "==> nxge_m_getcapab: rx nrings[%d] ngroups[%d]", 4348da14cebeSEric Cheng p_cfgp->max_rdcs, p_cfgp->max_rdc_grpids)); 4349da14cebeSEric Cheng } else { 435063f531d1SSriharsha Basavapatna /* 435163f531d1SSriharsha Basavapatna * TX Rings. 435263f531d1SSriharsha Basavapatna */ 435363f531d1SSriharsha Basavapatna if (isLDOMguest(nxgep)) { 435463f531d1SSriharsha Basavapatna cap_rings->mr_group_type = 435563f531d1SSriharsha Basavapatna MAC_GROUP_TYPE_STATIC; 435663f531d1SSriharsha Basavapatna cap_rings->mr_rnum = 435763f531d1SSriharsha Basavapatna NXGE_HIO_SHARE_MAX_CHANNELS; 435863f531d1SSriharsha Basavapatna cap_rings->mr_rget = nxge_fill_ring; 435963f531d1SSriharsha Basavapatna cap_rings->mr_gnum = 0; 436063f531d1SSriharsha Basavapatna cap_rings->mr_gget = NULL; 436163f531d1SSriharsha Basavapatna cap_rings->mr_gaddring = NULL; 436263f531d1SSriharsha Basavapatna cap_rings->mr_gremring = NULL; 436363f531d1SSriharsha Basavapatna } else { 436463f531d1SSriharsha Basavapatna /* 436563f531d1SSriharsha Basavapatna * Service Domain. 436663f531d1SSriharsha Basavapatna */ 436763f531d1SSriharsha Basavapatna cap_rings->mr_group_type = 436863f531d1SSriharsha Basavapatna MAC_GROUP_TYPE_DYNAMIC; 436963f531d1SSriharsha Basavapatna cap_rings->mr_rnum = p_cfgp->tdc.count; 437063f531d1SSriharsha Basavapatna cap_rings->mr_rget = nxge_fill_ring; 437163f531d1SSriharsha Basavapatna 437263f531d1SSriharsha Basavapatna /* 437363f531d1SSriharsha Basavapatna * Share capable. 437463f531d1SSriharsha Basavapatna * 437563f531d1SSriharsha Basavapatna * Do not report the default group: hence -1 437663f531d1SSriharsha Basavapatna */ 4377da14cebeSEric Cheng cap_rings->mr_gnum = 4378da14cebeSEric Cheng NXGE_MAX_TDC_GROUPS / nxgep->nports - 1; 437963f531d1SSriharsha Basavapatna cap_rings->mr_gget = nxge_hio_group_get; 438063f531d1SSriharsha Basavapatna cap_rings->mr_gaddring = nxge_group_add_ring; 438163f531d1SSriharsha Basavapatna cap_rings->mr_gremring = nxge_group_rem_ring; 4382678453a8Sspeer } 4383da14cebeSEric Cheng 4384da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, TX_CTL, 4385da14cebeSEric Cheng "==> nxge_m_getcapab: tx rings # of rings %d", 4386da14cebeSEric Cheng p_cfgp->tdc.count)); 4387da14cebeSEric Cheng } 4388da14cebeSEric Cheng mutex_exit(nxgep->genlock); 4389678453a8Sspeer break; 4390678453a8Sspeer } 4391678453a8Sspeer 4392da14cebeSEric Cheng #if defined(sun4v) 4393678453a8Sspeer case MAC_CAPAB_SHARES: { 4394678453a8Sspeer mac_capab_share_t *mshares = (mac_capab_share_t *)cap_data; 4395678453a8Sspeer 4396678453a8Sspeer /* 4397678453a8Sspeer * Only the service domain driver responds to 4398678453a8Sspeer * this capability request. 4399678453a8Sspeer */ 4400da14cebeSEric Cheng mutex_enter(nxgep->genlock); 4401678453a8Sspeer if (isLDOMservice(nxgep)) { 4402678453a8Sspeer mshares->ms_snum = 3; 4403678453a8Sspeer mshares->ms_handle = (void *)nxgep; 4404678453a8Sspeer mshares->ms_salloc = nxge_hio_share_alloc; 4405678453a8Sspeer mshares->ms_sfree = nxge_hio_share_free; 4406da14cebeSEric Cheng mshares->ms_sadd = nxge_hio_share_add_group; 4407da14cebeSEric Cheng mshares->ms_sremove = nxge_hio_share_rem_group; 4408678453a8Sspeer mshares->ms_squery = nxge_hio_share_query; 4409da14cebeSEric Cheng mshares->ms_sbind = nxge_hio_share_bind; 4410da14cebeSEric Cheng mshares->ms_sunbind = nxge_hio_share_unbind; 4411da14cebeSEric Cheng mutex_exit(nxgep->genlock); 4412da14cebeSEric Cheng } else { 4413da14cebeSEric Cheng mutex_exit(nxgep->genlock); 4414678453a8Sspeer return (B_FALSE); 4415da14cebeSEric Cheng } 4416678453a8Sspeer break; 4417678453a8Sspeer } 4418678453a8Sspeer #endif 441944961713Sgirish default: 442044961713Sgirish return (B_FALSE); 442144961713Sgirish } 442244961713Sgirish return (B_TRUE); 442344961713Sgirish } 442444961713Sgirish 44251bd6825cSml static boolean_t 44261bd6825cSml nxge_param_locked(mac_prop_id_t pr_num) 44271bd6825cSml { 44281bd6825cSml /* 44291bd6825cSml * All adv_* parameters are locked (read-only) while 44301bd6825cSml * the device is in any sort of loopback mode ... 44311bd6825cSml */ 44321bd6825cSml switch (pr_num) { 44333fd94f8cSam case MAC_PROP_ADV_1000FDX_CAP: 44343fd94f8cSam case MAC_PROP_EN_1000FDX_CAP: 44353fd94f8cSam case MAC_PROP_ADV_1000HDX_CAP: 44363fd94f8cSam case MAC_PROP_EN_1000HDX_CAP: 44373fd94f8cSam case MAC_PROP_ADV_100FDX_CAP: 44383fd94f8cSam case MAC_PROP_EN_100FDX_CAP: 44393fd94f8cSam case MAC_PROP_ADV_100HDX_CAP: 44403fd94f8cSam case MAC_PROP_EN_100HDX_CAP: 44413fd94f8cSam case MAC_PROP_ADV_10FDX_CAP: 44423fd94f8cSam case MAC_PROP_EN_10FDX_CAP: 44433fd94f8cSam case MAC_PROP_ADV_10HDX_CAP: 44443fd94f8cSam case MAC_PROP_EN_10HDX_CAP: 44453fd94f8cSam case MAC_PROP_AUTONEG: 44463fd94f8cSam case MAC_PROP_FLOWCTRL: 44471bd6825cSml return (B_TRUE); 44481bd6825cSml } 44491bd6825cSml return (B_FALSE); 44501bd6825cSml } 44511bd6825cSml 44521bd6825cSml /* 44531bd6825cSml * callback functions for set/get of properties 44541bd6825cSml */ 44551bd6825cSml static int 44561bd6825cSml nxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 44571bd6825cSml uint_t pr_valsize, const void *pr_val) 44581bd6825cSml { 44591bd6825cSml nxge_t *nxgep = barg; 44601bd6825cSml p_nxge_param_t param_arr; 44611bd6825cSml p_nxge_stats_t statsp; 44621bd6825cSml int err = 0; 44631bd6825cSml uint8_t val; 44641bd6825cSml uint32_t cur_mtu, new_mtu, old_framesize; 44651bd6825cSml link_flowctrl_t fl; 44661bd6825cSml 44671bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_setprop")); 44681bd6825cSml param_arr = nxgep->param_arr; 44691bd6825cSml statsp = nxgep->statsp; 44701bd6825cSml mutex_enter(nxgep->genlock); 44711bd6825cSml if (statsp->port_stats.lb_mode != nxge_lb_normal && 44721bd6825cSml nxge_param_locked(pr_num)) { 44731bd6825cSml /* 44741bd6825cSml * All adv_* parameters are locked (read-only) 44751bd6825cSml * while the device is in any sort of loopback mode. 44761bd6825cSml */ 44771bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 44781bd6825cSml "==> nxge_m_setprop: loopback mode: read only")); 44791bd6825cSml mutex_exit(nxgep->genlock); 44801bd6825cSml return (EBUSY); 44811bd6825cSml } 44821bd6825cSml 44831bd6825cSml val = *(uint8_t *)pr_val; 44841bd6825cSml switch (pr_num) { 44853fd94f8cSam case MAC_PROP_EN_1000FDX_CAP: 44861bd6825cSml nxgep->param_en_1000fdx = val; 44871bd6825cSml param_arr[param_anar_1000fdx].value = val; 44881bd6825cSml 44891bd6825cSml goto reprogram; 44901bd6825cSml 44913fd94f8cSam case MAC_PROP_EN_100FDX_CAP: 44921bd6825cSml nxgep->param_en_100fdx = val; 44931bd6825cSml param_arr[param_anar_100fdx].value = val; 44941bd6825cSml 44951bd6825cSml goto reprogram; 44961bd6825cSml 44973fd94f8cSam case MAC_PROP_EN_10FDX_CAP: 44981bd6825cSml nxgep->param_en_10fdx = val; 44991bd6825cSml param_arr[param_anar_10fdx].value = val; 45001bd6825cSml 45011bd6825cSml goto reprogram; 45021bd6825cSml 45033fd94f8cSam case MAC_PROP_EN_1000HDX_CAP: 45043fd94f8cSam case MAC_PROP_EN_100HDX_CAP: 45053fd94f8cSam case MAC_PROP_EN_10HDX_CAP: 45063fd94f8cSam case MAC_PROP_ADV_1000FDX_CAP: 45073fd94f8cSam case MAC_PROP_ADV_1000HDX_CAP: 45083fd94f8cSam case MAC_PROP_ADV_100FDX_CAP: 45093fd94f8cSam case MAC_PROP_ADV_100HDX_CAP: 45103fd94f8cSam case MAC_PROP_ADV_10FDX_CAP: 45113fd94f8cSam case MAC_PROP_ADV_10HDX_CAP: 45123fd94f8cSam case MAC_PROP_STATUS: 45133fd94f8cSam case MAC_PROP_SPEED: 45143fd94f8cSam case MAC_PROP_DUPLEX: 45151bd6825cSml err = EINVAL; /* cannot set read-only properties */ 45161bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 45171bd6825cSml "==> nxge_m_setprop: read only property %d", 45181bd6825cSml pr_num)); 45191bd6825cSml break; 45201bd6825cSml 45213fd94f8cSam case MAC_PROP_AUTONEG: 45221bd6825cSml param_arr[param_autoneg].value = val; 45231bd6825cSml 45241bd6825cSml goto reprogram; 45251bd6825cSml 45263fd94f8cSam case MAC_PROP_MTU: 45271bd6825cSml cur_mtu = nxgep->mac.default_mtu; 45281bd6825cSml bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 45291bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 45301bd6825cSml "==> nxge_m_setprop: set MTU: %d is_jumbo %d", 45311bd6825cSml new_mtu, nxgep->mac.is_jumbo)); 45321bd6825cSml 45331bd6825cSml if (new_mtu == cur_mtu) { 45341bd6825cSml err = 0; 45351bd6825cSml break; 45361bd6825cSml } 453748056c53SMichael Speer 4538afdda45fSVasumathi Sundaram - Sun Microsystems if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 4539afdda45fSVasumathi Sundaram - Sun Microsystems err = EBUSY; 4540afdda45fSVasumathi Sundaram - Sun Microsystems break; 4541afdda45fSVasumathi Sundaram - Sun Microsystems } 45421bd6825cSml 454348056c53SMichael Speer if ((new_mtu < NXGE_DEFAULT_MTU) || 454448056c53SMichael Speer (new_mtu > NXGE_MAXIMUM_MTU)) { 45451bd6825cSml err = EINVAL; 45461bd6825cSml break; 45471bd6825cSml } 45481bd6825cSml 45491bd6825cSml old_framesize = (uint32_t)nxgep->mac.maxframesize; 45501bd6825cSml nxgep->mac.maxframesize = (uint16_t) 45511bd6825cSml (new_mtu + NXGE_EHEADER_VLAN_CRC); 45521bd6825cSml if (nxge_mac_set_framesize(nxgep)) { 4553c2d37b8bSml nxgep->mac.maxframesize = 4554c2d37b8bSml (uint16_t)old_framesize; 45551bd6825cSml err = EINVAL; 45561bd6825cSml break; 45571bd6825cSml } 45581bd6825cSml 45591bd6825cSml err = mac_maxsdu_update(nxgep->mach, new_mtu); 45601bd6825cSml if (err) { 4561c2d37b8bSml nxgep->mac.maxframesize = 4562c2d37b8bSml (uint16_t)old_framesize; 45631bd6825cSml err = EINVAL; 45641bd6825cSml break; 45651bd6825cSml } 45661bd6825cSml 45671bd6825cSml nxgep->mac.default_mtu = new_mtu; 456848056c53SMichael Speer if (new_mtu > NXGE_DEFAULT_MTU) 456948056c53SMichael Speer nxgep->mac.is_jumbo = B_TRUE; 457048056c53SMichael Speer else 457148056c53SMichael Speer nxgep->mac.is_jumbo = B_FALSE; 457248056c53SMichael Speer 45731bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 45741bd6825cSml "==> nxge_m_setprop: set MTU: %d maxframe %d", 45751bd6825cSml new_mtu, nxgep->mac.maxframesize)); 45761bd6825cSml break; 45771bd6825cSml 45783fd94f8cSam case MAC_PROP_FLOWCTRL: 45791bd6825cSml bcopy(pr_val, &fl, sizeof (fl)); 45801bd6825cSml switch (fl) { 45811bd6825cSml default: 45821bd6825cSml err = EINVAL; 45831bd6825cSml break; 45841bd6825cSml 45851bd6825cSml case LINK_FLOWCTRL_NONE: 45861bd6825cSml param_arr[param_anar_pause].value = 0; 45871bd6825cSml break; 45881bd6825cSml 45891bd6825cSml case LINK_FLOWCTRL_RX: 45901bd6825cSml param_arr[param_anar_pause].value = 1; 45911bd6825cSml break; 45921bd6825cSml 45931bd6825cSml case LINK_FLOWCTRL_TX: 45941bd6825cSml case LINK_FLOWCTRL_BI: 45951bd6825cSml err = EINVAL; 45961bd6825cSml break; 45971bd6825cSml } 45981bd6825cSml 45991bd6825cSml reprogram: 46001bd6825cSml if (err == 0) { 46011bd6825cSml if (!nxge_param_link_update(nxgep)) { 46021bd6825cSml err = EINVAL; 46031bd6825cSml } 46041bd6825cSml } 46051bd6825cSml break; 46063fd94f8cSam case MAC_PROP_PRIVATE: 46071bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46081bd6825cSml "==> nxge_m_setprop: private property")); 46091bd6825cSml err = nxge_set_priv_prop(nxgep, pr_name, pr_valsize, 46101bd6825cSml pr_val); 46111bd6825cSml break; 46124045d941Ssowmini 46134045d941Ssowmini default: 46144045d941Ssowmini err = ENOTSUP; 46154045d941Ssowmini break; 46161bd6825cSml } 46171bd6825cSml 46181bd6825cSml mutex_exit(nxgep->genlock); 46191bd6825cSml 46201bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46211bd6825cSml "<== nxge_m_setprop (return %d)", err)); 46221bd6825cSml return (err); 46231bd6825cSml } 46241bd6825cSml 46251bd6825cSml static int 46261bd6825cSml nxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 4627afdda45fSVasumathi Sundaram - Sun Microsystems uint_t pr_flags, uint_t pr_valsize, void *pr_val, uint_t *perm) 46281bd6825cSml { 46291bd6825cSml nxge_t *nxgep = barg; 46301bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 46311bd6825cSml p_nxge_stats_t statsp = nxgep->statsp; 46321bd6825cSml int err = 0; 46331bd6825cSml link_flowctrl_t fl; 46341bd6825cSml uint64_t tmp = 0; 46354045d941Ssowmini link_state_t ls; 46363fd94f8cSam boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT); 46371bd6825cSml 46381bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46391bd6825cSml "==> nxge_m_getprop: pr_num %d", pr_num)); 46404045d941Ssowmini 46414045d941Ssowmini if (pr_valsize == 0) 46424045d941Ssowmini return (EINVAL); 46434045d941Ssowmini 4644afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_RW; 4645afdda45fSVasumathi Sundaram - Sun Microsystems 46463fd94f8cSam if ((is_default) && (pr_num != MAC_PROP_PRIVATE)) { 46474045d941Ssowmini err = nxge_get_def_val(nxgep, pr_num, pr_valsize, pr_val); 46484045d941Ssowmini return (err); 46494045d941Ssowmini } 46504045d941Ssowmini 46511bd6825cSml bzero(pr_val, pr_valsize); 46521bd6825cSml switch (pr_num) { 46533fd94f8cSam case MAC_PROP_DUPLEX: 4654afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 46551bd6825cSml *(uint8_t *)pr_val = statsp->mac_stats.link_duplex; 46561bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46571bd6825cSml "==> nxge_m_getprop: duplex mode %d", 46581bd6825cSml *(uint8_t *)pr_val)); 46591bd6825cSml break; 46601bd6825cSml 46613fd94f8cSam case MAC_PROP_SPEED: 46621bd6825cSml if (pr_valsize < sizeof (uint64_t)) 46631bd6825cSml return (EINVAL); 4664afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 46651bd6825cSml tmp = statsp->mac_stats.link_speed * 1000000ull; 46661bd6825cSml bcopy(&tmp, pr_val, sizeof (tmp)); 46671bd6825cSml break; 46681bd6825cSml 46693fd94f8cSam case MAC_PROP_STATUS: 46704045d941Ssowmini if (pr_valsize < sizeof (link_state_t)) 46711bd6825cSml return (EINVAL); 4672afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 46734045d941Ssowmini if (!statsp->mac_stats.link_up) 46744045d941Ssowmini ls = LINK_STATE_DOWN; 46754045d941Ssowmini else 46764045d941Ssowmini ls = LINK_STATE_UP; 46774045d941Ssowmini bcopy(&ls, pr_val, sizeof (ls)); 46781bd6825cSml break; 46791bd6825cSml 46803fd94f8cSam case MAC_PROP_AUTONEG: 46811bd6825cSml *(uint8_t *)pr_val = 46821bd6825cSml param_arr[param_autoneg].value; 46831bd6825cSml break; 46841bd6825cSml 46853fd94f8cSam case MAC_PROP_FLOWCTRL: 46861bd6825cSml if (pr_valsize < sizeof (link_flowctrl_t)) 46871bd6825cSml return (EINVAL); 46881bd6825cSml 46891bd6825cSml fl = LINK_FLOWCTRL_NONE; 46901bd6825cSml if (param_arr[param_anar_pause].value) { 46911bd6825cSml fl = LINK_FLOWCTRL_RX; 46921bd6825cSml } 46931bd6825cSml bcopy(&fl, pr_val, sizeof (fl)); 46941bd6825cSml break; 46951bd6825cSml 46963fd94f8cSam case MAC_PROP_ADV_1000FDX_CAP: 4697afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 46981bd6825cSml *(uint8_t *)pr_val = 46991bd6825cSml param_arr[param_anar_1000fdx].value; 47001bd6825cSml break; 47011bd6825cSml 47023fd94f8cSam case MAC_PROP_EN_1000FDX_CAP: 47031bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_1000fdx; 47041bd6825cSml break; 47051bd6825cSml 47063fd94f8cSam case MAC_PROP_ADV_100FDX_CAP: 4707afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 47081bd6825cSml *(uint8_t *)pr_val = 47091bd6825cSml param_arr[param_anar_100fdx].value; 47101bd6825cSml break; 47111bd6825cSml 47123fd94f8cSam case MAC_PROP_EN_100FDX_CAP: 47131bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_100fdx; 47141bd6825cSml break; 47151bd6825cSml 47163fd94f8cSam case MAC_PROP_ADV_10FDX_CAP: 4717afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 47181bd6825cSml *(uint8_t *)pr_val = 47191bd6825cSml param_arr[param_anar_10fdx].value; 47201bd6825cSml break; 47211bd6825cSml 47223fd94f8cSam case MAC_PROP_EN_10FDX_CAP: 47231bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_10fdx; 47241bd6825cSml break; 47251bd6825cSml 47263fd94f8cSam case MAC_PROP_EN_1000HDX_CAP: 47273fd94f8cSam case MAC_PROP_EN_100HDX_CAP: 47283fd94f8cSam case MAC_PROP_EN_10HDX_CAP: 47293fd94f8cSam case MAC_PROP_ADV_1000HDX_CAP: 47303fd94f8cSam case MAC_PROP_ADV_100HDX_CAP: 47313fd94f8cSam case MAC_PROP_ADV_10HDX_CAP: 47324045d941Ssowmini err = ENOTSUP; 47331bd6825cSml break; 47341bd6825cSml 47353fd94f8cSam case MAC_PROP_PRIVATE: 47364045d941Ssowmini err = nxge_get_priv_prop(nxgep, pr_name, pr_flags, 4737afdda45fSVasumathi Sundaram - Sun Microsystems pr_valsize, pr_val, perm); 47384045d941Ssowmini break; 4739f0f2c3a5SGirish Moodalbail 4740f0f2c3a5SGirish Moodalbail case MAC_PROP_MTU: { 4741f0f2c3a5SGirish Moodalbail mac_propval_range_t range; 4742f0f2c3a5SGirish Moodalbail 4743f0f2c3a5SGirish Moodalbail if (!(pr_flags & MAC_PROP_POSSIBLE)) 4744f0f2c3a5SGirish Moodalbail return (ENOTSUP); 4745f0f2c3a5SGirish Moodalbail if (pr_valsize < sizeof (mac_propval_range_t)) 4746f0f2c3a5SGirish Moodalbail return (EINVAL); 4747f0f2c3a5SGirish Moodalbail range.mpr_count = 1; 4748f0f2c3a5SGirish Moodalbail range.mpr_type = MAC_PROPVAL_UINT32; 4749f0f2c3a5SGirish Moodalbail range.range_uint32[0].mpur_min = 4750f0f2c3a5SGirish Moodalbail range.range_uint32[0].mpur_max = NXGE_DEFAULT_MTU; 4751290b5530SMichael Speer range.range_uint32[0].mpur_max = NXGE_MAXIMUM_MTU; 4752f0f2c3a5SGirish Moodalbail bcopy(&range, pr_val, sizeof (range)); 4753f0f2c3a5SGirish Moodalbail break; 4754f0f2c3a5SGirish Moodalbail } 47551bd6825cSml default: 47564045d941Ssowmini err = EINVAL; 47574045d941Ssowmini break; 47581bd6825cSml } 47591bd6825cSml 47601bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_getprop")); 47611bd6825cSml 47621bd6825cSml return (err); 47631bd6825cSml } 47641bd6825cSml 47651bd6825cSml /* ARGSUSED */ 47661bd6825cSml static int 47671bd6825cSml nxge_set_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_valsize, 47681bd6825cSml const void *pr_val) 47691bd6825cSml { 47701bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 47711bd6825cSml int err = 0; 47721bd6825cSml long result; 47731bd6825cSml 47741bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47751bd6825cSml "==> nxge_set_priv_prop: name %s", pr_name)); 47761bd6825cSml 47771bd6825cSml /* Blanking */ 47781bd6825cSml if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 47791bd6825cSml err = nxge_param_rx_intr_time(nxgep, NULL, NULL, 47801bd6825cSml (char *)pr_val, 47811bd6825cSml (caddr_t)¶m_arr[param_rxdma_intr_time]); 47821bd6825cSml if (err) { 47831bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47841bd6825cSml "<== nxge_set_priv_prop: " 47851bd6825cSml "unable to set (%s)", pr_name)); 47861bd6825cSml err = EINVAL; 47871bd6825cSml } else { 47881bd6825cSml err = 0; 47891bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47901bd6825cSml "<== nxge_set_priv_prop: " 47911bd6825cSml "set (%s)", pr_name)); 47921bd6825cSml } 47931bd6825cSml 47941bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47951bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 47961bd6825cSml pr_name, result)); 47971bd6825cSml 47981bd6825cSml return (err); 47991bd6825cSml } 48001bd6825cSml 48011bd6825cSml if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 48021bd6825cSml err = nxge_param_rx_intr_pkts(nxgep, NULL, NULL, 48031bd6825cSml (char *)pr_val, 48041bd6825cSml (caddr_t)¶m_arr[param_rxdma_intr_pkts]); 48051bd6825cSml if (err) { 48061bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48071bd6825cSml "<== nxge_set_priv_prop: " 48081bd6825cSml "unable to set (%s)", pr_name)); 48091bd6825cSml err = EINVAL; 48101bd6825cSml } else { 48111bd6825cSml err = 0; 48121bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48131bd6825cSml "<== nxge_set_priv_prop: " 48141bd6825cSml "set (%s)", pr_name)); 48151bd6825cSml } 48161bd6825cSml 48171bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48181bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 48191bd6825cSml pr_name, result)); 48201bd6825cSml 48211bd6825cSml return (err); 48221bd6825cSml } 48231bd6825cSml 48241bd6825cSml /* Classification */ 48251bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 48261bd6825cSml if (pr_val == NULL) { 48271bd6825cSml err = EINVAL; 48281bd6825cSml return (err); 48291bd6825cSml } 48301bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 48311bd6825cSml 48321bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 48331bd6825cSml NULL, (char *)pr_val, 48341bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 48351bd6825cSml 48361bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48371bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 48381bd6825cSml pr_name, result)); 48391bd6825cSml 48401bd6825cSml return (err); 48411bd6825cSml } 48421bd6825cSml 48431bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 48441bd6825cSml if (pr_val == NULL) { 48451bd6825cSml err = EINVAL; 48461bd6825cSml return (err); 48471bd6825cSml } 48481bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 48491bd6825cSml 48501bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 48511bd6825cSml NULL, (char *)pr_val, 48521bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 48531bd6825cSml 48541bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48551bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 48561bd6825cSml pr_name, result)); 48571bd6825cSml 48581bd6825cSml return (err); 48591bd6825cSml } 48601bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 48611bd6825cSml if (pr_val == NULL) { 48621bd6825cSml err = EINVAL; 48631bd6825cSml return (err); 48641bd6825cSml } 48651bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 48661bd6825cSml 48671bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 48681bd6825cSml NULL, (char *)pr_val, 48691bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 48701bd6825cSml 48711bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48721bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 48731bd6825cSml pr_name, result)); 48741bd6825cSml 48751bd6825cSml return (err); 48761bd6825cSml } 48771bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 48781bd6825cSml if (pr_val == NULL) { 48791bd6825cSml err = EINVAL; 48801bd6825cSml return (err); 48811bd6825cSml } 48821bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 48831bd6825cSml 48841bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 48851bd6825cSml NULL, (char *)pr_val, 48861bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 48871bd6825cSml 48881bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48891bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 48901bd6825cSml pr_name, result)); 48911bd6825cSml 48921bd6825cSml return (err); 48931bd6825cSml } 48941bd6825cSml 48951bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 48961bd6825cSml if (pr_val == NULL) { 48971bd6825cSml err = EINVAL; 48981bd6825cSml return (err); 48991bd6825cSml } 49001bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49011bd6825cSml 49021bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 49031bd6825cSml NULL, (char *)pr_val, 49041bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 49051bd6825cSml 49061bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49071bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 49081bd6825cSml pr_name, result)); 49091bd6825cSml 49101bd6825cSml return (err); 49111bd6825cSml } 49121bd6825cSml 49131bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 49141bd6825cSml if (pr_val == NULL) { 49151bd6825cSml err = EINVAL; 49161bd6825cSml return (err); 49171bd6825cSml } 49181bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49191bd6825cSml 49201bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 49211bd6825cSml NULL, (char *)pr_val, 49221bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 49231bd6825cSml 49241bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49251bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 49261bd6825cSml pr_name, result)); 49271bd6825cSml 49281bd6825cSml return (err); 49291bd6825cSml } 49301bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 49311bd6825cSml if (pr_val == NULL) { 49321bd6825cSml err = EINVAL; 49331bd6825cSml return (err); 49341bd6825cSml } 49351bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49361bd6825cSml 49371bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 49381bd6825cSml NULL, (char *)pr_val, 49391bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 49401bd6825cSml 49411bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49421bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 49431bd6825cSml pr_name, result)); 49441bd6825cSml 49451bd6825cSml return (err); 49461bd6825cSml } 49471bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 49481bd6825cSml if (pr_val == NULL) { 49491bd6825cSml err = EINVAL; 49501bd6825cSml return (err); 49511bd6825cSml } 49521bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49531bd6825cSml 49541bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 49551bd6825cSml NULL, (char *)pr_val, 49561bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 49571bd6825cSml 49581bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49591bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 49601bd6825cSml pr_name, result)); 49611bd6825cSml 49621bd6825cSml return (err); 49631bd6825cSml } 49641bd6825cSml 49651bd6825cSml if (strcmp(pr_name, "_soft_lso_enable") == 0) { 49661bd6825cSml if (pr_val == NULL) { 49671bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49681bd6825cSml "==> nxge_set_priv_prop: name %s (null)", pr_name)); 49691bd6825cSml err = EINVAL; 49701bd6825cSml return (err); 49711bd6825cSml } 49721bd6825cSml 49731bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49741bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49751bd6825cSml "<== nxge_set_priv_prop: name %s " 49761bd6825cSml "(lso %d pr_val %s value %d)", 49771bd6825cSml pr_name, nxgep->soft_lso_enable, pr_val, result)); 49781bd6825cSml 49791bd6825cSml if (result > 1 || result < 0) { 49801bd6825cSml err = EINVAL; 49811bd6825cSml } else { 49821bd6825cSml if (nxgep->soft_lso_enable == (uint32_t)result) { 49831bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49841bd6825cSml "no change (%d %d)", 49851bd6825cSml nxgep->soft_lso_enable, result)); 49861bd6825cSml return (0); 49871bd6825cSml } 49881bd6825cSml } 49891bd6825cSml 49901bd6825cSml nxgep->soft_lso_enable = (int)result; 49911bd6825cSml 49921bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49931bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 49941bd6825cSml pr_name, result)); 49951bd6825cSml 49961bd6825cSml return (err); 49971bd6825cSml } 499800161856Syc /* 499900161856Syc * Commands like "ndd -set /dev/nxge0 adv_10gfdx_cap 1" cause the 500000161856Syc * following code to be executed. 500100161856Syc */ 50024045d941Ssowmini if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) { 50034045d941Ssowmini err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val, 50044045d941Ssowmini (caddr_t)¶m_arr[param_anar_10gfdx]); 50054045d941Ssowmini return (err); 50064045d941Ssowmini } 50074045d941Ssowmini if (strcmp(pr_name, "_adv_pause_cap") == 0) { 50084045d941Ssowmini err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val, 50094045d941Ssowmini (caddr_t)¶m_arr[param_anar_pause]); 50104045d941Ssowmini return (err); 50114045d941Ssowmini } 50121bd6825cSml 50131bd6825cSml return (EINVAL); 50141bd6825cSml } 50151bd6825cSml 50161bd6825cSml static int 50174045d941Ssowmini nxge_get_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_flags, 5018afdda45fSVasumathi Sundaram - Sun Microsystems uint_t pr_valsize, void *pr_val, uint_t *perm) 50191bd6825cSml { 50201bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 50211bd6825cSml char valstr[MAXNAMELEN]; 50221bd6825cSml int err = EINVAL; 50231bd6825cSml uint_t strsize; 50243fd94f8cSam boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT); 50251bd6825cSml 50261bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50271bd6825cSml "==> nxge_get_priv_prop: property %s", pr_name)); 50281bd6825cSml 50291bd6825cSml /* function number */ 50301bd6825cSml if (strcmp(pr_name, "_function_number") == 0) { 50314045d941Ssowmini if (is_default) 50324045d941Ssowmini return (ENOTSUP); 5033afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 50344045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 50354045d941Ssowmini nxgep->function_num); 50361bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50371bd6825cSml "==> nxge_get_priv_prop: name %s " 50381bd6825cSml "(value %d valstr %s)", 50391bd6825cSml pr_name, nxgep->function_num, valstr)); 50401bd6825cSml 50411bd6825cSml err = 0; 50421bd6825cSml goto done; 50431bd6825cSml } 50441bd6825cSml 50451bd6825cSml /* Neptune firmware version */ 50461bd6825cSml if (strcmp(pr_name, "_fw_version") == 0) { 50474045d941Ssowmini if (is_default) 50484045d941Ssowmini return (ENOTSUP); 5049afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 50504045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%s", 50514045d941Ssowmini nxgep->vpd_info.ver); 50521bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50531bd6825cSml "==> nxge_get_priv_prop: name %s " 50541bd6825cSml "(value %d valstr %s)", 50551bd6825cSml pr_name, nxgep->vpd_info.ver, valstr)); 50561bd6825cSml 50571bd6825cSml err = 0; 50581bd6825cSml goto done; 50591bd6825cSml } 50601bd6825cSml 50611bd6825cSml /* port PHY mode */ 50621bd6825cSml if (strcmp(pr_name, "_port_mode") == 0) { 50634045d941Ssowmini if (is_default) 50644045d941Ssowmini return (ENOTSUP); 5065afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 50661bd6825cSml switch (nxgep->mac.portmode) { 50671bd6825cSml case PORT_1G_COPPER: 50684045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G copper %s", 50691bd6825cSml nxgep->hot_swappable_phy ? 50701bd6825cSml "[Hot Swappable]" : ""); 50711bd6825cSml break; 50721bd6825cSml case PORT_1G_FIBER: 50734045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G fiber %s", 50741bd6825cSml nxgep->hot_swappable_phy ? 50751bd6825cSml "[hot swappable]" : ""); 50761bd6825cSml break; 50771bd6825cSml case PORT_10G_COPPER: 50784045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 50794045d941Ssowmini "10G copper %s", 50801bd6825cSml nxgep->hot_swappable_phy ? 50811bd6825cSml "[hot swappable]" : ""); 50821bd6825cSml break; 50831bd6825cSml case PORT_10G_FIBER: 50844045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "10G fiber %s", 50851bd6825cSml nxgep->hot_swappable_phy ? 50861bd6825cSml "[hot swappable]" : ""); 50871bd6825cSml break; 50881bd6825cSml case PORT_10G_SERDES: 50894045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 50904045d941Ssowmini "10G serdes %s", nxgep->hot_swappable_phy ? 50911bd6825cSml "[hot swappable]" : ""); 50921bd6825cSml break; 50931bd6825cSml case PORT_1G_SERDES: 50944045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G serdes %s", 50951bd6825cSml nxgep->hot_swappable_phy ? 50961bd6825cSml "[hot swappable]" : ""); 50971bd6825cSml break; 509800161856Syc case PORT_1G_TN1010: 509900161856Syc (void) snprintf(valstr, sizeof (valstr), 510000161856Syc "1G TN1010 copper %s", nxgep->hot_swappable_phy ? 510100161856Syc "[hot swappable]" : ""); 510200161856Syc break; 510300161856Syc case PORT_10G_TN1010: 510400161856Syc (void) snprintf(valstr, sizeof (valstr), 510500161856Syc "10G TN1010 copper %s", nxgep->hot_swappable_phy ? 510600161856Syc "[hot swappable]" : ""); 510700161856Syc break; 51081bd6825cSml case PORT_1G_RGMII_FIBER: 51094045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 51104045d941Ssowmini "1G rgmii fiber %s", nxgep->hot_swappable_phy ? 51111bd6825cSml "[hot swappable]" : ""); 51121bd6825cSml break; 51131bd6825cSml case PORT_HSP_MODE: 51144045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 5115c2d37b8bSml "phy not present[hot swappable]"); 51161bd6825cSml break; 51171bd6825cSml default: 51184045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "unknown %s", 51191bd6825cSml nxgep->hot_swappable_phy ? 51201bd6825cSml "[hot swappable]" : ""); 51211bd6825cSml break; 51221bd6825cSml } 51231bd6825cSml 51241bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51251bd6825cSml "==> nxge_get_priv_prop: name %s (value %s)", 51261bd6825cSml pr_name, valstr)); 51271bd6825cSml 51281bd6825cSml err = 0; 51291bd6825cSml goto done; 51301bd6825cSml } 51311bd6825cSml 51321bd6825cSml /* Hot swappable PHY */ 51331bd6825cSml if (strcmp(pr_name, "_hot_swap_phy") == 0) { 51344045d941Ssowmini if (is_default) 51354045d941Ssowmini return (ENOTSUP); 5136afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 51374045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%s", 51381bd6825cSml nxgep->hot_swappable_phy ? 51391bd6825cSml "yes" : "no"); 51401bd6825cSml 51411bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51421bd6825cSml "==> nxge_get_priv_prop: name %s " 51431bd6825cSml "(value %d valstr %s)", 51441bd6825cSml pr_name, nxgep->hot_swappable_phy, valstr)); 51451bd6825cSml 51461bd6825cSml err = 0; 51471bd6825cSml goto done; 51481bd6825cSml } 51491bd6825cSml 51501bd6825cSml 51511bd6825cSml /* Receive Interrupt Blanking Parameters */ 51521bd6825cSml if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 51534045d941Ssowmini err = 0; 51544045d941Ssowmini if (is_default) { 51554045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 51564045d941Ssowmini "%d", RXDMA_RCR_TO_DEFAULT); 51574045d941Ssowmini goto done; 51584045d941Ssowmini } 51594045d941Ssowmini 51604045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 51614045d941Ssowmini nxgep->intr_timeout); 51621bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51631bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 51641bd6825cSml pr_name, 51651bd6825cSml (uint32_t)nxgep->intr_timeout)); 51661bd6825cSml goto done; 51671bd6825cSml } 51681bd6825cSml 51691bd6825cSml if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 51704045d941Ssowmini err = 0; 51714045d941Ssowmini if (is_default) { 51724045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 51734045d941Ssowmini "%d", RXDMA_RCR_PTHRES_DEFAULT); 51744045d941Ssowmini goto done; 51754045d941Ssowmini } 51764045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 51774045d941Ssowmini nxgep->intr_threshold); 51781bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51791bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 51801bd6825cSml pr_name, (uint32_t)nxgep->intr_threshold)); 51811bd6825cSml 51821bd6825cSml goto done; 51831bd6825cSml } 51841bd6825cSml 51851bd6825cSml /* Classification and Load Distribution Configuration */ 51861bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 51874045d941Ssowmini if (is_default) { 51884045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 51894045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 51904045d941Ssowmini err = 0; 51914045d941Ssowmini goto done; 51924045d941Ssowmini } 51931bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 51941bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 51951bd6825cSml 51964045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 51971bd6825cSml (int)param_arr[param_class_opt_ipv4_tcp].value); 51981bd6825cSml 51991bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52001bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 52011bd6825cSml goto done; 52021bd6825cSml } 52031bd6825cSml 52041bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 52054045d941Ssowmini if (is_default) { 52064045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52074045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 52084045d941Ssowmini err = 0; 52094045d941Ssowmini goto done; 52104045d941Ssowmini } 52111bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 52121bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 52131bd6825cSml 52144045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52151bd6825cSml (int)param_arr[param_class_opt_ipv4_udp].value); 52161bd6825cSml 52171bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52181bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 52191bd6825cSml goto done; 52201bd6825cSml } 52211bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 52224045d941Ssowmini if (is_default) { 52234045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52244045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 52254045d941Ssowmini err = 0; 52264045d941Ssowmini goto done; 52274045d941Ssowmini } 52281bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 52291bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 52301bd6825cSml 52314045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52321bd6825cSml (int)param_arr[param_class_opt_ipv4_ah].value); 52331bd6825cSml 52341bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52351bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 52361bd6825cSml goto done; 52371bd6825cSml } 52381bd6825cSml 52391bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 52404045d941Ssowmini if (is_default) { 52414045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52424045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 52434045d941Ssowmini err = 0; 52444045d941Ssowmini goto done; 52454045d941Ssowmini } 52461bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 52471bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 52481bd6825cSml 52494045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52501bd6825cSml (int)param_arr[param_class_opt_ipv4_sctp].value); 52511bd6825cSml 52521bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52531bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 52541bd6825cSml goto done; 52551bd6825cSml } 52561bd6825cSml 52571bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 52584045d941Ssowmini if (is_default) { 52594045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52604045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 52614045d941Ssowmini err = 0; 52624045d941Ssowmini goto done; 52634045d941Ssowmini } 52641bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 52651bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 52661bd6825cSml 52674045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52681bd6825cSml (int)param_arr[param_class_opt_ipv6_tcp].value); 52691bd6825cSml 52701bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52711bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 52721bd6825cSml goto done; 52731bd6825cSml } 52741bd6825cSml 52751bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 52764045d941Ssowmini if (is_default) { 52774045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52784045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 52794045d941Ssowmini err = 0; 52804045d941Ssowmini goto done; 52814045d941Ssowmini } 52821bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 52831bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 52841bd6825cSml 52854045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52861bd6825cSml (int)param_arr[param_class_opt_ipv6_udp].value); 52871bd6825cSml 52881bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52891bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 52901bd6825cSml goto done; 52911bd6825cSml } 52921bd6825cSml 52931bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 52944045d941Ssowmini if (is_default) { 52954045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52964045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 52974045d941Ssowmini err = 0; 52984045d941Ssowmini goto done; 52994045d941Ssowmini } 53001bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 53011bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 53021bd6825cSml 53034045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53041bd6825cSml (int)param_arr[param_class_opt_ipv6_ah].value); 53051bd6825cSml 53061bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53071bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 53081bd6825cSml goto done; 53091bd6825cSml } 53101bd6825cSml 53111bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 53124045d941Ssowmini if (is_default) { 53134045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53144045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 53154045d941Ssowmini err = 0; 53164045d941Ssowmini goto done; 53174045d941Ssowmini } 53181bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 53191bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 53201bd6825cSml 53214045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53221bd6825cSml (int)param_arr[param_class_opt_ipv6_sctp].value); 53231bd6825cSml 53241bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53251bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 53261bd6825cSml goto done; 53271bd6825cSml } 53281bd6825cSml 53291bd6825cSml /* Software LSO */ 53301bd6825cSml if (strcmp(pr_name, "_soft_lso_enable") == 0) { 53314045d941Ssowmini if (is_default) { 53324045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 53334045d941Ssowmini err = 0; 53344045d941Ssowmini goto done; 53354045d941Ssowmini } 53364045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 53374045d941Ssowmini "%d", nxgep->soft_lso_enable); 53381bd6825cSml err = 0; 53391bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53401bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 53411bd6825cSml pr_name, nxgep->soft_lso_enable)); 53421bd6825cSml 53431bd6825cSml goto done; 53441bd6825cSml } 53454045d941Ssowmini if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) { 53464045d941Ssowmini err = 0; 53474045d941Ssowmini if (is_default || 53484045d941Ssowmini nxgep->param_arr[param_anar_10gfdx].value != 0) { 53494045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 1); 53504045d941Ssowmini goto done; 53514045d941Ssowmini } else { 53524045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 53534045d941Ssowmini goto done; 53544045d941Ssowmini } 53554045d941Ssowmini } 53564045d941Ssowmini if (strcmp(pr_name, "_adv_pause_cap") == 0) { 53574045d941Ssowmini err = 0; 53584045d941Ssowmini if (is_default || 53594045d941Ssowmini nxgep->param_arr[param_anar_pause].value != 0) { 53604045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 1); 53614045d941Ssowmini goto done; 53624045d941Ssowmini } else { 53634045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 53644045d941Ssowmini goto done; 53654045d941Ssowmini } 53664045d941Ssowmini } 53671bd6825cSml 53681bd6825cSml done: 53691bd6825cSml if (err == 0) { 53701bd6825cSml strsize = (uint_t)strlen(valstr); 53711bd6825cSml if (pr_valsize < strsize) { 53721bd6825cSml err = ENOBUFS; 53731bd6825cSml } else { 53741bd6825cSml (void) strlcpy(pr_val, valstr, pr_valsize); 53751bd6825cSml } 53761bd6825cSml } 53771bd6825cSml 53781bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53791bd6825cSml "<== nxge_get_priv_prop: return %d", err)); 53801bd6825cSml return (err); 53811bd6825cSml } 53821bd6825cSml 538344961713Sgirish /* 538444961713Sgirish * Module loading and removing entry points. 538544961713Sgirish */ 538644961713Sgirish 53876f157acbSml DDI_DEFINE_STREAM_OPS(nxge_dev_ops, nulldev, nulldev, nxge_attach, nxge_detach, 538819397407SSherry Moore nodev, NULL, D_MP, NULL, nxge_quiesce); 538944961713Sgirish 53902e59129aSraghus #define NXGE_DESC_VER "Sun NIU 10Gb Ethernet" 539144961713Sgirish 539244961713Sgirish /* 539344961713Sgirish * Module linkage information for the kernel. 539444961713Sgirish */ 539544961713Sgirish static struct modldrv nxge_modldrv = { 539644961713Sgirish &mod_driverops, 539744961713Sgirish NXGE_DESC_VER, 539844961713Sgirish &nxge_dev_ops 539944961713Sgirish }; 540044961713Sgirish 540144961713Sgirish static struct modlinkage modlinkage = { 540244961713Sgirish MODREV_1, (void *) &nxge_modldrv, NULL 540344961713Sgirish }; 540444961713Sgirish 540544961713Sgirish int 540644961713Sgirish _init(void) 540744961713Sgirish { 540844961713Sgirish int status; 540944961713Sgirish 54103b2d9860SMichael Speer MUTEX_INIT(&nxgedebuglock, NULL, MUTEX_DRIVER, NULL); 54113b2d9860SMichael Speer 541244961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init")); 54133b2d9860SMichael Speer 541444961713Sgirish mac_init_ops(&nxge_dev_ops, "nxge"); 54153b2d9860SMichael Speer 541644961713Sgirish status = ddi_soft_state_init(&nxge_list, sizeof (nxge_t), 0); 541744961713Sgirish if (status != 0) { 541844961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, 54194045d941Ssowmini "failed to init device soft state")); 542044961713Sgirish goto _init_exit; 542144961713Sgirish } 54223b2d9860SMichael Speer 542344961713Sgirish status = mod_install(&modlinkage); 542444961713Sgirish if (status != 0) { 542544961713Sgirish ddi_soft_state_fini(&nxge_list); 542644961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, "Mod install failed")); 542744961713Sgirish goto _init_exit; 542844961713Sgirish } 542944961713Sgirish 543044961713Sgirish MUTEX_INIT(&nxge_common_lock, NULL, MUTEX_DRIVER, NULL); 543144961713Sgirish 54323b2d9860SMichael Speer NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _init status = 0x%X", status)); 54333b2d9860SMichael Speer return (status); 543444961713Sgirish 54353b2d9860SMichael Speer _init_exit: 54363b2d9860SMichael Speer NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _init status = 0x%X", status)); 54373b2d9860SMichael Speer MUTEX_DESTROY(&nxgedebuglock); 543844961713Sgirish return (status); 543944961713Sgirish } 544044961713Sgirish 544144961713Sgirish int 544244961713Sgirish _fini(void) 544344961713Sgirish { 544444961713Sgirish int status; 544544961713Sgirish 544644961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini")); 544744961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove")); 5448a3c5bd6dSspeer 5449a3c5bd6dSspeer if (nxge_mblks_pending) 5450a3c5bd6dSspeer return (EBUSY); 5451a3c5bd6dSspeer 545244961713Sgirish status = mod_remove(&modlinkage); 545344961713Sgirish if (status != DDI_SUCCESS) { 545444961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, 54554045d941Ssowmini "Module removal failed 0x%08x", 54564045d941Ssowmini status)); 545744961713Sgirish goto _fini_exit; 545844961713Sgirish } 545944961713Sgirish 546044961713Sgirish mac_fini_ops(&nxge_dev_ops); 546144961713Sgirish 546244961713Sgirish ddi_soft_state_fini(&nxge_list); 546344961713Sgirish 54643b2d9860SMichael Speer NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _fini status = 0x%08x", status)); 54653b2d9860SMichael Speer 546644961713Sgirish MUTEX_DESTROY(&nxge_common_lock); 54673b2d9860SMichael Speer MUTEX_DESTROY(&nxgedebuglock); 54683b2d9860SMichael Speer return (status); 546944961713Sgirish 54703b2d9860SMichael Speer _fini_exit: 54713b2d9860SMichael Speer NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _fini status = 0x%08x", status)); 547244961713Sgirish return (status); 547344961713Sgirish } 547444961713Sgirish 547544961713Sgirish int 547644961713Sgirish _info(struct modinfo *modinfop) 547744961713Sgirish { 547844961713Sgirish int status; 547944961713Sgirish 548044961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info")); 548144961713Sgirish status = mod_info(&modlinkage, modinfop); 548244961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status)); 548344961713Sgirish 548444961713Sgirish return (status); 548544961713Sgirish } 548644961713Sgirish 5487da14cebeSEric Cheng /*ARGSUSED*/ 5488da14cebeSEric Cheng static int 5489da14cebeSEric Cheng nxge_tx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num) 5490da14cebeSEric Cheng { 5491da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5492da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5493da14cebeSEric Cheng uint32_t channel; 5494da14cebeSEric Cheng p_tx_ring_t ring; 5495da14cebeSEric Cheng 5496da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.tdc.start + rhp->index; 5497da14cebeSEric Cheng ring = nxgep->tx_rings->rings[channel]; 5498da14cebeSEric Cheng 5499da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 5500da14cebeSEric Cheng ring->tx_ring_handle = rhp->ring_handle; 5501da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5502da14cebeSEric Cheng 5503da14cebeSEric Cheng return (0); 5504da14cebeSEric Cheng } 5505da14cebeSEric Cheng 5506da14cebeSEric Cheng static void 5507da14cebeSEric Cheng nxge_tx_ring_stop(mac_ring_driver_t rdriver) 5508da14cebeSEric Cheng { 5509da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5510da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5511da14cebeSEric Cheng uint32_t channel; 5512da14cebeSEric Cheng p_tx_ring_t ring; 5513da14cebeSEric Cheng 5514da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.tdc.start + rhp->index; 5515da14cebeSEric Cheng ring = nxgep->tx_rings->rings[channel]; 5516da14cebeSEric Cheng 5517da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 5518da14cebeSEric Cheng ring->tx_ring_handle = (mac_ring_handle_t)NULL; 5519da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5520da14cebeSEric Cheng } 5521da14cebeSEric Cheng 5522da14cebeSEric Cheng static int 5523da14cebeSEric Cheng nxge_rx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num) 5524da14cebeSEric Cheng { 5525da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5526da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5527da14cebeSEric Cheng uint32_t channel; 5528da14cebeSEric Cheng p_rx_rcr_ring_t ring; 5529da14cebeSEric Cheng int i; 5530da14cebeSEric Cheng 5531da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.start_rdc + rhp->index; 5532da14cebeSEric Cheng ring = nxgep->rx_rcr_rings->rcr_rings[channel]; 5533da14cebeSEric Cheng 5534da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 5535da14cebeSEric Cheng 5536da14cebeSEric Cheng if (nxgep->rx_channel_started[channel] == B_TRUE) { 5537da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5538da14cebeSEric Cheng return (0); 5539da14cebeSEric Cheng } 5540da14cebeSEric Cheng 5541da14cebeSEric Cheng /* set rcr_ring */ 5542da14cebeSEric Cheng for (i = 0; i < nxgep->ldgvp->maxldvs; i++) { 5543da14cebeSEric Cheng if ((nxgep->ldgvp->ldvp[i].is_rxdma == 1) && 5544da14cebeSEric Cheng (nxgep->ldgvp->ldvp[i].channel == channel)) { 5545da14cebeSEric Cheng ring->ldvp = &nxgep->ldgvp->ldvp[i]; 5546da14cebeSEric Cheng ring->ldgp = nxgep->ldgvp->ldvp[i].ldgp; 5547da14cebeSEric Cheng } 5548da14cebeSEric Cheng } 5549da14cebeSEric Cheng 5550da14cebeSEric Cheng nxgep->rx_channel_started[channel] = B_TRUE; 5551da14cebeSEric Cheng ring->rcr_mac_handle = rhp->ring_handle; 5552da14cebeSEric Cheng ring->rcr_gen_num = mr_gen_num; 5553da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5554da14cebeSEric Cheng 5555da14cebeSEric Cheng return (0); 5556da14cebeSEric Cheng } 5557da14cebeSEric Cheng 5558da14cebeSEric Cheng static void 5559da14cebeSEric Cheng nxge_rx_ring_stop(mac_ring_driver_t rdriver) 5560da14cebeSEric Cheng { 5561da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5562da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5563da14cebeSEric Cheng uint32_t channel; 5564da14cebeSEric Cheng p_rx_rcr_ring_t ring; 5565da14cebeSEric Cheng 5566da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.start_rdc + rhp->index; 5567da14cebeSEric Cheng ring = nxgep->rx_rcr_rings->rcr_rings[channel]; 5568da14cebeSEric Cheng 5569da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 5570da14cebeSEric Cheng nxgep->rx_channel_started[channel] = B_FALSE; 5571da14cebeSEric Cheng ring->rcr_mac_handle = NULL; 5572da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5573da14cebeSEric Cheng } 5574da14cebeSEric Cheng 5575da14cebeSEric Cheng /* 5576da14cebeSEric Cheng * Callback funtion for MAC layer to register all rings. 5577da14cebeSEric Cheng */ 5578da14cebeSEric Cheng static void 5579da14cebeSEric Cheng nxge_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index, 5580da14cebeSEric Cheng const int index, mac_ring_info_t *infop, mac_ring_handle_t rh) 5581da14cebeSEric Cheng { 5582da14cebeSEric Cheng p_nxge_t nxgep = (p_nxge_t)arg; 5583da14cebeSEric Cheng p_nxge_hw_pt_cfg_t p_cfgp = &nxgep->pt_config.hw_config; 5584da14cebeSEric Cheng 5585da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, TX_CTL, 5586da14cebeSEric Cheng "==> nxge_fill_ring 0x%x index %d", rtype, index)); 5587da14cebeSEric Cheng 5588da14cebeSEric Cheng switch (rtype) { 5589da14cebeSEric Cheng case MAC_RING_TYPE_TX: { 5590da14cebeSEric Cheng p_nxge_ring_handle_t rhandlep; 5591da14cebeSEric Cheng 5592da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, TX_CTL, 5593da14cebeSEric Cheng "==> nxge_fill_ring (TX) 0x%x index %d ntdcs %d", 5594da14cebeSEric Cheng rtype, index, p_cfgp->tdc.count)); 5595da14cebeSEric Cheng 5596da14cebeSEric Cheng ASSERT((index >= 0) && (index < p_cfgp->tdc.count)); 5597da14cebeSEric Cheng rhandlep = &nxgep->tx_ring_handles[index]; 5598da14cebeSEric Cheng rhandlep->nxgep = nxgep; 5599da14cebeSEric Cheng rhandlep->index = index; 5600da14cebeSEric Cheng rhandlep->ring_handle = rh; 5601da14cebeSEric Cheng 5602da14cebeSEric Cheng infop->mri_driver = (mac_ring_driver_t)rhandlep; 5603da14cebeSEric Cheng infop->mri_start = nxge_tx_ring_start; 5604da14cebeSEric Cheng infop->mri_stop = nxge_tx_ring_stop; 5605da14cebeSEric Cheng infop->mri_tx = nxge_tx_ring_send; 5606da14cebeSEric Cheng 5607da14cebeSEric Cheng break; 5608da14cebeSEric Cheng } 5609da14cebeSEric Cheng case MAC_RING_TYPE_RX: { 5610da14cebeSEric Cheng p_nxge_ring_handle_t rhandlep; 5611da14cebeSEric Cheng int nxge_rindex; 5612da14cebeSEric Cheng mac_intr_t nxge_mac_intr; 5613da14cebeSEric Cheng 5614da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, RX_CTL, 5615da14cebeSEric Cheng "==> nxge_fill_ring (RX) 0x%x index %d nrdcs %d", 5616da14cebeSEric Cheng rtype, index, p_cfgp->max_rdcs)); 5617da14cebeSEric Cheng 5618da14cebeSEric Cheng /* 5619da14cebeSEric Cheng * 'index' is the ring index within the group. 5620da14cebeSEric Cheng * Find the ring index in the nxge instance. 5621da14cebeSEric Cheng */ 5622da14cebeSEric Cheng nxge_rindex = nxge_get_rxring_index(nxgep, rg_index, index); 5623da14cebeSEric Cheng 5624da14cebeSEric Cheng ASSERT((nxge_rindex >= 0) && (nxge_rindex < p_cfgp->max_rdcs)); 5625da14cebeSEric Cheng rhandlep = &nxgep->rx_ring_handles[nxge_rindex]; 5626da14cebeSEric Cheng rhandlep->nxgep = nxgep; 5627da14cebeSEric Cheng rhandlep->index = nxge_rindex; 5628da14cebeSEric Cheng rhandlep->ring_handle = rh; 5629da14cebeSEric Cheng 5630da14cebeSEric Cheng /* 5631da14cebeSEric Cheng * Entrypoint to enable interrupt (disable poll) and 5632da14cebeSEric Cheng * disable interrupt (enable poll). 5633da14cebeSEric Cheng */ 5634da14cebeSEric Cheng nxge_mac_intr.mi_handle = (mac_intr_handle_t)rhandlep; 5635da14cebeSEric Cheng nxge_mac_intr.mi_enable = (mac_intr_enable_t)nxge_disable_poll; 5636da14cebeSEric Cheng nxge_mac_intr.mi_disable = (mac_intr_disable_t)nxge_enable_poll; 5637da14cebeSEric Cheng infop->mri_driver = (mac_ring_driver_t)rhandlep; 5638da14cebeSEric Cheng infop->mri_start = nxge_rx_ring_start; 5639da14cebeSEric Cheng infop->mri_stop = nxge_rx_ring_stop; 5640da14cebeSEric Cheng infop->mri_intr = nxge_mac_intr; /* ??? */ 5641da14cebeSEric Cheng infop->mri_poll = nxge_rx_poll; 5642da14cebeSEric Cheng 5643da14cebeSEric Cheng break; 5644da14cebeSEric Cheng } 5645da14cebeSEric Cheng default: 5646da14cebeSEric Cheng break; 5647da14cebeSEric Cheng } 5648da14cebeSEric Cheng 5649da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_fill_ring 0x%x", 5650da14cebeSEric Cheng rtype)); 5651da14cebeSEric Cheng } 5652da14cebeSEric Cheng 5653da14cebeSEric Cheng static void 5654da14cebeSEric Cheng nxge_group_add_ring(mac_group_driver_t gh, mac_ring_driver_t rh, 5655da14cebeSEric Cheng mac_ring_type_t type) 5656da14cebeSEric Cheng { 5657da14cebeSEric Cheng nxge_ring_group_t *rgroup = (nxge_ring_group_t *)gh; 5658da14cebeSEric Cheng nxge_ring_handle_t *rhandle = (nxge_ring_handle_t *)rh; 5659da14cebeSEric Cheng nxge_t *nxge; 5660da14cebeSEric Cheng nxge_grp_t *grp; 5661da14cebeSEric Cheng nxge_rdc_grp_t *rdc_grp; 5662da14cebeSEric Cheng uint16_t channel; /* device-wise ring id */ 5663da14cebeSEric Cheng int dev_gindex; 5664da14cebeSEric Cheng int rv; 5665da14cebeSEric Cheng 5666da14cebeSEric Cheng nxge = rgroup->nxgep; 5667da14cebeSEric Cheng 5668da14cebeSEric Cheng switch (type) { 5669da14cebeSEric Cheng case MAC_RING_TYPE_TX: 5670da14cebeSEric Cheng /* 5671da14cebeSEric Cheng * nxge_grp_dc_add takes a channel number which is a 5672da14cebeSEric Cheng * "devise" ring ID. 5673da14cebeSEric Cheng */ 5674da14cebeSEric Cheng channel = nxge->pt_config.hw_config.tdc.start + rhandle->index; 5675da14cebeSEric Cheng 5676da14cebeSEric Cheng /* 5677da14cebeSEric Cheng * Remove the ring from the default group 5678da14cebeSEric Cheng */ 5679da14cebeSEric Cheng if (rgroup->gindex != 0) { 5680da14cebeSEric Cheng (void) nxge_grp_dc_remove(nxge, VP_BOUND_TX, channel); 5681da14cebeSEric Cheng } 5682da14cebeSEric Cheng 5683da14cebeSEric Cheng /* 5684da14cebeSEric Cheng * nxge->tx_set.group[] is an array of groups indexed by 5685da14cebeSEric Cheng * a "port" group ID. 5686da14cebeSEric Cheng */ 5687da14cebeSEric Cheng grp = nxge->tx_set.group[rgroup->gindex]; 5688da14cebeSEric Cheng rv = nxge_grp_dc_add(nxge, grp, VP_BOUND_TX, channel); 5689da14cebeSEric Cheng if (rv != 0) { 5690da14cebeSEric Cheng NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 5691da14cebeSEric Cheng "nxge_group_add_ring: nxge_grp_dc_add failed")); 5692da14cebeSEric Cheng } 5693da14cebeSEric Cheng break; 5694da14cebeSEric Cheng 5695da14cebeSEric Cheng case MAC_RING_TYPE_RX: 5696da14cebeSEric Cheng /* 5697da14cebeSEric Cheng * nxge->rx_set.group[] is an array of groups indexed by 5698da14cebeSEric Cheng * a "port" group ID. 5699da14cebeSEric Cheng */ 5700da14cebeSEric Cheng grp = nxge->rx_set.group[rgroup->gindex]; 5701da14cebeSEric Cheng 5702da14cebeSEric Cheng dev_gindex = nxge->pt_config.hw_config.def_mac_rxdma_grpid + 5703da14cebeSEric Cheng rgroup->gindex; 5704da14cebeSEric Cheng rdc_grp = &nxge->pt_config.rdc_grps[dev_gindex]; 5705da14cebeSEric Cheng 5706da14cebeSEric Cheng /* 5707da14cebeSEric Cheng * nxge_grp_dc_add takes a channel number which is a 5708da14cebeSEric Cheng * "devise" ring ID. 5709da14cebeSEric Cheng */ 5710da14cebeSEric Cheng channel = nxge->pt_config.hw_config.start_rdc + rhandle->index; 5711da14cebeSEric Cheng rv = nxge_grp_dc_add(nxge, grp, VP_BOUND_RX, channel); 5712da14cebeSEric Cheng if (rv != 0) { 5713da14cebeSEric Cheng NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 5714da14cebeSEric Cheng "nxge_group_add_ring: nxge_grp_dc_add failed")); 5715da14cebeSEric Cheng } 5716da14cebeSEric Cheng 5717da14cebeSEric Cheng rdc_grp->map |= (1 << channel); 5718da14cebeSEric Cheng rdc_grp->max_rdcs++; 5719da14cebeSEric Cheng 57204ba491f5SMichael Speer (void) nxge_init_fzc_rdc_tbl(nxge, rdc_grp, rgroup->rdctbl); 5721da14cebeSEric Cheng break; 5722da14cebeSEric Cheng } 5723da14cebeSEric Cheng } 5724da14cebeSEric Cheng 5725da14cebeSEric Cheng static void 5726da14cebeSEric Cheng nxge_group_rem_ring(mac_group_driver_t gh, mac_ring_driver_t rh, 5727da14cebeSEric Cheng mac_ring_type_t type) 5728da14cebeSEric Cheng { 5729da14cebeSEric Cheng nxge_ring_group_t *rgroup = (nxge_ring_group_t *)gh; 5730da14cebeSEric Cheng nxge_ring_handle_t *rhandle = (nxge_ring_handle_t *)rh; 5731da14cebeSEric Cheng nxge_t *nxge; 5732da14cebeSEric Cheng uint16_t channel; /* device-wise ring id */ 5733da14cebeSEric Cheng nxge_rdc_grp_t *rdc_grp; 5734da14cebeSEric Cheng int dev_gindex; 5735da14cebeSEric Cheng 5736da14cebeSEric Cheng nxge = rgroup->nxgep; 5737da14cebeSEric Cheng 5738da14cebeSEric Cheng switch (type) { 5739da14cebeSEric Cheng case MAC_RING_TYPE_TX: 5740da14cebeSEric Cheng dev_gindex = nxge->pt_config.hw_config.def_mac_txdma_grpid + 5741da14cebeSEric Cheng rgroup->gindex; 5742da14cebeSEric Cheng channel = nxge->pt_config.hw_config.tdc.start + rhandle->index; 5743da14cebeSEric Cheng nxge_grp_dc_remove(nxge, VP_BOUND_TX, channel); 5744da14cebeSEric Cheng 5745da14cebeSEric Cheng /* 5746da14cebeSEric Cheng * Add the ring back to the default group 5747da14cebeSEric Cheng */ 5748da14cebeSEric Cheng if (rgroup->gindex != 0) { 5749da14cebeSEric Cheng nxge_grp_t *grp; 5750da14cebeSEric Cheng grp = nxge->tx_set.group[0]; 5751da14cebeSEric Cheng (void) nxge_grp_dc_add(nxge, grp, VP_BOUND_TX, channel); 5752da14cebeSEric Cheng } 5753da14cebeSEric Cheng break; 5754da14cebeSEric Cheng 5755da14cebeSEric Cheng case MAC_RING_TYPE_RX: 5756da14cebeSEric Cheng dev_gindex = nxge->pt_config.hw_config.def_mac_rxdma_grpid + 5757da14cebeSEric Cheng rgroup->gindex; 5758da14cebeSEric Cheng rdc_grp = &nxge->pt_config.rdc_grps[dev_gindex]; 5759da14cebeSEric Cheng channel = rdc_grp->start_rdc + rhandle->index; 5760da14cebeSEric Cheng nxge_grp_dc_remove(nxge, VP_BOUND_RX, channel); 5761da14cebeSEric Cheng 5762da14cebeSEric Cheng rdc_grp->map &= ~(1 << channel); 5763da14cebeSEric Cheng rdc_grp->max_rdcs--; 5764da14cebeSEric Cheng 57654ba491f5SMichael Speer (void) nxge_init_fzc_rdc_tbl(nxge, rdc_grp, rgroup->rdctbl); 5766da14cebeSEric Cheng break; 5767da14cebeSEric Cheng } 5768da14cebeSEric Cheng } 5769da14cebeSEric Cheng 5770da14cebeSEric Cheng 577144961713Sgirish /*ARGSUSED*/ 577244961713Sgirish static nxge_status_t 577344961713Sgirish nxge_add_intrs(p_nxge_t nxgep) 577444961713Sgirish { 577544961713Sgirish 577644961713Sgirish int intr_types; 577744961713Sgirish int type = 0; 577844961713Sgirish int ddi_status = DDI_SUCCESS; 577944961713Sgirish nxge_status_t status = NXGE_OK; 578044961713Sgirish 578144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs")); 578244961713Sgirish 578344961713Sgirish nxgep->nxge_intr_type.intr_registered = B_FALSE; 578444961713Sgirish nxgep->nxge_intr_type.intr_enabled = B_FALSE; 578544961713Sgirish nxgep->nxge_intr_type.msi_intx_cnt = 0; 578644961713Sgirish nxgep->nxge_intr_type.intr_added = 0; 578744961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_FALSE; 578844961713Sgirish nxgep->nxge_intr_type.intr_type = 0; 578944961713Sgirish 579044961713Sgirish if (nxgep->niu_type == N2_NIU) { 579144961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 579244961713Sgirish } else if (nxge_msi_enable) { 579344961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 579444961713Sgirish } 579544961713Sgirish 579644961713Sgirish /* Get the supported interrupt types */ 579744961713Sgirish if ((ddi_status = ddi_intr_get_supported_types(nxgep->dip, &intr_types)) 57984045d941Ssowmini != DDI_SUCCESS) { 579944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_intrs: " 58004045d941Ssowmini "ddi_intr_get_supported_types failed: status 0x%08x", 58014045d941Ssowmini ddi_status)); 580244961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 580344961713Sgirish } 580444961713Sgirish nxgep->nxge_intr_type.intr_types = intr_types; 580544961713Sgirish 580644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 58074045d941Ssowmini "ddi_intr_get_supported_types: 0x%08x", intr_types)); 580844961713Sgirish 580944961713Sgirish /* 581044961713Sgirish * Solaris MSIX is not supported yet. use MSI for now. 581144961713Sgirish * nxge_msi_enable (1): 581244961713Sgirish * 1 - MSI 2 - MSI-X others - FIXED 581344961713Sgirish */ 581444961713Sgirish switch (nxge_msi_enable) { 581544961713Sgirish default: 581644961713Sgirish type = DDI_INTR_TYPE_FIXED; 581744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 58184045d941Ssowmini "use fixed (intx emulation) type %08x", 58194045d941Ssowmini type)); 582044961713Sgirish break; 582144961713Sgirish 582244961713Sgirish case 2: 582344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 58244045d941Ssowmini "ddi_intr_get_supported_types: 0x%08x", intr_types)); 582544961713Sgirish if (intr_types & DDI_INTR_TYPE_MSIX) { 582644961713Sgirish type = DDI_INTR_TYPE_MSIX; 582744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 58284045d941Ssowmini "ddi_intr_get_supported_types: MSIX 0x%08x", 58294045d941Ssowmini type)); 583044961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSI) { 583144961713Sgirish type = DDI_INTR_TYPE_MSI; 583244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 58334045d941Ssowmini "ddi_intr_get_supported_types: MSI 0x%08x", 58344045d941Ssowmini type)); 583544961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 583644961713Sgirish type = DDI_INTR_TYPE_FIXED; 583744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 58384045d941Ssowmini "ddi_intr_get_supported_types: MSXED0x%08x", 58394045d941Ssowmini type)); 584044961713Sgirish } 584144961713Sgirish break; 584244961713Sgirish 584344961713Sgirish case 1: 584444961713Sgirish if (intr_types & DDI_INTR_TYPE_MSI) { 584544961713Sgirish type = DDI_INTR_TYPE_MSI; 584644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 58474045d941Ssowmini "ddi_intr_get_supported_types: MSI 0x%08x", 58484045d941Ssowmini type)); 584944961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSIX) { 585044961713Sgirish type = DDI_INTR_TYPE_MSIX; 585144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 58524045d941Ssowmini "ddi_intr_get_supported_types: MSIX 0x%08x", 58534045d941Ssowmini type)); 585444961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 585544961713Sgirish type = DDI_INTR_TYPE_FIXED; 585644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 58574045d941Ssowmini "ddi_intr_get_supported_types: MSXED0x%08x", 58584045d941Ssowmini type)); 585944961713Sgirish } 586044961713Sgirish } 586144961713Sgirish 586244961713Sgirish nxgep->nxge_intr_type.intr_type = type; 586344961713Sgirish if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI || 58644045d941Ssowmini type == DDI_INTR_TYPE_FIXED) && 58654045d941Ssowmini nxgep->nxge_intr_type.niu_msi_enable) { 586644961713Sgirish if ((status = nxge_add_intrs_adv(nxgep)) != DDI_SUCCESS) { 586744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58684045d941Ssowmini " nxge_add_intrs: " 58694045d941Ssowmini " nxge_add_intrs_adv failed: status 0x%08x", 58704045d941Ssowmini status)); 587144961713Sgirish return (status); 587244961713Sgirish } else { 587344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 58744045d941Ssowmini "interrupts registered : type %d", type)); 587544961713Sgirish nxgep->nxge_intr_type.intr_registered = B_TRUE; 587644961713Sgirish 587744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 58784045d941Ssowmini "\nAdded advanced nxge add_intr_adv " 58794045d941Ssowmini "intr type 0x%x\n", type)); 588044961713Sgirish 588144961713Sgirish return (status); 588244961713Sgirish } 588344961713Sgirish } 588444961713Sgirish 588544961713Sgirish if (!nxgep->nxge_intr_type.intr_registered) { 588644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_add_intrs: " 58874045d941Ssowmini "failed to register interrupts")); 588844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 588944961713Sgirish } 589044961713Sgirish 589144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_add_intrs")); 589244961713Sgirish return (status); 589344961713Sgirish } 589444961713Sgirish 589544961713Sgirish static nxge_status_t 589644961713Sgirish nxge_add_intrs_adv(p_nxge_t nxgep) 589744961713Sgirish { 589844961713Sgirish int intr_type; 589944961713Sgirish p_nxge_intr_t intrp; 590044961713Sgirish 590144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv")); 590244961713Sgirish 590344961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 590444961713Sgirish intr_type = intrp->intr_type; 590544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv: type 0x%x", 59064045d941Ssowmini intr_type)); 590744961713Sgirish 590844961713Sgirish switch (intr_type) { 590944961713Sgirish case DDI_INTR_TYPE_MSI: /* 0x2 */ 591044961713Sgirish case DDI_INTR_TYPE_MSIX: /* 0x4 */ 591144961713Sgirish return (nxge_add_intrs_adv_type(nxgep, intr_type)); 591244961713Sgirish 591344961713Sgirish case DDI_INTR_TYPE_FIXED: /* 0x1 */ 591444961713Sgirish return (nxge_add_intrs_adv_type_fix(nxgep, intr_type)); 591544961713Sgirish 591644961713Sgirish default: 591744961713Sgirish return (NXGE_ERROR); 591844961713Sgirish } 591944961713Sgirish } 592044961713Sgirish 592144961713Sgirish 592244961713Sgirish /*ARGSUSED*/ 592344961713Sgirish static nxge_status_t 592444961713Sgirish nxge_add_intrs_adv_type(p_nxge_t nxgep, uint32_t int_type) 592544961713Sgirish { 592644961713Sgirish dev_info_t *dip = nxgep->dip; 592744961713Sgirish p_nxge_ldg_t ldgp; 592844961713Sgirish p_nxge_intr_t intrp; 592944961713Sgirish uint_t *inthandler; 593044961713Sgirish void *arg1, *arg2; 593144961713Sgirish int behavior; 5932ec090658Sml int nintrs, navail, nrequest; 593344961713Sgirish int nactual, nrequired; 593444961713Sgirish int inum = 0; 593544961713Sgirish int x, y; 593644961713Sgirish int ddi_status = DDI_SUCCESS; 593744961713Sgirish nxge_status_t status = NXGE_OK; 593844961713Sgirish 593944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type")); 594044961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 594144961713Sgirish intrp->start_inum = 0; 594244961713Sgirish 594344961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 594444961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 594544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59464045d941Ssowmini "ddi_intr_get_nintrs() failed, status: 0x%x%, " 59474045d941Ssowmini "nintrs: %d", ddi_status, nintrs)); 594844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 594944961713Sgirish } 595044961713Sgirish 595144961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 595244961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 595344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59544045d941Ssowmini "ddi_intr_get_navail() failed, status: 0x%x%, " 59554045d941Ssowmini "nintrs: %d", ddi_status, navail)); 595644961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 595744961713Sgirish } 595844961713Sgirish 595944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 59604045d941Ssowmini "ddi_intr_get_navail() returned: nintrs %d, navail %d", 59614045d941Ssowmini nintrs, navail)); 596244961713Sgirish 5963ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override */ 5964ec090658Sml if (int_type == DDI_INTR_TYPE_MSIX) { 5965ec090658Sml nrequest = nxge_create_msi_property(nxgep); 5966ec090658Sml if (nrequest < navail) { 5967ec090658Sml navail = nrequest; 5968ec090658Sml NXGE_DEBUG_MSG((nxgep, INT_CTL, 5969ec090658Sml "nxge_add_intrs_adv_type: nintrs %d " 5970ec090658Sml "navail %d (nrequest %d)", 5971ec090658Sml nintrs, navail, nrequest)); 5972ec090658Sml } 5973ec090658Sml } 5974ec090658Sml 597544961713Sgirish if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) { 597644961713Sgirish /* MSI must be power of 2 */ 597744961713Sgirish if ((navail & 16) == 16) { 597844961713Sgirish navail = 16; 597944961713Sgirish } else if ((navail & 8) == 8) { 598044961713Sgirish navail = 8; 598144961713Sgirish } else if ((navail & 4) == 4) { 598244961713Sgirish navail = 4; 598344961713Sgirish } else if ((navail & 2) == 2) { 598444961713Sgirish navail = 2; 598544961713Sgirish } else { 598644961713Sgirish navail = 1; 598744961713Sgirish } 598844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 59894045d941Ssowmini "ddi_intr_get_navail(): (msi power of 2) nintrs %d, " 59904045d941Ssowmini "navail %d", nintrs, navail)); 599144961713Sgirish } 599244961713Sgirish 599344961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 59944045d941Ssowmini DDI_INTR_ALLOC_NORMAL); 599544961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 599644961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 599744961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 59984045d941Ssowmini navail, &nactual, behavior); 599944961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 600044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60014045d941Ssowmini " ddi_intr_alloc() failed: %d", 60024045d941Ssowmini ddi_status)); 600344961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 600444961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 600544961713Sgirish } 600644961713Sgirish 600744961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 60084045d941Ssowmini (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 600944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60104045d941Ssowmini " ddi_intr_get_pri() failed: %d", 60114045d941Ssowmini ddi_status)); 601244961713Sgirish /* Free already allocated interrupts */ 601344961713Sgirish for (y = 0; y < nactual; y++) { 601444961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 601544961713Sgirish } 601644961713Sgirish 601744961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 601844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 601944961713Sgirish } 602044961713Sgirish 602144961713Sgirish nrequired = 0; 602244961713Sgirish switch (nxgep->niu_type) { 602344961713Sgirish default: 602444961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 602544961713Sgirish break; 602644961713Sgirish 602744961713Sgirish case N2_NIU: 602844961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 602944961713Sgirish break; 603044961713Sgirish } 603144961713Sgirish 603244961713Sgirish if (status != NXGE_OK) { 603344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60344045d941Ssowmini "nxge_add_intrs_adv_typ:nxge_ldgv_init " 60354045d941Ssowmini "failed: 0x%x", status)); 603644961713Sgirish /* Free already allocated interrupts */ 603744961713Sgirish for (y = 0; y < nactual; y++) { 603844961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 603944961713Sgirish } 604044961713Sgirish 604144961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 604244961713Sgirish return (status); 604344961713Sgirish } 604444961713Sgirish 604544961713Sgirish ldgp = nxgep->ldgvp->ldgp; 604644961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 604744961713Sgirish ldgp->vector = (uint8_t)x; 604844961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 604944961713Sgirish arg1 = ldgp->ldvp; 605044961713Sgirish arg2 = nxgep; 605144961713Sgirish if (ldgp->nldvs == 1) { 605244961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 605344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 60544045d941Ssowmini "nxge_add_intrs_adv_type: " 60554045d941Ssowmini "arg1 0x%x arg2 0x%x: " 60564045d941Ssowmini "1-1 int handler (entry %d intdata 0x%x)\n", 60574045d941Ssowmini arg1, arg2, 60584045d941Ssowmini x, ldgp->intdata)); 605944961713Sgirish } else if (ldgp->nldvs > 1) { 606044961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 606144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 60624045d941Ssowmini "nxge_add_intrs_adv_type: " 60634045d941Ssowmini "arg1 0x%x arg2 0x%x: " 60644045d941Ssowmini "nldevs %d int handler " 60654045d941Ssowmini "(entry %d intdata 0x%x)\n", 60664045d941Ssowmini arg1, arg2, 60674045d941Ssowmini ldgp->nldvs, x, ldgp->intdata)); 606844961713Sgirish } 606944961713Sgirish 607044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 60714045d941Ssowmini "==> nxge_add_intrs_adv_type: ddi_add_intr(inum) #%d " 60724045d941Ssowmini "htable 0x%llx", x, intrp->htable[x])); 607344961713Sgirish 607444961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 60754045d941Ssowmini (ddi_intr_handler_t *)inthandler, arg1, arg2)) 60764045d941Ssowmini != DDI_SUCCESS) { 607744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60784045d941Ssowmini "==> nxge_add_intrs_adv_type: failed #%d " 60794045d941Ssowmini "status 0x%x", x, ddi_status)); 608044961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 608144961713Sgirish (void) ddi_intr_remove_handler( 60824045d941Ssowmini intrp->htable[y]); 608344961713Sgirish } 608444961713Sgirish /* Free already allocated intr */ 608544961713Sgirish for (y = 0; y < nactual; y++) { 608644961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 608744961713Sgirish } 608844961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 608944961713Sgirish 609044961713Sgirish (void) nxge_ldgv_uninit(nxgep); 609144961713Sgirish 609244961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 609344961713Sgirish } 609444961713Sgirish intrp->intr_added++; 609544961713Sgirish } 609644961713Sgirish 609744961713Sgirish intrp->msi_intx_cnt = nactual; 609844961713Sgirish 609944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 61004045d941Ssowmini "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d", 61014045d941Ssowmini navail, nactual, 61024045d941Ssowmini intrp->msi_intx_cnt, 61034045d941Ssowmini intrp->intr_added)); 610444961713Sgirish 610544961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 610644961713Sgirish 610744961713Sgirish (void) nxge_intr_ldgv_init(nxgep); 610844961713Sgirish 610944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type")); 611044961713Sgirish 611144961713Sgirish return (status); 611244961713Sgirish } 611344961713Sgirish 611444961713Sgirish /*ARGSUSED*/ 611544961713Sgirish static nxge_status_t 611644961713Sgirish nxge_add_intrs_adv_type_fix(p_nxge_t nxgep, uint32_t int_type) 611744961713Sgirish { 611844961713Sgirish dev_info_t *dip = nxgep->dip; 611944961713Sgirish p_nxge_ldg_t ldgp; 612044961713Sgirish p_nxge_intr_t intrp; 612144961713Sgirish uint_t *inthandler; 612244961713Sgirish void *arg1, *arg2; 612344961713Sgirish int behavior; 612444961713Sgirish int nintrs, navail; 612544961713Sgirish int nactual, nrequired; 612644961713Sgirish int inum = 0; 612744961713Sgirish int x, y; 612844961713Sgirish int ddi_status = DDI_SUCCESS; 612944961713Sgirish nxge_status_t status = NXGE_OK; 613044961713Sgirish 613144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type_fix")); 613244961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 613344961713Sgirish intrp->start_inum = 0; 613444961713Sgirish 613544961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 613644961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 613744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 61384045d941Ssowmini "ddi_intr_get_nintrs() failed, status: 0x%x%, " 61394045d941Ssowmini "nintrs: %d", status, nintrs)); 614044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 614144961713Sgirish } 614244961713Sgirish 614344961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 614444961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 614544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61464045d941Ssowmini "ddi_intr_get_navail() failed, status: 0x%x%, " 61474045d941Ssowmini "nintrs: %d", ddi_status, navail)); 614844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 614944961713Sgirish } 615044961713Sgirish 615144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 61524045d941Ssowmini "ddi_intr_get_navail() returned: nintrs %d, naavail %d", 61534045d941Ssowmini nintrs, navail)); 615444961713Sgirish 615544961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 61564045d941Ssowmini DDI_INTR_ALLOC_NORMAL); 615744961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 615844961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 615944961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 61604045d941Ssowmini navail, &nactual, behavior); 616144961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 616244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61634045d941Ssowmini " ddi_intr_alloc() failed: %d", 61644045d941Ssowmini ddi_status)); 616544961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 616644961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 616744961713Sgirish } 616844961713Sgirish 616944961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 61704045d941Ssowmini (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 617144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61724045d941Ssowmini " ddi_intr_get_pri() failed: %d", 61734045d941Ssowmini ddi_status)); 617444961713Sgirish /* Free already allocated interrupts */ 617544961713Sgirish for (y = 0; y < nactual; y++) { 617644961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 617744961713Sgirish } 617844961713Sgirish 617944961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 618044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 618144961713Sgirish } 618244961713Sgirish 618344961713Sgirish nrequired = 0; 618444961713Sgirish switch (nxgep->niu_type) { 618544961713Sgirish default: 618644961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 618744961713Sgirish break; 618844961713Sgirish 618944961713Sgirish case N2_NIU: 619044961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 619144961713Sgirish break; 619244961713Sgirish } 619344961713Sgirish 619444961713Sgirish if (status != NXGE_OK) { 619544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61964045d941Ssowmini "nxge_add_intrs_adv_type_fix:nxge_ldgv_init " 61974045d941Ssowmini "failed: 0x%x", status)); 619844961713Sgirish /* Free already allocated interrupts */ 619944961713Sgirish for (y = 0; y < nactual; y++) { 620044961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 620144961713Sgirish } 620244961713Sgirish 620344961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 620444961713Sgirish return (status); 620544961713Sgirish } 620644961713Sgirish 620744961713Sgirish ldgp = nxgep->ldgvp->ldgp; 620844961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 620944961713Sgirish ldgp->vector = (uint8_t)x; 621044961713Sgirish if (nxgep->niu_type != N2_NIU) { 621144961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 621244961713Sgirish } 621344961713Sgirish 621444961713Sgirish arg1 = ldgp->ldvp; 621544961713Sgirish arg2 = nxgep; 621644961713Sgirish if (ldgp->nldvs == 1) { 621744961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 621844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 62194045d941Ssowmini "nxge_add_intrs_adv_type_fix: " 62204045d941Ssowmini "1-1 int handler(%d) ldg %d ldv %d " 62214045d941Ssowmini "arg1 $%p arg2 $%p\n", 62224045d941Ssowmini x, ldgp->ldg, ldgp->ldvp->ldv, 62234045d941Ssowmini arg1, arg2)); 622444961713Sgirish } else if (ldgp->nldvs > 1) { 622544961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 622644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 62274045d941Ssowmini "nxge_add_intrs_adv_type_fix: " 62284045d941Ssowmini "shared ldv %d int handler(%d) ldv %d ldg %d" 62294045d941Ssowmini "arg1 0x%016llx arg2 0x%016llx\n", 62304045d941Ssowmini x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv, 62314045d941Ssowmini arg1, arg2)); 623244961713Sgirish } 623344961713Sgirish 623444961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 62354045d941Ssowmini (ddi_intr_handler_t *)inthandler, arg1, arg2)) 62364045d941Ssowmini != DDI_SUCCESS) { 623744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 62384045d941Ssowmini "==> nxge_add_intrs_adv_type_fix: failed #%d " 62394045d941Ssowmini "status 0x%x", x, ddi_status)); 624044961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 624144961713Sgirish (void) ddi_intr_remove_handler( 62424045d941Ssowmini intrp->htable[y]); 624344961713Sgirish } 624444961713Sgirish for (y = 0; y < nactual; y++) { 624544961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 624644961713Sgirish } 624744961713Sgirish /* Free already allocated intr */ 624844961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 624944961713Sgirish 625044961713Sgirish (void) nxge_ldgv_uninit(nxgep); 625144961713Sgirish 625244961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 625344961713Sgirish } 625444961713Sgirish intrp->intr_added++; 625544961713Sgirish } 625644961713Sgirish 625744961713Sgirish intrp->msi_intx_cnt = nactual; 625844961713Sgirish 625944961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 626044961713Sgirish 626144961713Sgirish status = nxge_intr_ldgv_init(nxgep); 626244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type_fix")); 626344961713Sgirish 626444961713Sgirish return (status); 626544961713Sgirish } 626644961713Sgirish 626744961713Sgirish static void 626844961713Sgirish nxge_remove_intrs(p_nxge_t nxgep) 626944961713Sgirish { 627044961713Sgirish int i, inum; 627144961713Sgirish p_nxge_intr_t intrp; 627244961713Sgirish 627344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs")); 627444961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 627544961713Sgirish if (!intrp->intr_registered) { 627644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 62774045d941Ssowmini "<== nxge_remove_intrs: interrupts not registered")); 627844961713Sgirish return; 627944961713Sgirish } 628044961713Sgirish 628144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs:advanced")); 628244961713Sgirish 628344961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 628444961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 62854045d941Ssowmini intrp->intr_added); 628644961713Sgirish } else { 628744961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 628844961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 628944961713Sgirish } 629044961713Sgirish } 629144961713Sgirish 629244961713Sgirish for (inum = 0; inum < intrp->intr_added; inum++) { 629344961713Sgirish if (intrp->htable[inum]) { 629444961713Sgirish (void) ddi_intr_remove_handler(intrp->htable[inum]); 629544961713Sgirish } 629644961713Sgirish } 629744961713Sgirish 629844961713Sgirish for (inum = 0; inum < intrp->msi_intx_cnt; inum++) { 629944961713Sgirish if (intrp->htable[inum]) { 630044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 63014045d941Ssowmini "nxge_remove_intrs: ddi_intr_free inum %d " 63024045d941Ssowmini "msi_intx_cnt %d intr_added %d", 63034045d941Ssowmini inum, 63044045d941Ssowmini intrp->msi_intx_cnt, 63054045d941Ssowmini intrp->intr_added)); 630644961713Sgirish 630744961713Sgirish (void) ddi_intr_free(intrp->htable[inum]); 630844961713Sgirish } 630944961713Sgirish } 631044961713Sgirish 631144961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 631244961713Sgirish intrp->intr_registered = B_FALSE; 631344961713Sgirish intrp->intr_enabled = B_FALSE; 631444961713Sgirish intrp->msi_intx_cnt = 0; 631544961713Sgirish intrp->intr_added = 0; 631644961713Sgirish 6317a3c5bd6dSspeer (void) nxge_ldgv_uninit(nxgep); 6318a3c5bd6dSspeer 6319ec090658Sml (void) ddi_prop_remove(DDI_DEV_T_NONE, nxgep->dip, 6320ec090658Sml "#msix-request"); 6321ec090658Sml 632244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_intrs")); 632344961713Sgirish } 632444961713Sgirish 632544961713Sgirish /*ARGSUSED*/ 632644961713Sgirish static void 632744961713Sgirish nxge_intrs_enable(p_nxge_t nxgep) 632844961713Sgirish { 632944961713Sgirish p_nxge_intr_t intrp; 633044961713Sgirish int i; 633144961713Sgirish int status; 633244961713Sgirish 633344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable")); 633444961713Sgirish 633544961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 633644961713Sgirish 633744961713Sgirish if (!intrp->intr_registered) { 633844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_intrs_enable: " 63394045d941Ssowmini "interrupts are not registered")); 634044961713Sgirish return; 634144961713Sgirish } 634244961713Sgirish 634344961713Sgirish if (intrp->intr_enabled) { 634444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 63454045d941Ssowmini "<== nxge_intrs_enable: already enabled")); 634644961713Sgirish return; 634744961713Sgirish } 634844961713Sgirish 634944961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 635044961713Sgirish status = ddi_intr_block_enable(intrp->htable, 63514045d941Ssowmini intrp->intr_added); 635244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 63534045d941Ssowmini "block enable - status 0x%x total inums #%d\n", 63544045d941Ssowmini status, intrp->intr_added)); 635544961713Sgirish } else { 635644961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 635744961713Sgirish status = ddi_intr_enable(intrp->htable[i]); 635844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 63594045d941Ssowmini "ddi_intr_enable:enable - status 0x%x " 63604045d941Ssowmini "total inums %d enable inum #%d\n", 63614045d941Ssowmini status, intrp->intr_added, i)); 636244961713Sgirish if (status == DDI_SUCCESS) { 636344961713Sgirish intrp->intr_enabled = B_TRUE; 636444961713Sgirish } 636544961713Sgirish } 636644961713Sgirish } 636744961713Sgirish 636844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_enable")); 636944961713Sgirish } 637044961713Sgirish 637144961713Sgirish /*ARGSUSED*/ 637244961713Sgirish static void 637344961713Sgirish nxge_intrs_disable(p_nxge_t nxgep) 637444961713Sgirish { 637544961713Sgirish p_nxge_intr_t intrp; 637644961713Sgirish int i; 637744961713Sgirish 637844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_disable")); 637944961713Sgirish 638044961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 638144961713Sgirish 638244961713Sgirish if (!intrp->intr_registered) { 638344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable: " 63844045d941Ssowmini "interrupts are not registered")); 638544961713Sgirish return; 638644961713Sgirish } 638744961713Sgirish 638844961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 638944961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 63904045d941Ssowmini intrp->intr_added); 639144961713Sgirish } else { 639244961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 639344961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 639444961713Sgirish } 639544961713Sgirish } 639644961713Sgirish 639744961713Sgirish intrp->intr_enabled = B_FALSE; 639844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable")); 639944961713Sgirish } 640044961713Sgirish 640163f531d1SSriharsha Basavapatna nxge_status_t 640244961713Sgirish nxge_mac_register(p_nxge_t nxgep) 640344961713Sgirish { 640444961713Sgirish mac_register_t *macp; 640544961713Sgirish int status; 640644961713Sgirish 640744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_mac_register")); 640844961713Sgirish 640944961713Sgirish if ((macp = mac_alloc(MAC_VERSION)) == NULL) 641044961713Sgirish return (NXGE_ERROR); 641144961713Sgirish 641244961713Sgirish macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 641344961713Sgirish macp->m_driver = nxgep; 641444961713Sgirish macp->m_dip = nxgep->dip; 641563f531d1SSriharsha Basavapatna if (!isLDOMguest(nxgep)) { 641663f531d1SSriharsha Basavapatna macp->m_src_addr = nxgep->ouraddr.ether_addr_octet; 641763f531d1SSriharsha Basavapatna } else { 641863f531d1SSriharsha Basavapatna macp->m_src_addr = KMEM_ZALLOC(MAXMACADDRLEN, KM_SLEEP); 641963f531d1SSriharsha Basavapatna macp->m_dst_addr = KMEM_ZALLOC(MAXMACADDRLEN, KM_SLEEP); 642063f531d1SSriharsha Basavapatna (void) memset(macp->m_src_addr, 0xff, sizeof (MAXMACADDRLEN)); 642163f531d1SSriharsha Basavapatna } 642244961713Sgirish macp->m_callbacks = &nxge_m_callbacks; 642344961713Sgirish macp->m_min_sdu = 0; 64241bd6825cSml nxgep->mac.default_mtu = nxgep->mac.maxframesize - 64251bd6825cSml NXGE_EHEADER_VLAN_CRC; 64261bd6825cSml macp->m_max_sdu = nxgep->mac.default_mtu; 6427d62bc4baSyz macp->m_margin = VLAN_TAGSZ; 64284045d941Ssowmini macp->m_priv_props = nxge_priv_props; 64294045d941Ssowmini macp->m_priv_prop_count = NXGE_MAX_PRIV_PROPS; 643063f531d1SSriharsha Basavapatna if (isLDOMguest(nxgep)) { 643163f531d1SSriharsha Basavapatna macp->m_v12n = MAC_VIRT_LEVEL1 | MAC_VIRT_SERIALIZE; 643263f531d1SSriharsha Basavapatna } else { 643363f531d1SSriharsha Basavapatna macp->m_v12n = MAC_VIRT_HIO | MAC_VIRT_LEVEL1 | \ 643463f531d1SSriharsha Basavapatna MAC_VIRT_SERIALIZE; 643563f531d1SSriharsha Basavapatna } 643644961713Sgirish 64371bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 64381bd6825cSml "==> nxge_mac_register: instance %d " 64391bd6825cSml "max_sdu %d margin %d maxframe %d (header %d)", 64401bd6825cSml nxgep->instance, 64411bd6825cSml macp->m_max_sdu, macp->m_margin, 64421bd6825cSml nxgep->mac.maxframesize, 64431bd6825cSml NXGE_EHEADER_VLAN_CRC)); 64441bd6825cSml 644544961713Sgirish status = mac_register(macp, &nxgep->mach); 644663f531d1SSriharsha Basavapatna if (isLDOMguest(nxgep)) { 644763f531d1SSriharsha Basavapatna KMEM_FREE(macp->m_src_addr, MAXMACADDRLEN); 644863f531d1SSriharsha Basavapatna KMEM_FREE(macp->m_dst_addr, MAXMACADDRLEN); 644963f531d1SSriharsha Basavapatna } 645044961713Sgirish mac_free(macp); 645144961713Sgirish 645244961713Sgirish if (status != 0) { 645344961713Sgirish cmn_err(CE_WARN, 64544045d941Ssowmini "!nxge_mac_register failed (status %d instance %d)", 64554045d941Ssowmini status, nxgep->instance); 645644961713Sgirish return (NXGE_ERROR); 645744961713Sgirish } 645844961713Sgirish 645944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_mac_register success " 64604045d941Ssowmini "(instance %d)", nxgep->instance)); 646144961713Sgirish 646244961713Sgirish return (NXGE_OK); 646344961713Sgirish } 646444961713Sgirish 646544961713Sgirish void 646644961713Sgirish nxge_err_inject(p_nxge_t nxgep, queue_t *wq, mblk_t *mp) 646744961713Sgirish { 646844961713Sgirish ssize_t size; 646944961713Sgirish mblk_t *nmp; 647044961713Sgirish uint8_t blk_id; 647144961713Sgirish uint8_t chan; 647244961713Sgirish uint32_t err_id; 647344961713Sgirish err_inject_t *eip; 647444961713Sgirish 647544961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_err_inject")); 647644961713Sgirish 647744961713Sgirish size = 1024; 647844961713Sgirish nmp = mp->b_cont; 647944961713Sgirish eip = (err_inject_t *)nmp->b_rptr; 648044961713Sgirish blk_id = eip->blk_id; 648144961713Sgirish err_id = eip->err_id; 648244961713Sgirish chan = eip->chan; 648344961713Sgirish cmn_err(CE_NOTE, "!blk_id = 0x%x\n", blk_id); 648444961713Sgirish cmn_err(CE_NOTE, "!err_id = 0x%x\n", err_id); 648544961713Sgirish cmn_err(CE_NOTE, "!chan = 0x%x\n", chan); 648644961713Sgirish switch (blk_id) { 648744961713Sgirish case MAC_BLK_ID: 648844961713Sgirish break; 648944961713Sgirish case TXMAC_BLK_ID: 649044961713Sgirish break; 649144961713Sgirish case RXMAC_BLK_ID: 649244961713Sgirish break; 649344961713Sgirish case MIF_BLK_ID: 649444961713Sgirish break; 649544961713Sgirish case IPP_BLK_ID: 649644961713Sgirish nxge_ipp_inject_err(nxgep, err_id); 649744961713Sgirish break; 649844961713Sgirish case TXC_BLK_ID: 649944961713Sgirish nxge_txc_inject_err(nxgep, err_id); 650044961713Sgirish break; 650144961713Sgirish case TXDMA_BLK_ID: 650244961713Sgirish nxge_txdma_inject_err(nxgep, err_id, chan); 650344961713Sgirish break; 650444961713Sgirish case RXDMA_BLK_ID: 650544961713Sgirish nxge_rxdma_inject_err(nxgep, err_id, chan); 650644961713Sgirish break; 650744961713Sgirish case ZCP_BLK_ID: 650844961713Sgirish nxge_zcp_inject_err(nxgep, err_id); 650944961713Sgirish break; 651044961713Sgirish case ESPC_BLK_ID: 651144961713Sgirish break; 651244961713Sgirish case FFLP_BLK_ID: 651344961713Sgirish break; 651444961713Sgirish case PHY_BLK_ID: 651544961713Sgirish break; 651644961713Sgirish case ETHER_SERDES_BLK_ID: 651744961713Sgirish break; 651844961713Sgirish case PCIE_SERDES_BLK_ID: 651944961713Sgirish break; 652044961713Sgirish case VIR_BLK_ID: 652144961713Sgirish break; 652244961713Sgirish } 652344961713Sgirish 652444961713Sgirish nmp->b_wptr = nmp->b_rptr + size; 652544961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_err_inject")); 652644961713Sgirish 652744961713Sgirish miocack(wq, mp, (int)size, 0); 652844961713Sgirish } 652944961713Sgirish 653044961713Sgirish static int 653144961713Sgirish nxge_init_common_dev(p_nxge_t nxgep) 653244961713Sgirish { 653344961713Sgirish p_nxge_hw_list_t hw_p; 653444961713Sgirish dev_info_t *p_dip; 653544961713Sgirish 6536*ef523517SMichael Speer ASSERT(nxgep != NULL); 6537*ef523517SMichael Speer 653844961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_init_common_device")); 653944961713Sgirish 654044961713Sgirish p_dip = nxgep->p_dip; 654144961713Sgirish MUTEX_ENTER(&nxge_common_lock); 654244961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65434045d941Ssowmini "==> nxge_init_common_dev:func # %d", 65444045d941Ssowmini nxgep->function_num)); 654544961713Sgirish /* 654644961713Sgirish * Loop through existing per neptune hardware list. 654744961713Sgirish */ 654844961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 654944961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65504045d941Ssowmini "==> nxge_init_common_device:func # %d " 65514045d941Ssowmini "hw_p $%p parent dip $%p", 65524045d941Ssowmini nxgep->function_num, 65534045d941Ssowmini hw_p, 65544045d941Ssowmini p_dip)); 655544961713Sgirish if (hw_p->parent_devp == p_dip) { 655644961713Sgirish nxgep->nxge_hw_p = hw_p; 655744961713Sgirish hw_p->ndevs++; 655844961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 655944961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65604045d941Ssowmini "==> nxge_init_common_device:func # %d " 65614045d941Ssowmini "hw_p $%p parent dip $%p " 65624045d941Ssowmini "ndevs %d (found)", 65634045d941Ssowmini nxgep->function_num, 65644045d941Ssowmini hw_p, 65654045d941Ssowmini p_dip, 65664045d941Ssowmini hw_p->ndevs)); 656744961713Sgirish break; 656844961713Sgirish } 656944961713Sgirish } 657044961713Sgirish 657144961713Sgirish if (hw_p == NULL) { 657223b952a3SSantwona Behera 657323b952a3SSantwona Behera char **prop_val; 657423b952a3SSantwona Behera uint_t prop_len; 657523b952a3SSantwona Behera int i; 657623b952a3SSantwona Behera 657744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65784045d941Ssowmini "==> nxge_init_common_device:func # %d " 65794045d941Ssowmini "parent dip $%p (new)", 65804045d941Ssowmini nxgep->function_num, 65814045d941Ssowmini p_dip)); 658244961713Sgirish hw_p = kmem_zalloc(sizeof (nxge_hw_list_t), KM_SLEEP); 658344961713Sgirish hw_p->parent_devp = p_dip; 658444961713Sgirish hw_p->magic = NXGE_NEPTUNE_MAGIC; 658544961713Sgirish nxgep->nxge_hw_p = hw_p; 658644961713Sgirish hw_p->ndevs++; 658744961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 658844961713Sgirish hw_p->next = nxge_hw_list; 658959ac0c16Sdavemq if (nxgep->niu_type == N2_NIU) { 659059ac0c16Sdavemq hw_p->niu_type = N2_NIU; 659159ac0c16Sdavemq hw_p->platform_type = P_NEPTUNE_NIU; 659259ac0c16Sdavemq } else { 659359ac0c16Sdavemq hw_p->niu_type = NIU_TYPE_NONE; 65942e59129aSraghus hw_p->platform_type = P_NEPTUNE_NONE; 659559ac0c16Sdavemq } 659644961713Sgirish 659744961713Sgirish MUTEX_INIT(&hw_p->nxge_cfg_lock, NULL, MUTEX_DRIVER, NULL); 659844961713Sgirish MUTEX_INIT(&hw_p->nxge_tcam_lock, NULL, MUTEX_DRIVER, NULL); 659944961713Sgirish MUTEX_INIT(&hw_p->nxge_vlan_lock, NULL, MUTEX_DRIVER, NULL); 660044961713Sgirish MUTEX_INIT(&hw_p->nxge_mdio_lock, NULL, MUTEX_DRIVER, NULL); 660144961713Sgirish 660244961713Sgirish nxge_hw_list = hw_p; 660359ac0c16Sdavemq 660423b952a3SSantwona Behera if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, nxgep->dip, 0, 660523b952a3SSantwona Behera "compatible", &prop_val, &prop_len) == DDI_PROP_SUCCESS) { 660623b952a3SSantwona Behera for (i = 0; i < prop_len; i++) { 660723b952a3SSantwona Behera if ((strcmp((caddr_t)prop_val[i], 660823b952a3SSantwona Behera NXGE_ROCK_COMPATIBLE) == 0)) { 660923b952a3SSantwona Behera hw_p->platform_type = P_NEPTUNE_ROCK; 661023b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MOD_CTL, 661123b952a3SSantwona Behera "ROCK hw_p->platform_type %d", 661223b952a3SSantwona Behera hw_p->platform_type)); 661323b952a3SSantwona Behera break; 661423b952a3SSantwona Behera } 661523b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MOD_CTL, 661623b952a3SSantwona Behera "nxge_init_common_dev: read compatible" 661723b952a3SSantwona Behera " property[%d] val[%s]", 661823b952a3SSantwona Behera i, (caddr_t)prop_val[i])); 661923b952a3SSantwona Behera } 662023b952a3SSantwona Behera } 662123b952a3SSantwona Behera 662223b952a3SSantwona Behera ddi_prop_free(prop_val); 662323b952a3SSantwona Behera 662459ac0c16Sdavemq (void) nxge_scan_ports_phy(nxgep, nxge_hw_list); 662544961713Sgirish } 662644961713Sgirish 662744961713Sgirish MUTEX_EXIT(&nxge_common_lock); 662859ac0c16Sdavemq 66292e59129aSraghus nxgep->platform_type = hw_p->platform_type; 663023b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MOD_CTL, "nxgep->platform_type %d", 663123b952a3SSantwona Behera nxgep->platform_type)); 663259ac0c16Sdavemq if (nxgep->niu_type != N2_NIU) { 663359ac0c16Sdavemq nxgep->niu_type = hw_p->niu_type; 663459ac0c16Sdavemq } 663559ac0c16Sdavemq 663644961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66374045d941Ssowmini "==> nxge_init_common_device (nxge_hw_list) $%p", 66384045d941Ssowmini nxge_hw_list)); 663944961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<== nxge_init_common_device")); 664044961713Sgirish 664144961713Sgirish return (NXGE_OK); 664244961713Sgirish } 664344961713Sgirish 664444961713Sgirish static void 664544961713Sgirish nxge_uninit_common_dev(p_nxge_t nxgep) 664644961713Sgirish { 664744961713Sgirish p_nxge_hw_list_t hw_p, h_hw_p; 66480b0beae0Sspeer p_nxge_dma_pt_cfg_t p_dma_cfgp; 66490b0beae0Sspeer p_nxge_hw_pt_cfg_t p_cfgp; 665044961713Sgirish dev_info_t *p_dip; 665144961713Sgirish 6652*ef523517SMichael Speer ASSERT(nxgep != NULL); 6653*ef523517SMichael Speer 665444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_uninit_common_device")); 665544961713Sgirish if (nxgep->nxge_hw_p == NULL) { 665644961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66574045d941Ssowmini "<== nxge_uninit_common_device (no common)")); 665844961713Sgirish return; 665944961713Sgirish } 666044961713Sgirish 666144961713Sgirish MUTEX_ENTER(&nxge_common_lock); 666244961713Sgirish h_hw_p = nxge_hw_list; 666344961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 666444961713Sgirish p_dip = hw_p->parent_devp; 666544961713Sgirish if (nxgep->nxge_hw_p == hw_p && 66664045d941Ssowmini p_dip == nxgep->p_dip && 66674045d941Ssowmini nxgep->nxge_hw_p->magic == NXGE_NEPTUNE_MAGIC && 66684045d941Ssowmini hw_p->magic == NXGE_NEPTUNE_MAGIC) { 666944961713Sgirish 667044961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66714045d941Ssowmini "==> nxge_uninit_common_device:func # %d " 66724045d941Ssowmini "hw_p $%p parent dip $%p " 66734045d941Ssowmini "ndevs %d (found)", 66744045d941Ssowmini nxgep->function_num, 66754045d941Ssowmini hw_p, 66764045d941Ssowmini p_dip, 66774045d941Ssowmini hw_p->ndevs)); 667844961713Sgirish 66790b0beae0Sspeer /* 66800b0beae0Sspeer * Release the RDC table, a shared resoruce 66810b0beae0Sspeer * of the nxge hardware. The RDC table was 66820b0beae0Sspeer * assigned to this instance of nxge in 66830b0beae0Sspeer * nxge_use_cfg_dma_config(). 66840b0beae0Sspeer */ 66859d5b8bc5SMichael Speer if (!isLDOMguest(nxgep)) { 66869d5b8bc5SMichael Speer p_dma_cfgp = 66879d5b8bc5SMichael Speer (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 66889d5b8bc5SMichael Speer p_cfgp = 66899d5b8bc5SMichael Speer (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; 66909d5b8bc5SMichael Speer (void) nxge_fzc_rdc_tbl_unbind(nxgep, 66919d5b8bc5SMichael Speer p_cfgp->def_mac_rxdma_grpid); 6692651ce697SMichael Speer 6693651ce697SMichael Speer /* Cleanup any outstanding groups. */ 6694651ce697SMichael Speer nxge_grp_cleanup(nxgep); 66959d5b8bc5SMichael Speer } 66960b0beae0Sspeer 669744961713Sgirish if (hw_p->ndevs) { 669844961713Sgirish hw_p->ndevs--; 669944961713Sgirish } 670044961713Sgirish hw_p->nxge_p[nxgep->function_num] = NULL; 670144961713Sgirish if (!hw_p->ndevs) { 670244961713Sgirish MUTEX_DESTROY(&hw_p->nxge_vlan_lock); 670344961713Sgirish MUTEX_DESTROY(&hw_p->nxge_tcam_lock); 670444961713Sgirish MUTEX_DESTROY(&hw_p->nxge_cfg_lock); 670544961713Sgirish MUTEX_DESTROY(&hw_p->nxge_mdio_lock); 670644961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 67074045d941Ssowmini "==> nxge_uninit_common_device: " 67084045d941Ssowmini "func # %d " 67094045d941Ssowmini "hw_p $%p parent dip $%p " 67104045d941Ssowmini "ndevs %d (last)", 67114045d941Ssowmini nxgep->function_num, 67124045d941Ssowmini hw_p, 67134045d941Ssowmini p_dip, 67144045d941Ssowmini hw_p->ndevs)); 671544961713Sgirish 6716678453a8Sspeer nxge_hio_uninit(nxgep); 6717678453a8Sspeer 671844961713Sgirish if (hw_p == nxge_hw_list) { 671944961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 67204045d941Ssowmini "==> nxge_uninit_common_device:" 67214045d941Ssowmini "remove head func # %d " 67224045d941Ssowmini "hw_p $%p parent dip $%p " 67234045d941Ssowmini "ndevs %d (head)", 67244045d941Ssowmini nxgep->function_num, 67254045d941Ssowmini hw_p, 67264045d941Ssowmini p_dip, 67274045d941Ssowmini hw_p->ndevs)); 672844961713Sgirish nxge_hw_list = hw_p->next; 672944961713Sgirish } else { 673044961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 67314045d941Ssowmini "==> nxge_uninit_common_device:" 67324045d941Ssowmini "remove middle func # %d " 67334045d941Ssowmini "hw_p $%p parent dip $%p " 67344045d941Ssowmini "ndevs %d (middle)", 67354045d941Ssowmini nxgep->function_num, 67364045d941Ssowmini hw_p, 67374045d941Ssowmini p_dip, 67384045d941Ssowmini hw_p->ndevs)); 673944961713Sgirish h_hw_p->next = hw_p->next; 674044961713Sgirish } 674144961713Sgirish 6742678453a8Sspeer nxgep->nxge_hw_p = NULL; 674344961713Sgirish KMEM_FREE(hw_p, sizeof (nxge_hw_list_t)); 674444961713Sgirish } 674544961713Sgirish break; 674644961713Sgirish } else { 674744961713Sgirish h_hw_p = hw_p; 674844961713Sgirish } 674944961713Sgirish } 675044961713Sgirish 675144961713Sgirish MUTEX_EXIT(&nxge_common_lock); 675244961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 67534045d941Ssowmini "==> nxge_uninit_common_device (nxge_hw_list) $%p", 67544045d941Ssowmini nxge_hw_list)); 675544961713Sgirish 675644961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<= nxge_uninit_common_device")); 675744961713Sgirish } 675859ac0c16Sdavemq 675959ac0c16Sdavemq /* 67602e59129aSraghus * Determines the number of ports from the niu_type or the platform type. 676159ac0c16Sdavemq * Returns the number of ports, or returns zero on failure. 676259ac0c16Sdavemq */ 676359ac0c16Sdavemq 676459ac0c16Sdavemq int 67652e59129aSraghus nxge_get_nports(p_nxge_t nxgep) 676659ac0c16Sdavemq { 676759ac0c16Sdavemq int nports = 0; 676859ac0c16Sdavemq 67692e59129aSraghus switch (nxgep->niu_type) { 677059ac0c16Sdavemq case N2_NIU: 677159ac0c16Sdavemq case NEPTUNE_2_10GF: 677259ac0c16Sdavemq nports = 2; 677359ac0c16Sdavemq break; 677459ac0c16Sdavemq case NEPTUNE_4_1GC: 677559ac0c16Sdavemq case NEPTUNE_2_10GF_2_1GC: 677659ac0c16Sdavemq case NEPTUNE_1_10GF_3_1GC: 677759ac0c16Sdavemq case NEPTUNE_1_1GC_1_10GF_2_1GC: 677859a835ddSjoycey case NEPTUNE_2_10GF_2_1GRF: 677959ac0c16Sdavemq nports = 4; 678059ac0c16Sdavemq break; 678159ac0c16Sdavemq default: 67822e59129aSraghus switch (nxgep->platform_type) { 67832e59129aSraghus case P_NEPTUNE_NIU: 67842e59129aSraghus case P_NEPTUNE_ATLAS_2PORT: 67852e59129aSraghus nports = 2; 67862e59129aSraghus break; 67872e59129aSraghus case P_NEPTUNE_ATLAS_4PORT: 67882e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 67892e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 679023b952a3SSantwona Behera case P_NEPTUNE_ROCK: 6791d81011f0Ssbehera case P_NEPTUNE_ALONSO: 67922e59129aSraghus nports = 4; 67932e59129aSraghus break; 67942e59129aSraghus default: 67952e59129aSraghus break; 67962e59129aSraghus } 679759ac0c16Sdavemq break; 679859ac0c16Sdavemq } 679959ac0c16Sdavemq 680059ac0c16Sdavemq return (nports); 680159ac0c16Sdavemq } 6802ec090658Sml 6803ec090658Sml /* 6804ec090658Sml * The following two functions are to support 6805ec090658Sml * PSARC/2007/453 MSI-X interrupt limit override. 6806ec090658Sml */ 6807ec090658Sml static int 6808ec090658Sml nxge_create_msi_property(p_nxge_t nxgep) 6809ec090658Sml { 6810ec090658Sml int nmsi; 6811ec090658Sml extern int ncpus; 6812ec090658Sml 6813ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==>nxge_create_msi_property")); 6814ec090658Sml 6815ec090658Sml switch (nxgep->mac.portmode) { 6816ec090658Sml case PORT_10G_COPPER: 6817ec090658Sml case PORT_10G_FIBER: 681800161856Syc case PORT_10G_TN1010: 6819ec090658Sml (void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip, 6820ec090658Sml DDI_PROP_CANSLEEP, "#msix-request", NULL, 0); 6821ec090658Sml /* 6822ec090658Sml * The maximum MSI-X requested will be 8. 6823ef755e7aStc * If the # of CPUs is less than 8, we will request 6824ef755e7aStc * # MSI-X based on the # of CPUs (default). 6825ec090658Sml */ 6826ef755e7aStc NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6827ef755e7aStc "==>nxge_create_msi_property (10G): nxge_msix_10g_intrs %d", 6828ef755e7aStc nxge_msix_10g_intrs)); 6829ef755e7aStc if ((nxge_msix_10g_intrs == 0) || 6830ef755e7aStc (nxge_msix_10g_intrs > NXGE_MSIX_MAX_ALLOWED)) { 6831ec090658Sml nmsi = NXGE_MSIX_REQUEST_10G; 6832ef755e7aStc NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6833ef755e7aStc "==>nxge_create_msi_property (10G): reset to 8")); 6834ec090658Sml } else { 6835ef755e7aStc nmsi = nxge_msix_10g_intrs; 6836ef755e7aStc } 6837ef755e7aStc 6838ef755e7aStc /* 6839ef755e7aStc * If # of interrupts requested is 8 (default), 6840ef755e7aStc * the checking of the number of cpus will be 6841ef755e7aStc * be maintained. 6842ef755e7aStc */ 6843ef755e7aStc if ((nmsi == NXGE_MSIX_REQUEST_10G) && 6844ef755e7aStc (ncpus < nmsi)) { 6845ef755e7aStc NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6846ef755e7aStc "==>nxge_create_msi_property (10G): reset to 8")); 6847ec090658Sml nmsi = ncpus; 6848ec090658Sml } 6849ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6850ec090658Sml "==>nxge_create_msi_property(10G): exists 0x%x (nmsi %d)", 6851ec090658Sml ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 6852ec090658Sml DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 6853ec090658Sml break; 6854ec090658Sml 6855ec090658Sml default: 6856ef755e7aStc (void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip, 6857ef755e7aStc DDI_PROP_CANSLEEP, "#msix-request", NULL, 0); 6858ef755e7aStc NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6859ef755e7aStc "==>nxge_create_msi_property (1G): nxge_msix_1g_intrs %d", 6860ef755e7aStc nxge_msix_1g_intrs)); 6861ef755e7aStc if ((nxge_msix_1g_intrs == 0) || 6862ef755e7aStc (nxge_msix_1g_intrs > NXGE_MSIX_MAX_ALLOWED)) { 6863ef755e7aStc nmsi = NXGE_MSIX_REQUEST_1G; 6864ef755e7aStc NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6865ef755e7aStc "==>nxge_create_msi_property (1G): reset to 2")); 6866ef755e7aStc } else { 6867ef755e7aStc nmsi = nxge_msix_1g_intrs; 6868ef755e7aStc } 6869ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6870ec090658Sml "==>nxge_create_msi_property(1G): exists 0x%x (nmsi %d)", 6871ec090658Sml ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 6872ec090658Sml DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 6873ec090658Sml break; 6874ec090658Sml } 6875ec090658Sml 6876ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<==nxge_create_msi_property")); 6877ec090658Sml return (nmsi); 6878ec090658Sml } 68794045d941Ssowmini 68804045d941Ssowmini /* ARGSUSED */ 68814045d941Ssowmini static int 68824045d941Ssowmini nxge_get_def_val(nxge_t *nxgep, mac_prop_id_t pr_num, uint_t pr_valsize, 68834045d941Ssowmini void *pr_val) 68844045d941Ssowmini { 68854045d941Ssowmini int err = 0; 68864045d941Ssowmini link_flowctrl_t fl; 68874045d941Ssowmini 68884045d941Ssowmini switch (pr_num) { 68893fd94f8cSam case MAC_PROP_AUTONEG: 68904045d941Ssowmini *(uint8_t *)pr_val = 1; 68914045d941Ssowmini break; 68923fd94f8cSam case MAC_PROP_FLOWCTRL: 68934045d941Ssowmini if (pr_valsize < sizeof (link_flowctrl_t)) 68944045d941Ssowmini return (EINVAL); 68954045d941Ssowmini fl = LINK_FLOWCTRL_RX; 68964045d941Ssowmini bcopy(&fl, pr_val, sizeof (fl)); 68974045d941Ssowmini break; 68983fd94f8cSam case MAC_PROP_ADV_1000FDX_CAP: 68993fd94f8cSam case MAC_PROP_EN_1000FDX_CAP: 69004045d941Ssowmini *(uint8_t *)pr_val = 1; 69014045d941Ssowmini break; 69023fd94f8cSam case MAC_PROP_ADV_100FDX_CAP: 69033fd94f8cSam case MAC_PROP_EN_100FDX_CAP: 69044045d941Ssowmini *(uint8_t *)pr_val = 1; 69054045d941Ssowmini break; 69064045d941Ssowmini default: 69074045d941Ssowmini err = ENOTSUP; 69084045d941Ssowmini break; 69094045d941Ssowmini } 69104045d941Ssowmini return (err); 69114045d941Ssowmini } 69126f157acbSml 69136f157acbSml 69146f157acbSml /* 69156f157acbSml * The following is a software around for the Neptune hardware's 69166f157acbSml * interrupt bugs; The Neptune hardware may generate spurious interrupts when 69176f157acbSml * an interrupr handler is removed. 69186f157acbSml */ 69196f157acbSml #define NXGE_PCI_PORT_LOGIC_OFFSET 0x98 69206f157acbSml #define NXGE_PIM_RESET (1ULL << 29) 69216f157acbSml #define NXGE_GLU_RESET (1ULL << 30) 69226f157acbSml #define NXGE_NIU_RESET (1ULL << 31) 69236f157acbSml #define NXGE_PCI_RESET_ALL (NXGE_PIM_RESET | \ 69246f157acbSml NXGE_GLU_RESET | \ 69256f157acbSml NXGE_NIU_RESET) 69266f157acbSml 69276f157acbSml #define NXGE_WAIT_QUITE_TIME 200000 69286f157acbSml #define NXGE_WAIT_QUITE_RETRY 40 69296f157acbSml #define NXGE_PCI_RESET_WAIT 1000000 /* one second */ 69306f157acbSml 69316f157acbSml static void 69326f157acbSml nxge_niu_peu_reset(p_nxge_t nxgep) 69336f157acbSml { 69346f157acbSml uint32_t rvalue; 69356f157acbSml p_nxge_hw_list_t hw_p; 69366f157acbSml p_nxge_t fnxgep; 69376f157acbSml int i, j; 69386f157acbSml 69396f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_niu_peu_reset")); 69406f157acbSml if ((hw_p = nxgep->nxge_hw_p) == NULL) { 69416f157acbSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 69426f157acbSml "==> nxge_niu_peu_reset: NULL hardware pointer")); 69436f157acbSml return; 69446f157acbSml } 69456f157acbSml 69466f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 69476f157acbSml "==> nxge_niu_peu_reset: flags 0x%x link timer id %d timer id %d", 69486f157acbSml hw_p->flags, nxgep->nxge_link_poll_timerid, 69496f157acbSml nxgep->nxge_timerid)); 69506f157acbSml 69516f157acbSml MUTEX_ENTER(&hw_p->nxge_cfg_lock); 69526f157acbSml /* 69536f157acbSml * Make sure other instances from the same hardware 69546f157acbSml * stop sending PIO and in quiescent state. 69556f157acbSml */ 69566f157acbSml for (i = 0; i < NXGE_MAX_PORTS; i++) { 69576f157acbSml fnxgep = hw_p->nxge_p[i]; 69586f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 69596f157acbSml "==> nxge_niu_peu_reset: checking entry %d " 69606f157acbSml "nxgep $%p", i, fnxgep)); 69616f157acbSml #ifdef NXGE_DEBUG 69626f157acbSml if (fnxgep) { 69636f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 69646f157acbSml "==> nxge_niu_peu_reset: entry %d (function %d) " 69656f157acbSml "link timer id %d hw timer id %d", 69666f157acbSml i, fnxgep->function_num, 69676f157acbSml fnxgep->nxge_link_poll_timerid, 69686f157acbSml fnxgep->nxge_timerid)); 69696f157acbSml } 69706f157acbSml #endif 69716f157acbSml if (fnxgep && fnxgep != nxgep && 69726f157acbSml (fnxgep->nxge_timerid || fnxgep->nxge_link_poll_timerid)) { 69736f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 69746f157acbSml "==> nxge_niu_peu_reset: checking $%p " 69756f157acbSml "(function %d) timer ids", 69766f157acbSml fnxgep, fnxgep->function_num)); 69776f157acbSml for (j = 0; j < NXGE_WAIT_QUITE_RETRY; j++) { 69786f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 69796f157acbSml "==> nxge_niu_peu_reset: waiting")); 69806f157acbSml NXGE_DELAY(NXGE_WAIT_QUITE_TIME); 69816f157acbSml if (!fnxgep->nxge_timerid && 69826f157acbSml !fnxgep->nxge_link_poll_timerid) { 69836f157acbSml break; 69846f157acbSml } 69856f157acbSml } 69866f157acbSml NXGE_DELAY(NXGE_WAIT_QUITE_TIME); 69876f157acbSml if (fnxgep->nxge_timerid || 69886f157acbSml fnxgep->nxge_link_poll_timerid) { 69896f157acbSml MUTEX_EXIT(&hw_p->nxge_cfg_lock); 69906f157acbSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 69916f157acbSml "<== nxge_niu_peu_reset: cannot reset " 69926f157acbSml "hardware (devices are still in use)")); 69936f157acbSml return; 69946f157acbSml } 69956f157acbSml } 69966f157acbSml } 69976f157acbSml 69986f157acbSml if ((hw_p->flags & COMMON_RESET_NIU_PCI) != COMMON_RESET_NIU_PCI) { 69996f157acbSml hw_p->flags |= COMMON_RESET_NIU_PCI; 70006f157acbSml rvalue = pci_config_get32(nxgep->dev_regs->nxge_pciregh, 70016f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET); 70026f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 70036f157acbSml "nxge_niu_peu_reset: read offset 0x%x (%d) " 70046f157acbSml "(data 0x%x)", 70056f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, 70066f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, 70076f157acbSml rvalue)); 70086f157acbSml 70096f157acbSml rvalue |= NXGE_PCI_RESET_ALL; 70106f157acbSml pci_config_put32(nxgep->dev_regs->nxge_pciregh, 70116f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, rvalue); 70126f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 70136f157acbSml "nxge_niu_peu_reset: RESETTING NIU: write NIU reset 0x%x", 70146f157acbSml rvalue)); 70156f157acbSml 70166f157acbSml NXGE_DELAY(NXGE_PCI_RESET_WAIT); 70176f157acbSml } 70186f157acbSml 70196f157acbSml MUTEX_EXIT(&hw_p->nxge_cfg_lock); 70206f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_niu_peu_reset")); 70216f157acbSml } 7022d6d3405fSml 7023d6d3405fSml static void 7024d6d3405fSml nxge_set_pci_replay_timeout(p_nxge_t nxgep) 7025d6d3405fSml { 7026da14cebeSEric Cheng p_dev_regs_t dev_regs; 7027d6d3405fSml uint32_t value; 7028d6d3405fSml 7029d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_set_pci_replay_timeout")); 7030d6d3405fSml 7031d6d3405fSml if (!nxge_set_replay_timer) { 7032d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7033d6d3405fSml "==> nxge_set_pci_replay_timeout: will not change " 7034d6d3405fSml "the timeout")); 7035d6d3405fSml return; 7036d6d3405fSml } 7037d6d3405fSml 7038d6d3405fSml dev_regs = nxgep->dev_regs; 7039d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7040d6d3405fSml "==> nxge_set_pci_replay_timeout: dev_regs 0x%p pcireg 0x%p", 7041d6d3405fSml dev_regs, dev_regs->nxge_pciregh)); 7042d6d3405fSml 7043d6d3405fSml if (dev_regs == NULL || (dev_regs->nxge_pciregh == NULL)) { 7044f720bc57Syc NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7045d6d3405fSml "==> nxge_set_pci_replay_timeout: NULL dev_regs $%p or " 7046d6d3405fSml "no PCI handle", 7047d6d3405fSml dev_regs)); 7048d6d3405fSml return; 7049d6d3405fSml } 7050d6d3405fSml value = (pci_config_get32(dev_regs->nxge_pciregh, 7051d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET) | 7052d6d3405fSml (nxge_replay_timeout << PCI_REPLAY_TIMEOUT_SHIFT)); 7053d6d3405fSml 7054d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7055d6d3405fSml "nxge_set_pci_replay_timeout: replay timeout value before set 0x%x " 7056d6d3405fSml "(timeout value to set 0x%x at offset 0x%x) value 0x%x", 7057d6d3405fSml pci_config_get32(dev_regs->nxge_pciregh, 7058d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET), nxge_replay_timeout, 7059d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET, value)); 7060d6d3405fSml 7061d6d3405fSml pci_config_put32(dev_regs->nxge_pciregh, PCI_REPLAY_TIMEOUT_CFG_OFFSET, 7062d6d3405fSml value); 7063d6d3405fSml 7064d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7065d6d3405fSml "nxge_set_pci_replay_timeout: replay timeout value after set 0x%x", 7066d6d3405fSml pci_config_get32(dev_regs->nxge_pciregh, 7067d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET))); 7068d6d3405fSml 7069d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_set_pci_replay_timeout")); 7070d6d3405fSml } 707119397407SSherry Moore 707219397407SSherry Moore /* 707319397407SSherry Moore * quiesce(9E) entry point. 707419397407SSherry Moore * 707519397407SSherry Moore * This function is called when the system is single-threaded at high 707619397407SSherry Moore * PIL with preemption disabled. Therefore, this function must not be 707719397407SSherry Moore * blocked. 707819397407SSherry Moore * 707919397407SSherry Moore * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 708019397407SSherry Moore * DDI_FAILURE indicates an error condition and should almost never happen. 708119397407SSherry Moore */ 708219397407SSherry Moore static int 708319397407SSherry Moore nxge_quiesce(dev_info_t *dip) 708419397407SSherry Moore { 708519397407SSherry Moore int instance = ddi_get_instance(dip); 708619397407SSherry Moore p_nxge_t nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 708719397407SSherry Moore 708819397407SSherry Moore if (nxgep == NULL) 708919397407SSherry Moore return (DDI_FAILURE); 709019397407SSherry Moore 709119397407SSherry Moore /* Turn off debugging */ 709219397407SSherry Moore nxge_debug_level = NO_DEBUG; 709319397407SSherry Moore nxgep->nxge_debug_level = NO_DEBUG; 709419397407SSherry Moore npi_debug_level = NO_DEBUG; 709519397407SSherry Moore 709619397407SSherry Moore /* 709719397407SSherry Moore * Stop link monitor only when linkchkmod is interrupt based 709819397407SSherry Moore */ 709919397407SSherry Moore if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 710019397407SSherry Moore (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 710119397407SSherry Moore } 710219397407SSherry Moore 710319397407SSherry Moore (void) nxge_intr_hw_disable(nxgep); 710419397407SSherry Moore 710519397407SSherry Moore /* 710619397407SSherry Moore * Reset the receive MAC side. 710719397407SSherry Moore */ 710819397407SSherry Moore (void) nxge_rx_mac_disable(nxgep); 710919397407SSherry Moore 711019397407SSherry Moore /* Disable and soft reset the IPP */ 711119397407SSherry Moore if (!isLDOMguest(nxgep)) 711219397407SSherry Moore (void) nxge_ipp_disable(nxgep); 711319397407SSherry Moore 711419397407SSherry Moore /* 711519397407SSherry Moore * Reset the transmit/receive DMA side. 711619397407SSherry Moore */ 711719397407SSherry Moore (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 711819397407SSherry Moore (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 711919397407SSherry Moore 712019397407SSherry Moore /* 712119397407SSherry Moore * Reset the transmit MAC side. 712219397407SSherry Moore */ 712319397407SSherry Moore (void) nxge_tx_mac_disable(nxgep); 712419397407SSherry Moore 712519397407SSherry Moore return (DDI_SUCCESS); 712619397407SSherry Moore } 7127