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 */ 2144961713Sgirish /* 2230ac2e7bSml * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2344961713Sgirish * Use is subject to license terms. 2444961713Sgirish */ 2544961713Sgirish 2644961713Sgirish /* 2744961713Sgirish * SunOs MT STREAMS NIU/Neptune 10Gb Ethernet Device Driver. 2844961713Sgirish */ 2944961713Sgirish #include <sys/nxge/nxge_impl.h> 30678453a8Sspeer #include <sys/nxge/nxge_hio.h> 31678453a8Sspeer #include <sys/nxge/nxge_rxdma.h> 3214ea4bb7Ssd #include <sys/pcie.h> 3344961713Sgirish 3444961713Sgirish uint32_t nxge_use_partition = 0; /* debug partition flag */ 3544961713Sgirish uint32_t nxge_dma_obp_props_only = 1; /* use obp published props */ 3644961713Sgirish uint32_t nxge_use_rdc_intr = 1; /* debug to assign rdc intr */ 3744961713Sgirish /* 38ec090658Sml * PSARC/2007/453 MSI-X interrupt limit override 39ec090658Sml * (This PSARC case is limited to MSI-X vectors 40ec090658Sml * and SPARC platforms only). 4144961713Sgirish */ 42ec090658Sml #if defined(_BIG_ENDIAN) 43ec090658Sml uint32_t nxge_msi_enable = 2; 44ec090658Sml #else 45ec090658Sml uint32_t nxge_msi_enable = 1; 46ec090658Sml #endif 4744961713Sgirish 486f157acbSml /* 496f157acbSml * Software workaround for a Neptune (PCI-E) 506f157acbSml * hardware interrupt bug which the hardware 516f157acbSml * may generate spurious interrupts after the 526f157acbSml * device interrupt handler was removed. If this flag 536f157acbSml * is enabled, the driver will reset the 546f157acbSml * hardware when devices are being detached. 556f157acbSml */ 566f157acbSml uint32_t nxge_peu_reset_enable = 0; 576f157acbSml 58b4d05839Sml /* 59b4d05839Sml * Software workaround for the hardware 60b4d05839Sml * checksum bugs that affect packet transmission 61b4d05839Sml * and receive: 62b4d05839Sml * 63b4d05839Sml * Usage of nxge_cksum_offload: 64b4d05839Sml * 65b4d05839Sml * (1) nxge_cksum_offload = 0 (default): 66b4d05839Sml * - transmits packets: 67b4d05839Sml * TCP: uses the hardware checksum feature. 68b4d05839Sml * UDP: driver will compute the software checksum 69b4d05839Sml * based on the partial checksum computed 70b4d05839Sml * by the IP layer. 71b4d05839Sml * - receives packets 72b4d05839Sml * TCP: marks packets checksum flags based on hardware result. 73b4d05839Sml * UDP: will not mark checksum flags. 74b4d05839Sml * 75b4d05839Sml * (2) nxge_cksum_offload = 1: 76b4d05839Sml * - transmit packets: 77b4d05839Sml * TCP/UDP: uses the hardware checksum feature. 78b4d05839Sml * - receives packets 79b4d05839Sml * TCP/UDP: marks packet checksum flags based on hardware result. 80b4d05839Sml * 81b4d05839Sml * (3) nxge_cksum_offload = 2: 82b4d05839Sml * - The driver will not register its checksum capability. 83b4d05839Sml * Checksum for both TCP and UDP will be computed 84b4d05839Sml * by the stack. 85b4d05839Sml * - The software LSO is not allowed in this case. 86b4d05839Sml * 87b4d05839Sml * (4) nxge_cksum_offload > 2: 88b4d05839Sml * - Will be treated as it is set to 2 89b4d05839Sml * (stack will compute the checksum). 90b4d05839Sml * 91b4d05839Sml * (5) If the hardware bug is fixed, this workaround 92b4d05839Sml * needs to be updated accordingly to reflect 93b4d05839Sml * the new hardware revision. 94b4d05839Sml */ 95b4d05839Sml uint32_t nxge_cksum_offload = 0; 96678453a8Sspeer 9744961713Sgirish /* 9844961713Sgirish * Globals: tunable parameters (/etc/system or adb) 9944961713Sgirish * 10044961713Sgirish */ 10144961713Sgirish uint32_t nxge_rbr_size = NXGE_RBR_RBB_DEFAULT; 10244961713Sgirish uint32_t nxge_rbr_spare_size = 0; 10344961713Sgirish uint32_t nxge_rcr_size = NXGE_RCR_DEFAULT; 10444961713Sgirish uint32_t nxge_tx_ring_size = NXGE_TX_RING_DEFAULT; 105b3a0105bSspeer boolean_t nxge_no_msg = B_TRUE; /* control message display */ 10644961713Sgirish uint32_t nxge_no_link_notify = 0; /* control DL_NOTIFY */ 10744961713Sgirish uint32_t nxge_bcopy_thresh = TX_BCOPY_MAX; 10844961713Sgirish uint32_t nxge_dvma_thresh = TX_FASTDVMA_MIN; 10944961713Sgirish uint32_t nxge_dma_stream_thresh = TX_STREAM_MIN; 11044961713Sgirish uint32_t nxge_jumbo_mtu = TX_JUMBO_MTU; 11144961713Sgirish boolean_t nxge_jumbo_enable = B_FALSE; 11244961713Sgirish uint16_t nxge_rcr_timeout = NXGE_RDC_RCR_TIMEOUT; 11344961713Sgirish uint16_t nxge_rcr_threshold = NXGE_RDC_RCR_THRESHOLD; 1141f8914d5Sml nxge_tx_mode_t nxge_tx_scheme = NXGE_USE_SERIAL; 11544961713Sgirish 11630ac2e7bSml /* MAX LSO size */ 11730ac2e7bSml #define NXGE_LSO_MAXLEN 65535 11830ac2e7bSml uint32_t nxge_lso_max = NXGE_LSO_MAXLEN; 11930ac2e7bSml 12044961713Sgirish /* 12144961713Sgirish * Debugging flags: 12244961713Sgirish * nxge_no_tx_lb : transmit load balancing 12344961713Sgirish * nxge_tx_lb_policy: 0 - TCP port (default) 12444961713Sgirish * 3 - DEST MAC 12544961713Sgirish */ 12644961713Sgirish uint32_t nxge_no_tx_lb = 0; 12744961713Sgirish uint32_t nxge_tx_lb_policy = NXGE_TX_LB_TCPUDP; 12844961713Sgirish 12944961713Sgirish /* 13044961713Sgirish * Add tunable to reduce the amount of time spent in the 13144961713Sgirish * ISR doing Rx Processing. 13244961713Sgirish */ 13344961713Sgirish uint32_t nxge_max_rx_pkts = 1024; 13444961713Sgirish 13544961713Sgirish /* 13644961713Sgirish * Tunables to manage the receive buffer blocks. 13744961713Sgirish * 13844961713Sgirish * nxge_rx_threshold_hi: copy all buffers. 13944961713Sgirish * nxge_rx_bcopy_size_type: receive buffer block size type. 14044961713Sgirish * nxge_rx_threshold_lo: copy only up to tunable block size type. 14144961713Sgirish */ 14244961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_hi = NXGE_RX_COPY_6; 14344961713Sgirish nxge_rxbuf_type_t nxge_rx_buf_size_type = RCR_PKTBUFSZ_0; 14444961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_lo = NXGE_RX_COPY_3; 14544961713Sgirish 146678453a8Sspeer /* Use kmem_alloc() to allocate data buffers. */ 147b1000363Sml #if defined(_BIG_ENDIAN) 148d00f30bbSspeer uint32_t nxge_use_kmem_alloc = 1; 149678453a8Sspeer #else 150d00f30bbSspeer uint32_t nxge_use_kmem_alloc = 0; 151678453a8Sspeer #endif 152678453a8Sspeer 15344961713Sgirish rtrace_t npi_rtracebuf; 15444961713Sgirish 155d6d3405fSml /* 156d6d3405fSml * The hardware sometimes fails to allow enough time for the link partner 157d6d3405fSml * to send an acknowledgement for packets that the hardware sent to it. The 158d6d3405fSml * hardware resends the packets earlier than it should be in those instances. 159d6d3405fSml * This behavior caused some switches to acknowledge the wrong packets 160d6d3405fSml * and it triggered the fatal error. 161d6d3405fSml * This software workaround is to set the replay timer to a value 162d6d3405fSml * suggested by the hardware team. 163d6d3405fSml * 164d6d3405fSml * PCI config space replay timer register: 165d6d3405fSml * The following replay timeout value is 0xc 166d6d3405fSml * for bit 14:18. 167d6d3405fSml */ 168d6d3405fSml #define PCI_REPLAY_TIMEOUT_CFG_OFFSET 0xb8 169d6d3405fSml #define PCI_REPLAY_TIMEOUT_SHIFT 14 170d6d3405fSml 171d6d3405fSml uint32_t nxge_set_replay_timer = 1; 172d6d3405fSml uint32_t nxge_replay_timeout = 0xc; 173d6d3405fSml 174cf020df9Sml /* 175cf020df9Sml * The transmit serialization sometimes causes 176cf020df9Sml * longer sleep before calling the driver transmit 177cf020df9Sml * function as it sleeps longer than it should. 178cf020df9Sml * The performace group suggests that a time wait tunable 179cf020df9Sml * can be used to set the maximum wait time when needed 180cf020df9Sml * and the default is set to 1 tick. 181cf020df9Sml */ 182cf020df9Sml uint32_t nxge_tx_serial_maxsleep = 1; 183cf020df9Sml 18444961713Sgirish #if defined(sun4v) 18544961713Sgirish /* 18644961713Sgirish * Hypervisor N2/NIU services information. 18744961713Sgirish */ 18844961713Sgirish static hsvc_info_t niu_hsvc = { 18944961713Sgirish HSVC_REV_1, NULL, HSVC_GROUP_NIU, NIU_MAJOR_VER, 19044961713Sgirish NIU_MINOR_VER, "nxge" 19144961713Sgirish }; 192678453a8Sspeer 193678453a8Sspeer static int nxge_hsvc_register(p_nxge_t); 19444961713Sgirish #endif 19544961713Sgirish 19644961713Sgirish /* 19744961713Sgirish * Function Prototypes 19844961713Sgirish */ 19944961713Sgirish static int nxge_attach(dev_info_t *, ddi_attach_cmd_t); 20044961713Sgirish static int nxge_detach(dev_info_t *, ddi_detach_cmd_t); 20144961713Sgirish static void nxge_unattach(p_nxge_t); 20219397407SSherry Moore static int nxge_quiesce(dev_info_t *); 20344961713Sgirish 20444961713Sgirish #if NXGE_PROPERTY 20544961713Sgirish static void nxge_remove_hard_properties(p_nxge_t); 20644961713Sgirish #endif 20744961713Sgirish 208678453a8Sspeer /* 209678453a8Sspeer * These two functions are required by nxge_hio.c 210678453a8Sspeer */ 211678453a8Sspeer extern int nxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr); 212678453a8Sspeer extern int nxge_m_mmac_remove(void *arg, mac_addr_slot_t slot); 213*651ce697SMichael Speer extern void nxge_grp_cleanup(p_nxge_t nxge); 214678453a8Sspeer 21544961713Sgirish static nxge_status_t nxge_setup_system_dma_pages(p_nxge_t); 21644961713Sgirish 21744961713Sgirish static nxge_status_t nxge_setup_mutexes(p_nxge_t); 21844961713Sgirish static void nxge_destroy_mutexes(p_nxge_t); 21944961713Sgirish 22044961713Sgirish static nxge_status_t nxge_map_regs(p_nxge_t nxgep); 22144961713Sgirish static void nxge_unmap_regs(p_nxge_t nxgep); 22244961713Sgirish #ifdef NXGE_DEBUG 22344961713Sgirish static void nxge_test_map_regs(p_nxge_t nxgep); 22444961713Sgirish #endif 22544961713Sgirish 22644961713Sgirish static nxge_status_t nxge_add_intrs(p_nxge_t nxgep); 22744961713Sgirish static nxge_status_t nxge_add_soft_intrs(p_nxge_t nxgep); 22844961713Sgirish static void nxge_remove_intrs(p_nxge_t nxgep); 22944961713Sgirish static void nxge_remove_soft_intrs(p_nxge_t nxgep); 23044961713Sgirish 23144961713Sgirish static nxge_status_t nxge_add_intrs_adv(p_nxge_t nxgep); 23244961713Sgirish static nxge_status_t nxge_add_intrs_adv_type(p_nxge_t, uint32_t); 23344961713Sgirish static nxge_status_t nxge_add_intrs_adv_type_fix(p_nxge_t, uint32_t); 23444961713Sgirish static void nxge_intrs_enable(p_nxge_t nxgep); 23544961713Sgirish static void nxge_intrs_disable(p_nxge_t nxgep); 23644961713Sgirish 23744961713Sgirish static void nxge_suspend(p_nxge_t); 23844961713Sgirish static nxge_status_t nxge_resume(p_nxge_t); 23944961713Sgirish 24044961713Sgirish static nxge_status_t nxge_setup_dev(p_nxge_t); 24144961713Sgirish static void nxge_destroy_dev(p_nxge_t); 24244961713Sgirish 24344961713Sgirish static nxge_status_t nxge_alloc_mem_pool(p_nxge_t); 24444961713Sgirish static void nxge_free_mem_pool(p_nxge_t); 24544961713Sgirish 246678453a8Sspeer nxge_status_t nxge_alloc_rx_mem_pool(p_nxge_t); 24744961713Sgirish static void nxge_free_rx_mem_pool(p_nxge_t); 24844961713Sgirish 249678453a8Sspeer nxge_status_t nxge_alloc_tx_mem_pool(p_nxge_t); 25044961713Sgirish static void nxge_free_tx_mem_pool(p_nxge_t); 25144961713Sgirish 25244961713Sgirish static nxge_status_t nxge_dma_mem_alloc(p_nxge_t, dma_method_t, 25344961713Sgirish struct ddi_dma_attr *, 25444961713Sgirish size_t, ddi_device_acc_attr_t *, uint_t, 25544961713Sgirish p_nxge_dma_common_t); 25644961713Sgirish 25744961713Sgirish static void nxge_dma_mem_free(p_nxge_dma_common_t); 258678453a8Sspeer static void nxge_dma_free_rx_data_buf(p_nxge_dma_common_t); 25944961713Sgirish 26044961713Sgirish static nxge_status_t nxge_alloc_rx_buf_dma(p_nxge_t, uint16_t, 26144961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 26244961713Sgirish static void nxge_free_rx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 26344961713Sgirish 26444961713Sgirish static nxge_status_t nxge_alloc_rx_cntl_dma(p_nxge_t, uint16_t, 26544961713Sgirish p_nxge_dma_common_t *, size_t); 26644961713Sgirish static void nxge_free_rx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 26744961713Sgirish 268678453a8Sspeer extern nxge_status_t nxge_alloc_tx_buf_dma(p_nxge_t, uint16_t, 26944961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 27044961713Sgirish static void nxge_free_tx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 27144961713Sgirish 272678453a8Sspeer extern nxge_status_t nxge_alloc_tx_cntl_dma(p_nxge_t, uint16_t, 27344961713Sgirish p_nxge_dma_common_t *, 27444961713Sgirish size_t); 27544961713Sgirish static void nxge_free_tx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 27644961713Sgirish 27744961713Sgirish static int nxge_init_common_dev(p_nxge_t); 27844961713Sgirish static void nxge_uninit_common_dev(p_nxge_t); 2794045d941Ssowmini extern int nxge_param_set_mac(p_nxge_t, queue_t *, mblk_t *, 2804045d941Ssowmini char *, caddr_t); 28144961713Sgirish 28244961713Sgirish /* 28344961713Sgirish * The next declarations are for the GLDv3 interface. 28444961713Sgirish */ 28544961713Sgirish static int nxge_m_start(void *); 28644961713Sgirish static void nxge_m_stop(void *); 28744961713Sgirish static int nxge_m_unicst(void *, const uint8_t *); 28844961713Sgirish static int nxge_m_multicst(void *, boolean_t, const uint8_t *); 28944961713Sgirish static int nxge_m_promisc(void *, boolean_t); 29044961713Sgirish static void nxge_m_ioctl(void *, queue_t *, mblk_t *); 29144961713Sgirish static void nxge_m_resources(void *); 29244961713Sgirish mblk_t *nxge_m_tx(void *arg, mblk_t *); 29344961713Sgirish static nxge_status_t nxge_mac_register(p_nxge_t); 29458324dfcSspeer static int nxge_altmac_set(p_nxge_t nxgep, uint8_t *mac_addr, 29558324dfcSspeer mac_addr_slot_t slot); 296678453a8Sspeer void nxge_mmac_kstat_update(p_nxge_t nxgep, mac_addr_slot_t slot, 29758324dfcSspeer boolean_t factory); 29858324dfcSspeer static int nxge_m_mmac_reserve(void *arg, mac_multi_addr_t *maddr); 29958324dfcSspeer static int nxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr); 30058324dfcSspeer static int nxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr); 3011bd6825cSml static boolean_t nxge_m_getcapab(void *, mac_capab_t, void *); 3021bd6825cSml static int nxge_m_setprop(void *, const char *, mac_prop_id_t, 3031bd6825cSml uint_t, const void *); 3041bd6825cSml static int nxge_m_getprop(void *, const char *, mac_prop_id_t, 3054045d941Ssowmini uint_t, uint_t, void *); 3061bd6825cSml static int nxge_set_priv_prop(nxge_t *, const char *, uint_t, 3071bd6825cSml const void *); 3084045d941Ssowmini static int nxge_get_priv_prop(nxge_t *, const char *, uint_t, uint_t, 3091bd6825cSml void *); 3104045d941Ssowmini static int nxge_get_def_val(nxge_t *, mac_prop_id_t, uint_t, void *); 3114045d941Ssowmini 3126f157acbSml static void nxge_niu_peu_reset(p_nxge_t nxgep); 313d6d3405fSml static void nxge_set_pci_replay_timeout(nxge_t *); 3144045d941Ssowmini 3154045d941Ssowmini mac_priv_prop_t nxge_priv_props[] = { 3164045d941Ssowmini {"_adv_10gfdx_cap", MAC_PROP_PERM_RW}, 3174045d941Ssowmini {"_adv_pause_cap", MAC_PROP_PERM_RW}, 3184045d941Ssowmini {"_function_number", MAC_PROP_PERM_READ}, 3194045d941Ssowmini {"_fw_version", MAC_PROP_PERM_READ}, 3204045d941Ssowmini {"_port_mode", MAC_PROP_PERM_READ}, 3214045d941Ssowmini {"_hot_swap_phy", MAC_PROP_PERM_READ}, 3224045d941Ssowmini {"_accept_jumbo", MAC_PROP_PERM_RW}, 3234045d941Ssowmini {"_rxdma_intr_time", MAC_PROP_PERM_RW}, 3244045d941Ssowmini {"_rxdma_intr_pkts", MAC_PROP_PERM_RW}, 3254045d941Ssowmini {"_class_opt_ipv4_tcp", MAC_PROP_PERM_RW}, 3264045d941Ssowmini {"_class_opt_ipv4_udp", MAC_PROP_PERM_RW}, 3274045d941Ssowmini {"_class_opt_ipv4_ah", MAC_PROP_PERM_RW}, 3284045d941Ssowmini {"_class_opt_ipv4_sctp", MAC_PROP_PERM_RW}, 3294045d941Ssowmini {"_class_opt_ipv6_tcp", MAC_PROP_PERM_RW}, 3304045d941Ssowmini {"_class_opt_ipv6_udp", MAC_PROP_PERM_RW}, 3314045d941Ssowmini {"_class_opt_ipv6_ah", MAC_PROP_PERM_RW}, 3324045d941Ssowmini {"_class_opt_ipv6_sctp", MAC_PROP_PERM_RW}, 3334045d941Ssowmini {"_soft_lso_enable", MAC_PROP_PERM_RW} 3344045d941Ssowmini }; 3354045d941Ssowmini 3364045d941Ssowmini #define NXGE_MAX_PRIV_PROPS \ 3374045d941Ssowmini (sizeof (nxge_priv_props)/sizeof (mac_priv_prop_t)) 3381bd6825cSml 3391bd6825cSml #define NXGE_M_CALLBACK_FLAGS\ 3401bd6825cSml (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP) 3411bd6825cSml 34244961713Sgirish 34344961713Sgirish #define NXGE_NEPTUNE_MAGIC 0x4E584745UL 34444961713Sgirish #define MAX_DUMP_SZ 256 34544961713Sgirish 3461bd6825cSml #define NXGE_M_CALLBACK_FLAGS \ 3471bd6825cSml (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP) 34844961713Sgirish 349678453a8Sspeer mac_callbacks_t nxge_m_callbacks = { 35044961713Sgirish NXGE_M_CALLBACK_FLAGS, 35144961713Sgirish nxge_m_stat, 35244961713Sgirish nxge_m_start, 35344961713Sgirish nxge_m_stop, 35444961713Sgirish nxge_m_promisc, 35544961713Sgirish nxge_m_multicst, 35644961713Sgirish nxge_m_unicst, 35744961713Sgirish nxge_m_tx, 35844961713Sgirish nxge_m_resources, 35944961713Sgirish nxge_m_ioctl, 3601bd6825cSml nxge_m_getcapab, 3611bd6825cSml NULL, 3621bd6825cSml NULL, 3631bd6825cSml nxge_m_setprop, 3641bd6825cSml nxge_m_getprop 36544961713Sgirish }; 36644961713Sgirish 36744961713Sgirish void 36844961713Sgirish nxge_err_inject(p_nxge_t, queue_t *, mblk_t *); 36944961713Sgirish 370ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override. */ 371ec090658Sml #define NXGE_MSIX_REQUEST_10G 8 372ec090658Sml #define NXGE_MSIX_REQUEST_1G 2 373ec090658Sml static int nxge_create_msi_property(p_nxge_t); 374ec090658Sml 37544961713Sgirish /* 37644961713Sgirish * These global variables control the message 37744961713Sgirish * output. 37844961713Sgirish */ 37944961713Sgirish out_dbgmsg_t nxge_dbgmsg_out = DBG_CONSOLE | STR_LOG; 380678453a8Sspeer uint64_t nxge_debug_level; 38144961713Sgirish 38244961713Sgirish /* 38344961713Sgirish * This list contains the instance structures for the Neptune 38444961713Sgirish * devices present in the system. The lock exists to guarantee 38544961713Sgirish * mutually exclusive access to the list. 38644961713Sgirish */ 38744961713Sgirish void *nxge_list = NULL; 38844961713Sgirish 38944961713Sgirish void *nxge_hw_list = NULL; 39044961713Sgirish nxge_os_mutex_t nxge_common_lock; 39144961713Sgirish 39244961713Sgirish extern uint64_t npi_debug_level; 39344961713Sgirish 39444961713Sgirish extern nxge_status_t nxge_ldgv_init(p_nxge_t, int *, int *); 39544961713Sgirish extern nxge_status_t nxge_ldgv_init_n2(p_nxge_t, int *, int *); 39644961713Sgirish extern nxge_status_t nxge_ldgv_uninit(p_nxge_t); 39744961713Sgirish extern nxge_status_t nxge_intr_ldgv_init(p_nxge_t); 39844961713Sgirish extern void nxge_fm_init(p_nxge_t, 39944961713Sgirish ddi_device_acc_attr_t *, 40044961713Sgirish ddi_device_acc_attr_t *, 40144961713Sgirish ddi_dma_attr_t *); 40244961713Sgirish extern void nxge_fm_fini(p_nxge_t); 40358324dfcSspeer extern npi_status_t npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t); 40444961713Sgirish 40544961713Sgirish /* 40644961713Sgirish * Count used to maintain the number of buffers being used 40744961713Sgirish * by Neptune instances and loaned up to the upper layers. 40844961713Sgirish */ 40944961713Sgirish uint32_t nxge_mblks_pending = 0; 41044961713Sgirish 41144961713Sgirish /* 41244961713Sgirish * Device register access attributes for PIO. 41344961713Sgirish */ 41444961713Sgirish static ddi_device_acc_attr_t nxge_dev_reg_acc_attr = { 41544961713Sgirish DDI_DEVICE_ATTR_V0, 41644961713Sgirish DDI_STRUCTURE_LE_ACC, 41744961713Sgirish DDI_STRICTORDER_ACC, 41844961713Sgirish }; 41944961713Sgirish 42044961713Sgirish /* 42144961713Sgirish * Device descriptor access attributes for DMA. 42244961713Sgirish */ 42344961713Sgirish static ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr = { 42444961713Sgirish DDI_DEVICE_ATTR_V0, 42544961713Sgirish DDI_STRUCTURE_LE_ACC, 42644961713Sgirish DDI_STRICTORDER_ACC 42744961713Sgirish }; 42844961713Sgirish 42944961713Sgirish /* 43044961713Sgirish * Device buffer access attributes for DMA. 43144961713Sgirish */ 43244961713Sgirish static ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr = { 43344961713Sgirish DDI_DEVICE_ATTR_V0, 43444961713Sgirish DDI_STRUCTURE_BE_ACC, 43544961713Sgirish DDI_STRICTORDER_ACC 43644961713Sgirish }; 43744961713Sgirish 43844961713Sgirish ddi_dma_attr_t nxge_desc_dma_attr = { 43944961713Sgirish DMA_ATTR_V0, /* version number. */ 44044961713Sgirish 0, /* low address */ 44144961713Sgirish 0xffffffffffffffff, /* high address */ 44244961713Sgirish 0xffffffffffffffff, /* address counter max */ 44344961713Sgirish #ifndef NIU_PA_WORKAROUND 44444961713Sgirish 0x100000, /* alignment */ 44544961713Sgirish #else 44644961713Sgirish 0x2000, 44744961713Sgirish #endif 44844961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 44944961713Sgirish 0x1, /* minimum transfer size */ 45044961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 45144961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 45244961713Sgirish 1, /* scatter/gather list length */ 45344961713Sgirish (unsigned int) 1, /* granularity */ 45444961713Sgirish 0 /* attribute flags */ 45544961713Sgirish }; 45644961713Sgirish 45744961713Sgirish ddi_dma_attr_t nxge_tx_dma_attr = { 45844961713Sgirish DMA_ATTR_V0, /* version number. */ 45944961713Sgirish 0, /* low address */ 46044961713Sgirish 0xffffffffffffffff, /* high address */ 46144961713Sgirish 0xffffffffffffffff, /* address counter max */ 46244961713Sgirish #if defined(_BIG_ENDIAN) 46344961713Sgirish 0x2000, /* alignment */ 46444961713Sgirish #else 46544961713Sgirish 0x1000, /* alignment */ 46644961713Sgirish #endif 46744961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 46844961713Sgirish 0x1, /* minimum transfer size */ 46944961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 47044961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 47144961713Sgirish 5, /* scatter/gather list length */ 47244961713Sgirish (unsigned int) 1, /* granularity */ 47344961713Sgirish 0 /* attribute flags */ 47444961713Sgirish }; 47544961713Sgirish 47644961713Sgirish ddi_dma_attr_t nxge_rx_dma_attr = { 47744961713Sgirish DMA_ATTR_V0, /* version number. */ 47844961713Sgirish 0, /* low address */ 47944961713Sgirish 0xffffffffffffffff, /* high address */ 48044961713Sgirish 0xffffffffffffffff, /* address counter max */ 48144961713Sgirish 0x2000, /* alignment */ 48244961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 48344961713Sgirish 0x1, /* minimum transfer size */ 48444961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 48544961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 48644961713Sgirish 1, /* scatter/gather list length */ 48744961713Sgirish (unsigned int) 1, /* granularity */ 4880e2bd521Ssbehera DDI_DMA_RELAXED_ORDERING /* attribute flags */ 48944961713Sgirish }; 49044961713Sgirish 49144961713Sgirish ddi_dma_lim_t nxge_dma_limits = { 49244961713Sgirish (uint_t)0, /* dlim_addr_lo */ 49344961713Sgirish (uint_t)0xffffffff, /* dlim_addr_hi */ 49444961713Sgirish (uint_t)0xffffffff, /* dlim_cntr_max */ 49544961713Sgirish (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */ 49644961713Sgirish 0x1, /* dlim_minxfer */ 49744961713Sgirish 1024 /* dlim_speed */ 49844961713Sgirish }; 49944961713Sgirish 50044961713Sgirish dma_method_t nxge_force_dma = DVMA; 50144961713Sgirish 50244961713Sgirish /* 50344961713Sgirish * dma chunk sizes. 50444961713Sgirish * 50544961713Sgirish * Try to allocate the largest possible size 50644961713Sgirish * so that fewer number of dma chunks would be managed 50744961713Sgirish */ 50844961713Sgirish #ifdef NIU_PA_WORKAROUND 50944961713Sgirish size_t alloc_sizes [] = {0x2000}; 51044961713Sgirish #else 51144961713Sgirish size_t alloc_sizes [] = {0x1000, 0x2000, 0x4000, 0x8000, 51244961713Sgirish 0x10000, 0x20000, 0x40000, 0x80000, 51330ac2e7bSml 0x100000, 0x200000, 0x400000, 0x800000, 51430ac2e7bSml 0x1000000, 0x2000000, 0x4000000}; 51544961713Sgirish #endif 51644961713Sgirish 51744961713Sgirish /* 51844961713Sgirish * Translate "dev_t" to a pointer to the associated "dev_info_t". 51944961713Sgirish */ 52044961713Sgirish 521678453a8Sspeer extern void nxge_get_environs(nxge_t *); 522678453a8Sspeer 52344961713Sgirish static int 52444961713Sgirish nxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 52544961713Sgirish { 52644961713Sgirish p_nxge_t nxgep = NULL; 52744961713Sgirish int instance; 52844961713Sgirish int status = DDI_SUCCESS; 52944961713Sgirish uint8_t portn; 53058324dfcSspeer nxge_mmac_t *mmac_info; 5317b1f684aSSriharsha Basavapatna p_nxge_param_t param_arr; 53244961713Sgirish 53344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_attach")); 53444961713Sgirish 53544961713Sgirish /* 53644961713Sgirish * Get the device instance since we'll need to setup 53744961713Sgirish * or retrieve a soft state for this instance. 53844961713Sgirish */ 53944961713Sgirish instance = ddi_get_instance(dip); 54044961713Sgirish 54144961713Sgirish switch (cmd) { 54244961713Sgirish case DDI_ATTACH: 54344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_ATTACH")); 54444961713Sgirish break; 54544961713Sgirish 54644961713Sgirish case DDI_RESUME: 54744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_RESUME")); 54844961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 54944961713Sgirish if (nxgep == NULL) { 55044961713Sgirish status = DDI_FAILURE; 55144961713Sgirish break; 55244961713Sgirish } 55344961713Sgirish if (nxgep->dip != dip) { 55444961713Sgirish status = DDI_FAILURE; 55544961713Sgirish break; 55644961713Sgirish } 55744961713Sgirish if (nxgep->suspended == DDI_PM_SUSPEND) { 55844961713Sgirish status = ddi_dev_is_needed(nxgep->dip, 0, 1); 55944961713Sgirish } else { 56056d930aeSspeer status = nxge_resume(nxgep); 56144961713Sgirish } 56244961713Sgirish goto nxge_attach_exit; 56344961713Sgirish 56444961713Sgirish case DDI_PM_RESUME: 56544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_RESUME")); 56644961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 56744961713Sgirish if (nxgep == NULL) { 56844961713Sgirish status = DDI_FAILURE; 56944961713Sgirish break; 57044961713Sgirish } 57144961713Sgirish if (nxgep->dip != dip) { 57244961713Sgirish status = DDI_FAILURE; 57344961713Sgirish break; 57444961713Sgirish } 57556d930aeSspeer status = nxge_resume(nxgep); 57644961713Sgirish goto nxge_attach_exit; 57744961713Sgirish 57844961713Sgirish default: 57944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing unknown")); 58044961713Sgirish status = DDI_FAILURE; 58144961713Sgirish goto nxge_attach_exit; 58244961713Sgirish } 58344961713Sgirish 58444961713Sgirish 58544961713Sgirish if (ddi_soft_state_zalloc(nxge_list, instance) == DDI_FAILURE) { 58644961713Sgirish status = DDI_FAILURE; 58744961713Sgirish goto nxge_attach_exit; 58844961713Sgirish } 58944961713Sgirish 59044961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance); 59144961713Sgirish if (nxgep == NULL) { 5922e59129aSraghus status = NXGE_ERROR; 5932e59129aSraghus goto nxge_attach_fail2; 59444961713Sgirish } 59544961713Sgirish 59698ecde52Stm nxgep->nxge_magic = NXGE_MAGIC; 59798ecde52Stm 59844961713Sgirish nxgep->drv_state = 0; 59944961713Sgirish nxgep->dip = dip; 60044961713Sgirish nxgep->instance = instance; 60144961713Sgirish nxgep->p_dip = ddi_get_parent(dip); 60244961713Sgirish nxgep->nxge_debug_level = nxge_debug_level; 60344961713Sgirish npi_debug_level = nxge_debug_level; 60444961713Sgirish 605678453a8Sspeer /* Are we a guest running in a Hybrid I/O environment? */ 606678453a8Sspeer nxge_get_environs(nxgep); 60744961713Sgirish 60844961713Sgirish status = nxge_map_regs(nxgep); 609678453a8Sspeer 61044961713Sgirish if (status != NXGE_OK) { 61144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_map_regs failed")); 6122e59129aSraghus goto nxge_attach_fail3; 61344961713Sgirish } 61444961713Sgirish 615678453a8Sspeer nxge_fm_init(nxgep, &nxge_dev_reg_acc_attr, 616678453a8Sspeer &nxge_dev_desc_dma_acc_attr, 617678453a8Sspeer &nxge_rx_dma_attr); 618678453a8Sspeer 619678453a8Sspeer /* Create & initialize the per-Neptune data structure */ 620678453a8Sspeer /* (even if we're a guest). */ 62144961713Sgirish status = nxge_init_common_dev(nxgep); 62244961713Sgirish if (status != NXGE_OK) { 62344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6244045d941Ssowmini "nxge_init_common_dev failed")); 6252e59129aSraghus goto nxge_attach_fail4; 62644961713Sgirish } 62744961713Sgirish 628d6d3405fSml /* 629d6d3405fSml * Software workaround: set the replay timer. 630d6d3405fSml */ 631d6d3405fSml if (nxgep->niu_type != N2_NIU) { 632d6d3405fSml nxge_set_pci_replay_timeout(nxgep); 633d6d3405fSml } 634d6d3405fSml 635678453a8Sspeer #if defined(sun4v) 636678453a8Sspeer /* This is required by nxge_hio_init(), which follows. */ 637678453a8Sspeer if ((status = nxge_hsvc_register(nxgep)) != DDI_SUCCESS) 6389d5b8bc5SMichael Speer goto nxge_attach_fail4; 639678453a8Sspeer #endif 640678453a8Sspeer 641678453a8Sspeer if ((status = nxge_hio_init(nxgep)) != NXGE_OK) { 642678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6434045d941Ssowmini "nxge_hio_init failed")); 644678453a8Sspeer goto nxge_attach_fail4; 645678453a8Sspeer } 646678453a8Sspeer 64759ac0c16Sdavemq if (nxgep->niu_type == NEPTUNE_2_10GF) { 64859ac0c16Sdavemq if (nxgep->function_num > 1) { 6494202ea4bSsbehera NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Unsupported" 65059ac0c16Sdavemq " function %d. Only functions 0 and 1 are " 65159ac0c16Sdavemq "supported for this card.", nxgep->function_num)); 65259ac0c16Sdavemq status = NXGE_ERROR; 6532e59129aSraghus goto nxge_attach_fail4; 65459ac0c16Sdavemq } 65559ac0c16Sdavemq } 65659ac0c16Sdavemq 657678453a8Sspeer if (isLDOMguest(nxgep)) { 658678453a8Sspeer /* 659678453a8Sspeer * Use the function number here. 660678453a8Sspeer */ 661678453a8Sspeer nxgep->mac.portnum = nxgep->function_num; 662678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_LOGICAL; 663678453a8Sspeer 664678453a8Sspeer /* XXX We'll set the MAC address counts to 1 for now. */ 665678453a8Sspeer mmac_info = &nxgep->nxge_mmac_info; 666678453a8Sspeer mmac_info->num_mmac = 1; 667678453a8Sspeer mmac_info->naddrfree = 1; 66858324dfcSspeer } else { 669678453a8Sspeer portn = NXGE_GET_PORT_NUM(nxgep->function_num); 670678453a8Sspeer nxgep->mac.portnum = portn; 671678453a8Sspeer if ((portn == 0) || (portn == 1)) 672678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_XMAC; 673678453a8Sspeer else 674678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_BMAC; 675678453a8Sspeer /* 676678453a8Sspeer * Neptune has 4 ports, the first 2 ports use XMAC (10G MAC) 677678453a8Sspeer * internally, the rest 2 ports use BMAC (1G "Big" MAC). 678678453a8Sspeer * The two types of MACs have different characterizations. 679678453a8Sspeer */ 680678453a8Sspeer mmac_info = &nxgep->nxge_mmac_info; 681678453a8Sspeer if (nxgep->function_num < 2) { 682678453a8Sspeer mmac_info->num_mmac = XMAC_MAX_ALT_ADDR_ENTRY; 683678453a8Sspeer mmac_info->naddrfree = XMAC_MAX_ALT_ADDR_ENTRY; 684678453a8Sspeer } else { 685678453a8Sspeer mmac_info->num_mmac = BMAC_MAX_ALT_ADDR_ENTRY; 686678453a8Sspeer mmac_info->naddrfree = BMAC_MAX_ALT_ADDR_ENTRY; 687678453a8Sspeer } 68858324dfcSspeer } 68944961713Sgirish /* 69044961713Sgirish * Setup the Ndd parameters for the this instance. 69144961713Sgirish */ 69244961713Sgirish nxge_init_param(nxgep); 69344961713Sgirish 69444961713Sgirish /* 69544961713Sgirish * Setup Register Tracing Buffer. 69644961713Sgirish */ 69744961713Sgirish npi_rtrace_buf_init((rtrace_t *)&npi_rtracebuf); 69844961713Sgirish 69944961713Sgirish /* init stats ptr */ 70044961713Sgirish nxge_init_statsp(nxgep); 70156d930aeSspeer 7022e59129aSraghus /* 703678453a8Sspeer * Copy the vpd info from eeprom to a local data 704678453a8Sspeer * structure, and then check its validity. 7052e59129aSraghus */ 706678453a8Sspeer if (!isLDOMguest(nxgep)) { 707678453a8Sspeer int *regp; 708678453a8Sspeer uint_t reglen; 709678453a8Sspeer int rv; 71056d930aeSspeer 711678453a8Sspeer nxge_vpd_info_get(nxgep); 71244961713Sgirish 713678453a8Sspeer /* Find the NIU config handle. */ 714678453a8Sspeer rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, 715678453a8Sspeer ddi_get_parent(nxgep->dip), DDI_PROP_DONTPASS, 716678453a8Sspeer "reg", ®p, ®len); 717678453a8Sspeer 718678453a8Sspeer if (rv != DDI_PROP_SUCCESS) { 719678453a8Sspeer goto nxge_attach_fail5; 720678453a8Sspeer } 721678453a8Sspeer /* 722678453a8Sspeer * The address_hi, that is the first int, in the reg 723678453a8Sspeer * property consists of config handle, but need to remove 724678453a8Sspeer * the bits 28-31 which are OBP specific info. 725678453a8Sspeer */ 726678453a8Sspeer nxgep->niu_cfg_hdl = (*regp) & 0xFFFFFFF; 727678453a8Sspeer ddi_prop_free(regp); 72844961713Sgirish } 72944961713Sgirish 730678453a8Sspeer if (isLDOMguest(nxgep)) { 731678453a8Sspeer uchar_t *prop_val; 732678453a8Sspeer uint_t prop_len; 7337b1f684aSSriharsha Basavapatna uint32_t max_frame_size; 73444961713Sgirish 735678453a8Sspeer extern void nxge_get_logical_props(p_nxge_t); 736678453a8Sspeer 737678453a8Sspeer nxgep->statsp->mac_stats.xcvr_inuse = LOGICAL_XCVR; 738678453a8Sspeer nxgep->mac.portmode = PORT_LOGICAL; 739678453a8Sspeer (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 740678453a8Sspeer "phy-type", "virtual transceiver"); 741678453a8Sspeer 742678453a8Sspeer nxgep->nports = 1; 743678453a8Sspeer nxgep->board_ver = 0; /* XXX What? */ 744678453a8Sspeer 745678453a8Sspeer /* 746678453a8Sspeer * local-mac-address property gives us info on which 747678453a8Sspeer * specific MAC address the Hybrid resource is associated 748678453a8Sspeer * with. 749678453a8Sspeer */ 750678453a8Sspeer if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0, 751678453a8Sspeer "local-mac-address", &prop_val, 752678453a8Sspeer &prop_len) != DDI_PROP_SUCCESS) { 753678453a8Sspeer goto nxge_attach_fail5; 754678453a8Sspeer } 755678453a8Sspeer if (prop_len != ETHERADDRL) { 756678453a8Sspeer ddi_prop_free(prop_val); 757678453a8Sspeer goto nxge_attach_fail5; 758678453a8Sspeer } 759678453a8Sspeer ether_copy(prop_val, nxgep->hio_mac_addr); 760678453a8Sspeer ddi_prop_free(prop_val); 761678453a8Sspeer nxge_get_logical_props(nxgep); 762678453a8Sspeer 7637b1f684aSSriharsha Basavapatna /* 7647b1f684aSSriharsha Basavapatna * Enable Jumbo property based on the "max-frame-size" 7657b1f684aSSriharsha Basavapatna * property value. 7667b1f684aSSriharsha Basavapatna */ 7677b1f684aSSriharsha Basavapatna max_frame_size = ddi_prop_get_int(DDI_DEV_T_ANY, 7687b1f684aSSriharsha Basavapatna nxgep->dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 7697b1f684aSSriharsha Basavapatna "max-frame-size", NXGE_MTU_DEFAULT_MAX); 7707b1f684aSSriharsha Basavapatna if ((max_frame_size > NXGE_MTU_DEFAULT_MAX) && 7717b1f684aSSriharsha Basavapatna (max_frame_size <= TX_JUMBO_MTU)) { 7727b1f684aSSriharsha Basavapatna param_arr = nxgep->param_arr; 7737b1f684aSSriharsha Basavapatna 7747b1f684aSSriharsha Basavapatna param_arr[param_accept_jumbo].value = 1; 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 81344961713Sgirish nxge_hw_id_init(nxgep); 814678453a8Sspeer 815678453a8Sspeer if (!isLDOMguest(nxgep)) 816678453a8Sspeer nxge_hw_init_niu_common(nxgep); 81744961713Sgirish 81844961713Sgirish status = nxge_setup_mutexes(nxgep); 81944961713Sgirish if (status != NXGE_OK) { 82044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set mutex failed")); 82144961713Sgirish goto nxge_attach_fail; 82244961713Sgirish } 82344961713Sgirish 824678453a8Sspeer #if defined(sun4v) 825678453a8Sspeer if (isLDOMguest(nxgep)) { 826678453a8Sspeer /* Find our VR & channel sets. */ 827678453a8Sspeer status = nxge_hio_vr_add(nxgep); 828678453a8Sspeer goto nxge_attach_exit; 829678453a8Sspeer } 830678453a8Sspeer #endif 831678453a8Sspeer 83244961713Sgirish status = nxge_setup_dev(nxgep); 83344961713Sgirish if (status != DDI_SUCCESS) { 83444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set dev failed")); 83544961713Sgirish goto nxge_attach_fail; 83644961713Sgirish } 83744961713Sgirish 83844961713Sgirish status = nxge_add_intrs(nxgep); 83944961713Sgirish if (status != DDI_SUCCESS) { 84044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "add_intr failed")); 84144961713Sgirish goto nxge_attach_fail; 84244961713Sgirish } 84344961713Sgirish status = nxge_add_soft_intrs(nxgep); 84444961713Sgirish if (status != DDI_SUCCESS) { 845678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 846678453a8Sspeer "add_soft_intr failed")); 84744961713Sgirish goto nxge_attach_fail; 84844961713Sgirish } 84944961713Sgirish 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 959678453a8Sspeer if (isLDOMguest(nxgep)) { 960d7cf53fcSmisaki Miyashita if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) 961d7cf53fcSmisaki Miyashita nxge_m_stop((void *)nxgep); 962678453a8Sspeer nxge_hio_unregister(nxgep); 963678453a8Sspeer } else if (nxgep->mach && (status = mac_unregister(nxgep->mach)) != 0) { 96444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 9654045d941Ssowmini "<== nxge_detach status = 0x%08X", status)); 96644961713Sgirish return (DDI_FAILURE); 96744961713Sgirish } 96844961713Sgirish 96944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 9704045d941Ssowmini "<== nxge_detach (mac_unregister) status = 0x%08X", status)); 97144961713Sgirish 97244961713Sgirish nxge_unattach(nxgep); 97344961713Sgirish nxgep = NULL; 97444961713Sgirish 97544961713Sgirish nxge_detach_exit: 97644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_detach status = 0x%08X", 9774045d941Ssowmini status)); 97844961713Sgirish 97944961713Sgirish return (status); 98044961713Sgirish } 98144961713Sgirish 98244961713Sgirish static void 98344961713Sgirish nxge_unattach(p_nxge_t nxgep) 98444961713Sgirish { 98544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unattach")); 98644961713Sgirish 98744961713Sgirish if (nxgep == NULL || nxgep->dev_regs == NULL) { 98844961713Sgirish return; 98944961713Sgirish } 99044961713Sgirish 99198ecde52Stm nxgep->nxge_magic = 0; 99298ecde52Stm 99344961713Sgirish if (nxgep->nxge_timerid) { 99444961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 99544961713Sgirish nxgep->nxge_timerid = 0; 99644961713Sgirish } 99744961713Sgirish 9986f157acbSml /* 9996f157acbSml * If this flag is set, it will affect the Neptune 10006f157acbSml * only. 10016f157acbSml */ 10026f157acbSml if ((nxgep->niu_type != N2_NIU) && nxge_peu_reset_enable) { 10036f157acbSml nxge_niu_peu_reset(nxgep); 10046f157acbSml } 10056f157acbSml 1006678453a8Sspeer #if defined(sun4v) 1007678453a8Sspeer if (isLDOMguest(nxgep)) { 1008d00f30bbSspeer (void) nxge_hio_vr_release(nxgep); 1009678453a8Sspeer } 1010678453a8Sspeer #endif 1011678453a8Sspeer 101253560810Ssbehera if (nxgep->nxge_hw_p) { 101353560810Ssbehera nxge_uninit_common_dev(nxgep); 101453560810Ssbehera nxgep->nxge_hw_p = NULL; 101553560810Ssbehera } 101653560810Ssbehera 101744961713Sgirish #if defined(sun4v) 101844961713Sgirish if (nxgep->niu_type == N2_NIU && nxgep->niu_hsvc_available == B_TRUE) { 101944961713Sgirish (void) hsvc_unregister(&nxgep->niu_hsvc); 102044961713Sgirish nxgep->niu_hsvc_available = B_FALSE; 102144961713Sgirish } 102244961713Sgirish #endif 102344961713Sgirish /* 102444961713Sgirish * Stop any further interrupts. 102544961713Sgirish */ 102644961713Sgirish nxge_remove_intrs(nxgep); 102744961713Sgirish 102844961713Sgirish /* remove soft interrups */ 102944961713Sgirish nxge_remove_soft_intrs(nxgep); 103044961713Sgirish 103144961713Sgirish /* 103244961713Sgirish * Stop the device and free resources. 103344961713Sgirish */ 1034678453a8Sspeer if (!isLDOMguest(nxgep)) { 1035678453a8Sspeer nxge_destroy_dev(nxgep); 1036678453a8Sspeer } 103744961713Sgirish 103844961713Sgirish /* 103944961713Sgirish * Tear down the ndd parameters setup. 104044961713Sgirish */ 104144961713Sgirish nxge_destroy_param(nxgep); 104244961713Sgirish 104344961713Sgirish /* 104444961713Sgirish * Tear down the kstat setup. 104544961713Sgirish */ 104644961713Sgirish nxge_destroy_kstats(nxgep); 104744961713Sgirish 104844961713Sgirish /* 104944961713Sgirish * Destroy all mutexes. 105044961713Sgirish */ 105144961713Sgirish nxge_destroy_mutexes(nxgep); 105244961713Sgirish 105344961713Sgirish /* 105444961713Sgirish * Remove the list of ndd parameters which 105544961713Sgirish * were setup during attach. 105644961713Sgirish */ 105744961713Sgirish if (nxgep->dip) { 105844961713Sgirish NXGE_DEBUG_MSG((nxgep, OBP_CTL, 10594045d941Ssowmini " nxge_unattach: remove all properties")); 106044961713Sgirish 106144961713Sgirish (void) ddi_prop_remove_all(nxgep->dip); 106244961713Sgirish } 106344961713Sgirish 106444961713Sgirish #if NXGE_PROPERTY 106544961713Sgirish nxge_remove_hard_properties(nxgep); 106644961713Sgirish #endif 106744961713Sgirish 106844961713Sgirish /* 106944961713Sgirish * Unmap the register setup. 107044961713Sgirish */ 107144961713Sgirish nxge_unmap_regs(nxgep); 107244961713Sgirish 107344961713Sgirish nxge_fm_fini(nxgep); 107444961713Sgirish 107544961713Sgirish ddi_soft_state_free(nxge_list, nxgep->instance); 107644961713Sgirish 107744961713Sgirish NXGE_DEBUG_MSG((NULL, DDI_CTL, "<== nxge_unattach")); 107844961713Sgirish } 107944961713Sgirish 1080678453a8Sspeer #if defined(sun4v) 1081678453a8Sspeer int 10829d5b8bc5SMichael Speer nxge_hsvc_register(nxge_t *nxgep) 1083678453a8Sspeer { 1084678453a8Sspeer nxge_status_t status; 1085678453a8Sspeer 1086678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 1087678453a8Sspeer nxgep->niu_hsvc_available = B_FALSE; 1088678453a8Sspeer bcopy(&niu_hsvc, &nxgep->niu_hsvc, sizeof (hsvc_info_t)); 1089678453a8Sspeer if ((status = hsvc_register(&nxgep->niu_hsvc, 1090678453a8Sspeer &nxgep->niu_min_ver)) != 0) { 1091678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1092678453a8Sspeer "nxge_attach: %s: cannot negotiate " 1093678453a8Sspeer "hypervisor services revision %d group: 0x%lx " 1094678453a8Sspeer "major: 0x%lx minor: 0x%lx errno: %d", 1095678453a8Sspeer niu_hsvc.hsvc_modname, niu_hsvc.hsvc_rev, 1096678453a8Sspeer niu_hsvc.hsvc_group, niu_hsvc.hsvc_major, 1097678453a8Sspeer niu_hsvc.hsvc_minor, status)); 1098678453a8Sspeer return (DDI_FAILURE); 1099678453a8Sspeer } 1100678453a8Sspeer nxgep->niu_hsvc_available = B_TRUE; 1101678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11024045d941Ssowmini "NIU Hypervisor service enabled")); 1103678453a8Sspeer } 1104678453a8Sspeer 1105678453a8Sspeer return (DDI_SUCCESS); 1106678453a8Sspeer } 1107678453a8Sspeer #endif 1108678453a8Sspeer 110944961713Sgirish static char n2_siu_name[] = "niu"; 111044961713Sgirish 111144961713Sgirish static nxge_status_t 111244961713Sgirish nxge_map_regs(p_nxge_t nxgep) 111344961713Sgirish { 111444961713Sgirish int ddi_status = DDI_SUCCESS; 111544961713Sgirish p_dev_regs_t dev_regs; 111644961713Sgirish char buf[MAXPATHLEN + 1]; 111744961713Sgirish char *devname; 111844961713Sgirish #ifdef NXGE_DEBUG 111944961713Sgirish char *sysname; 112044961713Sgirish #endif 112144961713Sgirish off_t regsize; 112244961713Sgirish nxge_status_t status = NXGE_OK; 112314ea4bb7Ssd #if !defined(_BIG_ENDIAN) 112414ea4bb7Ssd off_t pci_offset; 112514ea4bb7Ssd uint16_t pcie_devctl; 112614ea4bb7Ssd #endif 112744961713Sgirish 1128678453a8Sspeer if (isLDOMguest(nxgep)) { 1129678453a8Sspeer return (nxge_guest_regs_map(nxgep)); 1130678453a8Sspeer } 1131678453a8Sspeer 113244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_map_regs")); 113344961713Sgirish nxgep->dev_regs = NULL; 113444961713Sgirish dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP); 113544961713Sgirish dev_regs->nxge_regh = NULL; 113644961713Sgirish dev_regs->nxge_pciregh = NULL; 113744961713Sgirish dev_regs->nxge_msix_regh = NULL; 113844961713Sgirish dev_regs->nxge_vir_regh = NULL; 113944961713Sgirish dev_regs->nxge_vir2_regh = NULL; 114059ac0c16Sdavemq nxgep->niu_type = NIU_TYPE_NONE; 114144961713Sgirish 114244961713Sgirish devname = ddi_pathname(nxgep->dip, buf); 114344961713Sgirish ASSERT(strlen(devname) > 0); 114444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11454045d941Ssowmini "nxge_map_regs: pathname devname %s", devname)); 114644961713Sgirish 114700161856Syc /* 114800161856Syc * The driver is running on a N2-NIU system if devname is something 114900161856Syc * like "/niu@80/network@0" 115000161856Syc */ 115144961713Sgirish if (strstr(devname, n2_siu_name)) { 115244961713Sgirish /* N2/NIU */ 115344961713Sgirish nxgep->niu_type = N2_NIU; 115444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11554045d941Ssowmini "nxge_map_regs: N2/NIU devname %s", devname)); 115644961713Sgirish /* get function number */ 115744961713Sgirish nxgep->function_num = 11584045d941Ssowmini (devname[strlen(devname) -1] == '1' ? 1 : 0); 115944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11604045d941Ssowmini "nxge_map_regs: N2/NIU function number %d", 11614045d941Ssowmini nxgep->function_num)); 116244961713Sgirish } else { 116344961713Sgirish int *prop_val; 116444961713Sgirish uint_t prop_len; 116544961713Sgirish uint8_t func_num; 116644961713Sgirish 116744961713Sgirish if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 11684045d941Ssowmini 0, "reg", 11694045d941Ssowmini &prop_val, &prop_len) != DDI_PROP_SUCCESS) { 117044961713Sgirish NXGE_DEBUG_MSG((nxgep, VPD_CTL, 11714045d941Ssowmini "Reg property not found")); 117244961713Sgirish ddi_status = DDI_FAILURE; 117344961713Sgirish goto nxge_map_regs_fail0; 117444961713Sgirish 117544961713Sgirish } else { 117644961713Sgirish func_num = (prop_val[0] >> 8) & 0x7; 117744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11784045d941Ssowmini "Reg property found: fun # %d", 11794045d941Ssowmini func_num)); 118044961713Sgirish nxgep->function_num = func_num; 1181678453a8Sspeer if (isLDOMguest(nxgep)) { 1182678453a8Sspeer nxgep->function_num /= 2; 1183678453a8Sspeer return (NXGE_OK); 1184678453a8Sspeer } 118544961713Sgirish ddi_prop_free(prop_val); 118644961713Sgirish } 118744961713Sgirish } 118844961713Sgirish 118944961713Sgirish switch (nxgep->niu_type) { 119044961713Sgirish default: 119144961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 0, ®size); 119244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11934045d941Ssowmini "nxge_map_regs: pci config size 0x%x", regsize)); 119444961713Sgirish 119544961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 0, 11964045d941Ssowmini (caddr_t *)&(dev_regs->nxge_pciregp), 0, 0, 11974045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_pciregh); 119844961713Sgirish if (ddi_status != DDI_SUCCESS) { 119944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12004045d941Ssowmini "ddi_map_regs, nxge bus config regs failed")); 120144961713Sgirish goto nxge_map_regs_fail0; 120244961713Sgirish } 120344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12044045d941Ssowmini "nxge_map_reg: PCI config addr 0x%0llx " 12054045d941Ssowmini " handle 0x%0llx", dev_regs->nxge_pciregp, 12064045d941Ssowmini dev_regs->nxge_pciregh)); 120744961713Sgirish /* 120844961713Sgirish * IMP IMP 120944961713Sgirish * workaround for bit swapping bug in HW 121044961713Sgirish * which ends up in no-snoop = yes 121144961713Sgirish * resulting, in DMA not synched properly 121244961713Sgirish */ 121344961713Sgirish #if !defined(_BIG_ENDIAN) 121414ea4bb7Ssd /* workarounds for x86 systems */ 121514ea4bb7Ssd pci_offset = 0x80 + PCIE_DEVCTL; 121614ea4bb7Ssd pcie_devctl = 0x0; 121714ea4bb7Ssd pcie_devctl &= PCIE_DEVCTL_ENABLE_NO_SNOOP; 121814ea4bb7Ssd pcie_devctl |= PCIE_DEVCTL_RO_EN; 121914ea4bb7Ssd pci_config_put16(dev_regs->nxge_pciregh, pci_offset, 12204045d941Ssowmini pcie_devctl); 122144961713Sgirish #endif 122214ea4bb7Ssd 122344961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 122444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12254045d941Ssowmini "nxge_map_regs: pio size 0x%x", regsize)); 122644961713Sgirish /* set up the device mapped register */ 122744961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 12284045d941Ssowmini (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 12294045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 123044961713Sgirish if (ddi_status != DDI_SUCCESS) { 123144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12324045d941Ssowmini "ddi_map_regs for Neptune global reg failed")); 123344961713Sgirish goto nxge_map_regs_fail1; 123444961713Sgirish } 123544961713Sgirish 123644961713Sgirish /* set up the msi/msi-x mapped register */ 123744961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 123844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12394045d941Ssowmini "nxge_map_regs: msix size 0x%x", regsize)); 124044961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 12414045d941Ssowmini (caddr_t *)&(dev_regs->nxge_msix_regp), 0, 0, 12424045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_msix_regh); 124344961713Sgirish if (ddi_status != DDI_SUCCESS) { 124444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12454045d941Ssowmini "ddi_map_regs for msi reg failed")); 124644961713Sgirish goto nxge_map_regs_fail2; 124744961713Sgirish } 124844961713Sgirish 124944961713Sgirish /* set up the vio region mapped register */ 125044961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 125144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12524045d941Ssowmini "nxge_map_regs: vio size 0x%x", regsize)); 125344961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 12544045d941Ssowmini (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 12554045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 125644961713Sgirish 125744961713Sgirish if (ddi_status != DDI_SUCCESS) { 125844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12594045d941Ssowmini "ddi_map_regs for nxge vio reg failed")); 126044961713Sgirish goto nxge_map_regs_fail3; 126144961713Sgirish } 126244961713Sgirish nxgep->dev_regs = dev_regs; 126344961713Sgirish 126444961713Sgirish NPI_PCI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_pciregh); 126544961713Sgirish NPI_PCI_ADD_HANDLE_SET(nxgep, 12664045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_pciregp); 126744961713Sgirish NPI_MSI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_msix_regh); 126844961713Sgirish NPI_MSI_ADD_HANDLE_SET(nxgep, 12694045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_msix_regp); 127044961713Sgirish 127144961713Sgirish NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 127244961713Sgirish NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 127344961713Sgirish 127444961713Sgirish NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 127544961713Sgirish NPI_REG_ADD_HANDLE_SET(nxgep, 12764045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_regp); 127744961713Sgirish 127844961713Sgirish NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 127944961713Sgirish NPI_VREG_ADD_HANDLE_SET(nxgep, 12804045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 128144961713Sgirish 128244961713Sgirish break; 128344961713Sgirish 128444961713Sgirish case N2_NIU: 128544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "ddi_map_regs, NIU")); 128644961713Sgirish /* 128744961713Sgirish * Set up the device mapped register (FWARC 2006/556) 128844961713Sgirish * (changed back to 1: reg starts at 1!) 128944961713Sgirish */ 129044961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 129144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12924045d941Ssowmini "nxge_map_regs: dev size 0x%x", regsize)); 129344961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 12944045d941Ssowmini (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 12954045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 129644961713Sgirish 129744961713Sgirish if (ddi_status != DDI_SUCCESS) { 129844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12994045d941Ssowmini "ddi_map_regs for N2/NIU, global reg failed ")); 130044961713Sgirish goto nxge_map_regs_fail1; 130144961713Sgirish } 130244961713Sgirish 1303678453a8Sspeer /* set up the first vio region mapped register */ 130444961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 130544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13064045d941Ssowmini "nxge_map_regs: vio (1) size 0x%x", regsize)); 130744961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 13084045d941Ssowmini (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 13094045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 131044961713Sgirish 131144961713Sgirish if (ddi_status != DDI_SUCCESS) { 131244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13134045d941Ssowmini "ddi_map_regs for nxge vio reg failed")); 131444961713Sgirish goto nxge_map_regs_fail2; 131544961713Sgirish } 1316678453a8Sspeer /* set up the second vio region mapped register */ 131744961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 131844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13194045d941Ssowmini "nxge_map_regs: vio (3) size 0x%x", regsize)); 132044961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 13214045d941Ssowmini (caddr_t *)&(dev_regs->nxge_vir2_regp), 0, 0, 13224045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir2_regh); 132344961713Sgirish 132444961713Sgirish if (ddi_status != DDI_SUCCESS) { 132544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13264045d941Ssowmini "ddi_map_regs for nxge vio2 reg failed")); 132744961713Sgirish goto nxge_map_regs_fail3; 132844961713Sgirish } 132944961713Sgirish nxgep->dev_regs = dev_regs; 133044961713Sgirish 133144961713Sgirish NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 133244961713Sgirish NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 133344961713Sgirish 133444961713Sgirish NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 133544961713Sgirish NPI_REG_ADD_HANDLE_SET(nxgep, 13364045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_regp); 133744961713Sgirish 133844961713Sgirish NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 133944961713Sgirish NPI_VREG_ADD_HANDLE_SET(nxgep, 13404045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 134144961713Sgirish 134244961713Sgirish NPI_V2REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir2_regh); 134344961713Sgirish NPI_V2REG_ADD_HANDLE_SET(nxgep, 13444045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_vir2_regp); 134544961713Sgirish 134644961713Sgirish break; 134744961713Sgirish } 134844961713Sgirish 134944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "nxge_map_reg: hardware addr 0x%0llx " 13504045d941Ssowmini " handle 0x%0llx", dev_regs->nxge_regp, dev_regs->nxge_regh)); 135144961713Sgirish 135244961713Sgirish goto nxge_map_regs_exit; 135344961713Sgirish nxge_map_regs_fail3: 135444961713Sgirish if (dev_regs->nxge_msix_regh) { 135544961713Sgirish ddi_regs_map_free(&dev_regs->nxge_msix_regh); 135644961713Sgirish } 135744961713Sgirish if (dev_regs->nxge_vir_regh) { 135844961713Sgirish ddi_regs_map_free(&dev_regs->nxge_regh); 135944961713Sgirish } 136044961713Sgirish nxge_map_regs_fail2: 136144961713Sgirish if (dev_regs->nxge_regh) { 136244961713Sgirish ddi_regs_map_free(&dev_regs->nxge_regh); 136344961713Sgirish } 136444961713Sgirish nxge_map_regs_fail1: 136544961713Sgirish if (dev_regs->nxge_pciregh) { 136644961713Sgirish ddi_regs_map_free(&dev_regs->nxge_pciregh); 136744961713Sgirish } 136844961713Sgirish nxge_map_regs_fail0: 136944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Freeing register set memory")); 137044961713Sgirish kmem_free(dev_regs, sizeof (dev_regs_t)); 137144961713Sgirish 137244961713Sgirish nxge_map_regs_exit: 137344961713Sgirish if (ddi_status != DDI_SUCCESS) 137444961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 137544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_map_regs")); 137644961713Sgirish return (status); 137744961713Sgirish } 137844961713Sgirish 137944961713Sgirish static void 138044961713Sgirish nxge_unmap_regs(p_nxge_t nxgep) 138144961713Sgirish { 138244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unmap_regs")); 1383678453a8Sspeer 1384678453a8Sspeer if (isLDOMguest(nxgep)) { 1385678453a8Sspeer nxge_guest_regs_map_free(nxgep); 1386678453a8Sspeer return; 1387678453a8Sspeer } 1388678453a8Sspeer 138944961713Sgirish if (nxgep->dev_regs) { 139044961713Sgirish if (nxgep->dev_regs->nxge_pciregh) { 139144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13924045d941Ssowmini "==> nxge_unmap_regs: bus")); 139344961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_pciregh); 139444961713Sgirish nxgep->dev_regs->nxge_pciregh = NULL; 139544961713Sgirish } 139644961713Sgirish if (nxgep->dev_regs->nxge_regh) { 139744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13984045d941Ssowmini "==> nxge_unmap_regs: device registers")); 139944961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_regh); 140044961713Sgirish nxgep->dev_regs->nxge_regh = NULL; 140144961713Sgirish } 140244961713Sgirish if (nxgep->dev_regs->nxge_msix_regh) { 140344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 14044045d941Ssowmini "==> nxge_unmap_regs: device interrupts")); 140544961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_msix_regh); 140644961713Sgirish nxgep->dev_regs->nxge_msix_regh = NULL; 140744961713Sgirish } 140844961713Sgirish if (nxgep->dev_regs->nxge_vir_regh) { 140944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 14104045d941Ssowmini "==> nxge_unmap_regs: vio region")); 141144961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_vir_regh); 141244961713Sgirish nxgep->dev_regs->nxge_vir_regh = NULL; 141344961713Sgirish } 141444961713Sgirish if (nxgep->dev_regs->nxge_vir2_regh) { 141544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 14164045d941Ssowmini "==> nxge_unmap_regs: vio2 region")); 141744961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_vir2_regh); 141844961713Sgirish nxgep->dev_regs->nxge_vir2_regh = NULL; 141944961713Sgirish } 142044961713Sgirish 142144961713Sgirish kmem_free(nxgep->dev_regs, sizeof (dev_regs_t)); 142244961713Sgirish nxgep->dev_regs = NULL; 142344961713Sgirish } 142444961713Sgirish 142544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_unmap_regs")); 142644961713Sgirish } 142744961713Sgirish 142844961713Sgirish static nxge_status_t 142944961713Sgirish nxge_setup_mutexes(p_nxge_t nxgep) 143044961713Sgirish { 143144961713Sgirish int ddi_status = DDI_SUCCESS; 143244961713Sgirish nxge_status_t status = NXGE_OK; 143344961713Sgirish nxge_classify_t *classify_ptr; 143444961713Sgirish int partition; 143544961713Sgirish 143644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_mutexes")); 143744961713Sgirish 143844961713Sgirish /* 143944961713Sgirish * Get the interrupt cookie so the mutexes can be 144058324dfcSspeer * Initialized. 144144961713Sgirish */ 1442678453a8Sspeer if (isLDOMguest(nxgep)) { 1443678453a8Sspeer nxgep->interrupt_cookie = 0; 1444678453a8Sspeer } else { 1445678453a8Sspeer ddi_status = ddi_get_iblock_cookie(nxgep->dip, 0, 1446678453a8Sspeer &nxgep->interrupt_cookie); 1447678453a8Sspeer 1448678453a8Sspeer if (ddi_status != DDI_SUCCESS) { 1449678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1450678453a8Sspeer "<== nxge_setup_mutexes: failed 0x%x", 1451678453a8Sspeer ddi_status)); 1452678453a8Sspeer goto nxge_setup_mutexes_exit; 1453678453a8Sspeer } 145444961713Sgirish } 145544961713Sgirish 145698ecde52Stm cv_init(&nxgep->poll_cv, NULL, CV_DRIVER, NULL); 145798ecde52Stm MUTEX_INIT(&nxgep->poll_lock, NULL, 145898ecde52Stm MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 145998ecde52Stm 146044961713Sgirish /* 146198ecde52Stm * Initialize mutexes for this device. 146244961713Sgirish */ 146344961713Sgirish MUTEX_INIT(nxgep->genlock, NULL, 14644045d941Ssowmini MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 146544961713Sgirish MUTEX_INIT(&nxgep->ouraddr_lock, NULL, 14664045d941Ssowmini MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 146744961713Sgirish MUTEX_INIT(&nxgep->mif_lock, NULL, 14684045d941Ssowmini MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 1469678453a8Sspeer MUTEX_INIT(&nxgep->group_lock, NULL, 1470678453a8Sspeer MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 147144961713Sgirish RW_INIT(&nxgep->filter_lock, NULL, 14724045d941Ssowmini RW_DRIVER, (void *)nxgep->interrupt_cookie); 147344961713Sgirish 147444961713Sgirish classify_ptr = &nxgep->classifier; 147544961713Sgirish /* 147644961713Sgirish * FFLP Mutexes are never used in interrupt context 147744961713Sgirish * as fflp operation can take very long time to 147844961713Sgirish * complete and hence not suitable to invoke from interrupt 147944961713Sgirish * handlers. 148044961713Sgirish */ 148144961713Sgirish MUTEX_INIT(&classify_ptr->tcam_lock, NULL, 148259ac0c16Sdavemq NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 14832e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 148444961713Sgirish MUTEX_INIT(&classify_ptr->fcram_lock, NULL, 148559ac0c16Sdavemq NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 148644961713Sgirish for (partition = 0; partition < MAX_PARTITION; partition++) { 148744961713Sgirish MUTEX_INIT(&classify_ptr->hash_lock[partition], NULL, 148844961713Sgirish NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 148944961713Sgirish } 149044961713Sgirish } 149144961713Sgirish 149244961713Sgirish nxge_setup_mutexes_exit: 149344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 149459ac0c16Sdavemq "<== nxge_setup_mutexes status = %x", status)); 149544961713Sgirish 149644961713Sgirish if (ddi_status != DDI_SUCCESS) 149744961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 149844961713Sgirish 149944961713Sgirish return (status); 150044961713Sgirish } 150144961713Sgirish 150244961713Sgirish static void 150344961713Sgirish nxge_destroy_mutexes(p_nxge_t nxgep) 150444961713Sgirish { 150544961713Sgirish int partition; 150644961713Sgirish nxge_classify_t *classify_ptr; 150744961713Sgirish 150844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_mutexes")); 150944961713Sgirish RW_DESTROY(&nxgep->filter_lock); 1510678453a8Sspeer MUTEX_DESTROY(&nxgep->group_lock); 151144961713Sgirish MUTEX_DESTROY(&nxgep->mif_lock); 151244961713Sgirish MUTEX_DESTROY(&nxgep->ouraddr_lock); 151344961713Sgirish MUTEX_DESTROY(nxgep->genlock); 151444961713Sgirish 151544961713Sgirish classify_ptr = &nxgep->classifier; 151644961713Sgirish MUTEX_DESTROY(&classify_ptr->tcam_lock); 151744961713Sgirish 151898ecde52Stm /* Destroy all polling resources. */ 151998ecde52Stm MUTEX_DESTROY(&nxgep->poll_lock); 152098ecde52Stm cv_destroy(&nxgep->poll_cv); 152198ecde52Stm 152298ecde52Stm /* free data structures, based on HW type */ 15232e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 152444961713Sgirish MUTEX_DESTROY(&classify_ptr->fcram_lock); 152544961713Sgirish for (partition = 0; partition < MAX_PARTITION; partition++) { 152644961713Sgirish MUTEX_DESTROY(&classify_ptr->hash_lock[partition]); 152744961713Sgirish } 152844961713Sgirish } 152944961713Sgirish 153044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_mutexes")); 153144961713Sgirish } 153244961713Sgirish 153344961713Sgirish nxge_status_t 153444961713Sgirish nxge_init(p_nxge_t nxgep) 153544961713Sgirish { 1536678453a8Sspeer nxge_status_t status = NXGE_OK; 153744961713Sgirish 153844961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_init")); 153944961713Sgirish 154014ea4bb7Ssd if (nxgep->drv_state & STATE_HW_INITIALIZED) { 154114ea4bb7Ssd return (status); 154214ea4bb7Ssd } 154314ea4bb7Ssd 154444961713Sgirish /* 154544961713Sgirish * Allocate system memory for the receive/transmit buffer blocks 154644961713Sgirish * and receive/transmit descriptor rings. 154744961713Sgirish */ 154844961713Sgirish status = nxge_alloc_mem_pool(nxgep); 154944961713Sgirish if (status != NXGE_OK) { 155044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "alloc mem failed\n")); 155144961713Sgirish goto nxge_init_fail1; 155244961713Sgirish } 155344961713Sgirish 1554678453a8Sspeer if (!isLDOMguest(nxgep)) { 1555678453a8Sspeer /* 1556678453a8Sspeer * Initialize and enable the TXC registers. 1557678453a8Sspeer * (Globally enable the Tx controller, 1558678453a8Sspeer * enable the port, configure the dma channel bitmap, 1559678453a8Sspeer * configure the max burst size). 1560678453a8Sspeer */ 1561678453a8Sspeer status = nxge_txc_init(nxgep); 1562678453a8Sspeer if (status != NXGE_OK) { 1563678453a8Sspeer NXGE_ERROR_MSG((nxgep, 1564678453a8Sspeer NXGE_ERR_CTL, "init txc failed\n")); 1565678453a8Sspeer goto nxge_init_fail2; 1566678453a8Sspeer } 156744961713Sgirish } 156844961713Sgirish 156944961713Sgirish /* 157044961713Sgirish * Initialize and enable TXDMA channels. 157144961713Sgirish */ 157244961713Sgirish status = nxge_init_txdma_channels(nxgep); 157344961713Sgirish if (status != NXGE_OK) { 157444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txdma failed\n")); 157544961713Sgirish goto nxge_init_fail3; 157644961713Sgirish } 157744961713Sgirish 157844961713Sgirish /* 157944961713Sgirish * Initialize and enable RXDMA channels. 158044961713Sgirish */ 158144961713Sgirish status = nxge_init_rxdma_channels(nxgep); 158244961713Sgirish if (status != NXGE_OK) { 158344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init rxdma failed\n")); 158444961713Sgirish goto nxge_init_fail4; 158544961713Sgirish } 158644961713Sgirish 1587678453a8Sspeer /* 1588678453a8Sspeer * The guest domain is now done. 1589678453a8Sspeer */ 1590678453a8Sspeer if (isLDOMguest(nxgep)) { 1591678453a8Sspeer nxgep->drv_state |= STATE_HW_INITIALIZED; 1592678453a8Sspeer goto nxge_init_exit; 1593678453a8Sspeer } 1594678453a8Sspeer 159544961713Sgirish /* 159644961713Sgirish * Initialize TCAM and FCRAM (Neptune). 159744961713Sgirish */ 159844961713Sgirish status = nxge_classify_init(nxgep); 159944961713Sgirish if (status != NXGE_OK) { 160044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init classify failed\n")); 160144961713Sgirish goto nxge_init_fail5; 160244961713Sgirish } 160344961713Sgirish 160444961713Sgirish /* 160544961713Sgirish * Initialize ZCP 160644961713Sgirish */ 160744961713Sgirish status = nxge_zcp_init(nxgep); 160844961713Sgirish if (status != NXGE_OK) { 160944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init ZCP failed\n")); 161044961713Sgirish goto nxge_init_fail5; 161144961713Sgirish } 161244961713Sgirish 161344961713Sgirish /* 161444961713Sgirish * Initialize IPP. 161544961713Sgirish */ 161644961713Sgirish status = nxge_ipp_init(nxgep); 161744961713Sgirish if (status != NXGE_OK) { 161844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init IPP failed\n")); 161944961713Sgirish goto nxge_init_fail5; 162044961713Sgirish } 162144961713Sgirish 162244961713Sgirish /* 162344961713Sgirish * Initialize the MAC block. 162444961713Sgirish */ 162544961713Sgirish status = nxge_mac_init(nxgep); 162644961713Sgirish if (status != NXGE_OK) { 162744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init MAC failed\n")); 162844961713Sgirish goto nxge_init_fail5; 162944961713Sgirish } 163044961713Sgirish 1631678453a8Sspeer nxge_intrs_enable(nxgep); /* XXX What changes do I need to make here? */ 163244961713Sgirish 163344961713Sgirish /* 163444961713Sgirish * Enable hardware interrupts. 163544961713Sgirish */ 163644961713Sgirish nxge_intr_hw_enable(nxgep); 163744961713Sgirish nxgep->drv_state |= STATE_HW_INITIALIZED; 163844961713Sgirish 163944961713Sgirish goto nxge_init_exit; 164044961713Sgirish 164144961713Sgirish nxge_init_fail5: 164244961713Sgirish nxge_uninit_rxdma_channels(nxgep); 164344961713Sgirish nxge_init_fail4: 164444961713Sgirish nxge_uninit_txdma_channels(nxgep); 164544961713Sgirish nxge_init_fail3: 1646678453a8Sspeer if (!isLDOMguest(nxgep)) { 1647678453a8Sspeer (void) nxge_txc_uninit(nxgep); 1648678453a8Sspeer } 164944961713Sgirish nxge_init_fail2: 165044961713Sgirish nxge_free_mem_pool(nxgep); 165144961713Sgirish nxge_init_fail1: 165244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16534045d941Ssowmini "<== nxge_init status (failed) = 0x%08x", status)); 165444961713Sgirish return (status); 165544961713Sgirish 165644961713Sgirish nxge_init_exit: 165744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_init status = 0x%08x", 16584045d941Ssowmini status)); 165944961713Sgirish return (status); 166044961713Sgirish } 166144961713Sgirish 166244961713Sgirish 166344961713Sgirish timeout_id_t 166444961713Sgirish nxge_start_timer(p_nxge_t nxgep, fptrv_t func, int msec) 166544961713Sgirish { 16664045d941Ssowmini if ((nxgep->suspended == 0) || (nxgep->suspended == DDI_RESUME)) { 166744961713Sgirish return (timeout(func, (caddr_t)nxgep, 16684045d941Ssowmini drv_usectohz(1000 * msec))); 166944961713Sgirish } 167044961713Sgirish return (NULL); 167144961713Sgirish } 167244961713Sgirish 167344961713Sgirish /*ARGSUSED*/ 167444961713Sgirish void 167544961713Sgirish nxge_stop_timer(p_nxge_t nxgep, timeout_id_t timerid) 167644961713Sgirish { 167744961713Sgirish if (timerid) { 167844961713Sgirish (void) untimeout(timerid); 167944961713Sgirish } 168044961713Sgirish } 168144961713Sgirish 168244961713Sgirish void 168344961713Sgirish nxge_uninit(p_nxge_t nxgep) 168444961713Sgirish { 168544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_uninit")); 168644961713Sgirish 168744961713Sgirish if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 168844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 16894045d941Ssowmini "==> nxge_uninit: not initialized")); 169044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 16914045d941Ssowmini "<== nxge_uninit")); 169244961713Sgirish return; 169344961713Sgirish } 169444961713Sgirish 169544961713Sgirish /* stop timer */ 169644961713Sgirish if (nxgep->nxge_timerid) { 169744961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 169844961713Sgirish nxgep->nxge_timerid = 0; 169944961713Sgirish } 170044961713Sgirish 170144961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 170244961713Sgirish (void) nxge_intr_hw_disable(nxgep); 170344961713Sgirish 170444961713Sgirish /* 170544961713Sgirish * Reset the receive MAC side. 170644961713Sgirish */ 170744961713Sgirish (void) nxge_rx_mac_disable(nxgep); 170844961713Sgirish 170944961713Sgirish /* Disable and soft reset the IPP */ 1710678453a8Sspeer if (!isLDOMguest(nxgep)) 1711678453a8Sspeer (void) nxge_ipp_disable(nxgep); 171244961713Sgirish 1713a3c5bd6dSspeer /* Free classification resources */ 1714a3c5bd6dSspeer (void) nxge_classify_uninit(nxgep); 1715a3c5bd6dSspeer 171644961713Sgirish /* 171744961713Sgirish * Reset the transmit/receive DMA side. 171844961713Sgirish */ 171944961713Sgirish (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 172044961713Sgirish (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 172144961713Sgirish 172244961713Sgirish nxge_uninit_txdma_channels(nxgep); 172344961713Sgirish nxge_uninit_rxdma_channels(nxgep); 172444961713Sgirish 172544961713Sgirish /* 172644961713Sgirish * Reset the transmit MAC side. 172744961713Sgirish */ 172844961713Sgirish (void) nxge_tx_mac_disable(nxgep); 172944961713Sgirish 173044961713Sgirish nxge_free_mem_pool(nxgep); 173144961713Sgirish 17326f157acbSml /* 17336f157acbSml * Start the timer if the reset flag is not set. 17346f157acbSml * If this reset flag is set, the link monitor 17356f157acbSml * will not be started in order to stop furthur bus 17366f157acbSml * activities coming from this interface. 17376f157acbSml * The driver will start the monitor function 17386f157acbSml * if the interface was initialized again later. 17396f157acbSml */ 17406f157acbSml if (!nxge_peu_reset_enable) { 17416f157acbSml (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 17426f157acbSml } 174344961713Sgirish 174444961713Sgirish nxgep->drv_state &= ~STATE_HW_INITIALIZED; 174544961713Sgirish 174644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_uninit: " 17474045d941Ssowmini "nxge_mblks_pending %d", nxge_mblks_pending)); 174844961713Sgirish } 174944961713Sgirish 175044961713Sgirish void 175144961713Sgirish nxge_get64(p_nxge_t nxgep, p_mblk_t mp) 175244961713Sgirish { 1753adfcba55Sjoycey #if defined(__i386) 1754adfcba55Sjoycey size_t reg; 1755adfcba55Sjoycey #else 175644961713Sgirish uint64_t reg; 1757adfcba55Sjoycey #endif 175844961713Sgirish uint64_t regdata; 175944961713Sgirish int i, retry; 176044961713Sgirish 176144961713Sgirish bcopy((char *)mp->b_rptr, (char *)®, sizeof (uint64_t)); 176244961713Sgirish regdata = 0; 176344961713Sgirish retry = 1; 176444961713Sgirish 176544961713Sgirish for (i = 0; i < retry; i++) { 176644961713Sgirish NXGE_REG_RD64(nxgep->npi_handle, reg, ®data); 176744961713Sgirish } 176844961713Sgirish bcopy((char *)®data, (char *)mp->b_rptr, sizeof (uint64_t)); 176944961713Sgirish } 177044961713Sgirish 177144961713Sgirish void 177244961713Sgirish nxge_put64(p_nxge_t nxgep, p_mblk_t mp) 177344961713Sgirish { 1774adfcba55Sjoycey #if defined(__i386) 1775adfcba55Sjoycey size_t reg; 1776adfcba55Sjoycey #else 177744961713Sgirish uint64_t reg; 1778adfcba55Sjoycey #endif 177944961713Sgirish uint64_t buf[2]; 178044961713Sgirish 178144961713Sgirish bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t)); 17827a8b1321Sjoycey #if defined(__i386) 17837a8b1321Sjoycey reg = (size_t)buf[0]; 17847a8b1321Sjoycey #else 178544961713Sgirish reg = buf[0]; 17867a8b1321Sjoycey #endif 178744961713Sgirish 178844961713Sgirish NXGE_NPI_PIO_WRITE64(nxgep->npi_handle, reg, buf[1]); 178944961713Sgirish } 179044961713Sgirish 179144961713Sgirish 179244961713Sgirish nxge_os_mutex_t nxgedebuglock; 179344961713Sgirish int nxge_debug_init = 0; 179444961713Sgirish 179544961713Sgirish /*ARGSUSED*/ 179644961713Sgirish /*VARARGS*/ 179744961713Sgirish void 179844961713Sgirish nxge_debug_msg(p_nxge_t nxgep, uint64_t level, char *fmt, ...) 179944961713Sgirish { 180044961713Sgirish char msg_buffer[1048]; 180144961713Sgirish char prefix_buffer[32]; 180244961713Sgirish int instance; 180344961713Sgirish uint64_t debug_level; 180444961713Sgirish int cmn_level = CE_CONT; 180544961713Sgirish va_list ap; 180644961713Sgirish 1807678453a8Sspeer if (nxgep && nxgep->nxge_debug_level != nxge_debug_level) { 1808678453a8Sspeer /* In case a developer has changed nxge_debug_level. */ 1809678453a8Sspeer if (nxgep->nxge_debug_level != nxge_debug_level) 1810678453a8Sspeer nxgep->nxge_debug_level = nxge_debug_level; 1811678453a8Sspeer } 1812678453a8Sspeer 181344961713Sgirish debug_level = (nxgep == NULL) ? nxge_debug_level : 18144045d941Ssowmini nxgep->nxge_debug_level; 181544961713Sgirish 181644961713Sgirish if ((level & debug_level) || 18174045d941Ssowmini (level == NXGE_NOTE) || 18184045d941Ssowmini (level == NXGE_ERR_CTL)) { 181944961713Sgirish /* do the msg processing */ 182044961713Sgirish if (nxge_debug_init == 0) { 182144961713Sgirish MUTEX_INIT(&nxgedebuglock, NULL, MUTEX_DRIVER, NULL); 182244961713Sgirish nxge_debug_init = 1; 182344961713Sgirish } 182444961713Sgirish 182544961713Sgirish MUTEX_ENTER(&nxgedebuglock); 182644961713Sgirish 182744961713Sgirish if ((level & NXGE_NOTE)) { 182844961713Sgirish cmn_level = CE_NOTE; 182944961713Sgirish } 183044961713Sgirish 183144961713Sgirish if (level & NXGE_ERR_CTL) { 183244961713Sgirish cmn_level = CE_WARN; 183344961713Sgirish } 183444961713Sgirish 183544961713Sgirish va_start(ap, fmt); 183644961713Sgirish (void) vsprintf(msg_buffer, fmt, ap); 183744961713Sgirish va_end(ap); 183844961713Sgirish if (nxgep == NULL) { 183944961713Sgirish instance = -1; 184044961713Sgirish (void) sprintf(prefix_buffer, "%s :", "nxge"); 184144961713Sgirish } else { 184244961713Sgirish instance = nxgep->instance; 184344961713Sgirish (void) sprintf(prefix_buffer, 18444045d941Ssowmini "%s%d :", "nxge", instance); 184544961713Sgirish } 184644961713Sgirish 184744961713Sgirish MUTEX_EXIT(&nxgedebuglock); 184844961713Sgirish cmn_err(cmn_level, "!%s %s\n", 18494045d941Ssowmini prefix_buffer, msg_buffer); 185044961713Sgirish 185144961713Sgirish } 185244961713Sgirish } 185344961713Sgirish 185444961713Sgirish char * 185544961713Sgirish nxge_dump_packet(char *addr, int size) 185644961713Sgirish { 185744961713Sgirish uchar_t *ap = (uchar_t *)addr; 185844961713Sgirish int i; 185944961713Sgirish static char etherbuf[1024]; 186044961713Sgirish char *cp = etherbuf; 186144961713Sgirish char digits[] = "0123456789abcdef"; 186244961713Sgirish 186344961713Sgirish if (!size) 186444961713Sgirish size = 60; 186544961713Sgirish 186644961713Sgirish if (size > MAX_DUMP_SZ) { 186744961713Sgirish /* Dump the leading bytes */ 186844961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 186944961713Sgirish if (*ap > 0x0f) 187044961713Sgirish *cp++ = digits[*ap >> 4]; 187144961713Sgirish *cp++ = digits[*ap++ & 0xf]; 187244961713Sgirish *cp++ = ':'; 187344961713Sgirish } 187444961713Sgirish for (i = 0; i < 20; i++) 187544961713Sgirish *cp++ = '.'; 187644961713Sgirish /* Dump the last MAX_DUMP_SZ/2 bytes */ 187744961713Sgirish ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ/2)); 187844961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 187944961713Sgirish if (*ap > 0x0f) 188044961713Sgirish *cp++ = digits[*ap >> 4]; 188144961713Sgirish *cp++ = digits[*ap++ & 0xf]; 188244961713Sgirish *cp++ = ':'; 188344961713Sgirish } 188444961713Sgirish } else { 188544961713Sgirish for (i = 0; i < size; i++) { 188644961713Sgirish if (*ap > 0x0f) 188744961713Sgirish *cp++ = digits[*ap >> 4]; 188844961713Sgirish *cp++ = digits[*ap++ & 0xf]; 188944961713Sgirish *cp++ = ':'; 189044961713Sgirish } 189144961713Sgirish } 189244961713Sgirish *--cp = 0; 189344961713Sgirish return (etherbuf); 189444961713Sgirish } 189544961713Sgirish 189644961713Sgirish #ifdef NXGE_DEBUG 189744961713Sgirish static void 189844961713Sgirish nxge_test_map_regs(p_nxge_t nxgep) 189944961713Sgirish { 190044961713Sgirish ddi_acc_handle_t cfg_handle; 190144961713Sgirish p_pci_cfg_t cfg_ptr; 190244961713Sgirish ddi_acc_handle_t dev_handle; 190344961713Sgirish char *dev_ptr; 190444961713Sgirish ddi_acc_handle_t pci_config_handle; 190544961713Sgirish uint32_t regval; 190644961713Sgirish int i; 190744961713Sgirish 190844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_test_map_regs")); 190944961713Sgirish 191044961713Sgirish dev_handle = nxgep->dev_regs->nxge_regh; 191144961713Sgirish dev_ptr = (char *)nxgep->dev_regs->nxge_regp; 191244961713Sgirish 19132e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 191444961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 191544961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 191644961713Sgirish 191744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 191859ac0c16Sdavemq "Neptune PCI regp cfg_ptr 0x%llx", (char *)cfg_ptr)); 191944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 192059ac0c16Sdavemq "Neptune PCI cfg_ptr vendor id ptr 0x%llx", 192159ac0c16Sdavemq &cfg_ptr->vendorid)); 192244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 192359ac0c16Sdavemq "\tvendorid 0x%x devid 0x%x", 192459ac0c16Sdavemq NXGE_PIO_READ16(cfg_handle, &cfg_ptr->vendorid, 0), 192559ac0c16Sdavemq NXGE_PIO_READ16(cfg_handle, &cfg_ptr->devid, 0))); 192644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 192759ac0c16Sdavemq "PCI BAR: base 0x%x base14 0x%x base 18 0x%x " 192859ac0c16Sdavemq "bar1c 0x%x", 192959ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base, 0), 193059ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base14, 0), 193159ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base18, 0), 193259ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base1c, 0))); 193344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 193459ac0c16Sdavemq "\nNeptune PCI BAR: base20 0x%x base24 0x%x " 193559ac0c16Sdavemq "base 28 0x%x bar2c 0x%x\n", 193659ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base20, 0), 193759ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base24, 0), 193859ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base28, 0), 193959ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base2c, 0))); 194044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 194159ac0c16Sdavemq "\nNeptune PCI BAR: base30 0x%x\n", 194259ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base30, 0))); 194344961713Sgirish 194444961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 194544961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 194644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 194759ac0c16Sdavemq "first 0x%llx second 0x%llx third 0x%llx " 194859ac0c16Sdavemq "last 0x%llx ", 194959ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 195059ac0c16Sdavemq (uint64_t *)(dev_ptr + 0), 0), 195159ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 195259ac0c16Sdavemq (uint64_t *)(dev_ptr + 8), 0), 195359ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 195459ac0c16Sdavemq (uint64_t *)(dev_ptr + 16), 0), 195559ac0c16Sdavemq NXGE_PIO_READ64(cfg_handle, 195659ac0c16Sdavemq (uint64_t *)(dev_ptr + 24), 0))); 195744961713Sgirish } 195844961713Sgirish } 195944961713Sgirish 196044961713Sgirish #endif 196144961713Sgirish 196244961713Sgirish static void 196344961713Sgirish nxge_suspend(p_nxge_t nxgep) 196444961713Sgirish { 196544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_suspend")); 196644961713Sgirish 196744961713Sgirish nxge_intrs_disable(nxgep); 196844961713Sgirish nxge_destroy_dev(nxgep); 196944961713Sgirish 197044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_suspend")); 197144961713Sgirish } 197244961713Sgirish 197344961713Sgirish static nxge_status_t 197444961713Sgirish nxge_resume(p_nxge_t nxgep) 197544961713Sgirish { 197644961713Sgirish nxge_status_t status = NXGE_OK; 197744961713Sgirish 197844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_resume")); 197944961713Sgirish 198091c98b31Sjoycey nxgep->suspended = DDI_RESUME; 198191c98b31Sjoycey (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 198291c98b31Sjoycey (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_START); 198391c98b31Sjoycey (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START); 198491c98b31Sjoycey (void) nxge_rx_mac_enable(nxgep); 198591c98b31Sjoycey (void) nxge_tx_mac_enable(nxgep); 198691c98b31Sjoycey nxge_intrs_enable(nxgep); 198744961713Sgirish nxgep->suspended = 0; 198844961713Sgirish 198944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 19904045d941Ssowmini "<== nxge_resume status = 0x%x", status)); 199144961713Sgirish return (status); 199244961713Sgirish } 199344961713Sgirish 199444961713Sgirish static nxge_status_t 199544961713Sgirish nxge_setup_dev(p_nxge_t nxgep) 199644961713Sgirish { 199744961713Sgirish nxge_status_t status = NXGE_OK; 199844961713Sgirish 199944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_dev port %d", 200059ac0c16Sdavemq nxgep->mac.portnum)); 200144961713Sgirish 200244961713Sgirish status = nxge_link_init(nxgep); 200314ea4bb7Ssd 200414ea4bb7Ssd if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) { 200514ea4bb7Ssd NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20064045d941Ssowmini "port%d Bad register acc handle", nxgep->mac.portnum)); 200714ea4bb7Ssd status = NXGE_ERROR; 200814ea4bb7Ssd } 200914ea4bb7Ssd 201044961713Sgirish if (status != NXGE_OK) { 201144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20124045d941Ssowmini " nxge_setup_dev status " 20134045d941Ssowmini "(xcvr init 0x%08x)", status)); 201444961713Sgirish goto nxge_setup_dev_exit; 201544961713Sgirish } 201644961713Sgirish 201744961713Sgirish nxge_setup_dev_exit: 201844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20194045d941Ssowmini "<== nxge_setup_dev port %d status = 0x%08x", 20204045d941Ssowmini nxgep->mac.portnum, status)); 202144961713Sgirish 202244961713Sgirish return (status); 202344961713Sgirish } 202444961713Sgirish 202544961713Sgirish static void 202644961713Sgirish nxge_destroy_dev(p_nxge_t nxgep) 202744961713Sgirish { 202844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_dev")); 202944961713Sgirish 203044961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 203144961713Sgirish 203244961713Sgirish (void) nxge_hw_stop(nxgep); 203344961713Sgirish 203444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_dev")); 203544961713Sgirish } 203644961713Sgirish 203744961713Sgirish static nxge_status_t 203844961713Sgirish nxge_setup_system_dma_pages(p_nxge_t nxgep) 203944961713Sgirish { 204044961713Sgirish int ddi_status = DDI_SUCCESS; 204144961713Sgirish uint_t count; 204244961713Sgirish ddi_dma_cookie_t cookie; 204344961713Sgirish uint_t iommu_pagesize; 204444961713Sgirish nxge_status_t status = NXGE_OK; 204544961713Sgirish 2046678453a8Sspeer NXGE_ERROR_MSG((nxgep, DDI_CTL, "==> nxge_setup_system_dma_pages")); 204744961713Sgirish nxgep->sys_page_sz = ddi_ptob(nxgep->dip, (ulong_t)1); 204844961713Sgirish if (nxgep->niu_type != N2_NIU) { 204944961713Sgirish iommu_pagesize = dvma_pagesize(nxgep->dip); 205044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20514045d941Ssowmini " nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 20524045d941Ssowmini " default_block_size %d iommu_pagesize %d", 20534045d941Ssowmini nxgep->sys_page_sz, 20544045d941Ssowmini ddi_ptob(nxgep->dip, (ulong_t)1), 20554045d941Ssowmini nxgep->rx_default_block_size, 20564045d941Ssowmini iommu_pagesize)); 205744961713Sgirish 205844961713Sgirish if (iommu_pagesize != 0) { 205944961713Sgirish if (nxgep->sys_page_sz == iommu_pagesize) { 206044961713Sgirish if (iommu_pagesize > 0x4000) 206144961713Sgirish nxgep->sys_page_sz = 0x4000; 206244961713Sgirish } else { 206344961713Sgirish if (nxgep->sys_page_sz > iommu_pagesize) 206444961713Sgirish nxgep->sys_page_sz = iommu_pagesize; 206544961713Sgirish } 206644961713Sgirish } 206744961713Sgirish } 206844961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 206944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20704045d941Ssowmini "==> nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 20714045d941Ssowmini "default_block_size %d page mask %d", 20724045d941Ssowmini nxgep->sys_page_sz, 20734045d941Ssowmini ddi_ptob(nxgep->dip, (ulong_t)1), 20744045d941Ssowmini nxgep->rx_default_block_size, 20754045d941Ssowmini nxgep->sys_page_mask)); 207644961713Sgirish 207744961713Sgirish 207844961713Sgirish switch (nxgep->sys_page_sz) { 207944961713Sgirish default: 208044961713Sgirish nxgep->sys_page_sz = 0x1000; 208144961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 208244961713Sgirish nxgep->rx_default_block_size = 0x1000; 208344961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 208444961713Sgirish break; 208544961713Sgirish case 0x1000: 208644961713Sgirish nxgep->rx_default_block_size = 0x1000; 208744961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 208844961713Sgirish break; 208944961713Sgirish case 0x2000: 209044961713Sgirish nxgep->rx_default_block_size = 0x2000; 209144961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 209244961713Sgirish break; 209344961713Sgirish case 0x4000: 209444961713Sgirish nxgep->rx_default_block_size = 0x4000; 209544961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_16K; 209644961713Sgirish break; 209744961713Sgirish case 0x8000: 209844961713Sgirish nxgep->rx_default_block_size = 0x8000; 209944961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_32K; 210044961713Sgirish break; 210144961713Sgirish } 210244961713Sgirish 210344961713Sgirish #ifndef USE_RX_BIG_BUF 210444961713Sgirish nxge_rx_dma_attr.dma_attr_align = nxgep->sys_page_sz; 210544961713Sgirish #else 210644961713Sgirish nxgep->rx_default_block_size = 0x2000; 210744961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 210844961713Sgirish #endif 210944961713Sgirish /* 211044961713Sgirish * Get the system DMA burst size. 211144961713Sgirish */ 211244961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr, 21134045d941Ssowmini DDI_DMA_DONTWAIT, 0, 21144045d941Ssowmini &nxgep->dmasparehandle); 211544961713Sgirish if (ddi_status != DDI_SUCCESS) { 211644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 21174045d941Ssowmini "ddi_dma_alloc_handle: failed " 21184045d941Ssowmini " status 0x%x", ddi_status)); 211944961713Sgirish goto nxge_get_soft_properties_exit; 212044961713Sgirish } 212144961713Sgirish 212244961713Sgirish ddi_status = ddi_dma_addr_bind_handle(nxgep->dmasparehandle, NULL, 21234045d941Ssowmini (caddr_t)nxgep->dmasparehandle, 21244045d941Ssowmini sizeof (nxgep->dmasparehandle), 21254045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 21264045d941Ssowmini DDI_DMA_DONTWAIT, 0, 21274045d941Ssowmini &cookie, &count); 212844961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 212944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 21304045d941Ssowmini "Binding spare handle to find system" 21314045d941Ssowmini " burstsize failed.")); 213244961713Sgirish ddi_status = DDI_FAILURE; 213344961713Sgirish goto nxge_get_soft_properties_fail1; 213444961713Sgirish } 213544961713Sgirish 213644961713Sgirish nxgep->sys_burst_sz = ddi_dma_burstsizes(nxgep->dmasparehandle); 213744961713Sgirish (void) ddi_dma_unbind_handle(nxgep->dmasparehandle); 213844961713Sgirish 213944961713Sgirish nxge_get_soft_properties_fail1: 214044961713Sgirish ddi_dma_free_handle(&nxgep->dmasparehandle); 214144961713Sgirish 214244961713Sgirish nxge_get_soft_properties_exit: 214344961713Sgirish 214444961713Sgirish if (ddi_status != DDI_SUCCESS) 214544961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 214644961713Sgirish 214744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 21484045d941Ssowmini "<== nxge_setup_system_dma_pages status = 0x%08x", status)); 214944961713Sgirish return (status); 215044961713Sgirish } 215144961713Sgirish 215244961713Sgirish static nxge_status_t 215344961713Sgirish nxge_alloc_mem_pool(p_nxge_t nxgep) 215444961713Sgirish { 215544961713Sgirish nxge_status_t status = NXGE_OK; 215644961713Sgirish 215744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_alloc_mem_pool")); 215844961713Sgirish 215944961713Sgirish status = nxge_alloc_rx_mem_pool(nxgep); 216044961713Sgirish if (status != NXGE_OK) { 216144961713Sgirish return (NXGE_ERROR); 216244961713Sgirish } 216344961713Sgirish 216444961713Sgirish status = nxge_alloc_tx_mem_pool(nxgep); 216544961713Sgirish if (status != NXGE_OK) { 216644961713Sgirish nxge_free_rx_mem_pool(nxgep); 216744961713Sgirish return (NXGE_ERROR); 216844961713Sgirish } 216944961713Sgirish 217044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_alloc_mem_pool")); 217144961713Sgirish return (NXGE_OK); 217244961713Sgirish } 217344961713Sgirish 217444961713Sgirish static void 217544961713Sgirish nxge_free_mem_pool(p_nxge_t nxgep) 217644961713Sgirish { 217744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_mem_pool")); 217844961713Sgirish 217944961713Sgirish nxge_free_rx_mem_pool(nxgep); 218044961713Sgirish nxge_free_tx_mem_pool(nxgep); 218144961713Sgirish 218244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_mem_pool")); 218344961713Sgirish } 218444961713Sgirish 2185678453a8Sspeer nxge_status_t 218644961713Sgirish nxge_alloc_rx_mem_pool(p_nxge_t nxgep) 218744961713Sgirish { 2188678453a8Sspeer uint32_t rdc_max; 218944961713Sgirish p_nxge_dma_pt_cfg_t p_all_cfgp; 219044961713Sgirish p_nxge_hw_pt_cfg_t p_cfgp; 219144961713Sgirish p_nxge_dma_pool_t dma_poolp; 219244961713Sgirish p_nxge_dma_common_t *dma_buf_p; 219344961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 219444961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 219544961713Sgirish uint32_t *num_chunks; /* per dma */ 219644961713Sgirish nxge_status_t status = NXGE_OK; 219744961713Sgirish 219844961713Sgirish uint32_t nxge_port_rbr_size; 219944961713Sgirish uint32_t nxge_port_rbr_spare_size; 220044961713Sgirish uint32_t nxge_port_rcr_size; 2201678453a8Sspeer uint32_t rx_cntl_alloc_size; 220244961713Sgirish 220344961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_mem_pool")); 220444961713Sgirish 220544961713Sgirish p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 220644961713Sgirish p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 2207678453a8Sspeer rdc_max = NXGE_MAX_RDCS; 220844961713Sgirish 220944961713Sgirish /* 2210678453a8Sspeer * Allocate memory for the common DMA data structures. 221144961713Sgirish */ 221244961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 22134045d941Ssowmini KM_SLEEP); 221444961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 22154045d941Ssowmini sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP); 221644961713Sgirish 221744961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 22184045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 221944961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 22204045d941Ssowmini sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP); 222144961713Sgirish 222244961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 22234045d941Ssowmini sizeof (uint32_t) * rdc_max, KM_SLEEP); 222444961713Sgirish 222544961713Sgirish /* 2226678453a8Sspeer * Assume that each DMA channel will be configured with 2227678453a8Sspeer * the default block size. 2228678453a8Sspeer * rbr block counts are modulo the batch count (16). 222944961713Sgirish */ 223044961713Sgirish nxge_port_rbr_size = p_all_cfgp->rbr_size; 223144961713Sgirish nxge_port_rcr_size = p_all_cfgp->rcr_size; 223244961713Sgirish 223344961713Sgirish if (!nxge_port_rbr_size) { 223444961713Sgirish nxge_port_rbr_size = NXGE_RBR_RBB_DEFAULT; 223544961713Sgirish } 223644961713Sgirish if (nxge_port_rbr_size % NXGE_RXDMA_POST_BATCH) { 223744961713Sgirish nxge_port_rbr_size = (NXGE_RXDMA_POST_BATCH * 22384045d941Ssowmini (nxge_port_rbr_size / NXGE_RXDMA_POST_BATCH + 1)); 223944961713Sgirish } 224044961713Sgirish 224144961713Sgirish p_all_cfgp->rbr_size = nxge_port_rbr_size; 224244961713Sgirish nxge_port_rbr_spare_size = nxge_rbr_spare_size; 224344961713Sgirish 224444961713Sgirish if (nxge_port_rbr_spare_size % NXGE_RXDMA_POST_BATCH) { 224544961713Sgirish nxge_port_rbr_spare_size = (NXGE_RXDMA_POST_BATCH * 22464045d941Ssowmini (nxge_port_rbr_spare_size / NXGE_RXDMA_POST_BATCH + 1)); 224744961713Sgirish } 224830ac2e7bSml if (nxge_port_rbr_size > RBR_DEFAULT_MAX_BLKS) { 224930ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 225030ac2e7bSml "nxge_alloc_rx_mem_pool: RBR size too high %d, " 225130ac2e7bSml "set to default %d", 225230ac2e7bSml nxge_port_rbr_size, RBR_DEFAULT_MAX_BLKS)); 225330ac2e7bSml nxge_port_rbr_size = RBR_DEFAULT_MAX_BLKS; 225430ac2e7bSml } 225530ac2e7bSml if (nxge_port_rcr_size > RCR_DEFAULT_MAX) { 225630ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 225730ac2e7bSml "nxge_alloc_rx_mem_pool: RCR too high %d, " 225830ac2e7bSml "set to default %d", 225930ac2e7bSml nxge_port_rcr_size, RCR_DEFAULT_MAX)); 226030ac2e7bSml nxge_port_rcr_size = RCR_DEFAULT_MAX; 226130ac2e7bSml } 226244961713Sgirish 226344961713Sgirish /* 226444961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 226544961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 226644961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 226744961713Sgirish * function). 226844961713Sgirish */ 226944961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 227044961713Sgirish if (nxgep->niu_type == N2_NIU) { 227144961713Sgirish nxge_port_rbr_spare_size = 0; 227244961713Sgirish if ((nxge_port_rbr_size > NXGE_NIU_CONTIG_RBR_MAX) || 22734045d941Ssowmini (!ISP2(nxge_port_rbr_size))) { 227444961713Sgirish nxge_port_rbr_size = NXGE_NIU_CONTIG_RBR_MAX; 227544961713Sgirish } 227644961713Sgirish if ((nxge_port_rcr_size > NXGE_NIU_CONTIG_RCR_MAX) || 22774045d941Ssowmini (!ISP2(nxge_port_rcr_size))) { 227844961713Sgirish nxge_port_rcr_size = NXGE_NIU_CONTIG_RCR_MAX; 227944961713Sgirish } 228044961713Sgirish } 228144961713Sgirish #endif 228244961713Sgirish 228344961713Sgirish /* 228444961713Sgirish * Addresses of receive block ring, receive completion ring and the 228544961713Sgirish * mailbox must be all cache-aligned (64 bytes). 228644961713Sgirish */ 228744961713Sgirish rx_cntl_alloc_size = nxge_port_rbr_size + nxge_port_rbr_spare_size; 228844961713Sgirish rx_cntl_alloc_size *= (sizeof (rx_desc_t)); 228944961713Sgirish rx_cntl_alloc_size += (sizeof (rcr_entry_t) * nxge_port_rcr_size); 229044961713Sgirish rx_cntl_alloc_size += sizeof (rxdma_mailbox_t); 229144961713Sgirish 229244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_alloc_rx_mem_pool: " 22934045d941Ssowmini "nxge_port_rbr_size = %d nxge_port_rbr_spare_size = %d " 22944045d941Ssowmini "nxge_port_rcr_size = %d " 22954045d941Ssowmini "rx_cntl_alloc_size = %d", 22964045d941Ssowmini nxge_port_rbr_size, nxge_port_rbr_spare_size, 22974045d941Ssowmini nxge_port_rcr_size, 22984045d941Ssowmini rx_cntl_alloc_size)); 229944961713Sgirish 230044961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 230144961713Sgirish if (nxgep->niu_type == N2_NIU) { 2302678453a8Sspeer uint32_t rx_buf_alloc_size = (nxgep->rx_default_block_size * 2303678453a8Sspeer (nxge_port_rbr_size + nxge_port_rbr_spare_size)); 2304678453a8Sspeer 230544961713Sgirish if (!ISP2(rx_buf_alloc_size)) { 230644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 23074045d941Ssowmini "==> nxge_alloc_rx_mem_pool: " 23084045d941Ssowmini " must be power of 2")); 230944961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 231044961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 231144961713Sgirish } 231244961713Sgirish 231344961713Sgirish if (rx_buf_alloc_size > (1 << 22)) { 231444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 23154045d941Ssowmini "==> nxge_alloc_rx_mem_pool: " 23164045d941Ssowmini " limit size to 4M")); 231744961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 231844961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 231944961713Sgirish } 232044961713Sgirish 232144961713Sgirish if (rx_cntl_alloc_size < 0x2000) { 232244961713Sgirish rx_cntl_alloc_size = 0x2000; 232344961713Sgirish } 232444961713Sgirish } 232544961713Sgirish #endif 232644961713Sgirish nxgep->nxge_port_rbr_size = nxge_port_rbr_size; 232744961713Sgirish nxgep->nxge_port_rcr_size = nxge_port_rcr_size; 2328678453a8Sspeer nxgep->nxge_port_rbr_spare_size = nxge_port_rbr_spare_size; 2329678453a8Sspeer nxgep->nxge_port_rx_cntl_alloc_size = rx_cntl_alloc_size; 233044961713Sgirish 2331678453a8Sspeer dma_poolp->ndmas = p_cfgp->max_rdcs; 233244961713Sgirish dma_poolp->num_chunks = num_chunks; 233344961713Sgirish dma_poolp->buf_allocated = B_TRUE; 233444961713Sgirish nxgep->rx_buf_pool_p = dma_poolp; 233544961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 233644961713Sgirish 2337678453a8Sspeer dma_cntl_poolp->ndmas = p_cfgp->max_rdcs; 233844961713Sgirish dma_cntl_poolp->buf_allocated = B_TRUE; 233944961713Sgirish nxgep->rx_cntl_pool_p = dma_cntl_poolp; 234044961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 234144961713Sgirish 2342678453a8Sspeer /* Allocate the receive rings, too. */ 2343678453a8Sspeer nxgep->rx_rbr_rings = 23444045d941Ssowmini KMEM_ZALLOC(sizeof (rx_rbr_rings_t), KM_SLEEP); 2345678453a8Sspeer nxgep->rx_rbr_rings->rbr_rings = 23464045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_rbr_ring_t) * rdc_max, KM_SLEEP); 2347678453a8Sspeer nxgep->rx_rcr_rings = 23484045d941Ssowmini KMEM_ZALLOC(sizeof (rx_rcr_rings_t), KM_SLEEP); 2349678453a8Sspeer nxgep->rx_rcr_rings->rcr_rings = 23504045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_rcr_ring_t) * rdc_max, KM_SLEEP); 2351678453a8Sspeer nxgep->rx_mbox_areas_p = 23524045d941Ssowmini KMEM_ZALLOC(sizeof (rx_mbox_areas_t), KM_SLEEP); 2353678453a8Sspeer nxgep->rx_mbox_areas_p->rxmbox_areas = 23544045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_mbox_t) * rdc_max, KM_SLEEP); 2355678453a8Sspeer 2356678453a8Sspeer nxgep->rx_rbr_rings->ndmas = nxgep->rx_rcr_rings->ndmas = 2357678453a8Sspeer p_cfgp->max_rdcs; 235844961713Sgirish 235944961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 23604045d941Ssowmini "<== nxge_alloc_rx_mem_pool:status 0x%08x", status)); 236144961713Sgirish 2362678453a8Sspeer nxge_alloc_rx_mem_pool_exit: 2363678453a8Sspeer return (status); 2364678453a8Sspeer } 2365678453a8Sspeer 2366678453a8Sspeer /* 2367678453a8Sspeer * nxge_alloc_rxb 2368678453a8Sspeer * 2369678453a8Sspeer * Allocate buffers for an RDC. 2370678453a8Sspeer * 2371678453a8Sspeer * Arguments: 2372678453a8Sspeer * nxgep 2373678453a8Sspeer * channel The channel to map into our kernel space. 2374678453a8Sspeer * 2375678453a8Sspeer * Notes: 2376678453a8Sspeer * 2377678453a8Sspeer * NPI function calls: 2378678453a8Sspeer * 2379678453a8Sspeer * NXGE function calls: 2380678453a8Sspeer * 2381678453a8Sspeer * Registers accessed: 2382678453a8Sspeer * 2383678453a8Sspeer * Context: 2384678453a8Sspeer * 2385678453a8Sspeer * Taking apart: 2386678453a8Sspeer * 2387678453a8Sspeer * Open questions: 2388678453a8Sspeer * 2389678453a8Sspeer */ 2390678453a8Sspeer nxge_status_t 2391678453a8Sspeer nxge_alloc_rxb( 2392678453a8Sspeer p_nxge_t nxgep, 2393678453a8Sspeer int channel) 2394678453a8Sspeer { 2395678453a8Sspeer size_t rx_buf_alloc_size; 2396678453a8Sspeer nxge_status_t status = NXGE_OK; 2397678453a8Sspeer 2398678453a8Sspeer nxge_dma_common_t **data; 2399678453a8Sspeer nxge_dma_common_t **control; 2400678453a8Sspeer uint32_t *num_chunks; 2401678453a8Sspeer 2402678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb")); 2403678453a8Sspeer 2404678453a8Sspeer /* 2405678453a8Sspeer * Allocate memory for the receive buffers and descriptor rings. 2406678453a8Sspeer * Replace these allocation functions with the interface functions 2407678453a8Sspeer * provided by the partition manager if/when they are available. 2408678453a8Sspeer */ 2409678453a8Sspeer 2410678453a8Sspeer /* 2411678453a8Sspeer * Allocate memory for the receive buffer blocks. 2412678453a8Sspeer */ 2413678453a8Sspeer rx_buf_alloc_size = (nxgep->rx_default_block_size * 24144045d941Ssowmini (nxgep->nxge_port_rbr_size + nxgep->nxge_port_rbr_spare_size)); 2415678453a8Sspeer 2416678453a8Sspeer data = &nxgep->rx_buf_pool_p->dma_buf_pool_p[channel]; 2417678453a8Sspeer num_chunks = &nxgep->rx_buf_pool_p->num_chunks[channel]; 2418678453a8Sspeer 2419678453a8Sspeer if ((status = nxge_alloc_rx_buf_dma( 2420678453a8Sspeer nxgep, channel, data, rx_buf_alloc_size, 2421678453a8Sspeer nxgep->rx_default_block_size, num_chunks)) != NXGE_OK) { 2422678453a8Sspeer return (status); 242344961713Sgirish } 242444961713Sgirish 2425678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_alloc_rxb(): " 2426678453a8Sspeer "dma %d dma_buf_p %llx &dma_buf_p %llx", channel, *data, data)); 2427678453a8Sspeer 2428678453a8Sspeer /* 2429678453a8Sspeer * Allocate memory for descriptor rings and mailbox. 2430678453a8Sspeer */ 2431678453a8Sspeer control = &nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel]; 2432678453a8Sspeer 2433678453a8Sspeer if ((status = nxge_alloc_rx_cntl_dma( 2434678453a8Sspeer nxgep, channel, control, nxgep->nxge_port_rx_cntl_alloc_size)) 2435678453a8Sspeer != NXGE_OK) { 2436678453a8Sspeer nxge_free_rx_cntl_dma(nxgep, *control); 2437678453a8Sspeer (*data)->buf_alloc_state |= BUF_ALLOCATED_WAIT_FREE; 2438678453a8Sspeer nxge_free_rx_buf_dma(nxgep, *data, *num_chunks); 2439678453a8Sspeer return (status); 2440678453a8Sspeer } 244144961713Sgirish 244244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 2443678453a8Sspeer "<== nxge_alloc_rx_mem_pool:status 0x%08x", status)); 244444961713Sgirish 244544961713Sgirish return (status); 244644961713Sgirish } 244744961713Sgirish 2448678453a8Sspeer void 2449678453a8Sspeer nxge_free_rxb( 2450678453a8Sspeer p_nxge_t nxgep, 2451678453a8Sspeer int channel) 2452678453a8Sspeer { 2453678453a8Sspeer nxge_dma_common_t *data; 2454678453a8Sspeer nxge_dma_common_t *control; 2455678453a8Sspeer uint32_t num_chunks; 2456678453a8Sspeer 2457678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb")); 2458678453a8Sspeer 2459678453a8Sspeer data = nxgep->rx_buf_pool_p->dma_buf_pool_p[channel]; 2460678453a8Sspeer num_chunks = nxgep->rx_buf_pool_p->num_chunks[channel]; 2461678453a8Sspeer nxge_free_rx_buf_dma(nxgep, data, num_chunks); 2462678453a8Sspeer 2463678453a8Sspeer nxgep->rx_buf_pool_p->dma_buf_pool_p[channel] = 0; 2464678453a8Sspeer nxgep->rx_buf_pool_p->num_chunks[channel] = 0; 2465678453a8Sspeer 2466678453a8Sspeer control = nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel]; 2467678453a8Sspeer nxge_free_rx_cntl_dma(nxgep, control); 2468678453a8Sspeer 2469678453a8Sspeer nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel] = 0; 2470678453a8Sspeer 2471678453a8Sspeer KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 2472678453a8Sspeer KMEM_FREE(control, sizeof (nxge_dma_common_t)); 2473678453a8Sspeer 2474678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_alloc_rbb")); 2475678453a8Sspeer } 2476678453a8Sspeer 247744961713Sgirish static void 247844961713Sgirish nxge_free_rx_mem_pool(p_nxge_t nxgep) 247944961713Sgirish { 2480678453a8Sspeer int rdc_max = NXGE_MAX_RDCS; 248144961713Sgirish 248244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_mem_pool")); 248344961713Sgirish 2484678453a8Sspeer if (!nxgep->rx_buf_pool_p || !nxgep->rx_buf_pool_p->buf_allocated) { 248544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 24864045d941Ssowmini "<== nxge_free_rx_mem_pool " 24874045d941Ssowmini "(null rx buf pool or buf not allocated")); 248844961713Sgirish return; 248944961713Sgirish } 2490678453a8Sspeer if (!nxgep->rx_cntl_pool_p || !nxgep->rx_cntl_pool_p->buf_allocated) { 249144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 24924045d941Ssowmini "<== nxge_free_rx_mem_pool " 24934045d941Ssowmini "(null rx cntl buf pool or cntl buf not allocated")); 249444961713Sgirish return; 249544961713Sgirish } 249644961713Sgirish 2497678453a8Sspeer KMEM_FREE(nxgep->rx_cntl_pool_p->dma_buf_pool_p, 2498678453a8Sspeer sizeof (p_nxge_dma_common_t) * rdc_max); 2499678453a8Sspeer KMEM_FREE(nxgep->rx_cntl_pool_p, sizeof (nxge_dma_pool_t)); 250044961713Sgirish 2501678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p->num_chunks, 2502678453a8Sspeer sizeof (uint32_t) * rdc_max); 2503678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p->dma_buf_pool_p, 2504678453a8Sspeer sizeof (p_nxge_dma_common_t) * rdc_max); 2505678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p, sizeof (nxge_dma_pool_t)); 250644961713Sgirish 2507678453a8Sspeer nxgep->rx_buf_pool_p = 0; 2508678453a8Sspeer nxgep->rx_cntl_pool_p = 0; 250944961713Sgirish 2510678453a8Sspeer KMEM_FREE(nxgep->rx_rbr_rings->rbr_rings, 2511678453a8Sspeer sizeof (p_rx_rbr_ring_t) * rdc_max); 2512678453a8Sspeer KMEM_FREE(nxgep->rx_rbr_rings, sizeof (rx_rbr_rings_t)); 2513678453a8Sspeer KMEM_FREE(nxgep->rx_rcr_rings->rcr_rings, 2514678453a8Sspeer sizeof (p_rx_rcr_ring_t) * rdc_max); 2515678453a8Sspeer KMEM_FREE(nxgep->rx_rcr_rings, sizeof (rx_rcr_rings_t)); 2516678453a8Sspeer KMEM_FREE(nxgep->rx_mbox_areas_p->rxmbox_areas, 2517678453a8Sspeer sizeof (p_rx_mbox_t) * rdc_max); 2518678453a8Sspeer KMEM_FREE(nxgep->rx_mbox_areas_p, sizeof (rx_mbox_areas_t)); 251944961713Sgirish 2520678453a8Sspeer nxgep->rx_rbr_rings = 0; 2521678453a8Sspeer nxgep->rx_rcr_rings = 0; 2522678453a8Sspeer nxgep->rx_mbox_areas_p = 0; 252344961713Sgirish 252444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_rx_mem_pool")); 252544961713Sgirish } 252644961713Sgirish 252744961713Sgirish 252844961713Sgirish static nxge_status_t 252944961713Sgirish nxge_alloc_rx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 253044961713Sgirish p_nxge_dma_common_t *dmap, 253144961713Sgirish size_t alloc_size, size_t block_size, uint32_t *num_chunks) 253244961713Sgirish { 253344961713Sgirish p_nxge_dma_common_t rx_dmap; 253444961713Sgirish nxge_status_t status = NXGE_OK; 253544961713Sgirish size_t total_alloc_size; 253644961713Sgirish size_t allocated = 0; 253744961713Sgirish int i, size_index, array_size; 2538678453a8Sspeer boolean_t use_kmem_alloc = B_FALSE; 253944961713Sgirish 254044961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_buf_dma")); 254144961713Sgirish 254244961713Sgirish rx_dmap = (p_nxge_dma_common_t) 25434045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 25444045d941Ssowmini KM_SLEEP); 254544961713Sgirish 254644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 25474045d941Ssowmini " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ", 25484045d941Ssowmini dma_channel, alloc_size, block_size, dmap)); 254944961713Sgirish 255044961713Sgirish total_alloc_size = alloc_size; 255144961713Sgirish 255244961713Sgirish #if defined(RX_USE_RECLAIM_POST) 255344961713Sgirish total_alloc_size = alloc_size + alloc_size/4; 255444961713Sgirish #endif 255544961713Sgirish 255644961713Sgirish i = 0; 255744961713Sgirish size_index = 0; 255844961713Sgirish array_size = sizeof (alloc_sizes)/sizeof (size_t); 255944961713Sgirish while ((alloc_sizes[size_index] < alloc_size) && 25604045d941Ssowmini (size_index < array_size)) 25614045d941Ssowmini size_index++; 256244961713Sgirish if (size_index >= array_size) { 256344961713Sgirish size_index = array_size - 1; 256444961713Sgirish } 256544961713Sgirish 2566678453a8Sspeer /* For Neptune, use kmem_alloc if the kmem flag is set. */ 2567678453a8Sspeer if (nxgep->niu_type != N2_NIU && nxge_use_kmem_alloc) { 2568678453a8Sspeer use_kmem_alloc = B_TRUE; 2569678453a8Sspeer #if defined(__i386) || defined(__amd64) 2570678453a8Sspeer size_index = 0; 2571678453a8Sspeer #endif 2572678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2573678453a8Sspeer "==> nxge_alloc_rx_buf_dma: " 2574678453a8Sspeer "Neptune use kmem_alloc() - size_index %d", 2575678453a8Sspeer size_index)); 2576678453a8Sspeer } 2577678453a8Sspeer 257844961713Sgirish while ((allocated < total_alloc_size) && 25794045d941Ssowmini (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 258044961713Sgirish rx_dmap[i].dma_chunk_index = i; 258144961713Sgirish rx_dmap[i].block_size = block_size; 258244961713Sgirish rx_dmap[i].alength = alloc_sizes[size_index]; 258344961713Sgirish rx_dmap[i].orig_alength = rx_dmap[i].alength; 258444961713Sgirish rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 258544961713Sgirish rx_dmap[i].dma_channel = dma_channel; 258644961713Sgirish rx_dmap[i].contig_alloc_type = B_FALSE; 2587678453a8Sspeer rx_dmap[i].kmem_alloc_type = B_FALSE; 2588678453a8Sspeer rx_dmap[i].buf_alloc_type = DDI_MEM_ALLOC; 258944961713Sgirish 259044961713Sgirish /* 259144961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 259244961713Sgirish * needs to call Hypervisor api to set up 259344961713Sgirish * logical pages. 259444961713Sgirish */ 259544961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 259644961713Sgirish rx_dmap[i].contig_alloc_type = B_TRUE; 2597678453a8Sspeer rx_dmap[i].buf_alloc_type = CONTIG_MEM_ALLOC; 2598678453a8Sspeer } else if (use_kmem_alloc) { 2599678453a8Sspeer /* For Neptune, use kmem_alloc */ 2600678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2601678453a8Sspeer "==> nxge_alloc_rx_buf_dma: " 2602678453a8Sspeer "Neptune use kmem_alloc()")); 2603678453a8Sspeer rx_dmap[i].kmem_alloc_type = B_TRUE; 2604678453a8Sspeer rx_dmap[i].buf_alloc_type = KMEM_ALLOC; 260544961713Sgirish } 260644961713Sgirish 260744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 26084045d941Ssowmini "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x " 26094045d941Ssowmini "i %d nblocks %d alength %d", 26104045d941Ssowmini dma_channel, i, &rx_dmap[i], block_size, 26114045d941Ssowmini i, rx_dmap[i].nblocks, 26124045d941Ssowmini rx_dmap[i].alength)); 261344961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 26144045d941Ssowmini &nxge_rx_dma_attr, 26154045d941Ssowmini rx_dmap[i].alength, 26164045d941Ssowmini &nxge_dev_buf_dma_acc_attr, 26174045d941Ssowmini DDI_DMA_READ | DDI_DMA_STREAMING, 26184045d941Ssowmini (p_nxge_dma_common_t)(&rx_dmap[i])); 261944961713Sgirish if (status != NXGE_OK) { 262044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2621678453a8Sspeer "nxge_alloc_rx_buf_dma: Alloc Failed: " 2622678453a8Sspeer "dma %d size_index %d size requested %d", 2623678453a8Sspeer dma_channel, 2624678453a8Sspeer size_index, 2625678453a8Sspeer rx_dmap[i].alength)); 262644961713Sgirish size_index--; 262744961713Sgirish } else { 2628678453a8Sspeer rx_dmap[i].buf_alloc_state = BUF_ALLOCATED; 2629678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2630678453a8Sspeer " nxge_alloc_rx_buf_dma DONE alloc mem: " 2631678453a8Sspeer "dma %d dma_buf_p $%p kaddrp $%p alength %d " 2632678453a8Sspeer "buf_alloc_state %d alloc_type %d", 2633678453a8Sspeer dma_channel, 2634678453a8Sspeer &rx_dmap[i], 2635678453a8Sspeer rx_dmap[i].kaddrp, 2636678453a8Sspeer rx_dmap[i].alength, 2637678453a8Sspeer rx_dmap[i].buf_alloc_state, 2638678453a8Sspeer rx_dmap[i].buf_alloc_type)); 2639678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2640678453a8Sspeer " alloc_rx_buf_dma allocated rdc %d " 2641678453a8Sspeer "chunk %d size %x dvma %x bufp %llx kaddrp $%p", 2642678453a8Sspeer dma_channel, i, rx_dmap[i].alength, 2643678453a8Sspeer rx_dmap[i].ioaddr_pp, &rx_dmap[i], 2644678453a8Sspeer rx_dmap[i].kaddrp)); 264544961713Sgirish i++; 264644961713Sgirish allocated += alloc_sizes[size_index]; 264744961713Sgirish } 264844961713Sgirish } 264944961713Sgirish 265044961713Sgirish if (allocated < total_alloc_size) { 265130ac2e7bSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2652678453a8Sspeer "==> nxge_alloc_rx_buf_dma: not enough for channel %d " 265330ac2e7bSml "allocated 0x%x requested 0x%x", 265430ac2e7bSml dma_channel, 265530ac2e7bSml allocated, total_alloc_size)); 265630ac2e7bSml status = NXGE_ERROR; 265744961713Sgirish goto nxge_alloc_rx_mem_fail1; 265844961713Sgirish } 265944961713Sgirish 266030ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2661678453a8Sspeer "==> nxge_alloc_rx_buf_dma: Allocated for channel %d " 266230ac2e7bSml "allocated 0x%x requested 0x%x", 266330ac2e7bSml dma_channel, 266430ac2e7bSml allocated, total_alloc_size)); 266530ac2e7bSml 266644961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 26674045d941Ssowmini " alloc_rx_buf_dma rdc %d allocated %d chunks", 26684045d941Ssowmini dma_channel, i)); 266944961713Sgirish *num_chunks = i; 267044961713Sgirish *dmap = rx_dmap; 267144961713Sgirish 267244961713Sgirish goto nxge_alloc_rx_mem_exit; 267344961713Sgirish 267444961713Sgirish nxge_alloc_rx_mem_fail1: 267544961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 267644961713Sgirish 267744961713Sgirish nxge_alloc_rx_mem_exit: 267844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 26794045d941Ssowmini "<== nxge_alloc_rx_buf_dma status 0x%08x", status)); 268044961713Sgirish 268144961713Sgirish return (status); 268244961713Sgirish } 268344961713Sgirish 268444961713Sgirish /*ARGSUSED*/ 268544961713Sgirish static void 268644961713Sgirish nxge_free_rx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 268744961713Sgirish uint32_t num_chunks) 268844961713Sgirish { 268944961713Sgirish int i; 269044961713Sgirish 269144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 26924045d941Ssowmini "==> nxge_free_rx_buf_dma: # of chunks %d", num_chunks)); 269344961713Sgirish 2694678453a8Sspeer if (dmap == 0) 2695678453a8Sspeer return; 2696678453a8Sspeer 269744961713Sgirish for (i = 0; i < num_chunks; i++) { 269844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 26994045d941Ssowmini "==> nxge_free_rx_buf_dma: chunk %d dmap 0x%llx", 27004045d941Ssowmini i, dmap)); 2701678453a8Sspeer nxge_dma_free_rx_data_buf(dmap++); 270244961713Sgirish } 270344961713Sgirish 270444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_buf_dma")); 270544961713Sgirish } 270644961713Sgirish 270744961713Sgirish /*ARGSUSED*/ 270844961713Sgirish static nxge_status_t 270944961713Sgirish nxge_alloc_rx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 271044961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 271144961713Sgirish { 271244961713Sgirish p_nxge_dma_common_t rx_dmap; 271344961713Sgirish nxge_status_t status = NXGE_OK; 271444961713Sgirish 271544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_cntl_dma")); 271644961713Sgirish 271744961713Sgirish rx_dmap = (p_nxge_dma_common_t) 27184045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 271944961713Sgirish 272044961713Sgirish rx_dmap->contig_alloc_type = B_FALSE; 2721678453a8Sspeer rx_dmap->kmem_alloc_type = B_FALSE; 272244961713Sgirish 272344961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 27244045d941Ssowmini &nxge_desc_dma_attr, 27254045d941Ssowmini size, 27264045d941Ssowmini &nxge_dev_desc_dma_acc_attr, 27274045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 27284045d941Ssowmini rx_dmap); 272944961713Sgirish if (status != NXGE_OK) { 273044961713Sgirish goto nxge_alloc_rx_cntl_dma_fail1; 273144961713Sgirish } 273244961713Sgirish 273344961713Sgirish *dmap = rx_dmap; 273444961713Sgirish goto nxge_alloc_rx_cntl_dma_exit; 273544961713Sgirish 273644961713Sgirish nxge_alloc_rx_cntl_dma_fail1: 273744961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t)); 273844961713Sgirish 273944961713Sgirish nxge_alloc_rx_cntl_dma_exit: 274044961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 27414045d941Ssowmini "<== nxge_alloc_rx_cntl_dma status 0x%08x", status)); 274244961713Sgirish 2743678453a8Sspeer return (status); 2744678453a8Sspeer } 2745678453a8Sspeer 2746678453a8Sspeer /*ARGSUSED*/ 2747678453a8Sspeer static void 2748678453a8Sspeer nxge_free_rx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 2749678453a8Sspeer { 2750678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_rx_cntl_dma")); 2751678453a8Sspeer 2752678453a8Sspeer if (dmap == 0) 2753678453a8Sspeer return; 2754678453a8Sspeer 2755678453a8Sspeer nxge_dma_mem_free(dmap); 2756678453a8Sspeer 2757678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_rx_cntl_dma")); 2758678453a8Sspeer } 2759678453a8Sspeer 2760678453a8Sspeer typedef struct { 2761678453a8Sspeer size_t tx_size; 2762678453a8Sspeer size_t cr_size; 2763678453a8Sspeer size_t threshhold; 2764678453a8Sspeer } nxge_tdc_sizes_t; 2765678453a8Sspeer 2766678453a8Sspeer static 2767678453a8Sspeer nxge_status_t 2768678453a8Sspeer nxge_tdc_sizes( 2769678453a8Sspeer nxge_t *nxgep, 2770678453a8Sspeer nxge_tdc_sizes_t *sizes) 2771678453a8Sspeer { 2772678453a8Sspeer uint32_t threshhold; /* The bcopy() threshhold */ 2773678453a8Sspeer size_t tx_size; /* Transmit buffer size */ 2774678453a8Sspeer size_t cr_size; /* Completion ring size */ 2775678453a8Sspeer 2776678453a8Sspeer /* 2777678453a8Sspeer * Assume that each DMA channel will be configured with the 2778678453a8Sspeer * default transmit buffer size for copying transmit data. 2779678453a8Sspeer * (If a packet is bigger than this, it will not be copied.) 2780678453a8Sspeer */ 2781678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 2782678453a8Sspeer threshhold = TX_BCOPY_SIZE; 2783678453a8Sspeer } else { 2784678453a8Sspeer threshhold = nxge_bcopy_thresh; 2785678453a8Sspeer } 2786678453a8Sspeer tx_size = nxge_tx_ring_size * threshhold; 2787678453a8Sspeer 2788678453a8Sspeer cr_size = nxge_tx_ring_size * sizeof (tx_desc_t); 2789678453a8Sspeer cr_size += sizeof (txdma_mailbox_t); 2790678453a8Sspeer 2791678453a8Sspeer #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 2792678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 2793678453a8Sspeer if (!ISP2(tx_size)) { 2794678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27954045d941Ssowmini "==> nxge_tdc_sizes: Tx size" 27964045d941Ssowmini " must be power of 2")); 2797678453a8Sspeer return (NXGE_ERROR); 2798678453a8Sspeer } 2799678453a8Sspeer 2800678453a8Sspeer if (tx_size > (1 << 22)) { 2801678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 28024045d941Ssowmini "==> nxge_tdc_sizes: Tx size" 28034045d941Ssowmini " limited to 4M")); 2804678453a8Sspeer return (NXGE_ERROR); 2805678453a8Sspeer } 2806678453a8Sspeer 2807678453a8Sspeer if (cr_size < 0x2000) 2808678453a8Sspeer cr_size = 0x2000; 2809678453a8Sspeer } 2810678453a8Sspeer #endif 2811678453a8Sspeer 2812678453a8Sspeer sizes->threshhold = threshhold; 2813678453a8Sspeer sizes->tx_size = tx_size; 2814678453a8Sspeer sizes->cr_size = cr_size; 2815678453a8Sspeer 2816678453a8Sspeer return (NXGE_OK); 2817678453a8Sspeer } 2818678453a8Sspeer /* 2819678453a8Sspeer * nxge_alloc_txb 2820678453a8Sspeer * 2821678453a8Sspeer * Allocate buffers for an TDC. 2822678453a8Sspeer * 2823678453a8Sspeer * Arguments: 2824678453a8Sspeer * nxgep 2825678453a8Sspeer * channel The channel to map into our kernel space. 2826678453a8Sspeer * 2827678453a8Sspeer * Notes: 2828678453a8Sspeer * 2829678453a8Sspeer * NPI function calls: 2830678453a8Sspeer * 2831678453a8Sspeer * NXGE function calls: 2832678453a8Sspeer * 2833678453a8Sspeer * Registers accessed: 2834678453a8Sspeer * 2835678453a8Sspeer * Context: 2836678453a8Sspeer * 2837678453a8Sspeer * Taking apart: 2838678453a8Sspeer * 2839678453a8Sspeer * Open questions: 2840678453a8Sspeer * 2841678453a8Sspeer */ 2842678453a8Sspeer nxge_status_t 2843678453a8Sspeer nxge_alloc_txb( 2844678453a8Sspeer p_nxge_t nxgep, 2845678453a8Sspeer int channel) 2846678453a8Sspeer { 2847678453a8Sspeer nxge_dma_common_t **dma_buf_p; 2848678453a8Sspeer nxge_dma_common_t **dma_cntl_p; 2849678453a8Sspeer uint32_t *num_chunks; 2850678453a8Sspeer nxge_status_t status = NXGE_OK; 2851678453a8Sspeer 2852678453a8Sspeer nxge_tdc_sizes_t sizes; 2853678453a8Sspeer 2854678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tbb")); 2855678453a8Sspeer 2856678453a8Sspeer if (nxge_tdc_sizes(nxgep, &sizes) != NXGE_OK) 2857678453a8Sspeer return (NXGE_ERROR); 2858678453a8Sspeer 2859678453a8Sspeer /* 2860678453a8Sspeer * Allocate memory for transmit buffers and descriptor rings. 2861678453a8Sspeer * Replace these allocation functions with the interface functions 2862678453a8Sspeer * provided by the partition manager Real Soon Now. 2863678453a8Sspeer */ 2864678453a8Sspeer dma_buf_p = &nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2865678453a8Sspeer num_chunks = &nxgep->tx_buf_pool_p->num_chunks[channel]; 2866678453a8Sspeer 2867678453a8Sspeer dma_cntl_p = &nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2868678453a8Sspeer 2869678453a8Sspeer /* 2870678453a8Sspeer * Allocate memory for transmit buffers and descriptor rings. 2871678453a8Sspeer * Replace allocation functions with interface functions provided 2872678453a8Sspeer * by the partition manager when it is available. 2873678453a8Sspeer * 2874678453a8Sspeer * Allocate memory for the transmit buffer pool. 2875678453a8Sspeer */ 2876678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 28774045d941Ssowmini "sizes: tx: %ld, cr:%ld, th:%ld", 28784045d941Ssowmini sizes.tx_size, sizes.cr_size, sizes.threshhold)); 2879678453a8Sspeer 2880678453a8Sspeer *num_chunks = 0; 2881678453a8Sspeer status = nxge_alloc_tx_buf_dma(nxgep, channel, dma_buf_p, 2882678453a8Sspeer sizes.tx_size, sizes.threshhold, num_chunks); 2883678453a8Sspeer if (status != NXGE_OK) { 2884678453a8Sspeer cmn_err(CE_NOTE, "nxge_alloc_tx_buf_dma failed!"); 2885678453a8Sspeer return (status); 2886678453a8Sspeer } 2887678453a8Sspeer 2888678453a8Sspeer /* 2889678453a8Sspeer * Allocate memory for descriptor rings and mailbox. 2890678453a8Sspeer */ 2891678453a8Sspeer status = nxge_alloc_tx_cntl_dma(nxgep, channel, dma_cntl_p, 2892678453a8Sspeer sizes.cr_size); 2893678453a8Sspeer if (status != NXGE_OK) { 2894678453a8Sspeer nxge_free_tx_buf_dma(nxgep, *dma_buf_p, *num_chunks); 2895678453a8Sspeer cmn_err(CE_NOTE, "nxge_alloc_tx_cntl_dma failed!"); 2896678453a8Sspeer return (status); 2897678453a8Sspeer } 2898678453a8Sspeer 2899678453a8Sspeer return (NXGE_OK); 2900678453a8Sspeer } 2901678453a8Sspeer 2902678453a8Sspeer void 2903678453a8Sspeer nxge_free_txb( 2904678453a8Sspeer p_nxge_t nxgep, 2905678453a8Sspeer int channel) 2906678453a8Sspeer { 2907678453a8Sspeer nxge_dma_common_t *data; 2908678453a8Sspeer nxge_dma_common_t *control; 2909678453a8Sspeer uint32_t num_chunks; 2910678453a8Sspeer 2911678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_txb")); 2912678453a8Sspeer 2913678453a8Sspeer data = nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2914678453a8Sspeer num_chunks = nxgep->tx_buf_pool_p->num_chunks[channel]; 2915678453a8Sspeer nxge_free_tx_buf_dma(nxgep, data, num_chunks); 2916678453a8Sspeer 2917678453a8Sspeer nxgep->tx_buf_pool_p->dma_buf_pool_p[channel] = 0; 2918678453a8Sspeer nxgep->tx_buf_pool_p->num_chunks[channel] = 0; 2919678453a8Sspeer 2920678453a8Sspeer control = nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2921678453a8Sspeer nxge_free_tx_cntl_dma(nxgep, control); 292244961713Sgirish 2923678453a8Sspeer nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel] = 0; 292444961713Sgirish 2925678453a8Sspeer KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 2926678453a8Sspeer KMEM_FREE(control, sizeof (nxge_dma_common_t)); 292744961713Sgirish 2928678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_txb")); 292944961713Sgirish } 293044961713Sgirish 2931678453a8Sspeer /* 2932678453a8Sspeer * nxge_alloc_tx_mem_pool 2933678453a8Sspeer * 2934678453a8Sspeer * This function allocates all of the per-port TDC control data structures. 2935678453a8Sspeer * The per-channel (TDC) data structures are allocated when needed. 2936678453a8Sspeer * 2937678453a8Sspeer * Arguments: 2938678453a8Sspeer * nxgep 2939678453a8Sspeer * 2940678453a8Sspeer * Notes: 2941678453a8Sspeer * 2942678453a8Sspeer * Context: 2943678453a8Sspeer * Any domain 2944678453a8Sspeer */ 2945678453a8Sspeer nxge_status_t 294644961713Sgirish nxge_alloc_tx_mem_pool(p_nxge_t nxgep) 294744961713Sgirish { 2948678453a8Sspeer nxge_hw_pt_cfg_t *p_cfgp; 2949678453a8Sspeer nxge_dma_pool_t *dma_poolp; 2950678453a8Sspeer nxge_dma_common_t **dma_buf_p; 2951678453a8Sspeer nxge_dma_pool_t *dma_cntl_poolp; 2952678453a8Sspeer nxge_dma_common_t **dma_cntl_p; 295344961713Sgirish uint32_t *num_chunks; /* per dma */ 2954678453a8Sspeer int tdc_max; 295544961713Sgirish 295644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool")); 295744961713Sgirish 2958678453a8Sspeer p_cfgp = &nxgep->pt_config.hw_config; 2959678453a8Sspeer tdc_max = NXGE_MAX_TDCS; 296044961713Sgirish 296144961713Sgirish /* 296244961713Sgirish * Allocate memory for each transmit DMA channel. 296344961713Sgirish */ 296444961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 29654045d941Ssowmini KM_SLEEP); 296644961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 29674045d941Ssowmini sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP); 296844961713Sgirish 296944961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 29704045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 297144961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 29724045d941Ssowmini sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP); 297344961713Sgirish 297430ac2e7bSml if (nxge_tx_ring_size > TDC_DEFAULT_MAX) { 297530ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 297630ac2e7bSml "nxge_alloc_tx_mem_pool: TDC too high %d, " 297730ac2e7bSml "set to default %d", 297830ac2e7bSml nxge_tx_ring_size, TDC_DEFAULT_MAX)); 297930ac2e7bSml nxge_tx_ring_size = TDC_DEFAULT_MAX; 298030ac2e7bSml } 298130ac2e7bSml 298244961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 298344961713Sgirish /* 298444961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 298544961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 298644961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 298744961713Sgirish * function). The transmit ring is limited to 8K (includes the 298844961713Sgirish * mailbox). 298944961713Sgirish */ 299044961713Sgirish if (nxgep->niu_type == N2_NIU) { 299144961713Sgirish if ((nxge_tx_ring_size > NXGE_NIU_CONTIG_TX_MAX) || 29924045d941Ssowmini (!ISP2(nxge_tx_ring_size))) { 299344961713Sgirish nxge_tx_ring_size = NXGE_NIU_CONTIG_TX_MAX; 299444961713Sgirish } 299544961713Sgirish } 299644961713Sgirish #endif 299744961713Sgirish 299844961713Sgirish nxgep->nxge_port_tx_ring_size = nxge_tx_ring_size; 299944961713Sgirish 300044961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 30014045d941Ssowmini sizeof (uint32_t) * tdc_max, KM_SLEEP); 300244961713Sgirish 3003678453a8Sspeer dma_poolp->ndmas = p_cfgp->tdc.owned; 300444961713Sgirish dma_poolp->num_chunks = num_chunks; 300544961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 300644961713Sgirish nxgep->tx_buf_pool_p = dma_poolp; 300744961713Sgirish 3008678453a8Sspeer dma_poolp->buf_allocated = B_TRUE; 3009678453a8Sspeer 3010678453a8Sspeer dma_cntl_poolp->ndmas = p_cfgp->tdc.owned; 301144961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 301244961713Sgirish nxgep->tx_cntl_pool_p = dma_cntl_poolp; 301344961713Sgirish 3014678453a8Sspeer dma_cntl_poolp->buf_allocated = B_TRUE; 301544961713Sgirish 3016678453a8Sspeer nxgep->tx_rings = 3017678453a8Sspeer KMEM_ZALLOC(sizeof (tx_rings_t), KM_SLEEP); 3018678453a8Sspeer nxgep->tx_rings->rings = 3019678453a8Sspeer KMEM_ZALLOC(sizeof (p_tx_ring_t) * tdc_max, KM_SLEEP); 3020678453a8Sspeer nxgep->tx_mbox_areas_p = 3021678453a8Sspeer KMEM_ZALLOC(sizeof (tx_mbox_areas_t), KM_SLEEP); 3022678453a8Sspeer nxgep->tx_mbox_areas_p->txmbox_areas_p = 3023678453a8Sspeer KMEM_ZALLOC(sizeof (p_tx_mbox_t) * tdc_max, KM_SLEEP); 302444961713Sgirish 3025678453a8Sspeer nxgep->tx_rings->ndmas = p_cfgp->tdc.owned; 302644961713Sgirish 302744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, 30284045d941Ssowmini "==> nxge_alloc_tx_mem_pool: ndmas %d poolp->ndmas %d", 30294045d941Ssowmini tdc_max, dma_poolp->ndmas)); 303044961713Sgirish 3031678453a8Sspeer return (NXGE_OK); 303244961713Sgirish } 303344961713Sgirish 3034678453a8Sspeer nxge_status_t 303544961713Sgirish nxge_alloc_tx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 303644961713Sgirish p_nxge_dma_common_t *dmap, size_t alloc_size, 303744961713Sgirish size_t block_size, uint32_t *num_chunks) 303844961713Sgirish { 303944961713Sgirish p_nxge_dma_common_t tx_dmap; 304044961713Sgirish nxge_status_t status = NXGE_OK; 304144961713Sgirish size_t total_alloc_size; 304244961713Sgirish size_t allocated = 0; 304344961713Sgirish int i, size_index, array_size; 304444961713Sgirish 304544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_buf_dma")); 304644961713Sgirish 304744961713Sgirish tx_dmap = (p_nxge_dma_common_t) 30484045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 30494045d941Ssowmini KM_SLEEP); 305044961713Sgirish 305144961713Sgirish total_alloc_size = alloc_size; 305244961713Sgirish i = 0; 305344961713Sgirish size_index = 0; 305444961713Sgirish array_size = sizeof (alloc_sizes) / sizeof (size_t); 305544961713Sgirish while ((alloc_sizes[size_index] < alloc_size) && 30564045d941Ssowmini (size_index < array_size)) 305744961713Sgirish size_index++; 305844961713Sgirish if (size_index >= array_size) { 305944961713Sgirish size_index = array_size - 1; 306044961713Sgirish } 306144961713Sgirish 306244961713Sgirish while ((allocated < total_alloc_size) && 30634045d941Ssowmini (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 306444961713Sgirish 306544961713Sgirish tx_dmap[i].dma_chunk_index = i; 306644961713Sgirish tx_dmap[i].block_size = block_size; 306744961713Sgirish tx_dmap[i].alength = alloc_sizes[size_index]; 306844961713Sgirish tx_dmap[i].orig_alength = tx_dmap[i].alength; 306944961713Sgirish tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 307044961713Sgirish tx_dmap[i].dma_channel = dma_channel; 307144961713Sgirish tx_dmap[i].contig_alloc_type = B_FALSE; 3072678453a8Sspeer tx_dmap[i].kmem_alloc_type = B_FALSE; 307344961713Sgirish 307444961713Sgirish /* 307544961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 307644961713Sgirish * needs to call Hypervisor api to set up 307744961713Sgirish * logical pages. 307844961713Sgirish */ 307944961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 308044961713Sgirish tx_dmap[i].contig_alloc_type = B_TRUE; 308144961713Sgirish } 308244961713Sgirish 308344961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 30844045d941Ssowmini &nxge_tx_dma_attr, 30854045d941Ssowmini tx_dmap[i].alength, 30864045d941Ssowmini &nxge_dev_buf_dma_acc_attr, 30874045d941Ssowmini DDI_DMA_WRITE | DDI_DMA_STREAMING, 30884045d941Ssowmini (p_nxge_dma_common_t)(&tx_dmap[i])); 308944961713Sgirish if (status != NXGE_OK) { 309044961713Sgirish size_index--; 309144961713Sgirish } else { 309244961713Sgirish i++; 309344961713Sgirish allocated += alloc_sizes[size_index]; 309444961713Sgirish } 309544961713Sgirish } 309644961713Sgirish 309744961713Sgirish if (allocated < total_alloc_size) { 309830ac2e7bSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 309930ac2e7bSml "==> nxge_alloc_tx_buf_dma: not enough channel %d: " 310030ac2e7bSml "allocated 0x%x requested 0x%x", 310130ac2e7bSml dma_channel, 310230ac2e7bSml allocated, total_alloc_size)); 310330ac2e7bSml status = NXGE_ERROR; 310444961713Sgirish goto nxge_alloc_tx_mem_fail1; 310544961713Sgirish } 310644961713Sgirish 310730ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 310830ac2e7bSml "==> nxge_alloc_tx_buf_dma: Allocated for channel %d: " 310930ac2e7bSml "allocated 0x%x requested 0x%x", 311030ac2e7bSml dma_channel, 311130ac2e7bSml allocated, total_alloc_size)); 311230ac2e7bSml 311344961713Sgirish *num_chunks = i; 311444961713Sgirish *dmap = tx_dmap; 311544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 31164045d941Ssowmini "==> nxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d", 31174045d941Ssowmini *dmap, i)); 311844961713Sgirish goto nxge_alloc_tx_mem_exit; 311944961713Sgirish 312044961713Sgirish nxge_alloc_tx_mem_fail1: 312144961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 312244961713Sgirish 312344961713Sgirish nxge_alloc_tx_mem_exit: 312444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 31254045d941Ssowmini "<== nxge_alloc_tx_buf_dma status 0x%08x", status)); 312644961713Sgirish 312744961713Sgirish return (status); 312844961713Sgirish } 312944961713Sgirish 313044961713Sgirish /*ARGSUSED*/ 313144961713Sgirish static void 313244961713Sgirish nxge_free_tx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 313344961713Sgirish uint32_t num_chunks) 313444961713Sgirish { 313544961713Sgirish int i; 313644961713Sgirish 313744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_tx_buf_dma")); 313844961713Sgirish 3139678453a8Sspeer if (dmap == 0) 3140678453a8Sspeer return; 3141678453a8Sspeer 314244961713Sgirish for (i = 0; i < num_chunks; i++) { 314344961713Sgirish nxge_dma_mem_free(dmap++); 314444961713Sgirish } 314544961713Sgirish 314644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_tx_buf_dma")); 314744961713Sgirish } 314844961713Sgirish 314944961713Sgirish /*ARGSUSED*/ 3150678453a8Sspeer nxge_status_t 315144961713Sgirish nxge_alloc_tx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 315244961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 315344961713Sgirish { 315444961713Sgirish p_nxge_dma_common_t tx_dmap; 315544961713Sgirish nxge_status_t status = NXGE_OK; 315644961713Sgirish 315744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_cntl_dma")); 315844961713Sgirish tx_dmap = (p_nxge_dma_common_t) 31594045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 316044961713Sgirish 316144961713Sgirish tx_dmap->contig_alloc_type = B_FALSE; 3162678453a8Sspeer tx_dmap->kmem_alloc_type = B_FALSE; 316344961713Sgirish 316444961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 31654045d941Ssowmini &nxge_desc_dma_attr, 31664045d941Ssowmini size, 31674045d941Ssowmini &nxge_dev_desc_dma_acc_attr, 31684045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 31694045d941Ssowmini tx_dmap); 317044961713Sgirish if (status != NXGE_OK) { 317144961713Sgirish goto nxge_alloc_tx_cntl_dma_fail1; 317244961713Sgirish } 317344961713Sgirish 317444961713Sgirish *dmap = tx_dmap; 317544961713Sgirish goto nxge_alloc_tx_cntl_dma_exit; 317644961713Sgirish 317744961713Sgirish nxge_alloc_tx_cntl_dma_fail1: 317844961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t)); 317944961713Sgirish 318044961713Sgirish nxge_alloc_tx_cntl_dma_exit: 318144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 31824045d941Ssowmini "<== nxge_alloc_tx_cntl_dma status 0x%08x", status)); 318344961713Sgirish 318444961713Sgirish return (status); 318544961713Sgirish } 318644961713Sgirish 318744961713Sgirish /*ARGSUSED*/ 318844961713Sgirish static void 318944961713Sgirish nxge_free_tx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 319044961713Sgirish { 319144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_tx_cntl_dma")); 319244961713Sgirish 3193678453a8Sspeer if (dmap == 0) 3194678453a8Sspeer return; 3195678453a8Sspeer 319644961713Sgirish nxge_dma_mem_free(dmap); 319744961713Sgirish 319844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_tx_cntl_dma")); 319944961713Sgirish } 320044961713Sgirish 3201678453a8Sspeer /* 3202678453a8Sspeer * nxge_free_tx_mem_pool 3203678453a8Sspeer * 3204678453a8Sspeer * This function frees all of the per-port TDC control data structures. 3205678453a8Sspeer * The per-channel (TDC) data structures are freed when the channel 3206678453a8Sspeer * is stopped. 3207678453a8Sspeer * 3208678453a8Sspeer * Arguments: 3209678453a8Sspeer * nxgep 3210678453a8Sspeer * 3211678453a8Sspeer * Notes: 3212678453a8Sspeer * 3213678453a8Sspeer * Context: 3214678453a8Sspeer * Any domain 3215678453a8Sspeer */ 321644961713Sgirish static void 321744961713Sgirish nxge_free_tx_mem_pool(p_nxge_t nxgep) 321844961713Sgirish { 3219678453a8Sspeer int tdc_max = NXGE_MAX_TDCS; 322044961713Sgirish 3221678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_tx_mem_pool")); 322244961713Sgirish 3223678453a8Sspeer if (!nxgep->tx_buf_pool_p || !nxgep->tx_buf_pool_p->buf_allocated) { 3224678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 32254045d941Ssowmini "<== nxge_free_tx_mem_pool " 32264045d941Ssowmini "(null tx buf pool or buf not allocated")); 322744961713Sgirish return; 322844961713Sgirish } 3229678453a8Sspeer if (!nxgep->tx_cntl_pool_p || !nxgep->tx_cntl_pool_p->buf_allocated) { 3230678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 32314045d941Ssowmini "<== nxge_free_tx_mem_pool " 32324045d941Ssowmini "(null tx cntl buf pool or cntl buf not allocated")); 323344961713Sgirish return; 323444961713Sgirish } 323544961713Sgirish 3236678453a8Sspeer /* 1. Free the mailboxes. */ 3237678453a8Sspeer KMEM_FREE(nxgep->tx_mbox_areas_p->txmbox_areas_p, 3238678453a8Sspeer sizeof (p_tx_mbox_t) * tdc_max); 3239678453a8Sspeer KMEM_FREE(nxgep->tx_mbox_areas_p, sizeof (tx_mbox_areas_t)); 324044961713Sgirish 3241678453a8Sspeer nxgep->tx_mbox_areas_p = 0; 324244961713Sgirish 3243678453a8Sspeer /* 2. Free the transmit ring arrays. */ 3244678453a8Sspeer KMEM_FREE(nxgep->tx_rings->rings, 3245678453a8Sspeer sizeof (p_tx_ring_t) * tdc_max); 3246678453a8Sspeer KMEM_FREE(nxgep->tx_rings, sizeof (tx_rings_t)); 324744961713Sgirish 3248678453a8Sspeer nxgep->tx_rings = 0; 324944961713Sgirish 3250678453a8Sspeer /* 3. Free the completion ring data structures. */ 3251678453a8Sspeer KMEM_FREE(nxgep->tx_cntl_pool_p->dma_buf_pool_p, 3252678453a8Sspeer sizeof (p_nxge_dma_common_t) * tdc_max); 3253678453a8Sspeer KMEM_FREE(nxgep->tx_cntl_pool_p, sizeof (nxge_dma_pool_t)); 325444961713Sgirish 3255678453a8Sspeer nxgep->tx_cntl_pool_p = 0; 325644961713Sgirish 3257678453a8Sspeer /* 4. Free the data ring data structures. */ 3258678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p->num_chunks, 3259678453a8Sspeer sizeof (uint32_t) * tdc_max); 3260678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p->dma_buf_pool_p, 3261678453a8Sspeer sizeof (p_nxge_dma_common_t) * tdc_max); 3262678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p, sizeof (nxge_dma_pool_t)); 326344961713Sgirish 3264678453a8Sspeer nxgep->tx_buf_pool_p = 0; 3265678453a8Sspeer 3266678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_tx_mem_pool")); 326744961713Sgirish } 326844961713Sgirish 326944961713Sgirish /*ARGSUSED*/ 327044961713Sgirish static nxge_status_t 327144961713Sgirish nxge_dma_mem_alloc(p_nxge_t nxgep, dma_method_t method, 327244961713Sgirish struct ddi_dma_attr *dma_attrp, 327344961713Sgirish size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags, 327444961713Sgirish p_nxge_dma_common_t dma_p) 327544961713Sgirish { 327644961713Sgirish caddr_t kaddrp; 327744961713Sgirish int ddi_status = DDI_SUCCESS; 327844961713Sgirish boolean_t contig_alloc_type; 3279678453a8Sspeer boolean_t kmem_alloc_type; 328044961713Sgirish 328144961713Sgirish contig_alloc_type = dma_p->contig_alloc_type; 328244961713Sgirish 328344961713Sgirish if (contig_alloc_type && (nxgep->niu_type != N2_NIU)) { 328444961713Sgirish /* 328544961713Sgirish * contig_alloc_type for contiguous memory only allowed 328644961713Sgirish * for N2/NIU. 328744961713Sgirish */ 328844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 32894045d941Ssowmini "nxge_dma_mem_alloc: alloc type not allowed (%d)", 32904045d941Ssowmini dma_p->contig_alloc_type)); 329144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 329244961713Sgirish } 329344961713Sgirish 329444961713Sgirish dma_p->dma_handle = NULL; 329544961713Sgirish dma_p->acc_handle = NULL; 329644961713Sgirish dma_p->kaddrp = dma_p->last_kaddrp = NULL; 329744961713Sgirish dma_p->first_ioaddr_pp = dma_p->last_ioaddr_pp = NULL; 329844961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, dma_attrp, 32994045d941Ssowmini DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle); 330044961713Sgirish if (ddi_status != DDI_SUCCESS) { 330144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 33024045d941Ssowmini "nxge_dma_mem_alloc:ddi_dma_alloc_handle failed.")); 330344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 330444961713Sgirish } 330544961713Sgirish 3306678453a8Sspeer kmem_alloc_type = dma_p->kmem_alloc_type; 3307678453a8Sspeer 330844961713Sgirish switch (contig_alloc_type) { 330944961713Sgirish case B_FALSE: 3310678453a8Sspeer switch (kmem_alloc_type) { 3311678453a8Sspeer case B_FALSE: 3312678453a8Sspeer ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, 33134045d941Ssowmini length, 33144045d941Ssowmini acc_attr_p, 33154045d941Ssowmini xfer_flags, 33164045d941Ssowmini DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength, 33174045d941Ssowmini &dma_p->acc_handle); 3318678453a8Sspeer if (ddi_status != DDI_SUCCESS) { 3319678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3320678453a8Sspeer "nxge_dma_mem_alloc: " 3321678453a8Sspeer "ddi_dma_mem_alloc failed")); 3322678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3323678453a8Sspeer dma_p->dma_handle = NULL; 3324678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3325678453a8Sspeer } 3326678453a8Sspeer if (dma_p->alength < length) { 3327678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3328678453a8Sspeer "nxge_dma_mem_alloc:di_dma_mem_alloc " 3329678453a8Sspeer "< length.")); 333044961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 3331678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 333244961713Sgirish dma_p->acc_handle = NULL; 3333678453a8Sspeer dma_p->dma_handle = NULL; 3334678453a8Sspeer return (NXGE_ERROR); 333544961713Sgirish } 333644961713Sgirish 3337678453a8Sspeer ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, 3338678453a8Sspeer NULL, 3339678453a8Sspeer kaddrp, dma_p->alength, xfer_flags, 3340678453a8Sspeer DDI_DMA_DONTWAIT, 3341678453a8Sspeer 0, &dma_p->dma_cookie, &dma_p->ncookies); 3342678453a8Sspeer if (ddi_status != DDI_DMA_MAPPED) { 3343678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3344678453a8Sspeer "nxge_dma_mem_alloc: ddi_dma_addr_bind " 3345678453a8Sspeer "failed " 3346678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 3347678453a8Sspeer dma_p->ncookies)); 3348678453a8Sspeer if (dma_p->acc_handle) { 3349678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3350678453a8Sspeer dma_p->acc_handle = NULL; 3351678453a8Sspeer } 3352678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3353678453a8Sspeer dma_p->dma_handle = NULL; 3354678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3355678453a8Sspeer } 3356678453a8Sspeer 3357678453a8Sspeer if (dma_p->ncookies != 1) { 3358678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 3359678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind " 3360678453a8Sspeer "> 1 cookie" 3361678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 3362678453a8Sspeer dma_p->ncookies)); 3363678453a8Sspeer if (dma_p->acc_handle) { 3364678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3365678453a8Sspeer dma_p->acc_handle = NULL; 3366678453a8Sspeer } 3367678453a8Sspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3368678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3369678453a8Sspeer dma_p->dma_handle = NULL; 3370678453a8Sspeer return (NXGE_ERROR); 3371678453a8Sspeer } 3372678453a8Sspeer break; 3373678453a8Sspeer 3374678453a8Sspeer case B_TRUE: 3375678453a8Sspeer kaddrp = KMEM_ALLOC(length, KM_NOSLEEP); 3376678453a8Sspeer if (kaddrp == NULL) { 3377678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3378678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_mem_alloc " 3379678453a8Sspeer "kmem alloc failed")); 3380678453a8Sspeer return (NXGE_ERROR); 3381678453a8Sspeer } 3382678453a8Sspeer 3383678453a8Sspeer dma_p->alength = length; 3384678453a8Sspeer ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, 3385678453a8Sspeer NULL, kaddrp, dma_p->alength, xfer_flags, 3386678453a8Sspeer DDI_DMA_DONTWAIT, 0, 3387678453a8Sspeer &dma_p->dma_cookie, &dma_p->ncookies); 3388678453a8Sspeer if (ddi_status != DDI_DMA_MAPPED) { 3389678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3390678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind: " 3391678453a8Sspeer "(kmem_alloc) failed kaddrp $%p length %d " 3392678453a8Sspeer "(staus 0x%x (%d) ncookies %d.)", 3393678453a8Sspeer kaddrp, length, 3394678453a8Sspeer ddi_status, ddi_status, dma_p->ncookies)); 3395678453a8Sspeer KMEM_FREE(kaddrp, length); 3396678453a8Sspeer dma_p->acc_handle = NULL; 3397678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3398678453a8Sspeer dma_p->dma_handle = NULL; 3399678453a8Sspeer dma_p->kaddrp = NULL; 3400678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3401678453a8Sspeer } 3402678453a8Sspeer 3403678453a8Sspeer if (dma_p->ncookies != 1) { 3404678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 3405678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind " 3406678453a8Sspeer "(kmem_alloc) > 1 cookie" 3407678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 34084045d941Ssowmini dma_p->ncookies)); 3409678453a8Sspeer KMEM_FREE(kaddrp, length); 341044961713Sgirish dma_p->acc_handle = NULL; 3411678453a8Sspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3412678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3413678453a8Sspeer dma_p->dma_handle = NULL; 3414678453a8Sspeer dma_p->kaddrp = NULL; 3415678453a8Sspeer return (NXGE_ERROR); 341644961713Sgirish } 3417678453a8Sspeer 3418678453a8Sspeer dma_p->kaddrp = kaddrp; 3419678453a8Sspeer 3420678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 34214045d941Ssowmini "nxge_dma_mem_alloc: kmem_alloc dmap $%p " 34224045d941Ssowmini "kaddr $%p alength %d", 34234045d941Ssowmini dma_p, 34244045d941Ssowmini kaddrp, 34254045d941Ssowmini dma_p->alength)); 3426678453a8Sspeer break; 342744961713Sgirish } 342844961713Sgirish break; 342944961713Sgirish 343044961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 343144961713Sgirish case B_TRUE: 343244961713Sgirish kaddrp = (caddr_t)contig_mem_alloc(length); 343344961713Sgirish if (kaddrp == NULL) { 343444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34354045d941Ssowmini "nxge_dma_mem_alloc:contig_mem_alloc failed.")); 343644961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 343744961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 343844961713Sgirish } 343944961713Sgirish 344044961713Sgirish dma_p->alength = length; 344144961713Sgirish ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL, 34424045d941Ssowmini kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0, 34434045d941Ssowmini &dma_p->dma_cookie, &dma_p->ncookies); 344444961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 344544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34464045d941Ssowmini "nxge_dma_mem_alloc:di_dma_addr_bind failed " 34474045d941Ssowmini "(status 0x%x ncookies %d.)", ddi_status, 34484045d941Ssowmini dma_p->ncookies)); 344944961713Sgirish 345044961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 34514045d941Ssowmini "==> nxge_dma_mem_alloc: (not mapped)" 34524045d941Ssowmini "length %lu (0x%x) " 34534045d941Ssowmini "free contig kaddrp $%p " 34544045d941Ssowmini "va_to_pa $%p", 34554045d941Ssowmini length, length, 34564045d941Ssowmini kaddrp, 34574045d941Ssowmini va_to_pa(kaddrp))); 345844961713Sgirish 345944961713Sgirish 346044961713Sgirish contig_mem_free((void *)kaddrp, length); 346144961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 346244961713Sgirish 346344961713Sgirish dma_p->dma_handle = NULL; 346444961713Sgirish dma_p->acc_handle = NULL; 346544961713Sgirish dma_p->alength = NULL; 346644961713Sgirish dma_p->kaddrp = NULL; 346744961713Sgirish 346844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 346944961713Sgirish } 347044961713Sgirish 347144961713Sgirish if (dma_p->ncookies != 1 || 34724045d941Ssowmini (dma_p->dma_cookie.dmac_laddress == NULL)) { 347344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34744045d941Ssowmini "nxge_dma_mem_alloc:di_dma_addr_bind > 1 " 34754045d941Ssowmini "cookie or " 34764045d941Ssowmini "dmac_laddress is NULL $%p size %d " 34774045d941Ssowmini " (status 0x%x ncookies %d.)", 34784045d941Ssowmini ddi_status, 34794045d941Ssowmini dma_p->dma_cookie.dmac_laddress, 34804045d941Ssowmini dma_p->dma_cookie.dmac_size, 34814045d941Ssowmini dma_p->ncookies)); 348244961713Sgirish 348344961713Sgirish contig_mem_free((void *)kaddrp, length); 348456d930aeSspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 348544961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 348644961713Sgirish 348744961713Sgirish dma_p->alength = 0; 348844961713Sgirish dma_p->dma_handle = NULL; 348944961713Sgirish dma_p->acc_handle = NULL; 349044961713Sgirish dma_p->kaddrp = NULL; 349144961713Sgirish 349244961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 349344961713Sgirish } 349444961713Sgirish break; 349544961713Sgirish 349644961713Sgirish #else 349744961713Sgirish case B_TRUE: 349844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34994045d941Ssowmini "nxge_dma_mem_alloc: invalid alloc type for !sun4v")); 350044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 350144961713Sgirish #endif 350244961713Sgirish } 350344961713Sgirish 350444961713Sgirish dma_p->kaddrp = kaddrp; 350544961713Sgirish dma_p->last_kaddrp = (unsigned char *)kaddrp + 35064045d941Ssowmini dma_p->alength - RXBUF_64B_ALIGNED; 3507adfcba55Sjoycey #if defined(__i386) 3508adfcba55Sjoycey dma_p->ioaddr_pp = 35094045d941Ssowmini (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress; 3510adfcba55Sjoycey #else 351144961713Sgirish dma_p->ioaddr_pp = (unsigned char *)dma_p->dma_cookie.dmac_laddress; 3512adfcba55Sjoycey #endif 351344961713Sgirish dma_p->last_ioaddr_pp = 3514adfcba55Sjoycey #if defined(__i386) 35154045d941Ssowmini (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress + 3516adfcba55Sjoycey #else 35174045d941Ssowmini (unsigned char *)dma_p->dma_cookie.dmac_laddress + 3518adfcba55Sjoycey #endif 35194045d941Ssowmini dma_p->alength - RXBUF_64B_ALIGNED; 352044961713Sgirish 352144961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle); 352244961713Sgirish 352344961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 352444961713Sgirish dma_p->orig_ioaddr_pp = 35254045d941Ssowmini (unsigned char *)dma_p->dma_cookie.dmac_laddress; 352644961713Sgirish dma_p->orig_alength = length; 352744961713Sgirish dma_p->orig_kaddrp = kaddrp; 352844961713Sgirish dma_p->orig_vatopa = (uint64_t)va_to_pa(kaddrp); 352944961713Sgirish #endif 353044961713Sgirish 353144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_dma_mem_alloc: " 35324045d941Ssowmini "dma buffer allocated: dma_p $%p " 35334045d941Ssowmini "return dmac_ladress from cookie $%p cookie dmac_size %d " 35344045d941Ssowmini "dma_p->ioaddr_p $%p " 35354045d941Ssowmini "dma_p->orig_ioaddr_p $%p " 35364045d941Ssowmini "orig_vatopa $%p " 35374045d941Ssowmini "alength %d (0x%x) " 35384045d941Ssowmini "kaddrp $%p " 35394045d941Ssowmini "length %d (0x%x)", 35404045d941Ssowmini dma_p, 35414045d941Ssowmini dma_p->dma_cookie.dmac_laddress, dma_p->dma_cookie.dmac_size, 35424045d941Ssowmini dma_p->ioaddr_pp, 35434045d941Ssowmini dma_p->orig_ioaddr_pp, 35444045d941Ssowmini dma_p->orig_vatopa, 35454045d941Ssowmini dma_p->alength, dma_p->alength, 35464045d941Ssowmini kaddrp, 35474045d941Ssowmini length, length)); 354844961713Sgirish 354944961713Sgirish return (NXGE_OK); 355044961713Sgirish } 355144961713Sgirish 355244961713Sgirish static void 355344961713Sgirish nxge_dma_mem_free(p_nxge_dma_common_t dma_p) 355444961713Sgirish { 355544961713Sgirish if (dma_p->dma_handle != NULL) { 355644961713Sgirish if (dma_p->ncookies) { 355744961713Sgirish (void) ddi_dma_unbind_handle(dma_p->dma_handle); 355844961713Sgirish dma_p->ncookies = 0; 355944961713Sgirish } 356044961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 356144961713Sgirish dma_p->dma_handle = NULL; 356244961713Sgirish } 356344961713Sgirish 356444961713Sgirish if (dma_p->acc_handle != NULL) { 356544961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 356644961713Sgirish dma_p->acc_handle = NULL; 356744961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 356844961713Sgirish } 356944961713Sgirish 357044961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 357144961713Sgirish if (dma_p->contig_alloc_type && 35724045d941Ssowmini dma_p->orig_kaddrp && dma_p->orig_alength) { 357344961713Sgirish NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_mem_free: " 35744045d941Ssowmini "kaddrp $%p (orig_kaddrp $%p)" 35754045d941Ssowmini "mem type %d ", 35764045d941Ssowmini "orig_alength %d " 35774045d941Ssowmini "alength 0x%x (%d)", 35784045d941Ssowmini dma_p->kaddrp, 35794045d941Ssowmini dma_p->orig_kaddrp, 35804045d941Ssowmini dma_p->contig_alloc_type, 35814045d941Ssowmini dma_p->orig_alength, 35824045d941Ssowmini dma_p->alength, dma_p->alength)); 358344961713Sgirish 358444961713Sgirish contig_mem_free(dma_p->orig_kaddrp, dma_p->orig_alength); 358544961713Sgirish dma_p->orig_alength = NULL; 358644961713Sgirish dma_p->orig_kaddrp = NULL; 358744961713Sgirish dma_p->contig_alloc_type = B_FALSE; 358844961713Sgirish } 358944961713Sgirish #endif 359044961713Sgirish dma_p->kaddrp = NULL; 359144961713Sgirish dma_p->alength = NULL; 359244961713Sgirish } 359344961713Sgirish 3594678453a8Sspeer static void 3595678453a8Sspeer nxge_dma_free_rx_data_buf(p_nxge_dma_common_t dma_p) 3596678453a8Sspeer { 3597678453a8Sspeer uint64_t kaddr; 3598678453a8Sspeer uint32_t buf_size; 3599678453a8Sspeer 3600678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "==> nxge_dma_free_rx_data_buf")); 3601678453a8Sspeer 3602678453a8Sspeer if (dma_p->dma_handle != NULL) { 3603678453a8Sspeer if (dma_p->ncookies) { 3604678453a8Sspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3605678453a8Sspeer dma_p->ncookies = 0; 3606678453a8Sspeer } 3607678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3608678453a8Sspeer dma_p->dma_handle = NULL; 3609678453a8Sspeer } 3610678453a8Sspeer 3611678453a8Sspeer if (dma_p->acc_handle != NULL) { 3612678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3613678453a8Sspeer dma_p->acc_handle = NULL; 3614678453a8Sspeer NPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 3615678453a8Sspeer } 3616678453a8Sspeer 3617678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3618678453a8Sspeer "==> nxge_dma_free_rx_data_buf: dmap $%p buf_alloc_state %d", 3619678453a8Sspeer dma_p, 3620678453a8Sspeer dma_p->buf_alloc_state)); 3621678453a8Sspeer 3622678453a8Sspeer if (!(dma_p->buf_alloc_state & BUF_ALLOCATED_WAIT_FREE)) { 3623678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3624678453a8Sspeer "<== nxge_dma_free_rx_data_buf: " 3625678453a8Sspeer "outstanding data buffers")); 3626678453a8Sspeer return; 3627678453a8Sspeer } 3628678453a8Sspeer 3629678453a8Sspeer #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 3630678453a8Sspeer if (dma_p->contig_alloc_type && 36314045d941Ssowmini dma_p->orig_kaddrp && dma_p->orig_alength) { 3632678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_free_rx_data_buf: " 3633678453a8Sspeer "kaddrp $%p (orig_kaddrp $%p)" 3634678453a8Sspeer "mem type %d ", 3635678453a8Sspeer "orig_alength %d " 3636678453a8Sspeer "alength 0x%x (%d)", 3637678453a8Sspeer dma_p->kaddrp, 3638678453a8Sspeer dma_p->orig_kaddrp, 3639678453a8Sspeer dma_p->contig_alloc_type, 3640678453a8Sspeer dma_p->orig_alength, 3641678453a8Sspeer dma_p->alength, dma_p->alength)); 3642678453a8Sspeer 3643678453a8Sspeer kaddr = (uint64_t)dma_p->orig_kaddrp; 3644678453a8Sspeer buf_size = dma_p->orig_alength; 3645678453a8Sspeer nxge_free_buf(CONTIG_MEM_ALLOC, kaddr, buf_size); 3646678453a8Sspeer dma_p->orig_alength = NULL; 3647678453a8Sspeer dma_p->orig_kaddrp = NULL; 3648678453a8Sspeer dma_p->contig_alloc_type = B_FALSE; 3649678453a8Sspeer dma_p->kaddrp = NULL; 3650678453a8Sspeer dma_p->alength = NULL; 3651678453a8Sspeer return; 3652678453a8Sspeer } 3653678453a8Sspeer #endif 3654678453a8Sspeer 3655678453a8Sspeer if (dma_p->kmem_alloc_type) { 3656678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3657678453a8Sspeer "nxge_dma_free_rx_data_buf: free kmem " 36584045d941Ssowmini "kaddrp $%p (orig_kaddrp $%p)" 36594045d941Ssowmini "alloc type %d " 36604045d941Ssowmini "orig_alength %d " 36614045d941Ssowmini "alength 0x%x (%d)", 36624045d941Ssowmini dma_p->kaddrp, 36634045d941Ssowmini dma_p->orig_kaddrp, 36644045d941Ssowmini dma_p->kmem_alloc_type, 36654045d941Ssowmini dma_p->orig_alength, 36664045d941Ssowmini dma_p->alength, dma_p->alength)); 3667678453a8Sspeer #if defined(__i386) 3668678453a8Sspeer kaddr = (uint64_t)(uint32_t)dma_p->kaddrp; 3669678453a8Sspeer #else 3670678453a8Sspeer kaddr = (uint64_t)dma_p->kaddrp; 3671678453a8Sspeer #endif 3672678453a8Sspeer buf_size = dma_p->orig_alength; 3673678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3674678453a8Sspeer "nxge_dma_free_rx_data_buf: free dmap $%p " 3675678453a8Sspeer "kaddr $%p buf_size %d", 3676678453a8Sspeer dma_p, 3677678453a8Sspeer kaddr, buf_size)); 3678678453a8Sspeer nxge_free_buf(KMEM_ALLOC, kaddr, buf_size); 3679678453a8Sspeer dma_p->alength = 0; 3680678453a8Sspeer dma_p->orig_alength = 0; 3681678453a8Sspeer dma_p->kaddrp = NULL; 3682678453a8Sspeer dma_p->kmem_alloc_type = B_FALSE; 3683678453a8Sspeer } 3684678453a8Sspeer 3685678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_dma_free_rx_data_buf")); 3686678453a8Sspeer } 3687678453a8Sspeer 368844961713Sgirish /* 368944961713Sgirish * nxge_m_start() -- start transmitting and receiving. 369044961713Sgirish * 369144961713Sgirish * This function is called by the MAC layer when the first 369244961713Sgirish * stream is open to prepare the hardware ready for sending 369344961713Sgirish * and transmitting packets. 369444961713Sgirish */ 369544961713Sgirish static int 369644961713Sgirish nxge_m_start(void *arg) 369744961713Sgirish { 369844961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 369944961713Sgirish 370044961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_start")); 370144961713Sgirish 37026f157acbSml if (nxge_peu_reset_enable && !nxgep->nxge_link_poll_timerid) { 37036f157acbSml (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 37046f157acbSml } 37056f157acbSml 370644961713Sgirish MUTEX_ENTER(nxgep->genlock); 370714ea4bb7Ssd if (nxge_init(nxgep) != NXGE_OK) { 370844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 37094045d941Ssowmini "<== nxge_m_start: initialization failed")); 371044961713Sgirish MUTEX_EXIT(nxgep->genlock); 371144961713Sgirish return (EIO); 371244961713Sgirish } 371344961713Sgirish 371414ea4bb7Ssd if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) 371514ea4bb7Ssd goto nxge_m_start_exit; 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); 3722678453a8Sspeer #if defined(sun4v) 3723678453a8Sspeer else 3724678453a8Sspeer nxge_hio_start_timer(nxgep); 3725678453a8Sspeer #endif 372644961713Sgirish 3727a3c5bd6dSspeer nxgep->link_notify = B_TRUE; 3728a3c5bd6dSspeer 372944961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STARTED; 373044961713Sgirish 373114ea4bb7Ssd nxge_m_start_exit: 373244961713Sgirish MUTEX_EXIT(nxgep->genlock); 373344961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_start")); 373444961713Sgirish return (0); 373544961713Sgirish } 373644961713Sgirish 373744961713Sgirish /* 373844961713Sgirish * nxge_m_stop(): stop transmitting and receiving. 373944961713Sgirish */ 374044961713Sgirish static void 374144961713Sgirish nxge_m_stop(void *arg) 374244961713Sgirish { 374344961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 374444961713Sgirish 374544961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_stop")); 374644961713Sgirish 3747d7cf53fcSmisaki Miyashita MUTEX_ENTER(nxgep->genlock); 3748d7cf53fcSmisaki Miyashita nxgep->nxge_mac_state = NXGE_MAC_STOPPING; 3749d7cf53fcSmisaki Miyashita 375044961713Sgirish if (nxgep->nxge_timerid) { 375144961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 375244961713Sgirish nxgep->nxge_timerid = 0; 375344961713Sgirish } 3754a3c5bd6dSspeer 375544961713Sgirish nxge_uninit(nxgep); 375644961713Sgirish 375744961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STOPPED; 375844961713Sgirish 375944961713Sgirish MUTEX_EXIT(nxgep->genlock); 376044961713Sgirish 376144961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_stop")); 376244961713Sgirish } 376344961713Sgirish 376444961713Sgirish static int 376544961713Sgirish nxge_m_unicst(void *arg, const uint8_t *macaddr) 376644961713Sgirish { 376744961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 376844961713Sgirish struct ether_addr addrp; 376944961713Sgirish 377044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_m_unicst")); 377144961713Sgirish 377244961713Sgirish bcopy(macaddr, (uint8_t *)&addrp, ETHERADDRL); 377344961713Sgirish if (nxge_set_mac_addr(nxgep, &addrp)) { 377444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 37754045d941Ssowmini "<== nxge_m_unicst: set unitcast failed")); 377644961713Sgirish return (EINVAL); 377744961713Sgirish } 377844961713Sgirish 377944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_unicst")); 378044961713Sgirish 378144961713Sgirish return (0); 378244961713Sgirish } 378344961713Sgirish 378444961713Sgirish static int 378544961713Sgirish nxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 378644961713Sgirish { 378744961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 378844961713Sgirish struct ether_addr addrp; 378944961713Sgirish 379044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 37914045d941Ssowmini "==> nxge_m_multicst: add %d", add)); 379244961713Sgirish 379344961713Sgirish bcopy(mca, (uint8_t *)&addrp, ETHERADDRL); 379444961713Sgirish if (add) { 379544961713Sgirish if (nxge_add_mcast_addr(nxgep, &addrp)) { 379644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 37974045d941Ssowmini "<== nxge_m_multicst: add multicast failed")); 379844961713Sgirish return (EINVAL); 379944961713Sgirish } 380044961713Sgirish } else { 380144961713Sgirish if (nxge_del_mcast_addr(nxgep, &addrp)) { 380244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 38034045d941Ssowmini "<== nxge_m_multicst: del multicast failed")); 380444961713Sgirish return (EINVAL); 380544961713Sgirish } 380644961713Sgirish } 380744961713Sgirish 380844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_multicst")); 380944961713Sgirish 381044961713Sgirish return (0); 381144961713Sgirish } 381244961713Sgirish 381344961713Sgirish static int 381444961713Sgirish nxge_m_promisc(void *arg, boolean_t on) 381544961713Sgirish { 381644961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 381744961713Sgirish 381844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38194045d941Ssowmini "==> nxge_m_promisc: on %d", on)); 382044961713Sgirish 382144961713Sgirish if (nxge_set_promisc(nxgep, on)) { 382244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 38234045d941Ssowmini "<== nxge_m_promisc: set promisc failed")); 382444961713Sgirish return (EINVAL); 382544961713Sgirish } 382644961713Sgirish 382744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38284045d941Ssowmini "<== nxge_m_promisc: on %d", on)); 382944961713Sgirish 383044961713Sgirish return (0); 383144961713Sgirish } 383244961713Sgirish 383344961713Sgirish static void 383444961713Sgirish nxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 383544961713Sgirish { 383644961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 383756d930aeSspeer struct iocblk *iocp; 383844961713Sgirish boolean_t need_privilege; 383944961713Sgirish int err; 384044961713Sgirish int cmd; 384144961713Sgirish 384244961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl")); 384344961713Sgirish 384444961713Sgirish iocp = (struct iocblk *)mp->b_rptr; 384544961713Sgirish iocp->ioc_error = 0; 384644961713Sgirish need_privilege = B_TRUE; 384744961713Sgirish cmd = iocp->ioc_cmd; 384844961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl: cmd 0x%08x", cmd)); 384944961713Sgirish switch (cmd) { 385044961713Sgirish default: 385144961713Sgirish miocnak(wq, mp, 0, EINVAL); 385244961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl: invalid")); 385344961713Sgirish return; 385444961713Sgirish 385544961713Sgirish case LB_GET_INFO_SIZE: 385644961713Sgirish case LB_GET_INFO: 385744961713Sgirish case LB_GET_MODE: 385844961713Sgirish need_privilege = B_FALSE; 385944961713Sgirish break; 386044961713Sgirish case LB_SET_MODE: 386144961713Sgirish break; 386244961713Sgirish 386344961713Sgirish 386444961713Sgirish case NXGE_GET_MII: 386544961713Sgirish case NXGE_PUT_MII: 386644961713Sgirish case NXGE_GET64: 386744961713Sgirish case NXGE_PUT64: 386844961713Sgirish case NXGE_GET_TX_RING_SZ: 386944961713Sgirish case NXGE_GET_TX_DESC: 387044961713Sgirish case NXGE_TX_SIDE_RESET: 387144961713Sgirish case NXGE_RX_SIDE_RESET: 387244961713Sgirish case NXGE_GLOBAL_RESET: 387344961713Sgirish case NXGE_RESET_MAC: 387444961713Sgirish case NXGE_TX_REGS_DUMP: 387544961713Sgirish case NXGE_RX_REGS_DUMP: 387644961713Sgirish case NXGE_INT_REGS_DUMP: 387744961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 387844961713Sgirish case NXGE_PUT_TCAM: 387944961713Sgirish case NXGE_GET_TCAM: 388044961713Sgirish case NXGE_RTRACE: 388144961713Sgirish case NXGE_RDUMP: 388244961713Sgirish 388344961713Sgirish need_privilege = B_FALSE; 388444961713Sgirish break; 388544961713Sgirish case NXGE_INJECT_ERR: 388644961713Sgirish cmn_err(CE_NOTE, "!nxge_m_ioctl: Inject error\n"); 388744961713Sgirish nxge_err_inject(nxgep, wq, mp); 388844961713Sgirish break; 388944961713Sgirish } 389044961713Sgirish 389144961713Sgirish if (need_privilege) { 389256d930aeSspeer err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 389344961713Sgirish if (err != 0) { 389444961713Sgirish miocnak(wq, mp, 0, err); 389544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 38964045d941Ssowmini "<== nxge_m_ioctl: no priv")); 389744961713Sgirish return; 389844961713Sgirish } 389944961713Sgirish } 390044961713Sgirish 390144961713Sgirish switch (cmd) { 390244961713Sgirish 390344961713Sgirish case LB_GET_MODE: 390444961713Sgirish case LB_SET_MODE: 390544961713Sgirish case LB_GET_INFO_SIZE: 390644961713Sgirish case LB_GET_INFO: 390744961713Sgirish nxge_loopback_ioctl(nxgep, wq, mp, iocp); 390844961713Sgirish break; 390944961713Sgirish 391044961713Sgirish case NXGE_GET_MII: 391144961713Sgirish case NXGE_PUT_MII: 391244961713Sgirish case NXGE_PUT_TCAM: 391344961713Sgirish case NXGE_GET_TCAM: 391444961713Sgirish case NXGE_GET64: 391544961713Sgirish case NXGE_PUT64: 391644961713Sgirish case NXGE_GET_TX_RING_SZ: 391744961713Sgirish case NXGE_GET_TX_DESC: 391844961713Sgirish case NXGE_TX_SIDE_RESET: 391944961713Sgirish case NXGE_RX_SIDE_RESET: 392044961713Sgirish case NXGE_GLOBAL_RESET: 392144961713Sgirish case NXGE_RESET_MAC: 392244961713Sgirish case NXGE_TX_REGS_DUMP: 392344961713Sgirish case NXGE_RX_REGS_DUMP: 392444961713Sgirish case NXGE_INT_REGS_DUMP: 392544961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 392644961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 39274045d941Ssowmini "==> nxge_m_ioctl: cmd 0x%x", cmd)); 392844961713Sgirish nxge_hw_ioctl(nxgep, wq, mp, iocp); 392944961713Sgirish break; 393044961713Sgirish } 393144961713Sgirish 393244961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl")); 393344961713Sgirish } 393444961713Sgirish 393544961713Sgirish extern void nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count); 393644961713Sgirish 393744961713Sgirish static void 393844961713Sgirish nxge_m_resources(void *arg) 393944961713Sgirish { 394044961713Sgirish p_nxge_t nxgep = arg; 394144961713Sgirish mac_rx_fifo_t mrf; 3942678453a8Sspeer 3943678453a8Sspeer nxge_grp_set_t *set = &nxgep->rx_set; 3944678453a8Sspeer uint8_t rdc; 3945678453a8Sspeer 3946678453a8Sspeer rx_rcr_ring_t *ring; 394744961713Sgirish 394844961713Sgirish NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_m_resources")); 394944961713Sgirish 395044961713Sgirish MUTEX_ENTER(nxgep->genlock); 395114ea4bb7Ssd 3952678453a8Sspeer if (set->owned.map == 0) { 3953678453a8Sspeer NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, 3954678453a8Sspeer "nxge_m_resources: no receive resources")); 3955678453a8Sspeer goto nxge_m_resources_exit; 3956678453a8Sspeer } 3957678453a8Sspeer 395814ea4bb7Ssd /* 395958324dfcSspeer * CR 6492541 Check to see if the drv_state has been initialized, 396014ea4bb7Ssd * if not * call nxge_init(). 396114ea4bb7Ssd */ 396214ea4bb7Ssd if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 3963678453a8Sspeer if (nxge_init(nxgep) != NXGE_OK) 396414ea4bb7Ssd goto nxge_m_resources_exit; 396514ea4bb7Ssd } 396614ea4bb7Ssd 396744961713Sgirish mrf.mrf_type = MAC_RX_FIFO; 396844961713Sgirish mrf.mrf_blank = nxge_rx_hw_blank; 396944961713Sgirish mrf.mrf_arg = (void *)nxgep; 397044961713Sgirish 397144961713Sgirish mrf.mrf_normal_blank_time = 128; 397244961713Sgirish mrf.mrf_normal_pkt_count = 8; 397344961713Sgirish 397414ea4bb7Ssd /* 397514ea4bb7Ssd * Export our receive resources to the MAC layer. 397614ea4bb7Ssd */ 3977678453a8Sspeer for (rdc = 0; rdc < NXGE_MAX_RDCS; rdc++) { 3978678453a8Sspeer if ((1 << rdc) & set->owned.map) { 3979678453a8Sspeer ring = nxgep->rx_rcr_rings->rcr_rings[rdc]; 3980678453a8Sspeer if (ring == 0) { 3981678453a8Sspeer /* 3982678453a8Sspeer * This is a big deal only if we are 3983678453a8Sspeer * *not* in an LDOMs environment. 3984678453a8Sspeer */ 3985678453a8Sspeer if (nxgep->environs == SOLARIS_DOMAIN) { 3986678453a8Sspeer cmn_err(CE_NOTE, 3987678453a8Sspeer "==> nxge_m_resources: " 3988678453a8Sspeer "ring %d == 0", rdc); 3989678453a8Sspeer } 3990678453a8Sspeer continue; 3991678453a8Sspeer } 3992678453a8Sspeer ring->rcr_mac_handle = mac_resource_add 3993678453a8Sspeer (nxgep->mach, (mac_resource_t *)&mrf); 399444961713Sgirish 3995678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 3996678453a8Sspeer "==> nxge_m_resources: RDC %d RCR %p MAC handle %p", 3997678453a8Sspeer rdc, ring, ring->rcr_mac_handle)); 3998678453a8Sspeer } 399944961713Sgirish } 400044961713Sgirish 400114ea4bb7Ssd nxge_m_resources_exit: 400244961713Sgirish MUTEX_EXIT(nxgep->genlock); 400344961713Sgirish NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_m_resources")); 400444961713Sgirish } 400544961713Sgirish 4006678453a8Sspeer void 400758324dfcSspeer nxge_mmac_kstat_update(p_nxge_t nxgep, mac_addr_slot_t slot, boolean_t factory) 400858324dfcSspeer { 400958324dfcSspeer p_nxge_mmac_stats_t mmac_stats; 401058324dfcSspeer int i; 401158324dfcSspeer nxge_mmac_t *mmac_info; 401258324dfcSspeer 401358324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 401458324dfcSspeer 401558324dfcSspeer mmac_stats = &nxgep->statsp->mmac_stats; 401658324dfcSspeer mmac_stats->mmac_max_cnt = mmac_info->num_mmac; 401758324dfcSspeer mmac_stats->mmac_avail_cnt = mmac_info->naddrfree; 401858324dfcSspeer 401958324dfcSspeer for (i = 0; i < ETHERADDRL; i++) { 402058324dfcSspeer if (factory) { 402158324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 40224045d941Ssowmini = mmac_info->factory_mac_pool[slot][ 40234045d941Ssowmini (ETHERADDRL-1) - i]; 402458324dfcSspeer } else { 402558324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 40264045d941Ssowmini = mmac_info->mac_pool[slot].addr[ 40274045d941Ssowmini (ETHERADDRL - 1) - i]; 402858324dfcSspeer } 402958324dfcSspeer } 403058324dfcSspeer } 403158324dfcSspeer 403258324dfcSspeer /* 403358324dfcSspeer * nxge_altmac_set() -- Set an alternate MAC address 403458324dfcSspeer */ 403558324dfcSspeer static int 403658324dfcSspeer nxge_altmac_set(p_nxge_t nxgep, uint8_t *maddr, mac_addr_slot_t slot) 403758324dfcSspeer { 403858324dfcSspeer uint8_t addrn; 403958324dfcSspeer uint8_t portn; 404058324dfcSspeer npi_mac_addr_t altmac; 40417b9fa28bSspeer hostinfo_t mac_rdc; 40427b9fa28bSspeer p_nxge_class_pt_cfg_t clscfgp; 404358324dfcSspeer 404458324dfcSspeer altmac.w2 = ((uint16_t)maddr[0] << 8) | ((uint16_t)maddr[1] & 0x0ff); 404558324dfcSspeer altmac.w1 = ((uint16_t)maddr[2] << 8) | ((uint16_t)maddr[3] & 0x0ff); 404658324dfcSspeer altmac.w0 = ((uint16_t)maddr[4] << 8) | ((uint16_t)maddr[5] & 0x0ff); 404758324dfcSspeer 404858324dfcSspeer portn = nxgep->mac.portnum; 404958324dfcSspeer addrn = (uint8_t)slot - 1; 405058324dfcSspeer 405158324dfcSspeer if (npi_mac_altaddr_entry(nxgep->npi_handle, OP_SET, portn, 40524045d941Ssowmini addrn, &altmac) != NPI_SUCCESS) 405358324dfcSspeer return (EIO); 40547b9fa28bSspeer 40557b9fa28bSspeer /* 40567b9fa28bSspeer * Set the rdc table number for the host info entry 40577b9fa28bSspeer * for this mac address slot. 40587b9fa28bSspeer */ 40597b9fa28bSspeer clscfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config; 40607b9fa28bSspeer mac_rdc.value = 0; 40617b9fa28bSspeer mac_rdc.bits.w0.rdc_tbl_num = clscfgp->mac_host_info[addrn].rdctbl; 40627b9fa28bSspeer mac_rdc.bits.w0.mac_pref = clscfgp->mac_host_info[addrn].mpr_npr; 40637b9fa28bSspeer 40647b9fa28bSspeer if (npi_mac_hostinfo_entry(nxgep->npi_handle, OP_SET, 40657b9fa28bSspeer nxgep->function_num, addrn, &mac_rdc) != NPI_SUCCESS) { 40667b9fa28bSspeer return (EIO); 40677b9fa28bSspeer } 40687b9fa28bSspeer 406958324dfcSspeer /* 407058324dfcSspeer * Enable comparison with the alternate MAC address. 407158324dfcSspeer * While the first alternate addr is enabled by bit 1 of register 407258324dfcSspeer * BMAC_ALTAD_CMPEN, it is enabled by bit 0 of register 407358324dfcSspeer * XMAC_ADDR_CMPEN, so slot needs to be converted to addrn 407458324dfcSspeer * accordingly before calling npi_mac_altaddr_entry. 407558324dfcSspeer */ 407658324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 407758324dfcSspeer addrn = (uint8_t)slot - 1; 407858324dfcSspeer else 407958324dfcSspeer addrn = (uint8_t)slot; 408058324dfcSspeer 408158324dfcSspeer if (npi_mac_altaddr_enable(nxgep->npi_handle, portn, addrn) 40824045d941Ssowmini != NPI_SUCCESS) 408358324dfcSspeer return (EIO); 408458324dfcSspeer 408558324dfcSspeer return (0); 408658324dfcSspeer } 408758324dfcSspeer 408858324dfcSspeer /* 408958324dfcSspeer * nxeg_m_mmac_add() - find an unused address slot, set the address 409058324dfcSspeer * value to the one specified, enable the port to start filtering on 409158324dfcSspeer * the new MAC address. Returns 0 on success. 409258324dfcSspeer */ 4093678453a8Sspeer int 409458324dfcSspeer nxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr) 409558324dfcSspeer { 409658324dfcSspeer p_nxge_t nxgep = arg; 409758324dfcSspeer mac_addr_slot_t slot; 409858324dfcSspeer nxge_mmac_t *mmac_info; 409958324dfcSspeer int err; 410058324dfcSspeer nxge_status_t status; 410158324dfcSspeer 410258324dfcSspeer mutex_enter(nxgep->genlock); 410358324dfcSspeer 410458324dfcSspeer /* 410558324dfcSspeer * Make sure that nxge is initialized, if _start() has 410658324dfcSspeer * not been called. 410758324dfcSspeer */ 410858324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 410958324dfcSspeer status = nxge_init(nxgep); 411058324dfcSspeer if (status != NXGE_OK) { 411158324dfcSspeer mutex_exit(nxgep->genlock); 411258324dfcSspeer return (ENXIO); 411358324dfcSspeer } 411458324dfcSspeer } 411558324dfcSspeer 411658324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 411758324dfcSspeer if (mmac_info->naddrfree == 0) { 411858324dfcSspeer mutex_exit(nxgep->genlock); 411958324dfcSspeer return (ENOSPC); 412058324dfcSspeer } 412158324dfcSspeer if (!mac_unicst_verify(nxgep->mach, maddr->mma_addr, 41224045d941Ssowmini maddr->mma_addrlen)) { 412358324dfcSspeer mutex_exit(nxgep->genlock); 412458324dfcSspeer return (EINVAL); 412558324dfcSspeer } 412658324dfcSspeer /* 412758324dfcSspeer * Search for the first available slot. Because naddrfree 412858324dfcSspeer * is not zero, we are guaranteed to find one. 412958324dfcSspeer * Slot 0 is for unique (primary) MAC. The first alternate 413058324dfcSspeer * MAC slot is slot 1. 413158324dfcSspeer * Each of the first two ports of Neptune has 16 alternate 4132678453a8Sspeer * MAC slots but only the first 7 (of 15) slots have assigned factory 413358324dfcSspeer * MAC addresses. We first search among the slots without bundled 413458324dfcSspeer * factory MACs. If we fail to find one in that range, then we 413558324dfcSspeer * search the slots with bundled factory MACs. A factory MAC 413658324dfcSspeer * will be wasted while the slot is used with a user MAC address. 413758324dfcSspeer * But the slot could be used by factory MAC again after calling 413858324dfcSspeer * nxge_m_mmac_remove and nxge_m_mmac_reserve. 413958324dfcSspeer */ 414058324dfcSspeer if (mmac_info->num_factory_mmac < mmac_info->num_mmac) { 414158324dfcSspeer for (slot = mmac_info->num_factory_mmac + 1; 41424045d941Ssowmini slot <= mmac_info->num_mmac; slot++) { 414358324dfcSspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 414458324dfcSspeer break; 414558324dfcSspeer } 414658324dfcSspeer if (slot > mmac_info->num_mmac) { 414758324dfcSspeer for (slot = 1; slot <= mmac_info->num_factory_mmac; 41484045d941Ssowmini slot++) { 414958324dfcSspeer if (!(mmac_info->mac_pool[slot].flags 41504045d941Ssowmini & MMAC_SLOT_USED)) 415158324dfcSspeer break; 415258324dfcSspeer } 415358324dfcSspeer } 415458324dfcSspeer } else { 415558324dfcSspeer for (slot = 1; slot <= mmac_info->num_mmac; slot++) { 415658324dfcSspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 415758324dfcSspeer break; 415858324dfcSspeer } 415958324dfcSspeer } 416058324dfcSspeer ASSERT(slot <= mmac_info->num_mmac); 416158324dfcSspeer if ((err = nxge_altmac_set(nxgep, maddr->mma_addr, slot)) != 0) { 416258324dfcSspeer mutex_exit(nxgep->genlock); 416358324dfcSspeer return (err); 416458324dfcSspeer } 416558324dfcSspeer bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr, ETHERADDRL); 416658324dfcSspeer mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED; 416758324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR; 416858324dfcSspeer mmac_info->naddrfree--; 416958324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 417058324dfcSspeer 417158324dfcSspeer maddr->mma_slot = slot; 417258324dfcSspeer 417358324dfcSspeer mutex_exit(nxgep->genlock); 417458324dfcSspeer return (0); 417558324dfcSspeer } 417658324dfcSspeer 417758324dfcSspeer /* 417858324dfcSspeer * This function reserves an unused slot and programs the slot and the HW 417958324dfcSspeer * with a factory mac address. 418058324dfcSspeer */ 418158324dfcSspeer static int 418258324dfcSspeer nxge_m_mmac_reserve(void *arg, mac_multi_addr_t *maddr) 418358324dfcSspeer { 418458324dfcSspeer p_nxge_t nxgep = arg; 418558324dfcSspeer mac_addr_slot_t slot; 418658324dfcSspeer nxge_mmac_t *mmac_info; 418758324dfcSspeer int err; 418858324dfcSspeer nxge_status_t status; 418958324dfcSspeer 419058324dfcSspeer mutex_enter(nxgep->genlock); 419158324dfcSspeer 419258324dfcSspeer /* 419358324dfcSspeer * Make sure that nxge is initialized, if _start() has 419458324dfcSspeer * not been called. 419558324dfcSspeer */ 419658324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 419758324dfcSspeer status = nxge_init(nxgep); 419858324dfcSspeer if (status != NXGE_OK) { 419958324dfcSspeer mutex_exit(nxgep->genlock); 420058324dfcSspeer return (ENXIO); 420158324dfcSspeer } 420258324dfcSspeer } 420358324dfcSspeer 420458324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 420558324dfcSspeer if (mmac_info->naddrfree == 0) { 420658324dfcSspeer mutex_exit(nxgep->genlock); 420758324dfcSspeer return (ENOSPC); 420858324dfcSspeer } 420958324dfcSspeer 421058324dfcSspeer slot = maddr->mma_slot; 421158324dfcSspeer if (slot == -1) { /* -1: Take the first available slot */ 421258324dfcSspeer for (slot = 1; slot <= mmac_info->num_factory_mmac; slot++) { 421358324dfcSspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 421458324dfcSspeer break; 421558324dfcSspeer } 421658324dfcSspeer if (slot > mmac_info->num_factory_mmac) { 421758324dfcSspeer mutex_exit(nxgep->genlock); 421858324dfcSspeer return (ENOSPC); 421958324dfcSspeer } 422058324dfcSspeer } 422158324dfcSspeer if (slot < 1 || slot > mmac_info->num_factory_mmac) { 422258324dfcSspeer /* 422358324dfcSspeer * Do not support factory MAC at a slot greater than 422458324dfcSspeer * num_factory_mmac even when there are available factory 422558324dfcSspeer * MAC addresses because the alternate MACs are bundled with 422658324dfcSspeer * slot[1] through slot[num_factory_mmac] 422758324dfcSspeer */ 422858324dfcSspeer mutex_exit(nxgep->genlock); 422958324dfcSspeer return (EINVAL); 423058324dfcSspeer } 423158324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 423258324dfcSspeer mutex_exit(nxgep->genlock); 423358324dfcSspeer return (EBUSY); 423458324dfcSspeer } 423558324dfcSspeer /* Verify the address to be reserved */ 423658324dfcSspeer if (!mac_unicst_verify(nxgep->mach, 42374045d941Ssowmini mmac_info->factory_mac_pool[slot], ETHERADDRL)) { 423858324dfcSspeer mutex_exit(nxgep->genlock); 423958324dfcSspeer return (EINVAL); 424058324dfcSspeer } 424158324dfcSspeer if (err = nxge_altmac_set(nxgep, 42424045d941Ssowmini mmac_info->factory_mac_pool[slot], slot)) { 424358324dfcSspeer mutex_exit(nxgep->genlock); 424458324dfcSspeer return (err); 424558324dfcSspeer } 424658324dfcSspeer bcopy(mmac_info->factory_mac_pool[slot], maddr->mma_addr, ETHERADDRL); 424758324dfcSspeer mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED | MMAC_VENDOR_ADDR; 424858324dfcSspeer mmac_info->naddrfree--; 424958324dfcSspeer 425058324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_TRUE); 425158324dfcSspeer mutex_exit(nxgep->genlock); 425258324dfcSspeer 425358324dfcSspeer /* Pass info back to the caller */ 425458324dfcSspeer maddr->mma_slot = slot; 425558324dfcSspeer maddr->mma_addrlen = ETHERADDRL; 425658324dfcSspeer maddr->mma_flags = MMAC_SLOT_USED | MMAC_VENDOR_ADDR; 425758324dfcSspeer 425858324dfcSspeer return (0); 425958324dfcSspeer } 426058324dfcSspeer 426158324dfcSspeer /* 426258324dfcSspeer * Remove the specified mac address and update the HW not to filter 426358324dfcSspeer * the mac address anymore. 426458324dfcSspeer */ 4265678453a8Sspeer int 426658324dfcSspeer nxge_m_mmac_remove(void *arg, mac_addr_slot_t slot) 426758324dfcSspeer { 426858324dfcSspeer p_nxge_t nxgep = arg; 426958324dfcSspeer nxge_mmac_t *mmac_info; 427058324dfcSspeer uint8_t addrn; 427158324dfcSspeer uint8_t portn; 427258324dfcSspeer int err = 0; 427358324dfcSspeer nxge_status_t status; 427458324dfcSspeer 427558324dfcSspeer mutex_enter(nxgep->genlock); 427658324dfcSspeer 427758324dfcSspeer /* 427858324dfcSspeer * Make sure that nxge is initialized, if _start() has 427958324dfcSspeer * not been called. 428058324dfcSspeer */ 428158324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 428258324dfcSspeer status = nxge_init(nxgep); 428358324dfcSspeer if (status != NXGE_OK) { 428458324dfcSspeer mutex_exit(nxgep->genlock); 428558324dfcSspeer return (ENXIO); 428658324dfcSspeer } 428758324dfcSspeer } 428858324dfcSspeer 428958324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 429058324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 429158324dfcSspeer mutex_exit(nxgep->genlock); 429258324dfcSspeer return (EINVAL); 429358324dfcSspeer } 429458324dfcSspeer 429558324dfcSspeer portn = nxgep->mac.portnum; 429658324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 429758324dfcSspeer addrn = (uint8_t)slot - 1; 429858324dfcSspeer else 429958324dfcSspeer addrn = (uint8_t)slot; 430058324dfcSspeer 430158324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 430258324dfcSspeer if (npi_mac_altaddr_disable(nxgep->npi_handle, portn, addrn) 43034045d941Ssowmini == NPI_SUCCESS) { 430458324dfcSspeer mmac_info->naddrfree++; 430558324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_SLOT_USED; 430658324dfcSspeer /* 430758324dfcSspeer * Regardless if the MAC we just stopped filtering 430858324dfcSspeer * is a user addr or a facory addr, we must set 430958324dfcSspeer * the MMAC_VENDOR_ADDR flag if this slot has an 431058324dfcSspeer * associated factory MAC to indicate that a factory 431158324dfcSspeer * MAC is available. 431258324dfcSspeer */ 431358324dfcSspeer if (slot <= mmac_info->num_factory_mmac) { 431458324dfcSspeer mmac_info->mac_pool[slot].flags 43154045d941Ssowmini |= MMAC_VENDOR_ADDR; 431658324dfcSspeer } 431758324dfcSspeer /* 431858324dfcSspeer * Clear mac_pool[slot].addr so that kstat shows 0 431958324dfcSspeer * alternate MAC address if the slot is not used. 432058324dfcSspeer * (But nxge_m_mmac_get returns the factory MAC even 432158324dfcSspeer * when the slot is not used!) 432258324dfcSspeer */ 432358324dfcSspeer bzero(mmac_info->mac_pool[slot].addr, ETHERADDRL); 432458324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 432558324dfcSspeer } else { 432658324dfcSspeer err = EIO; 432758324dfcSspeer } 432858324dfcSspeer } else { 432958324dfcSspeer err = EINVAL; 433058324dfcSspeer } 433158324dfcSspeer 433258324dfcSspeer mutex_exit(nxgep->genlock); 433358324dfcSspeer return (err); 433458324dfcSspeer } 433558324dfcSspeer 433658324dfcSspeer /* 433758324dfcSspeer * Modify a mac address added by nxge_m_mmac_add or nxge_m_mmac_reserve(). 433858324dfcSspeer */ 433958324dfcSspeer static int 434058324dfcSspeer nxge_m_mmac_modify(void *arg, mac_multi_addr_t *maddr) 434158324dfcSspeer { 434258324dfcSspeer p_nxge_t nxgep = arg; 434358324dfcSspeer mac_addr_slot_t slot; 434458324dfcSspeer nxge_mmac_t *mmac_info; 434558324dfcSspeer int err = 0; 434658324dfcSspeer nxge_status_t status; 434758324dfcSspeer 434858324dfcSspeer if (!mac_unicst_verify(nxgep->mach, maddr->mma_addr, 43494045d941Ssowmini maddr->mma_addrlen)) 435058324dfcSspeer return (EINVAL); 435158324dfcSspeer 435258324dfcSspeer slot = maddr->mma_slot; 435358324dfcSspeer 435458324dfcSspeer mutex_enter(nxgep->genlock); 435558324dfcSspeer 435658324dfcSspeer /* 435758324dfcSspeer * Make sure that nxge is initialized, if _start() has 435858324dfcSspeer * not been called. 435958324dfcSspeer */ 436058324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 436158324dfcSspeer status = nxge_init(nxgep); 436258324dfcSspeer if (status != NXGE_OK) { 436358324dfcSspeer mutex_exit(nxgep->genlock); 436458324dfcSspeer return (ENXIO); 436558324dfcSspeer } 436658324dfcSspeer } 436758324dfcSspeer 436858324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 436958324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 437058324dfcSspeer mutex_exit(nxgep->genlock); 437158324dfcSspeer return (EINVAL); 437258324dfcSspeer } 437358324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 437458324dfcSspeer if ((err = nxge_altmac_set(nxgep, maddr->mma_addr, slot)) 43754045d941Ssowmini != 0) { 437658324dfcSspeer bcopy(maddr->mma_addr, mmac_info->mac_pool[slot].addr, 43774045d941Ssowmini ETHERADDRL); 437858324dfcSspeer /* 437958324dfcSspeer * Assume that the MAC passed down from the caller 438058324dfcSspeer * is not a factory MAC address (The user should 438158324dfcSspeer * call mmac_remove followed by mmac_reserve if 438258324dfcSspeer * he wants to use the factory MAC for this slot). 438358324dfcSspeer */ 438458324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR; 438558324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 438658324dfcSspeer } 438758324dfcSspeer } else { 438858324dfcSspeer err = EINVAL; 438958324dfcSspeer } 439058324dfcSspeer mutex_exit(nxgep->genlock); 439158324dfcSspeer return (err); 439258324dfcSspeer } 439358324dfcSspeer 439458324dfcSspeer /* 439558324dfcSspeer * nxge_m_mmac_get() - Get the MAC address and other information 439658324dfcSspeer * related to the slot. mma_flags should be set to 0 in the call. 439758324dfcSspeer * Note: although kstat shows MAC address as zero when a slot is 439858324dfcSspeer * not used, Crossbow expects nxge_m_mmac_get to copy factory MAC 439958324dfcSspeer * to the caller as long as the slot is not using a user MAC address. 440058324dfcSspeer * The following table shows the rules, 440158324dfcSspeer * 440258324dfcSspeer * USED VENDOR mma_addr 440358324dfcSspeer * ------------------------------------------------------------ 440458324dfcSspeer * (1) Slot uses a user MAC: yes no user MAC 440558324dfcSspeer * (2) Slot uses a factory MAC: yes yes factory MAC 440658324dfcSspeer * (3) Slot is not used but is 440758324dfcSspeer * factory MAC capable: no yes factory MAC 440858324dfcSspeer * (4) Slot is not used and is 440958324dfcSspeer * not factory MAC capable: no no 0 441058324dfcSspeer * ------------------------------------------------------------ 441158324dfcSspeer */ 441258324dfcSspeer static int 441358324dfcSspeer nxge_m_mmac_get(void *arg, mac_multi_addr_t *maddr) 441458324dfcSspeer { 441558324dfcSspeer nxge_t *nxgep = arg; 441658324dfcSspeer mac_addr_slot_t slot; 441758324dfcSspeer nxge_mmac_t *mmac_info; 441858324dfcSspeer nxge_status_t status; 441958324dfcSspeer 442058324dfcSspeer slot = maddr->mma_slot; 442158324dfcSspeer 442258324dfcSspeer mutex_enter(nxgep->genlock); 442358324dfcSspeer 442458324dfcSspeer /* 442558324dfcSspeer * Make sure that nxge is initialized, if _start() has 442658324dfcSspeer * not been called. 442758324dfcSspeer */ 442858324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 442958324dfcSspeer status = nxge_init(nxgep); 443058324dfcSspeer if (status != NXGE_OK) { 443158324dfcSspeer mutex_exit(nxgep->genlock); 443258324dfcSspeer return (ENXIO); 443358324dfcSspeer } 443458324dfcSspeer } 443558324dfcSspeer 443658324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 443758324dfcSspeer 443858324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 443958324dfcSspeer mutex_exit(nxgep->genlock); 444058324dfcSspeer return (EINVAL); 444158324dfcSspeer } 444258324dfcSspeer maddr->mma_flags = 0; 444358324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) 444458324dfcSspeer maddr->mma_flags |= MMAC_SLOT_USED; 444558324dfcSspeer 444658324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_VENDOR_ADDR) { 444758324dfcSspeer maddr->mma_flags |= MMAC_VENDOR_ADDR; 444858324dfcSspeer bcopy(mmac_info->factory_mac_pool[slot], 44494045d941Ssowmini maddr->mma_addr, ETHERADDRL); 445058324dfcSspeer maddr->mma_addrlen = ETHERADDRL; 445158324dfcSspeer } else { 445258324dfcSspeer if (maddr->mma_flags & MMAC_SLOT_USED) { 445358324dfcSspeer bcopy(mmac_info->mac_pool[slot].addr, 44544045d941Ssowmini maddr->mma_addr, ETHERADDRL); 445558324dfcSspeer maddr->mma_addrlen = ETHERADDRL; 445658324dfcSspeer } else { 445758324dfcSspeer bzero(maddr->mma_addr, ETHERADDRL); 445858324dfcSspeer maddr->mma_addrlen = 0; 445958324dfcSspeer } 446058324dfcSspeer } 446158324dfcSspeer mutex_exit(nxgep->genlock); 446258324dfcSspeer return (0); 446358324dfcSspeer } 446458324dfcSspeer 446544961713Sgirish static boolean_t 446644961713Sgirish nxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 446744961713Sgirish { 446858324dfcSspeer nxge_t *nxgep = arg; 446958324dfcSspeer uint32_t *txflags = cap_data; 447058324dfcSspeer multiaddress_capab_t *mmacp = cap_data; 447144961713Sgirish 447258324dfcSspeer switch (cap) { 447358324dfcSspeer case MAC_CAPAB_HCKSUM: 4474678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4475b4d05839Sml "==> nxge_m_getcapab: checksum %d", nxge_cksum_offload)); 4476b4d05839Sml if (nxge_cksum_offload <= 1) { 4477678453a8Sspeer *txflags = HCKSUM_INET_PARTIAL; 4478678453a8Sspeer } 447944961713Sgirish break; 4480678453a8Sspeer 448144961713Sgirish case MAC_CAPAB_POLL: 448244961713Sgirish /* 448344961713Sgirish * There's nothing for us to fill in, simply returning 448444961713Sgirish * B_TRUE stating that we support polling is sufficient. 448544961713Sgirish */ 448644961713Sgirish break; 448744961713Sgirish 448858324dfcSspeer case MAC_CAPAB_MULTIADDRESS: 4489678453a8Sspeer mmacp = (multiaddress_capab_t *)cap_data; 449058324dfcSspeer mutex_enter(nxgep->genlock); 449158324dfcSspeer 449258324dfcSspeer mmacp->maddr_naddr = nxgep->nxge_mmac_info.num_mmac; 449358324dfcSspeer mmacp->maddr_naddrfree = nxgep->nxge_mmac_info.naddrfree; 4494b4d05839Sml mmacp->maddr_flag = 0; /* 0 is required by PSARC2006/265 */ 449558324dfcSspeer /* 449658324dfcSspeer * maddr_handle is driver's private data, passed back to 449758324dfcSspeer * entry point functions as arg. 449858324dfcSspeer */ 449958324dfcSspeer mmacp->maddr_handle = nxgep; 450058324dfcSspeer mmacp->maddr_add = nxge_m_mmac_add; 450158324dfcSspeer mmacp->maddr_remove = nxge_m_mmac_remove; 450258324dfcSspeer mmacp->maddr_modify = nxge_m_mmac_modify; 450358324dfcSspeer mmacp->maddr_get = nxge_m_mmac_get; 450458324dfcSspeer mmacp->maddr_reserve = nxge_m_mmac_reserve; 450558324dfcSspeer 450658324dfcSspeer mutex_exit(nxgep->genlock); 450758324dfcSspeer break; 4508678453a8Sspeer 450930ac2e7bSml case MAC_CAPAB_LSO: { 451030ac2e7bSml mac_capab_lso_t *cap_lso = cap_data; 451130ac2e7bSml 45123d16f8e7Sml if (nxgep->soft_lso_enable) { 4513b4d05839Sml if (nxge_cksum_offload <= 1) { 4514b4d05839Sml cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 4515b4d05839Sml if (nxge_lso_max > NXGE_LSO_MAXLEN) { 4516b4d05839Sml nxge_lso_max = NXGE_LSO_MAXLEN; 4517b4d05839Sml } 4518b4d05839Sml cap_lso->lso_basic_tcp_ipv4.lso_max = 4519b4d05839Sml nxge_lso_max; 452030ac2e7bSml } 452130ac2e7bSml break; 452230ac2e7bSml } else { 452330ac2e7bSml return (B_FALSE); 452430ac2e7bSml } 452530ac2e7bSml } 452630ac2e7bSml 4527678453a8Sspeer #if defined(sun4v) 4528678453a8Sspeer case MAC_CAPAB_RINGS: { 4529678453a8Sspeer mac_capab_rings_t *mrings = (mac_capab_rings_t *)cap_data; 4530678453a8Sspeer 4531678453a8Sspeer /* 4532678453a8Sspeer * Only the service domain driver responds to 4533678453a8Sspeer * this capability request. 4534678453a8Sspeer */ 4535678453a8Sspeer if (isLDOMservice(nxgep)) { 4536678453a8Sspeer mrings->mr_handle = (void *)nxgep; 4537678453a8Sspeer 4538678453a8Sspeer /* 4539678453a8Sspeer * No dynamic allocation of groups and 4540678453a8Sspeer * rings at this time. Shares dictate the 45416f157acbSml * configuration. 4542678453a8Sspeer */ 4543678453a8Sspeer mrings->mr_gadd_ring = NULL; 4544678453a8Sspeer mrings->mr_grem_ring = NULL; 4545678453a8Sspeer mrings->mr_rget = NULL; 4546678453a8Sspeer mrings->mr_gget = nxge_hio_group_get; 4547678453a8Sspeer 4548678453a8Sspeer if (mrings->mr_type == MAC_RING_TYPE_RX) { 4549678453a8Sspeer mrings->mr_rnum = 8; /* XXX */ 4550678453a8Sspeer mrings->mr_gnum = 6; /* XXX */ 4551678453a8Sspeer } else { 4552678453a8Sspeer mrings->mr_rnum = 8; /* XXX */ 4553678453a8Sspeer mrings->mr_gnum = 0; /* XXX */ 4554678453a8Sspeer } 4555678453a8Sspeer } else 4556678453a8Sspeer return (B_FALSE); 4557678453a8Sspeer break; 4558678453a8Sspeer } 4559678453a8Sspeer 4560678453a8Sspeer case MAC_CAPAB_SHARES: { 4561678453a8Sspeer mac_capab_share_t *mshares = (mac_capab_share_t *)cap_data; 4562678453a8Sspeer 4563678453a8Sspeer /* 4564678453a8Sspeer * Only the service domain driver responds to 4565678453a8Sspeer * this capability request. 4566678453a8Sspeer */ 4567678453a8Sspeer if (isLDOMservice(nxgep)) { 4568678453a8Sspeer mshares->ms_snum = 3; 4569678453a8Sspeer mshares->ms_handle = (void *)nxgep; 4570678453a8Sspeer mshares->ms_salloc = nxge_hio_share_alloc; 4571678453a8Sspeer mshares->ms_sfree = nxge_hio_share_free; 4572678453a8Sspeer mshares->ms_sadd = NULL; 4573678453a8Sspeer mshares->ms_sremove = NULL; 4574678453a8Sspeer mshares->ms_squery = nxge_hio_share_query; 4575678453a8Sspeer } else 4576678453a8Sspeer return (B_FALSE); 4577678453a8Sspeer break; 4578678453a8Sspeer } 4579678453a8Sspeer #endif 458044961713Sgirish default: 458144961713Sgirish return (B_FALSE); 458244961713Sgirish } 458344961713Sgirish return (B_TRUE); 458444961713Sgirish } 458544961713Sgirish 45861bd6825cSml static boolean_t 45871bd6825cSml nxge_param_locked(mac_prop_id_t pr_num) 45881bd6825cSml { 45891bd6825cSml /* 45901bd6825cSml * All adv_* parameters are locked (read-only) while 45911bd6825cSml * the device is in any sort of loopback mode ... 45921bd6825cSml */ 45931bd6825cSml switch (pr_num) { 45943fd94f8cSam case MAC_PROP_ADV_1000FDX_CAP: 45953fd94f8cSam case MAC_PROP_EN_1000FDX_CAP: 45963fd94f8cSam case MAC_PROP_ADV_1000HDX_CAP: 45973fd94f8cSam case MAC_PROP_EN_1000HDX_CAP: 45983fd94f8cSam case MAC_PROP_ADV_100FDX_CAP: 45993fd94f8cSam case MAC_PROP_EN_100FDX_CAP: 46003fd94f8cSam case MAC_PROP_ADV_100HDX_CAP: 46013fd94f8cSam case MAC_PROP_EN_100HDX_CAP: 46023fd94f8cSam case MAC_PROP_ADV_10FDX_CAP: 46033fd94f8cSam case MAC_PROP_EN_10FDX_CAP: 46043fd94f8cSam case MAC_PROP_ADV_10HDX_CAP: 46053fd94f8cSam case MAC_PROP_EN_10HDX_CAP: 46063fd94f8cSam case MAC_PROP_AUTONEG: 46073fd94f8cSam case MAC_PROP_FLOWCTRL: 46081bd6825cSml return (B_TRUE); 46091bd6825cSml } 46101bd6825cSml return (B_FALSE); 46111bd6825cSml } 46121bd6825cSml 46131bd6825cSml /* 46141bd6825cSml * callback functions for set/get of properties 46151bd6825cSml */ 46161bd6825cSml static int 46171bd6825cSml nxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 46181bd6825cSml uint_t pr_valsize, const void *pr_val) 46191bd6825cSml { 46201bd6825cSml nxge_t *nxgep = barg; 46211bd6825cSml p_nxge_param_t param_arr; 46221bd6825cSml p_nxge_stats_t statsp; 46231bd6825cSml int err = 0; 46241bd6825cSml uint8_t val; 46251bd6825cSml uint32_t cur_mtu, new_mtu, old_framesize; 46261bd6825cSml link_flowctrl_t fl; 46271bd6825cSml 46281bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_setprop")); 46291bd6825cSml param_arr = nxgep->param_arr; 46301bd6825cSml statsp = nxgep->statsp; 46311bd6825cSml mutex_enter(nxgep->genlock); 46321bd6825cSml if (statsp->port_stats.lb_mode != nxge_lb_normal && 46331bd6825cSml nxge_param_locked(pr_num)) { 46341bd6825cSml /* 46351bd6825cSml * All adv_* parameters are locked (read-only) 46361bd6825cSml * while the device is in any sort of loopback mode. 46371bd6825cSml */ 46381bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46391bd6825cSml "==> nxge_m_setprop: loopback mode: read only")); 46401bd6825cSml mutex_exit(nxgep->genlock); 46411bd6825cSml return (EBUSY); 46421bd6825cSml } 46431bd6825cSml 46441bd6825cSml val = *(uint8_t *)pr_val; 46451bd6825cSml switch (pr_num) { 46463fd94f8cSam case MAC_PROP_EN_1000FDX_CAP: 46471bd6825cSml nxgep->param_en_1000fdx = val; 46481bd6825cSml param_arr[param_anar_1000fdx].value = val; 46491bd6825cSml 46501bd6825cSml goto reprogram; 46511bd6825cSml 46523fd94f8cSam case MAC_PROP_EN_100FDX_CAP: 46531bd6825cSml nxgep->param_en_100fdx = val; 46541bd6825cSml param_arr[param_anar_100fdx].value = val; 46551bd6825cSml 46561bd6825cSml goto reprogram; 46571bd6825cSml 46583fd94f8cSam case MAC_PROP_EN_10FDX_CAP: 46591bd6825cSml nxgep->param_en_10fdx = val; 46601bd6825cSml param_arr[param_anar_10fdx].value = val; 46611bd6825cSml 46621bd6825cSml goto reprogram; 46631bd6825cSml 46643fd94f8cSam case MAC_PROP_EN_1000HDX_CAP: 46653fd94f8cSam case MAC_PROP_EN_100HDX_CAP: 46663fd94f8cSam case MAC_PROP_EN_10HDX_CAP: 46673fd94f8cSam case MAC_PROP_ADV_1000FDX_CAP: 46683fd94f8cSam case MAC_PROP_ADV_1000HDX_CAP: 46693fd94f8cSam case MAC_PROP_ADV_100FDX_CAP: 46703fd94f8cSam case MAC_PROP_ADV_100HDX_CAP: 46713fd94f8cSam case MAC_PROP_ADV_10FDX_CAP: 46723fd94f8cSam case MAC_PROP_ADV_10HDX_CAP: 46733fd94f8cSam case MAC_PROP_STATUS: 46743fd94f8cSam case MAC_PROP_SPEED: 46753fd94f8cSam case MAC_PROP_DUPLEX: 46761bd6825cSml err = EINVAL; /* cannot set read-only properties */ 46771bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46781bd6825cSml "==> nxge_m_setprop: read only property %d", 46791bd6825cSml pr_num)); 46801bd6825cSml break; 46811bd6825cSml 46823fd94f8cSam case MAC_PROP_AUTONEG: 46831bd6825cSml param_arr[param_autoneg].value = val; 46841bd6825cSml 46851bd6825cSml goto reprogram; 46861bd6825cSml 46873fd94f8cSam case MAC_PROP_MTU: 46881bd6825cSml if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 46891bd6825cSml err = EBUSY; 46901bd6825cSml break; 46911bd6825cSml } 46921bd6825cSml 46931bd6825cSml cur_mtu = nxgep->mac.default_mtu; 46941bd6825cSml bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 46951bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46961bd6825cSml "==> nxge_m_setprop: set MTU: %d is_jumbo %d", 46971bd6825cSml new_mtu, nxgep->mac.is_jumbo)); 46981bd6825cSml 46991bd6825cSml if (new_mtu == cur_mtu) { 47001bd6825cSml err = 0; 47011bd6825cSml break; 47021bd6825cSml } 47031bd6825cSml if (new_mtu < NXGE_DEFAULT_MTU || 47041bd6825cSml new_mtu > NXGE_MAXIMUM_MTU) { 47051bd6825cSml err = EINVAL; 47061bd6825cSml break; 47071bd6825cSml } 47081bd6825cSml 47091bd6825cSml if ((new_mtu > NXGE_DEFAULT_MTU) && 47101bd6825cSml !nxgep->mac.is_jumbo) { 47111bd6825cSml err = EINVAL; 47121bd6825cSml break; 47131bd6825cSml } 47141bd6825cSml 47151bd6825cSml old_framesize = (uint32_t)nxgep->mac.maxframesize; 47161bd6825cSml nxgep->mac.maxframesize = (uint16_t) 47171bd6825cSml (new_mtu + NXGE_EHEADER_VLAN_CRC); 47181bd6825cSml if (nxge_mac_set_framesize(nxgep)) { 4719c2d37b8bSml nxgep->mac.maxframesize = 4720c2d37b8bSml (uint16_t)old_framesize; 47211bd6825cSml err = EINVAL; 47221bd6825cSml break; 47231bd6825cSml } 47241bd6825cSml 47251bd6825cSml err = mac_maxsdu_update(nxgep->mach, new_mtu); 47261bd6825cSml if (err) { 4727c2d37b8bSml nxgep->mac.maxframesize = 4728c2d37b8bSml (uint16_t)old_framesize; 47291bd6825cSml err = EINVAL; 47301bd6825cSml break; 47311bd6825cSml } 47321bd6825cSml 47331bd6825cSml nxgep->mac.default_mtu = new_mtu; 47341bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47351bd6825cSml "==> nxge_m_setprop: set MTU: %d maxframe %d", 47361bd6825cSml new_mtu, nxgep->mac.maxframesize)); 47371bd6825cSml break; 47381bd6825cSml 47393fd94f8cSam case MAC_PROP_FLOWCTRL: 47401bd6825cSml bcopy(pr_val, &fl, sizeof (fl)); 47411bd6825cSml switch (fl) { 47421bd6825cSml default: 47431bd6825cSml err = EINVAL; 47441bd6825cSml break; 47451bd6825cSml 47461bd6825cSml case LINK_FLOWCTRL_NONE: 47471bd6825cSml param_arr[param_anar_pause].value = 0; 47481bd6825cSml break; 47491bd6825cSml 47501bd6825cSml case LINK_FLOWCTRL_RX: 47511bd6825cSml param_arr[param_anar_pause].value = 1; 47521bd6825cSml break; 47531bd6825cSml 47541bd6825cSml case LINK_FLOWCTRL_TX: 47551bd6825cSml case LINK_FLOWCTRL_BI: 47561bd6825cSml err = EINVAL; 47571bd6825cSml break; 47581bd6825cSml } 47591bd6825cSml 47601bd6825cSml reprogram: 47611bd6825cSml if (err == 0) { 47621bd6825cSml if (!nxge_param_link_update(nxgep)) { 47631bd6825cSml err = EINVAL; 47641bd6825cSml } 47651bd6825cSml } 47661bd6825cSml break; 47673fd94f8cSam case MAC_PROP_PRIVATE: 47681bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47691bd6825cSml "==> nxge_m_setprop: private property")); 47701bd6825cSml err = nxge_set_priv_prop(nxgep, pr_name, pr_valsize, 47711bd6825cSml pr_val); 47721bd6825cSml break; 47734045d941Ssowmini 47744045d941Ssowmini default: 47754045d941Ssowmini err = ENOTSUP; 47764045d941Ssowmini break; 47771bd6825cSml } 47781bd6825cSml 47791bd6825cSml mutex_exit(nxgep->genlock); 47801bd6825cSml 47811bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47821bd6825cSml "<== nxge_m_setprop (return %d)", err)); 47831bd6825cSml return (err); 47841bd6825cSml } 47851bd6825cSml 47861bd6825cSml static int 47871bd6825cSml nxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 47884045d941Ssowmini uint_t pr_flags, uint_t pr_valsize, void *pr_val) 47891bd6825cSml { 47901bd6825cSml nxge_t *nxgep = barg; 47911bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 47921bd6825cSml p_nxge_stats_t statsp = nxgep->statsp; 47931bd6825cSml int err = 0; 47941bd6825cSml link_flowctrl_t fl; 47951bd6825cSml uint64_t tmp = 0; 47964045d941Ssowmini link_state_t ls; 47973fd94f8cSam boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT); 47981bd6825cSml 47991bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48001bd6825cSml "==> nxge_m_getprop: pr_num %d", pr_num)); 48014045d941Ssowmini 48024045d941Ssowmini if (pr_valsize == 0) 48034045d941Ssowmini return (EINVAL); 48044045d941Ssowmini 48053fd94f8cSam if ((is_default) && (pr_num != MAC_PROP_PRIVATE)) { 48064045d941Ssowmini err = nxge_get_def_val(nxgep, pr_num, pr_valsize, pr_val); 48074045d941Ssowmini return (err); 48084045d941Ssowmini } 48094045d941Ssowmini 48101bd6825cSml bzero(pr_val, pr_valsize); 48111bd6825cSml switch (pr_num) { 48123fd94f8cSam case MAC_PROP_DUPLEX: 48131bd6825cSml *(uint8_t *)pr_val = statsp->mac_stats.link_duplex; 48141bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48151bd6825cSml "==> nxge_m_getprop: duplex mode %d", 48161bd6825cSml *(uint8_t *)pr_val)); 48171bd6825cSml break; 48181bd6825cSml 48193fd94f8cSam case MAC_PROP_SPEED: 48201bd6825cSml if (pr_valsize < sizeof (uint64_t)) 48211bd6825cSml return (EINVAL); 48221bd6825cSml tmp = statsp->mac_stats.link_speed * 1000000ull; 48231bd6825cSml bcopy(&tmp, pr_val, sizeof (tmp)); 48241bd6825cSml break; 48251bd6825cSml 48263fd94f8cSam case MAC_PROP_STATUS: 48274045d941Ssowmini if (pr_valsize < sizeof (link_state_t)) 48281bd6825cSml return (EINVAL); 48294045d941Ssowmini if (!statsp->mac_stats.link_up) 48304045d941Ssowmini ls = LINK_STATE_DOWN; 48314045d941Ssowmini else 48324045d941Ssowmini ls = LINK_STATE_UP; 48334045d941Ssowmini bcopy(&ls, pr_val, sizeof (ls)); 48341bd6825cSml break; 48351bd6825cSml 48363fd94f8cSam case MAC_PROP_AUTONEG: 48371bd6825cSml *(uint8_t *)pr_val = 48381bd6825cSml param_arr[param_autoneg].value; 48391bd6825cSml break; 48401bd6825cSml 48413fd94f8cSam case MAC_PROP_FLOWCTRL: 48421bd6825cSml if (pr_valsize < sizeof (link_flowctrl_t)) 48431bd6825cSml return (EINVAL); 48441bd6825cSml 48451bd6825cSml fl = LINK_FLOWCTRL_NONE; 48461bd6825cSml if (param_arr[param_anar_pause].value) { 48471bd6825cSml fl = LINK_FLOWCTRL_RX; 48481bd6825cSml } 48491bd6825cSml bcopy(&fl, pr_val, sizeof (fl)); 48501bd6825cSml break; 48511bd6825cSml 48523fd94f8cSam case MAC_PROP_ADV_1000FDX_CAP: 48531bd6825cSml *(uint8_t *)pr_val = 48541bd6825cSml param_arr[param_anar_1000fdx].value; 48551bd6825cSml break; 48561bd6825cSml 48573fd94f8cSam case MAC_PROP_EN_1000FDX_CAP: 48581bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_1000fdx; 48591bd6825cSml break; 48601bd6825cSml 48613fd94f8cSam case MAC_PROP_ADV_100FDX_CAP: 48621bd6825cSml *(uint8_t *)pr_val = 48631bd6825cSml param_arr[param_anar_100fdx].value; 48641bd6825cSml break; 48651bd6825cSml 48663fd94f8cSam case MAC_PROP_EN_100FDX_CAP: 48671bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_100fdx; 48681bd6825cSml break; 48691bd6825cSml 48703fd94f8cSam case MAC_PROP_ADV_10FDX_CAP: 48711bd6825cSml *(uint8_t *)pr_val = 48721bd6825cSml param_arr[param_anar_10fdx].value; 48731bd6825cSml break; 48741bd6825cSml 48753fd94f8cSam case MAC_PROP_EN_10FDX_CAP: 48761bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_10fdx; 48771bd6825cSml break; 48781bd6825cSml 48793fd94f8cSam case MAC_PROP_EN_1000HDX_CAP: 48803fd94f8cSam case MAC_PROP_EN_100HDX_CAP: 48813fd94f8cSam case MAC_PROP_EN_10HDX_CAP: 48823fd94f8cSam case MAC_PROP_ADV_1000HDX_CAP: 48833fd94f8cSam case MAC_PROP_ADV_100HDX_CAP: 48843fd94f8cSam case MAC_PROP_ADV_10HDX_CAP: 48854045d941Ssowmini err = ENOTSUP; 48861bd6825cSml break; 48871bd6825cSml 48883fd94f8cSam case MAC_PROP_PRIVATE: 48894045d941Ssowmini err = nxge_get_priv_prop(nxgep, pr_name, pr_flags, 48904045d941Ssowmini pr_valsize, pr_val); 48914045d941Ssowmini break; 48921bd6825cSml default: 48934045d941Ssowmini err = EINVAL; 48944045d941Ssowmini break; 48951bd6825cSml } 48961bd6825cSml 48971bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_getprop")); 48981bd6825cSml 48991bd6825cSml return (err); 49001bd6825cSml } 49011bd6825cSml 49021bd6825cSml /* ARGSUSED */ 49031bd6825cSml static int 49041bd6825cSml nxge_set_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_valsize, 49051bd6825cSml const void *pr_val) 49061bd6825cSml { 49071bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 49081bd6825cSml int err = 0; 49091bd6825cSml long result; 49101bd6825cSml 49111bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49121bd6825cSml "==> nxge_set_priv_prop: name %s", pr_name)); 49131bd6825cSml 49141bd6825cSml if (strcmp(pr_name, "_accept_jumbo") == 0) { 49151bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49161bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49171bd6825cSml "<== nxge_set_priv_prop: name %s " 49181bd6825cSml "pr_val %s result %d " 49191bd6825cSml "param %d is_jumbo %d", 49201bd6825cSml pr_name, pr_val, result, 49211bd6825cSml param_arr[param_accept_jumbo].value, 49221bd6825cSml nxgep->mac.is_jumbo)); 49231bd6825cSml 49241bd6825cSml if (result > 1 || result < 0) { 49251bd6825cSml err = EINVAL; 49261bd6825cSml } else { 49271bd6825cSml if (nxgep->mac.is_jumbo == 49281bd6825cSml (uint32_t)result) { 49291bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49301bd6825cSml "no change (%d %d)", 49311bd6825cSml nxgep->mac.is_jumbo, 49321bd6825cSml result)); 49331bd6825cSml return (0); 49341bd6825cSml } 49351bd6825cSml } 49361bd6825cSml 49371bd6825cSml param_arr[param_accept_jumbo].value = result; 49381bd6825cSml nxgep->mac.is_jumbo = B_FALSE; 49391bd6825cSml if (result) { 49401bd6825cSml nxgep->mac.is_jumbo = B_TRUE; 49411bd6825cSml } 49421bd6825cSml 49431bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49441bd6825cSml "<== nxge_set_priv_prop: name %s (value %d) is_jumbo %d", 49451bd6825cSml pr_name, result, nxgep->mac.is_jumbo)); 49461bd6825cSml 49471bd6825cSml return (err); 49481bd6825cSml } 49491bd6825cSml 49501bd6825cSml /* Blanking */ 49511bd6825cSml if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 49521bd6825cSml err = nxge_param_rx_intr_time(nxgep, NULL, NULL, 49531bd6825cSml (char *)pr_val, 49541bd6825cSml (caddr_t)¶m_arr[param_rxdma_intr_time]); 49551bd6825cSml if (err) { 49561bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49571bd6825cSml "<== nxge_set_priv_prop: " 49581bd6825cSml "unable to set (%s)", pr_name)); 49591bd6825cSml err = EINVAL; 49601bd6825cSml } else { 49611bd6825cSml err = 0; 49621bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49631bd6825cSml "<== nxge_set_priv_prop: " 49641bd6825cSml "set (%s)", pr_name)); 49651bd6825cSml } 49661bd6825cSml 49671bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49681bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 49691bd6825cSml pr_name, result)); 49701bd6825cSml 49711bd6825cSml return (err); 49721bd6825cSml } 49731bd6825cSml 49741bd6825cSml if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 49751bd6825cSml err = nxge_param_rx_intr_pkts(nxgep, NULL, NULL, 49761bd6825cSml (char *)pr_val, 49771bd6825cSml (caddr_t)¶m_arr[param_rxdma_intr_pkts]); 49781bd6825cSml if (err) { 49791bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49801bd6825cSml "<== nxge_set_priv_prop: " 49811bd6825cSml "unable to set (%s)", pr_name)); 49821bd6825cSml err = EINVAL; 49831bd6825cSml } else { 49841bd6825cSml err = 0; 49851bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49861bd6825cSml "<== nxge_set_priv_prop: " 49871bd6825cSml "set (%s)", pr_name)); 49881bd6825cSml } 49891bd6825cSml 49901bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49911bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 49921bd6825cSml pr_name, result)); 49931bd6825cSml 49941bd6825cSml return (err); 49951bd6825cSml } 49961bd6825cSml 49971bd6825cSml /* Classification */ 49981bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 49991bd6825cSml if (pr_val == NULL) { 50001bd6825cSml err = EINVAL; 50011bd6825cSml return (err); 50021bd6825cSml } 50031bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50041bd6825cSml 50051bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 50061bd6825cSml NULL, (char *)pr_val, 50071bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 50081bd6825cSml 50091bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50101bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 50111bd6825cSml pr_name, result)); 50121bd6825cSml 50131bd6825cSml return (err); 50141bd6825cSml } 50151bd6825cSml 50161bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 50171bd6825cSml if (pr_val == NULL) { 50181bd6825cSml err = EINVAL; 50191bd6825cSml return (err); 50201bd6825cSml } 50211bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50221bd6825cSml 50231bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 50241bd6825cSml NULL, (char *)pr_val, 50251bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 50261bd6825cSml 50271bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50281bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 50291bd6825cSml pr_name, result)); 50301bd6825cSml 50311bd6825cSml return (err); 50321bd6825cSml } 50331bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 50341bd6825cSml if (pr_val == NULL) { 50351bd6825cSml err = EINVAL; 50361bd6825cSml return (err); 50371bd6825cSml } 50381bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50391bd6825cSml 50401bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 50411bd6825cSml NULL, (char *)pr_val, 50421bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 50431bd6825cSml 50441bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50451bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 50461bd6825cSml pr_name, result)); 50471bd6825cSml 50481bd6825cSml return (err); 50491bd6825cSml } 50501bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 50511bd6825cSml if (pr_val == NULL) { 50521bd6825cSml err = EINVAL; 50531bd6825cSml return (err); 50541bd6825cSml } 50551bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50561bd6825cSml 50571bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 50581bd6825cSml NULL, (char *)pr_val, 50591bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 50601bd6825cSml 50611bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50621bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 50631bd6825cSml pr_name, result)); 50641bd6825cSml 50651bd6825cSml return (err); 50661bd6825cSml } 50671bd6825cSml 50681bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 50691bd6825cSml if (pr_val == NULL) { 50701bd6825cSml err = EINVAL; 50711bd6825cSml return (err); 50721bd6825cSml } 50731bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50741bd6825cSml 50751bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 50761bd6825cSml NULL, (char *)pr_val, 50771bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 50781bd6825cSml 50791bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50801bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 50811bd6825cSml pr_name, result)); 50821bd6825cSml 50831bd6825cSml return (err); 50841bd6825cSml } 50851bd6825cSml 50861bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 50871bd6825cSml if (pr_val == NULL) { 50881bd6825cSml err = EINVAL; 50891bd6825cSml return (err); 50901bd6825cSml } 50911bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50921bd6825cSml 50931bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 50941bd6825cSml NULL, (char *)pr_val, 50951bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 50961bd6825cSml 50971bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50981bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 50991bd6825cSml pr_name, result)); 51001bd6825cSml 51011bd6825cSml return (err); 51021bd6825cSml } 51031bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 51041bd6825cSml if (pr_val == NULL) { 51051bd6825cSml err = EINVAL; 51061bd6825cSml return (err); 51071bd6825cSml } 51081bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 51091bd6825cSml 51101bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 51111bd6825cSml NULL, (char *)pr_val, 51121bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 51131bd6825cSml 51141bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51151bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 51161bd6825cSml pr_name, result)); 51171bd6825cSml 51181bd6825cSml return (err); 51191bd6825cSml } 51201bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 51211bd6825cSml if (pr_val == NULL) { 51221bd6825cSml err = EINVAL; 51231bd6825cSml return (err); 51241bd6825cSml } 51251bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 51261bd6825cSml 51271bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 51281bd6825cSml NULL, (char *)pr_val, 51291bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 51301bd6825cSml 51311bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51321bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 51331bd6825cSml pr_name, result)); 51341bd6825cSml 51351bd6825cSml return (err); 51361bd6825cSml } 51371bd6825cSml 51381bd6825cSml if (strcmp(pr_name, "_soft_lso_enable") == 0) { 51391bd6825cSml if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 51401bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51411bd6825cSml "==> nxge_set_priv_prop: name %s (busy)", pr_name)); 51421bd6825cSml err = EBUSY; 51431bd6825cSml return (err); 51441bd6825cSml } 51451bd6825cSml if (pr_val == NULL) { 51461bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51471bd6825cSml "==> nxge_set_priv_prop: name %s (null)", pr_name)); 51481bd6825cSml err = EINVAL; 51491bd6825cSml return (err); 51501bd6825cSml } 51511bd6825cSml 51521bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 51531bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51541bd6825cSml "<== nxge_set_priv_prop: name %s " 51551bd6825cSml "(lso %d pr_val %s value %d)", 51561bd6825cSml pr_name, nxgep->soft_lso_enable, pr_val, result)); 51571bd6825cSml 51581bd6825cSml if (result > 1 || result < 0) { 51591bd6825cSml err = EINVAL; 51601bd6825cSml } else { 51611bd6825cSml if (nxgep->soft_lso_enable == (uint32_t)result) { 51621bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51631bd6825cSml "no change (%d %d)", 51641bd6825cSml nxgep->soft_lso_enable, result)); 51651bd6825cSml return (0); 51661bd6825cSml } 51671bd6825cSml } 51681bd6825cSml 51691bd6825cSml nxgep->soft_lso_enable = (int)result; 51701bd6825cSml 51711bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51721bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 51731bd6825cSml pr_name, result)); 51741bd6825cSml 51751bd6825cSml return (err); 51761bd6825cSml } 517700161856Syc /* 517800161856Syc * Commands like "ndd -set /dev/nxge0 adv_10gfdx_cap 1" cause the 517900161856Syc * following code to be executed. 518000161856Syc */ 51814045d941Ssowmini if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) { 51824045d941Ssowmini err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val, 51834045d941Ssowmini (caddr_t)¶m_arr[param_anar_10gfdx]); 51844045d941Ssowmini return (err); 51854045d941Ssowmini } 51864045d941Ssowmini if (strcmp(pr_name, "_adv_pause_cap") == 0) { 51874045d941Ssowmini err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val, 51884045d941Ssowmini (caddr_t)¶m_arr[param_anar_pause]); 51894045d941Ssowmini return (err); 51904045d941Ssowmini } 51911bd6825cSml 51921bd6825cSml return (EINVAL); 51931bd6825cSml } 51941bd6825cSml 51951bd6825cSml static int 51964045d941Ssowmini nxge_get_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_flags, 51974045d941Ssowmini uint_t pr_valsize, void *pr_val) 51981bd6825cSml { 51991bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 52001bd6825cSml char valstr[MAXNAMELEN]; 52011bd6825cSml int err = EINVAL; 52021bd6825cSml uint_t strsize; 52033fd94f8cSam boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT); 52041bd6825cSml 52051bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52061bd6825cSml "==> nxge_get_priv_prop: property %s", pr_name)); 52071bd6825cSml 52081bd6825cSml /* function number */ 52091bd6825cSml if (strcmp(pr_name, "_function_number") == 0) { 52104045d941Ssowmini if (is_default) 52114045d941Ssowmini return (ENOTSUP); 52124045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 52134045d941Ssowmini nxgep->function_num); 52141bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52151bd6825cSml "==> nxge_get_priv_prop: name %s " 52161bd6825cSml "(value %d valstr %s)", 52171bd6825cSml pr_name, nxgep->function_num, valstr)); 52181bd6825cSml 52191bd6825cSml err = 0; 52201bd6825cSml goto done; 52211bd6825cSml } 52221bd6825cSml 52231bd6825cSml /* Neptune firmware version */ 52241bd6825cSml if (strcmp(pr_name, "_fw_version") == 0) { 52254045d941Ssowmini if (is_default) 52264045d941Ssowmini return (ENOTSUP); 52274045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%s", 52284045d941Ssowmini nxgep->vpd_info.ver); 52291bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52301bd6825cSml "==> nxge_get_priv_prop: name %s " 52311bd6825cSml "(value %d valstr %s)", 52321bd6825cSml pr_name, nxgep->vpd_info.ver, valstr)); 52331bd6825cSml 52341bd6825cSml err = 0; 52351bd6825cSml goto done; 52361bd6825cSml } 52371bd6825cSml 52381bd6825cSml /* port PHY mode */ 52391bd6825cSml if (strcmp(pr_name, "_port_mode") == 0) { 52404045d941Ssowmini if (is_default) 52414045d941Ssowmini return (ENOTSUP); 52421bd6825cSml switch (nxgep->mac.portmode) { 52431bd6825cSml case PORT_1G_COPPER: 52444045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G copper %s", 52451bd6825cSml nxgep->hot_swappable_phy ? 52461bd6825cSml "[Hot Swappable]" : ""); 52471bd6825cSml break; 52481bd6825cSml case PORT_1G_FIBER: 52494045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G fiber %s", 52501bd6825cSml nxgep->hot_swappable_phy ? 52511bd6825cSml "[hot swappable]" : ""); 52521bd6825cSml break; 52531bd6825cSml case PORT_10G_COPPER: 52544045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 52554045d941Ssowmini "10G copper %s", 52561bd6825cSml nxgep->hot_swappable_phy ? 52571bd6825cSml "[hot swappable]" : ""); 52581bd6825cSml break; 52591bd6825cSml case PORT_10G_FIBER: 52604045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "10G fiber %s", 52611bd6825cSml nxgep->hot_swappable_phy ? 52621bd6825cSml "[hot swappable]" : ""); 52631bd6825cSml break; 52641bd6825cSml case PORT_10G_SERDES: 52654045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 52664045d941Ssowmini "10G serdes %s", nxgep->hot_swappable_phy ? 52671bd6825cSml "[hot swappable]" : ""); 52681bd6825cSml break; 52691bd6825cSml case PORT_1G_SERDES: 52704045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G serdes %s", 52711bd6825cSml nxgep->hot_swappable_phy ? 52721bd6825cSml "[hot swappable]" : ""); 52731bd6825cSml break; 527400161856Syc case PORT_1G_TN1010: 527500161856Syc (void) snprintf(valstr, sizeof (valstr), 527600161856Syc "1G TN1010 copper %s", nxgep->hot_swappable_phy ? 527700161856Syc "[hot swappable]" : ""); 527800161856Syc break; 527900161856Syc case PORT_10G_TN1010: 528000161856Syc (void) snprintf(valstr, sizeof (valstr), 528100161856Syc "10G TN1010 copper %s", nxgep->hot_swappable_phy ? 528200161856Syc "[hot swappable]" : ""); 528300161856Syc break; 52841bd6825cSml case PORT_1G_RGMII_FIBER: 52854045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 52864045d941Ssowmini "1G rgmii fiber %s", nxgep->hot_swappable_phy ? 52871bd6825cSml "[hot swappable]" : ""); 52881bd6825cSml break; 52891bd6825cSml case PORT_HSP_MODE: 52904045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 5291c2d37b8bSml "phy not present[hot swappable]"); 52921bd6825cSml break; 52931bd6825cSml default: 52944045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "unknown %s", 52951bd6825cSml nxgep->hot_swappable_phy ? 52961bd6825cSml "[hot swappable]" : ""); 52971bd6825cSml break; 52981bd6825cSml } 52991bd6825cSml 53001bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53011bd6825cSml "==> nxge_get_priv_prop: name %s (value %s)", 53021bd6825cSml pr_name, valstr)); 53031bd6825cSml 53041bd6825cSml err = 0; 53051bd6825cSml goto done; 53061bd6825cSml } 53071bd6825cSml 53081bd6825cSml /* Hot swappable PHY */ 53091bd6825cSml if (strcmp(pr_name, "_hot_swap_phy") == 0) { 53104045d941Ssowmini if (is_default) 53114045d941Ssowmini return (ENOTSUP); 53124045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%s", 53131bd6825cSml nxgep->hot_swappable_phy ? 53141bd6825cSml "yes" : "no"); 53151bd6825cSml 53161bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53171bd6825cSml "==> nxge_get_priv_prop: name %s " 53181bd6825cSml "(value %d valstr %s)", 53191bd6825cSml pr_name, nxgep->hot_swappable_phy, valstr)); 53201bd6825cSml 53211bd6825cSml err = 0; 53221bd6825cSml goto done; 53231bd6825cSml } 53241bd6825cSml 53251bd6825cSml 53261bd6825cSml /* accept jumbo */ 53271bd6825cSml if (strcmp(pr_name, "_accept_jumbo") == 0) { 53284045d941Ssowmini if (is_default) 53294045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 53304045d941Ssowmini else 53314045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 53324045d941Ssowmini "%d", nxgep->mac.is_jumbo); 53331bd6825cSml err = 0; 53341bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53351bd6825cSml "==> nxge_get_priv_prop: name %s (value %d (%d, %d))", 53361bd6825cSml pr_name, 53371bd6825cSml (uint32_t)param_arr[param_accept_jumbo].value, 53381bd6825cSml nxgep->mac.is_jumbo, 53391bd6825cSml nxge_jumbo_enable)); 53401bd6825cSml 53411bd6825cSml goto done; 53421bd6825cSml } 53431bd6825cSml 53441bd6825cSml /* Receive Interrupt Blanking Parameters */ 53451bd6825cSml if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 53464045d941Ssowmini err = 0; 53474045d941Ssowmini if (is_default) { 53484045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 53494045d941Ssowmini "%d", RXDMA_RCR_TO_DEFAULT); 53504045d941Ssowmini goto done; 53514045d941Ssowmini } 53524045d941Ssowmini 53534045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 53544045d941Ssowmini nxgep->intr_timeout); 53551bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53561bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 53571bd6825cSml pr_name, 53581bd6825cSml (uint32_t)nxgep->intr_timeout)); 53591bd6825cSml goto done; 53601bd6825cSml } 53611bd6825cSml 53621bd6825cSml if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 53634045d941Ssowmini err = 0; 53644045d941Ssowmini if (is_default) { 53654045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 53664045d941Ssowmini "%d", RXDMA_RCR_PTHRES_DEFAULT); 53674045d941Ssowmini goto done; 53684045d941Ssowmini } 53694045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 53704045d941Ssowmini nxgep->intr_threshold); 53711bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53721bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 53731bd6825cSml pr_name, (uint32_t)nxgep->intr_threshold)); 53741bd6825cSml 53751bd6825cSml goto done; 53761bd6825cSml } 53771bd6825cSml 53781bd6825cSml /* Classification and Load Distribution Configuration */ 53791bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 53804045d941Ssowmini if (is_default) { 53814045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53824045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 53834045d941Ssowmini err = 0; 53844045d941Ssowmini goto done; 53854045d941Ssowmini } 53861bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 53871bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 53881bd6825cSml 53894045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53901bd6825cSml (int)param_arr[param_class_opt_ipv4_tcp].value); 53911bd6825cSml 53921bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53931bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 53941bd6825cSml goto done; 53951bd6825cSml } 53961bd6825cSml 53971bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 53984045d941Ssowmini if (is_default) { 53994045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 54004045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 54014045d941Ssowmini err = 0; 54024045d941Ssowmini goto done; 54034045d941Ssowmini } 54041bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 54051bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 54061bd6825cSml 54074045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 54081bd6825cSml (int)param_arr[param_class_opt_ipv4_udp].value); 54091bd6825cSml 54101bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 54111bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 54121bd6825cSml goto done; 54131bd6825cSml } 54141bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 54154045d941Ssowmini if (is_default) { 54164045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 54174045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 54184045d941Ssowmini err = 0; 54194045d941Ssowmini goto done; 54204045d941Ssowmini } 54211bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 54221bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 54231bd6825cSml 54244045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 54251bd6825cSml (int)param_arr[param_class_opt_ipv4_ah].value); 54261bd6825cSml 54271bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 54281bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 54291bd6825cSml goto done; 54301bd6825cSml } 54311bd6825cSml 54321bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 54334045d941Ssowmini if (is_default) { 54344045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 54354045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 54364045d941Ssowmini err = 0; 54374045d941Ssowmini goto done; 54384045d941Ssowmini } 54391bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 54401bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 54411bd6825cSml 54424045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 54431bd6825cSml (int)param_arr[param_class_opt_ipv4_sctp].value); 54441bd6825cSml 54451bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 54461bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 54471bd6825cSml goto done; 54481bd6825cSml } 54491bd6825cSml 54501bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 54514045d941Ssowmini if (is_default) { 54524045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 54534045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 54544045d941Ssowmini err = 0; 54554045d941Ssowmini goto done; 54564045d941Ssowmini } 54571bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 54581bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 54591bd6825cSml 54604045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 54611bd6825cSml (int)param_arr[param_class_opt_ipv6_tcp].value); 54621bd6825cSml 54631bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 54641bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 54651bd6825cSml goto done; 54661bd6825cSml } 54671bd6825cSml 54681bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 54694045d941Ssowmini if (is_default) { 54704045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 54714045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 54724045d941Ssowmini err = 0; 54734045d941Ssowmini goto done; 54744045d941Ssowmini } 54751bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 54761bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 54771bd6825cSml 54784045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 54791bd6825cSml (int)param_arr[param_class_opt_ipv6_udp].value); 54801bd6825cSml 54811bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 54821bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 54831bd6825cSml goto done; 54841bd6825cSml } 54851bd6825cSml 54861bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 54874045d941Ssowmini if (is_default) { 54884045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 54894045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 54904045d941Ssowmini err = 0; 54914045d941Ssowmini goto done; 54924045d941Ssowmini } 54931bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 54941bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 54951bd6825cSml 54964045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 54971bd6825cSml (int)param_arr[param_class_opt_ipv6_ah].value); 54981bd6825cSml 54991bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 55001bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 55011bd6825cSml goto done; 55021bd6825cSml } 55031bd6825cSml 55041bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 55054045d941Ssowmini if (is_default) { 55064045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 55074045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 55084045d941Ssowmini err = 0; 55094045d941Ssowmini goto done; 55104045d941Ssowmini } 55111bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 55121bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 55131bd6825cSml 55144045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 55151bd6825cSml (int)param_arr[param_class_opt_ipv6_sctp].value); 55161bd6825cSml 55171bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 55181bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 55191bd6825cSml goto done; 55201bd6825cSml } 55211bd6825cSml 55221bd6825cSml /* Software LSO */ 55231bd6825cSml if (strcmp(pr_name, "_soft_lso_enable") == 0) { 55244045d941Ssowmini if (is_default) { 55254045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 55264045d941Ssowmini err = 0; 55274045d941Ssowmini goto done; 55284045d941Ssowmini } 55294045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 55304045d941Ssowmini "%d", nxgep->soft_lso_enable); 55311bd6825cSml err = 0; 55321bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 55331bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 55341bd6825cSml pr_name, nxgep->soft_lso_enable)); 55351bd6825cSml 55361bd6825cSml goto done; 55371bd6825cSml } 55384045d941Ssowmini if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) { 55394045d941Ssowmini err = 0; 55404045d941Ssowmini if (is_default || 55414045d941Ssowmini nxgep->param_arr[param_anar_10gfdx].value != 0) { 55424045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 1); 55434045d941Ssowmini goto done; 55444045d941Ssowmini } else { 55454045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 55464045d941Ssowmini goto done; 55474045d941Ssowmini } 55484045d941Ssowmini } 55494045d941Ssowmini if (strcmp(pr_name, "_adv_pause_cap") == 0) { 55504045d941Ssowmini err = 0; 55514045d941Ssowmini if (is_default || 55524045d941Ssowmini nxgep->param_arr[param_anar_pause].value != 0) { 55534045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 1); 55544045d941Ssowmini goto done; 55554045d941Ssowmini } else { 55564045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 55574045d941Ssowmini goto done; 55584045d941Ssowmini } 55594045d941Ssowmini } 55601bd6825cSml 55611bd6825cSml done: 55621bd6825cSml if (err == 0) { 55631bd6825cSml strsize = (uint_t)strlen(valstr); 55641bd6825cSml if (pr_valsize < strsize) { 55651bd6825cSml err = ENOBUFS; 55661bd6825cSml } else { 55671bd6825cSml (void) strlcpy(pr_val, valstr, pr_valsize); 55681bd6825cSml } 55691bd6825cSml } 55701bd6825cSml 55711bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 55721bd6825cSml "<== nxge_get_priv_prop: return %d", err)); 55731bd6825cSml return (err); 55741bd6825cSml } 55751bd6825cSml 557644961713Sgirish /* 557744961713Sgirish * Module loading and removing entry points. 557844961713Sgirish */ 557944961713Sgirish 55806f157acbSml DDI_DEFINE_STREAM_OPS(nxge_dev_ops, nulldev, nulldev, nxge_attach, nxge_detach, 558119397407SSherry Moore nodev, NULL, D_MP, NULL, nxge_quiesce); 558244961713Sgirish 55832e59129aSraghus #define NXGE_DESC_VER "Sun NIU 10Gb Ethernet" 558444961713Sgirish 558544961713Sgirish /* 558644961713Sgirish * Module linkage information for the kernel. 558744961713Sgirish */ 558844961713Sgirish static struct modldrv nxge_modldrv = { 558944961713Sgirish &mod_driverops, 559044961713Sgirish NXGE_DESC_VER, 559144961713Sgirish &nxge_dev_ops 559244961713Sgirish }; 559344961713Sgirish 559444961713Sgirish static struct modlinkage modlinkage = { 559544961713Sgirish MODREV_1, (void *) &nxge_modldrv, NULL 559644961713Sgirish }; 559744961713Sgirish 559844961713Sgirish int 559944961713Sgirish _init(void) 560044961713Sgirish { 560144961713Sgirish int status; 560244961713Sgirish 560344961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init")); 560444961713Sgirish mac_init_ops(&nxge_dev_ops, "nxge"); 560544961713Sgirish status = ddi_soft_state_init(&nxge_list, sizeof (nxge_t), 0); 560644961713Sgirish if (status != 0) { 560744961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, 56084045d941Ssowmini "failed to init device soft state")); 560944961713Sgirish goto _init_exit; 561044961713Sgirish } 561144961713Sgirish status = mod_install(&modlinkage); 561244961713Sgirish if (status != 0) { 561344961713Sgirish ddi_soft_state_fini(&nxge_list); 561444961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, "Mod install failed")); 561544961713Sgirish goto _init_exit; 561644961713Sgirish } 561744961713Sgirish 561844961713Sgirish MUTEX_INIT(&nxge_common_lock, NULL, MUTEX_DRIVER, NULL); 561944961713Sgirish 562044961713Sgirish _init_exit: 562144961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "_init status = 0x%X", status)); 562244961713Sgirish 562344961713Sgirish return (status); 562444961713Sgirish } 562544961713Sgirish 562644961713Sgirish int 562744961713Sgirish _fini(void) 562844961713Sgirish { 562944961713Sgirish int status; 563044961713Sgirish 563144961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini")); 563244961713Sgirish 563344961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove")); 5634a3c5bd6dSspeer 5635a3c5bd6dSspeer if (nxge_mblks_pending) 5636a3c5bd6dSspeer return (EBUSY); 5637a3c5bd6dSspeer 563844961713Sgirish status = mod_remove(&modlinkage); 563944961713Sgirish if (status != DDI_SUCCESS) { 564044961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, 56414045d941Ssowmini "Module removal failed 0x%08x", 56424045d941Ssowmini status)); 564344961713Sgirish goto _fini_exit; 564444961713Sgirish } 564544961713Sgirish 564644961713Sgirish mac_fini_ops(&nxge_dev_ops); 564744961713Sgirish 564844961713Sgirish ddi_soft_state_fini(&nxge_list); 564944961713Sgirish 565044961713Sgirish MUTEX_DESTROY(&nxge_common_lock); 565144961713Sgirish _fini_exit: 565244961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "_fini status = 0x%08x", status)); 565344961713Sgirish 565444961713Sgirish return (status); 565544961713Sgirish } 565644961713Sgirish 565744961713Sgirish int 565844961713Sgirish _info(struct modinfo *modinfop) 565944961713Sgirish { 566044961713Sgirish int status; 566144961713Sgirish 566244961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info")); 566344961713Sgirish status = mod_info(&modlinkage, modinfop); 566444961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status)); 566544961713Sgirish 566644961713Sgirish return (status); 566744961713Sgirish } 566844961713Sgirish 566944961713Sgirish /*ARGSUSED*/ 567044961713Sgirish static nxge_status_t 567144961713Sgirish nxge_add_intrs(p_nxge_t nxgep) 567244961713Sgirish { 567344961713Sgirish 567444961713Sgirish int intr_types; 567544961713Sgirish int type = 0; 567644961713Sgirish int ddi_status = DDI_SUCCESS; 567744961713Sgirish nxge_status_t status = NXGE_OK; 567844961713Sgirish 567944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs")); 568044961713Sgirish 568144961713Sgirish nxgep->nxge_intr_type.intr_registered = B_FALSE; 568244961713Sgirish nxgep->nxge_intr_type.intr_enabled = B_FALSE; 568344961713Sgirish nxgep->nxge_intr_type.msi_intx_cnt = 0; 568444961713Sgirish nxgep->nxge_intr_type.intr_added = 0; 568544961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_FALSE; 568644961713Sgirish nxgep->nxge_intr_type.intr_type = 0; 568744961713Sgirish 568844961713Sgirish if (nxgep->niu_type == N2_NIU) { 568944961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 569044961713Sgirish } else if (nxge_msi_enable) { 569144961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 569244961713Sgirish } 569344961713Sgirish 569444961713Sgirish /* Get the supported interrupt types */ 569544961713Sgirish if ((ddi_status = ddi_intr_get_supported_types(nxgep->dip, &intr_types)) 56964045d941Ssowmini != DDI_SUCCESS) { 569744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_intrs: " 56984045d941Ssowmini "ddi_intr_get_supported_types failed: status 0x%08x", 56994045d941Ssowmini ddi_status)); 570044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 570144961713Sgirish } 570244961713Sgirish nxgep->nxge_intr_type.intr_types = intr_types; 570344961713Sgirish 570444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 57054045d941Ssowmini "ddi_intr_get_supported_types: 0x%08x", intr_types)); 570644961713Sgirish 570744961713Sgirish /* 570844961713Sgirish * Solaris MSIX is not supported yet. use MSI for now. 570944961713Sgirish * nxge_msi_enable (1): 571044961713Sgirish * 1 - MSI 2 - MSI-X others - FIXED 571144961713Sgirish */ 571244961713Sgirish switch (nxge_msi_enable) { 571344961713Sgirish default: 571444961713Sgirish type = DDI_INTR_TYPE_FIXED; 571544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 57164045d941Ssowmini "use fixed (intx emulation) type %08x", 57174045d941Ssowmini type)); 571844961713Sgirish break; 571944961713Sgirish 572044961713Sgirish case 2: 572144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 57224045d941Ssowmini "ddi_intr_get_supported_types: 0x%08x", intr_types)); 572344961713Sgirish if (intr_types & DDI_INTR_TYPE_MSIX) { 572444961713Sgirish type = DDI_INTR_TYPE_MSIX; 572544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 57264045d941Ssowmini "ddi_intr_get_supported_types: MSIX 0x%08x", 57274045d941Ssowmini type)); 572844961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSI) { 572944961713Sgirish type = DDI_INTR_TYPE_MSI; 573044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 57314045d941Ssowmini "ddi_intr_get_supported_types: MSI 0x%08x", 57324045d941Ssowmini type)); 573344961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 573444961713Sgirish type = DDI_INTR_TYPE_FIXED; 573544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 57364045d941Ssowmini "ddi_intr_get_supported_types: MSXED0x%08x", 57374045d941Ssowmini type)); 573844961713Sgirish } 573944961713Sgirish break; 574044961713Sgirish 574144961713Sgirish case 1: 574244961713Sgirish if (intr_types & DDI_INTR_TYPE_MSI) { 574344961713Sgirish type = DDI_INTR_TYPE_MSI; 574444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 57454045d941Ssowmini "ddi_intr_get_supported_types: MSI 0x%08x", 57464045d941Ssowmini type)); 574744961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSIX) { 574844961713Sgirish type = DDI_INTR_TYPE_MSIX; 574944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 57504045d941Ssowmini "ddi_intr_get_supported_types: MSIX 0x%08x", 57514045d941Ssowmini type)); 575244961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 575344961713Sgirish type = DDI_INTR_TYPE_FIXED; 575444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 57554045d941Ssowmini "ddi_intr_get_supported_types: MSXED0x%08x", 57564045d941Ssowmini type)); 575744961713Sgirish } 575844961713Sgirish } 575944961713Sgirish 576044961713Sgirish nxgep->nxge_intr_type.intr_type = type; 576144961713Sgirish if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI || 57624045d941Ssowmini type == DDI_INTR_TYPE_FIXED) && 57634045d941Ssowmini nxgep->nxge_intr_type.niu_msi_enable) { 576444961713Sgirish if ((status = nxge_add_intrs_adv(nxgep)) != DDI_SUCCESS) { 576544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 57664045d941Ssowmini " nxge_add_intrs: " 57674045d941Ssowmini " nxge_add_intrs_adv failed: status 0x%08x", 57684045d941Ssowmini status)); 576944961713Sgirish return (status); 577044961713Sgirish } else { 577144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 57724045d941Ssowmini "interrupts registered : type %d", type)); 577344961713Sgirish nxgep->nxge_intr_type.intr_registered = B_TRUE; 577444961713Sgirish 577544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 57764045d941Ssowmini "\nAdded advanced nxge add_intr_adv " 57774045d941Ssowmini "intr type 0x%x\n", type)); 577844961713Sgirish 577944961713Sgirish return (status); 578044961713Sgirish } 578144961713Sgirish } 578244961713Sgirish 578344961713Sgirish if (!nxgep->nxge_intr_type.intr_registered) { 578444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_add_intrs: " 57854045d941Ssowmini "failed to register interrupts")); 578644961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 578744961713Sgirish } 578844961713Sgirish 578944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_add_intrs")); 579044961713Sgirish return (status); 579144961713Sgirish } 579244961713Sgirish 579344961713Sgirish /*ARGSUSED*/ 579444961713Sgirish static nxge_status_t 579544961713Sgirish nxge_add_soft_intrs(p_nxge_t nxgep) 579644961713Sgirish { 579744961713Sgirish 579844961713Sgirish int ddi_status = DDI_SUCCESS; 579944961713Sgirish nxge_status_t status = NXGE_OK; 580044961713Sgirish 580144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_soft_intrs")); 580244961713Sgirish 580344961713Sgirish nxgep->resched_id = NULL; 580444961713Sgirish nxgep->resched_running = B_FALSE; 580544961713Sgirish ddi_status = ddi_add_softintr(nxgep->dip, DDI_SOFTINT_LOW, 58064045d941Ssowmini &nxgep->resched_id, 58074045d941Ssowmini NULL, NULL, nxge_reschedule, (caddr_t)nxgep); 580844961713Sgirish if (ddi_status != DDI_SUCCESS) { 580944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_soft_intrs: " 58104045d941Ssowmini "ddi_add_softintrs failed: status 0x%08x", 58114045d941Ssowmini ddi_status)); 581244961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 581344961713Sgirish } 581444961713Sgirish 581544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_ddi_add_soft_intrs")); 581644961713Sgirish 581744961713Sgirish return (status); 581844961713Sgirish } 581944961713Sgirish 582044961713Sgirish static nxge_status_t 582144961713Sgirish nxge_add_intrs_adv(p_nxge_t nxgep) 582244961713Sgirish { 582344961713Sgirish int intr_type; 582444961713Sgirish p_nxge_intr_t intrp; 582544961713Sgirish 582644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv")); 582744961713Sgirish 582844961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 582944961713Sgirish intr_type = intrp->intr_type; 583044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv: type 0x%x", 58314045d941Ssowmini intr_type)); 583244961713Sgirish 583344961713Sgirish switch (intr_type) { 583444961713Sgirish case DDI_INTR_TYPE_MSI: /* 0x2 */ 583544961713Sgirish case DDI_INTR_TYPE_MSIX: /* 0x4 */ 583644961713Sgirish return (nxge_add_intrs_adv_type(nxgep, intr_type)); 583744961713Sgirish 583844961713Sgirish case DDI_INTR_TYPE_FIXED: /* 0x1 */ 583944961713Sgirish return (nxge_add_intrs_adv_type_fix(nxgep, intr_type)); 584044961713Sgirish 584144961713Sgirish default: 584244961713Sgirish return (NXGE_ERROR); 584344961713Sgirish } 584444961713Sgirish } 584544961713Sgirish 584644961713Sgirish 584744961713Sgirish /*ARGSUSED*/ 584844961713Sgirish static nxge_status_t 584944961713Sgirish nxge_add_intrs_adv_type(p_nxge_t nxgep, uint32_t int_type) 585044961713Sgirish { 585144961713Sgirish dev_info_t *dip = nxgep->dip; 585244961713Sgirish p_nxge_ldg_t ldgp; 585344961713Sgirish p_nxge_intr_t intrp; 585444961713Sgirish uint_t *inthandler; 585544961713Sgirish void *arg1, *arg2; 585644961713Sgirish int behavior; 5857ec090658Sml int nintrs, navail, nrequest; 585844961713Sgirish int nactual, nrequired; 585944961713Sgirish int inum = 0; 586044961713Sgirish int x, y; 586144961713Sgirish int ddi_status = DDI_SUCCESS; 586244961713Sgirish nxge_status_t status = NXGE_OK; 586344961713Sgirish 586444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type")); 586544961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 586644961713Sgirish intrp->start_inum = 0; 586744961713Sgirish 586844961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 586944961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 587044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58714045d941Ssowmini "ddi_intr_get_nintrs() failed, status: 0x%x%, " 58724045d941Ssowmini "nintrs: %d", ddi_status, nintrs)); 587344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 587444961713Sgirish } 587544961713Sgirish 587644961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 587744961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 587844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58794045d941Ssowmini "ddi_intr_get_navail() failed, status: 0x%x%, " 58804045d941Ssowmini "nintrs: %d", ddi_status, navail)); 588144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 588244961713Sgirish } 588344961713Sgirish 588444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 58854045d941Ssowmini "ddi_intr_get_navail() returned: nintrs %d, navail %d", 58864045d941Ssowmini nintrs, navail)); 588744961713Sgirish 5888ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override */ 5889ec090658Sml if (int_type == DDI_INTR_TYPE_MSIX) { 5890ec090658Sml nrequest = nxge_create_msi_property(nxgep); 5891ec090658Sml if (nrequest < navail) { 5892ec090658Sml navail = nrequest; 5893ec090658Sml NXGE_DEBUG_MSG((nxgep, INT_CTL, 5894ec090658Sml "nxge_add_intrs_adv_type: nintrs %d " 5895ec090658Sml "navail %d (nrequest %d)", 5896ec090658Sml nintrs, navail, nrequest)); 5897ec090658Sml } 5898ec090658Sml } 5899ec090658Sml 590044961713Sgirish if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) { 590144961713Sgirish /* MSI must be power of 2 */ 590244961713Sgirish if ((navail & 16) == 16) { 590344961713Sgirish navail = 16; 590444961713Sgirish } else if ((navail & 8) == 8) { 590544961713Sgirish navail = 8; 590644961713Sgirish } else if ((navail & 4) == 4) { 590744961713Sgirish navail = 4; 590844961713Sgirish } else if ((navail & 2) == 2) { 590944961713Sgirish navail = 2; 591044961713Sgirish } else { 591144961713Sgirish navail = 1; 591244961713Sgirish } 591344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 59144045d941Ssowmini "ddi_intr_get_navail(): (msi power of 2) nintrs %d, " 59154045d941Ssowmini "navail %d", nintrs, navail)); 591644961713Sgirish } 591744961713Sgirish 591844961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 59194045d941Ssowmini DDI_INTR_ALLOC_NORMAL); 592044961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 592144961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 592244961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 59234045d941Ssowmini navail, &nactual, behavior); 592444961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 592544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59264045d941Ssowmini " ddi_intr_alloc() failed: %d", 59274045d941Ssowmini ddi_status)); 592844961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 592944961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 593044961713Sgirish } 593144961713Sgirish 593244961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 59334045d941Ssowmini (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 593444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59354045d941Ssowmini " ddi_intr_get_pri() failed: %d", 59364045d941Ssowmini ddi_status)); 593744961713Sgirish /* Free already allocated interrupts */ 593844961713Sgirish for (y = 0; y < nactual; y++) { 593944961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 594044961713Sgirish } 594144961713Sgirish 594244961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 594344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 594444961713Sgirish } 594544961713Sgirish 594644961713Sgirish nrequired = 0; 594744961713Sgirish switch (nxgep->niu_type) { 594844961713Sgirish default: 594944961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 595044961713Sgirish break; 595144961713Sgirish 595244961713Sgirish case N2_NIU: 595344961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 595444961713Sgirish break; 595544961713Sgirish } 595644961713Sgirish 595744961713Sgirish if (status != NXGE_OK) { 595844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59594045d941Ssowmini "nxge_add_intrs_adv_typ:nxge_ldgv_init " 59604045d941Ssowmini "failed: 0x%x", status)); 596144961713Sgirish /* Free already allocated interrupts */ 596244961713Sgirish for (y = 0; y < nactual; y++) { 596344961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 596444961713Sgirish } 596544961713Sgirish 596644961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 596744961713Sgirish return (status); 596844961713Sgirish } 596944961713Sgirish 597044961713Sgirish ldgp = nxgep->ldgvp->ldgp; 597144961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 597244961713Sgirish ldgp->vector = (uint8_t)x; 597344961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 597444961713Sgirish arg1 = ldgp->ldvp; 597544961713Sgirish arg2 = nxgep; 597644961713Sgirish if (ldgp->nldvs == 1) { 597744961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 597844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 59794045d941Ssowmini "nxge_add_intrs_adv_type: " 59804045d941Ssowmini "arg1 0x%x arg2 0x%x: " 59814045d941Ssowmini "1-1 int handler (entry %d intdata 0x%x)\n", 59824045d941Ssowmini arg1, arg2, 59834045d941Ssowmini x, ldgp->intdata)); 598444961713Sgirish } else if (ldgp->nldvs > 1) { 598544961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 598644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 59874045d941Ssowmini "nxge_add_intrs_adv_type: " 59884045d941Ssowmini "arg1 0x%x arg2 0x%x: " 59894045d941Ssowmini "nldevs %d int handler " 59904045d941Ssowmini "(entry %d intdata 0x%x)\n", 59914045d941Ssowmini arg1, arg2, 59924045d941Ssowmini ldgp->nldvs, x, ldgp->intdata)); 599344961713Sgirish } 599444961713Sgirish 599544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 59964045d941Ssowmini "==> nxge_add_intrs_adv_type: ddi_add_intr(inum) #%d " 59974045d941Ssowmini "htable 0x%llx", x, intrp->htable[x])); 599844961713Sgirish 599944961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 60004045d941Ssowmini (ddi_intr_handler_t *)inthandler, arg1, arg2)) 60014045d941Ssowmini != DDI_SUCCESS) { 600244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60034045d941Ssowmini "==> nxge_add_intrs_adv_type: failed #%d " 60044045d941Ssowmini "status 0x%x", x, ddi_status)); 600544961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 600644961713Sgirish (void) ddi_intr_remove_handler( 60074045d941Ssowmini intrp->htable[y]); 600844961713Sgirish } 600944961713Sgirish /* Free already allocated intr */ 601044961713Sgirish for (y = 0; y < nactual; y++) { 601144961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 601244961713Sgirish } 601344961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 601444961713Sgirish 601544961713Sgirish (void) nxge_ldgv_uninit(nxgep); 601644961713Sgirish 601744961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 601844961713Sgirish } 601944961713Sgirish intrp->intr_added++; 602044961713Sgirish } 602144961713Sgirish 602244961713Sgirish intrp->msi_intx_cnt = nactual; 602344961713Sgirish 602444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 60254045d941Ssowmini "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d", 60264045d941Ssowmini navail, nactual, 60274045d941Ssowmini intrp->msi_intx_cnt, 60284045d941Ssowmini intrp->intr_added)); 602944961713Sgirish 603044961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 603144961713Sgirish 603244961713Sgirish (void) nxge_intr_ldgv_init(nxgep); 603344961713Sgirish 603444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type")); 603544961713Sgirish 603644961713Sgirish return (status); 603744961713Sgirish } 603844961713Sgirish 603944961713Sgirish /*ARGSUSED*/ 604044961713Sgirish static nxge_status_t 604144961713Sgirish nxge_add_intrs_adv_type_fix(p_nxge_t nxgep, uint32_t int_type) 604244961713Sgirish { 604344961713Sgirish dev_info_t *dip = nxgep->dip; 604444961713Sgirish p_nxge_ldg_t ldgp; 604544961713Sgirish p_nxge_intr_t intrp; 604644961713Sgirish uint_t *inthandler; 604744961713Sgirish void *arg1, *arg2; 604844961713Sgirish int behavior; 604944961713Sgirish int nintrs, navail; 605044961713Sgirish int nactual, nrequired; 605144961713Sgirish int inum = 0; 605244961713Sgirish int x, y; 605344961713Sgirish int ddi_status = DDI_SUCCESS; 605444961713Sgirish nxge_status_t status = NXGE_OK; 605544961713Sgirish 605644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type_fix")); 605744961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 605844961713Sgirish intrp->start_inum = 0; 605944961713Sgirish 606044961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 606144961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 606244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 60634045d941Ssowmini "ddi_intr_get_nintrs() failed, status: 0x%x%, " 60644045d941Ssowmini "nintrs: %d", status, nintrs)); 606544961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 606644961713Sgirish } 606744961713Sgirish 606844961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 606944961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 607044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60714045d941Ssowmini "ddi_intr_get_navail() failed, status: 0x%x%, " 60724045d941Ssowmini "nintrs: %d", ddi_status, navail)); 607344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 607444961713Sgirish } 607544961713Sgirish 607644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 60774045d941Ssowmini "ddi_intr_get_navail() returned: nintrs %d, naavail %d", 60784045d941Ssowmini nintrs, navail)); 607944961713Sgirish 608044961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 60814045d941Ssowmini DDI_INTR_ALLOC_NORMAL); 608244961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 608344961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 608444961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 60854045d941Ssowmini navail, &nactual, behavior); 608644961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 608744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60884045d941Ssowmini " ddi_intr_alloc() failed: %d", 60894045d941Ssowmini ddi_status)); 609044961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 609144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 609244961713Sgirish } 609344961713Sgirish 609444961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 60954045d941Ssowmini (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 609644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60974045d941Ssowmini " ddi_intr_get_pri() failed: %d", 60984045d941Ssowmini ddi_status)); 609944961713Sgirish /* Free already allocated interrupts */ 610044961713Sgirish for (y = 0; y < nactual; y++) { 610144961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 610244961713Sgirish } 610344961713Sgirish 610444961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 610544961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 610644961713Sgirish } 610744961713Sgirish 610844961713Sgirish nrequired = 0; 610944961713Sgirish switch (nxgep->niu_type) { 611044961713Sgirish default: 611144961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 611244961713Sgirish break; 611344961713Sgirish 611444961713Sgirish case N2_NIU: 611544961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 611644961713Sgirish break; 611744961713Sgirish } 611844961713Sgirish 611944961713Sgirish if (status != NXGE_OK) { 612044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61214045d941Ssowmini "nxge_add_intrs_adv_type_fix:nxge_ldgv_init " 61224045d941Ssowmini "failed: 0x%x", status)); 612344961713Sgirish /* Free already allocated interrupts */ 612444961713Sgirish for (y = 0; y < nactual; y++) { 612544961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 612644961713Sgirish } 612744961713Sgirish 612844961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 612944961713Sgirish return (status); 613044961713Sgirish } 613144961713Sgirish 613244961713Sgirish ldgp = nxgep->ldgvp->ldgp; 613344961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 613444961713Sgirish ldgp->vector = (uint8_t)x; 613544961713Sgirish if (nxgep->niu_type != N2_NIU) { 613644961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 613744961713Sgirish } 613844961713Sgirish 613944961713Sgirish arg1 = ldgp->ldvp; 614044961713Sgirish arg2 = nxgep; 614144961713Sgirish if (ldgp->nldvs == 1) { 614244961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 614344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 61444045d941Ssowmini "nxge_add_intrs_adv_type_fix: " 61454045d941Ssowmini "1-1 int handler(%d) ldg %d ldv %d " 61464045d941Ssowmini "arg1 $%p arg2 $%p\n", 61474045d941Ssowmini x, ldgp->ldg, ldgp->ldvp->ldv, 61484045d941Ssowmini arg1, arg2)); 614944961713Sgirish } else if (ldgp->nldvs > 1) { 615044961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 615144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 61524045d941Ssowmini "nxge_add_intrs_adv_type_fix: " 61534045d941Ssowmini "shared ldv %d int handler(%d) ldv %d ldg %d" 61544045d941Ssowmini "arg1 0x%016llx arg2 0x%016llx\n", 61554045d941Ssowmini x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv, 61564045d941Ssowmini arg1, arg2)); 615744961713Sgirish } 615844961713Sgirish 615944961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 61604045d941Ssowmini (ddi_intr_handler_t *)inthandler, arg1, arg2)) 61614045d941Ssowmini != DDI_SUCCESS) { 616244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61634045d941Ssowmini "==> nxge_add_intrs_adv_type_fix: failed #%d " 61644045d941Ssowmini "status 0x%x", x, ddi_status)); 616544961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 616644961713Sgirish (void) ddi_intr_remove_handler( 61674045d941Ssowmini intrp->htable[y]); 616844961713Sgirish } 616944961713Sgirish for (y = 0; y < nactual; y++) { 617044961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 617144961713Sgirish } 617244961713Sgirish /* Free already allocated intr */ 617344961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 617444961713Sgirish 617544961713Sgirish (void) nxge_ldgv_uninit(nxgep); 617644961713Sgirish 617744961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 617844961713Sgirish } 617944961713Sgirish intrp->intr_added++; 618044961713Sgirish } 618144961713Sgirish 618244961713Sgirish intrp->msi_intx_cnt = nactual; 618344961713Sgirish 618444961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 618544961713Sgirish 618644961713Sgirish status = nxge_intr_ldgv_init(nxgep); 618744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type_fix")); 618844961713Sgirish 618944961713Sgirish return (status); 619044961713Sgirish } 619144961713Sgirish 619244961713Sgirish static void 619344961713Sgirish nxge_remove_intrs(p_nxge_t nxgep) 619444961713Sgirish { 619544961713Sgirish int i, inum; 619644961713Sgirish p_nxge_intr_t intrp; 619744961713Sgirish 619844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs")); 619944961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 620044961713Sgirish if (!intrp->intr_registered) { 620144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 62024045d941Ssowmini "<== nxge_remove_intrs: interrupts not registered")); 620344961713Sgirish return; 620444961713Sgirish } 620544961713Sgirish 620644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs:advanced")); 620744961713Sgirish 620844961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 620944961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 62104045d941Ssowmini intrp->intr_added); 621144961713Sgirish } else { 621244961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 621344961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 621444961713Sgirish } 621544961713Sgirish } 621644961713Sgirish 621744961713Sgirish for (inum = 0; inum < intrp->intr_added; inum++) { 621844961713Sgirish if (intrp->htable[inum]) { 621944961713Sgirish (void) ddi_intr_remove_handler(intrp->htable[inum]); 622044961713Sgirish } 622144961713Sgirish } 622244961713Sgirish 622344961713Sgirish for (inum = 0; inum < intrp->msi_intx_cnt; inum++) { 622444961713Sgirish if (intrp->htable[inum]) { 622544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 62264045d941Ssowmini "nxge_remove_intrs: ddi_intr_free inum %d " 62274045d941Ssowmini "msi_intx_cnt %d intr_added %d", 62284045d941Ssowmini inum, 62294045d941Ssowmini intrp->msi_intx_cnt, 62304045d941Ssowmini intrp->intr_added)); 623144961713Sgirish 623244961713Sgirish (void) ddi_intr_free(intrp->htable[inum]); 623344961713Sgirish } 623444961713Sgirish } 623544961713Sgirish 623644961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 623744961713Sgirish intrp->intr_registered = B_FALSE; 623844961713Sgirish intrp->intr_enabled = B_FALSE; 623944961713Sgirish intrp->msi_intx_cnt = 0; 624044961713Sgirish intrp->intr_added = 0; 624144961713Sgirish 6242a3c5bd6dSspeer (void) nxge_ldgv_uninit(nxgep); 6243a3c5bd6dSspeer 6244ec090658Sml (void) ddi_prop_remove(DDI_DEV_T_NONE, nxgep->dip, 6245ec090658Sml "#msix-request"); 6246ec090658Sml 624744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_intrs")); 624844961713Sgirish } 624944961713Sgirish 625044961713Sgirish /*ARGSUSED*/ 625144961713Sgirish static void 625244961713Sgirish nxge_remove_soft_intrs(p_nxge_t nxgep) 625344961713Sgirish { 625444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_soft_intrs")); 625544961713Sgirish if (nxgep->resched_id) { 625644961713Sgirish ddi_remove_softintr(nxgep->resched_id); 625744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 62584045d941Ssowmini "==> nxge_remove_soft_intrs: removed")); 625944961713Sgirish nxgep->resched_id = NULL; 626044961713Sgirish } 626144961713Sgirish 626244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_soft_intrs")); 626344961713Sgirish } 626444961713Sgirish 626544961713Sgirish /*ARGSUSED*/ 626644961713Sgirish static void 626744961713Sgirish nxge_intrs_enable(p_nxge_t nxgep) 626844961713Sgirish { 626944961713Sgirish p_nxge_intr_t intrp; 627044961713Sgirish int i; 627144961713Sgirish int status; 627244961713Sgirish 627344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable")); 627444961713Sgirish 627544961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 627644961713Sgirish 627744961713Sgirish if (!intrp->intr_registered) { 627844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_intrs_enable: " 62794045d941Ssowmini "interrupts are not registered")); 628044961713Sgirish return; 628144961713Sgirish } 628244961713Sgirish 628344961713Sgirish if (intrp->intr_enabled) { 628444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 62854045d941Ssowmini "<== nxge_intrs_enable: already enabled")); 628644961713Sgirish return; 628744961713Sgirish } 628844961713Sgirish 628944961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 629044961713Sgirish status = ddi_intr_block_enable(intrp->htable, 62914045d941Ssowmini intrp->intr_added); 629244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 62934045d941Ssowmini "block enable - status 0x%x total inums #%d\n", 62944045d941Ssowmini status, intrp->intr_added)); 629544961713Sgirish } else { 629644961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 629744961713Sgirish status = ddi_intr_enable(intrp->htable[i]); 629844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 62994045d941Ssowmini "ddi_intr_enable:enable - status 0x%x " 63004045d941Ssowmini "total inums %d enable inum #%d\n", 63014045d941Ssowmini status, intrp->intr_added, i)); 630244961713Sgirish if (status == DDI_SUCCESS) { 630344961713Sgirish intrp->intr_enabled = B_TRUE; 630444961713Sgirish } 630544961713Sgirish } 630644961713Sgirish } 630744961713Sgirish 630844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_enable")); 630944961713Sgirish } 631044961713Sgirish 631144961713Sgirish /*ARGSUSED*/ 631244961713Sgirish static void 631344961713Sgirish nxge_intrs_disable(p_nxge_t nxgep) 631444961713Sgirish { 631544961713Sgirish p_nxge_intr_t intrp; 631644961713Sgirish int i; 631744961713Sgirish 631844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_disable")); 631944961713Sgirish 632044961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 632144961713Sgirish 632244961713Sgirish if (!intrp->intr_registered) { 632344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable: " 63244045d941Ssowmini "interrupts are not registered")); 632544961713Sgirish return; 632644961713Sgirish } 632744961713Sgirish 632844961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 632944961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 63304045d941Ssowmini intrp->intr_added); 633144961713Sgirish } else { 633244961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 633344961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 633444961713Sgirish } 633544961713Sgirish } 633644961713Sgirish 633744961713Sgirish intrp->intr_enabled = B_FALSE; 633844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable")); 633944961713Sgirish } 634044961713Sgirish 634144961713Sgirish static nxge_status_t 634244961713Sgirish nxge_mac_register(p_nxge_t nxgep) 634344961713Sgirish { 634444961713Sgirish mac_register_t *macp; 634544961713Sgirish int status; 634644961713Sgirish 634744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_mac_register")); 634844961713Sgirish 634944961713Sgirish if ((macp = mac_alloc(MAC_VERSION)) == NULL) 635044961713Sgirish return (NXGE_ERROR); 635144961713Sgirish 635244961713Sgirish macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 635344961713Sgirish macp->m_driver = nxgep; 635444961713Sgirish macp->m_dip = nxgep->dip; 635544961713Sgirish macp->m_src_addr = nxgep->ouraddr.ether_addr_octet; 635644961713Sgirish macp->m_callbacks = &nxge_m_callbacks; 635744961713Sgirish macp->m_min_sdu = 0; 63581bd6825cSml nxgep->mac.default_mtu = nxgep->mac.maxframesize - 63591bd6825cSml NXGE_EHEADER_VLAN_CRC; 63601bd6825cSml macp->m_max_sdu = nxgep->mac.default_mtu; 6361d62bc4baSyz macp->m_margin = VLAN_TAGSZ; 63624045d941Ssowmini macp->m_priv_props = nxge_priv_props; 63634045d941Ssowmini macp->m_priv_prop_count = NXGE_MAX_PRIV_PROPS; 636444961713Sgirish 63651bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 63661bd6825cSml "==> nxge_mac_register: instance %d " 63671bd6825cSml "max_sdu %d margin %d maxframe %d (header %d)", 63681bd6825cSml nxgep->instance, 63691bd6825cSml macp->m_max_sdu, macp->m_margin, 63701bd6825cSml nxgep->mac.maxframesize, 63711bd6825cSml NXGE_EHEADER_VLAN_CRC)); 63721bd6825cSml 637344961713Sgirish status = mac_register(macp, &nxgep->mach); 637444961713Sgirish mac_free(macp); 637544961713Sgirish 637644961713Sgirish if (status != 0) { 637744961713Sgirish cmn_err(CE_WARN, 63784045d941Ssowmini "!nxge_mac_register failed (status %d instance %d)", 63794045d941Ssowmini status, nxgep->instance); 638044961713Sgirish return (NXGE_ERROR); 638144961713Sgirish } 638244961713Sgirish 638344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_mac_register success " 63844045d941Ssowmini "(instance %d)", nxgep->instance)); 638544961713Sgirish 638644961713Sgirish return (NXGE_OK); 638744961713Sgirish } 638844961713Sgirish 638944961713Sgirish void 639044961713Sgirish nxge_err_inject(p_nxge_t nxgep, queue_t *wq, mblk_t *mp) 639144961713Sgirish { 639244961713Sgirish ssize_t size; 639344961713Sgirish mblk_t *nmp; 639444961713Sgirish uint8_t blk_id; 639544961713Sgirish uint8_t chan; 639644961713Sgirish uint32_t err_id; 639744961713Sgirish err_inject_t *eip; 639844961713Sgirish 639944961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_err_inject")); 640044961713Sgirish 640144961713Sgirish size = 1024; 640244961713Sgirish nmp = mp->b_cont; 640344961713Sgirish eip = (err_inject_t *)nmp->b_rptr; 640444961713Sgirish blk_id = eip->blk_id; 640544961713Sgirish err_id = eip->err_id; 640644961713Sgirish chan = eip->chan; 640744961713Sgirish cmn_err(CE_NOTE, "!blk_id = 0x%x\n", blk_id); 640844961713Sgirish cmn_err(CE_NOTE, "!err_id = 0x%x\n", err_id); 640944961713Sgirish cmn_err(CE_NOTE, "!chan = 0x%x\n", chan); 641044961713Sgirish switch (blk_id) { 641144961713Sgirish case MAC_BLK_ID: 641244961713Sgirish break; 641344961713Sgirish case TXMAC_BLK_ID: 641444961713Sgirish break; 641544961713Sgirish case RXMAC_BLK_ID: 641644961713Sgirish break; 641744961713Sgirish case MIF_BLK_ID: 641844961713Sgirish break; 641944961713Sgirish case IPP_BLK_ID: 642044961713Sgirish nxge_ipp_inject_err(nxgep, err_id); 642144961713Sgirish break; 642244961713Sgirish case TXC_BLK_ID: 642344961713Sgirish nxge_txc_inject_err(nxgep, err_id); 642444961713Sgirish break; 642544961713Sgirish case TXDMA_BLK_ID: 642644961713Sgirish nxge_txdma_inject_err(nxgep, err_id, chan); 642744961713Sgirish break; 642844961713Sgirish case RXDMA_BLK_ID: 642944961713Sgirish nxge_rxdma_inject_err(nxgep, err_id, chan); 643044961713Sgirish break; 643144961713Sgirish case ZCP_BLK_ID: 643244961713Sgirish nxge_zcp_inject_err(nxgep, err_id); 643344961713Sgirish break; 643444961713Sgirish case ESPC_BLK_ID: 643544961713Sgirish break; 643644961713Sgirish case FFLP_BLK_ID: 643744961713Sgirish break; 643844961713Sgirish case PHY_BLK_ID: 643944961713Sgirish break; 644044961713Sgirish case ETHER_SERDES_BLK_ID: 644144961713Sgirish break; 644244961713Sgirish case PCIE_SERDES_BLK_ID: 644344961713Sgirish break; 644444961713Sgirish case VIR_BLK_ID: 644544961713Sgirish break; 644644961713Sgirish } 644744961713Sgirish 644844961713Sgirish nmp->b_wptr = nmp->b_rptr + size; 644944961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_err_inject")); 645044961713Sgirish 645144961713Sgirish miocack(wq, mp, (int)size, 0); 645244961713Sgirish } 645344961713Sgirish 645444961713Sgirish static int 645544961713Sgirish nxge_init_common_dev(p_nxge_t nxgep) 645644961713Sgirish { 645744961713Sgirish p_nxge_hw_list_t hw_p; 645844961713Sgirish dev_info_t *p_dip; 645944961713Sgirish 646044961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_init_common_device")); 646144961713Sgirish 646244961713Sgirish p_dip = nxgep->p_dip; 646344961713Sgirish MUTEX_ENTER(&nxge_common_lock); 646444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 64654045d941Ssowmini "==> nxge_init_common_dev:func # %d", 64664045d941Ssowmini nxgep->function_num)); 646744961713Sgirish /* 646844961713Sgirish * Loop through existing per neptune hardware list. 646944961713Sgirish */ 647044961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 647144961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 64724045d941Ssowmini "==> nxge_init_common_device:func # %d " 64734045d941Ssowmini "hw_p $%p parent dip $%p", 64744045d941Ssowmini nxgep->function_num, 64754045d941Ssowmini hw_p, 64764045d941Ssowmini p_dip)); 647744961713Sgirish if (hw_p->parent_devp == p_dip) { 647844961713Sgirish nxgep->nxge_hw_p = hw_p; 647944961713Sgirish hw_p->ndevs++; 648044961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 648144961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 64824045d941Ssowmini "==> nxge_init_common_device:func # %d " 64834045d941Ssowmini "hw_p $%p parent dip $%p " 64844045d941Ssowmini "ndevs %d (found)", 64854045d941Ssowmini nxgep->function_num, 64864045d941Ssowmini hw_p, 64874045d941Ssowmini p_dip, 64884045d941Ssowmini hw_p->ndevs)); 648944961713Sgirish break; 649044961713Sgirish } 649144961713Sgirish } 649244961713Sgirish 649344961713Sgirish if (hw_p == NULL) { 649444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 64954045d941Ssowmini "==> nxge_init_common_device:func # %d " 64964045d941Ssowmini "parent dip $%p (new)", 64974045d941Ssowmini nxgep->function_num, 64984045d941Ssowmini p_dip)); 649944961713Sgirish hw_p = kmem_zalloc(sizeof (nxge_hw_list_t), KM_SLEEP); 650044961713Sgirish hw_p->parent_devp = p_dip; 650144961713Sgirish hw_p->magic = NXGE_NEPTUNE_MAGIC; 650244961713Sgirish nxgep->nxge_hw_p = hw_p; 650344961713Sgirish hw_p->ndevs++; 650444961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 650544961713Sgirish hw_p->next = nxge_hw_list; 650659ac0c16Sdavemq if (nxgep->niu_type == N2_NIU) { 650759ac0c16Sdavemq hw_p->niu_type = N2_NIU; 650859ac0c16Sdavemq hw_p->platform_type = P_NEPTUNE_NIU; 650959ac0c16Sdavemq } else { 651059ac0c16Sdavemq hw_p->niu_type = NIU_TYPE_NONE; 65112e59129aSraghus hw_p->platform_type = P_NEPTUNE_NONE; 651259ac0c16Sdavemq } 651344961713Sgirish 651444961713Sgirish MUTEX_INIT(&hw_p->nxge_cfg_lock, NULL, MUTEX_DRIVER, NULL); 651544961713Sgirish MUTEX_INIT(&hw_p->nxge_tcam_lock, NULL, MUTEX_DRIVER, NULL); 651644961713Sgirish MUTEX_INIT(&hw_p->nxge_vlan_lock, NULL, MUTEX_DRIVER, NULL); 651744961713Sgirish MUTEX_INIT(&hw_p->nxge_mdio_lock, NULL, MUTEX_DRIVER, NULL); 651844961713Sgirish 651944961713Sgirish nxge_hw_list = hw_p; 652059ac0c16Sdavemq 652159ac0c16Sdavemq (void) nxge_scan_ports_phy(nxgep, nxge_hw_list); 652244961713Sgirish } 652344961713Sgirish 652444961713Sgirish MUTEX_EXIT(&nxge_common_lock); 652559ac0c16Sdavemq 65262e59129aSraghus nxgep->platform_type = hw_p->platform_type; 652759ac0c16Sdavemq if (nxgep->niu_type != N2_NIU) { 652859ac0c16Sdavemq nxgep->niu_type = hw_p->niu_type; 652959ac0c16Sdavemq } 653059ac0c16Sdavemq 653144961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65324045d941Ssowmini "==> nxge_init_common_device (nxge_hw_list) $%p", 65334045d941Ssowmini nxge_hw_list)); 653444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<== nxge_init_common_device")); 653544961713Sgirish 653644961713Sgirish return (NXGE_OK); 653744961713Sgirish } 653844961713Sgirish 653944961713Sgirish static void 654044961713Sgirish nxge_uninit_common_dev(p_nxge_t nxgep) 654144961713Sgirish { 654244961713Sgirish p_nxge_hw_list_t hw_p, h_hw_p; 65430b0beae0Sspeer p_nxge_dma_pt_cfg_t p_dma_cfgp; 65440b0beae0Sspeer p_nxge_hw_pt_cfg_t p_cfgp; 654544961713Sgirish dev_info_t *p_dip; 654644961713Sgirish 654744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_uninit_common_device")); 654844961713Sgirish if (nxgep->nxge_hw_p == NULL) { 654944961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65504045d941Ssowmini "<== nxge_uninit_common_device (no common)")); 655144961713Sgirish return; 655244961713Sgirish } 655344961713Sgirish 655444961713Sgirish MUTEX_ENTER(&nxge_common_lock); 655544961713Sgirish h_hw_p = nxge_hw_list; 655644961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 655744961713Sgirish p_dip = hw_p->parent_devp; 655844961713Sgirish if (nxgep->nxge_hw_p == hw_p && 65594045d941Ssowmini p_dip == nxgep->p_dip && 65604045d941Ssowmini nxgep->nxge_hw_p->magic == NXGE_NEPTUNE_MAGIC && 65614045d941Ssowmini hw_p->magic == NXGE_NEPTUNE_MAGIC) { 656244961713Sgirish 656344961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65644045d941Ssowmini "==> nxge_uninit_common_device:func # %d " 65654045d941Ssowmini "hw_p $%p parent dip $%p " 65664045d941Ssowmini "ndevs %d (found)", 65674045d941Ssowmini nxgep->function_num, 65684045d941Ssowmini hw_p, 65694045d941Ssowmini p_dip, 65704045d941Ssowmini hw_p->ndevs)); 657144961713Sgirish 65720b0beae0Sspeer /* 65730b0beae0Sspeer * Release the RDC table, a shared resoruce 65740b0beae0Sspeer * of the nxge hardware. The RDC table was 65750b0beae0Sspeer * assigned to this instance of nxge in 65760b0beae0Sspeer * nxge_use_cfg_dma_config(). 65770b0beae0Sspeer */ 65789d5b8bc5SMichael Speer if (!isLDOMguest(nxgep)) { 65799d5b8bc5SMichael Speer p_dma_cfgp = 65809d5b8bc5SMichael Speer (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 65819d5b8bc5SMichael Speer p_cfgp = 65829d5b8bc5SMichael Speer (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; 65839d5b8bc5SMichael Speer (void) nxge_fzc_rdc_tbl_unbind(nxgep, 65849d5b8bc5SMichael Speer p_cfgp->def_mac_rxdma_grpid); 6585*651ce697SMichael Speer 6586*651ce697SMichael Speer /* Cleanup any outstanding groups. */ 6587*651ce697SMichael Speer nxge_grp_cleanup(nxgep); 65889d5b8bc5SMichael Speer } 65890b0beae0Sspeer 659044961713Sgirish if (hw_p->ndevs) { 659144961713Sgirish hw_p->ndevs--; 659244961713Sgirish } 659344961713Sgirish hw_p->nxge_p[nxgep->function_num] = NULL; 659444961713Sgirish if (!hw_p->ndevs) { 659544961713Sgirish MUTEX_DESTROY(&hw_p->nxge_vlan_lock); 659644961713Sgirish MUTEX_DESTROY(&hw_p->nxge_tcam_lock); 659744961713Sgirish MUTEX_DESTROY(&hw_p->nxge_cfg_lock); 659844961713Sgirish MUTEX_DESTROY(&hw_p->nxge_mdio_lock); 659944961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66004045d941Ssowmini "==> nxge_uninit_common_device: " 66014045d941Ssowmini "func # %d " 66024045d941Ssowmini "hw_p $%p parent dip $%p " 66034045d941Ssowmini "ndevs %d (last)", 66044045d941Ssowmini nxgep->function_num, 66054045d941Ssowmini hw_p, 66064045d941Ssowmini p_dip, 66074045d941Ssowmini hw_p->ndevs)); 660844961713Sgirish 6609678453a8Sspeer nxge_hio_uninit(nxgep); 6610678453a8Sspeer 661144961713Sgirish if (hw_p == nxge_hw_list) { 661244961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66134045d941Ssowmini "==> nxge_uninit_common_device:" 66144045d941Ssowmini "remove head func # %d " 66154045d941Ssowmini "hw_p $%p parent dip $%p " 66164045d941Ssowmini "ndevs %d (head)", 66174045d941Ssowmini nxgep->function_num, 66184045d941Ssowmini hw_p, 66194045d941Ssowmini p_dip, 66204045d941Ssowmini hw_p->ndevs)); 662144961713Sgirish nxge_hw_list = hw_p->next; 662244961713Sgirish } else { 662344961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66244045d941Ssowmini "==> nxge_uninit_common_device:" 66254045d941Ssowmini "remove middle func # %d " 66264045d941Ssowmini "hw_p $%p parent dip $%p " 66274045d941Ssowmini "ndevs %d (middle)", 66284045d941Ssowmini nxgep->function_num, 66294045d941Ssowmini hw_p, 66304045d941Ssowmini p_dip, 66314045d941Ssowmini hw_p->ndevs)); 663244961713Sgirish h_hw_p->next = hw_p->next; 663344961713Sgirish } 663444961713Sgirish 6635678453a8Sspeer nxgep->nxge_hw_p = NULL; 663644961713Sgirish KMEM_FREE(hw_p, sizeof (nxge_hw_list_t)); 663744961713Sgirish } 663844961713Sgirish break; 663944961713Sgirish } else { 664044961713Sgirish h_hw_p = hw_p; 664144961713Sgirish } 664244961713Sgirish } 664344961713Sgirish 664444961713Sgirish MUTEX_EXIT(&nxge_common_lock); 664544961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66464045d941Ssowmini "==> nxge_uninit_common_device (nxge_hw_list) $%p", 66474045d941Ssowmini nxge_hw_list)); 664844961713Sgirish 664944961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<= nxge_uninit_common_device")); 665044961713Sgirish } 665159ac0c16Sdavemq 665259ac0c16Sdavemq /* 66532e59129aSraghus * Determines the number of ports from the niu_type or the platform type. 665459ac0c16Sdavemq * Returns the number of ports, or returns zero on failure. 665559ac0c16Sdavemq */ 665659ac0c16Sdavemq 665759ac0c16Sdavemq int 66582e59129aSraghus nxge_get_nports(p_nxge_t nxgep) 665959ac0c16Sdavemq { 666059ac0c16Sdavemq int nports = 0; 666159ac0c16Sdavemq 66622e59129aSraghus switch (nxgep->niu_type) { 666359ac0c16Sdavemq case N2_NIU: 666459ac0c16Sdavemq case NEPTUNE_2_10GF: 666559ac0c16Sdavemq nports = 2; 666659ac0c16Sdavemq break; 666759ac0c16Sdavemq case NEPTUNE_4_1GC: 666859ac0c16Sdavemq case NEPTUNE_2_10GF_2_1GC: 666959ac0c16Sdavemq case NEPTUNE_1_10GF_3_1GC: 667059ac0c16Sdavemq case NEPTUNE_1_1GC_1_10GF_2_1GC: 667159a835ddSjoycey case NEPTUNE_2_10GF_2_1GRF: 667259ac0c16Sdavemq nports = 4; 667359ac0c16Sdavemq break; 667459ac0c16Sdavemq default: 66752e59129aSraghus switch (nxgep->platform_type) { 66762e59129aSraghus case P_NEPTUNE_NIU: 66772e59129aSraghus case P_NEPTUNE_ATLAS_2PORT: 66782e59129aSraghus nports = 2; 66792e59129aSraghus break; 66802e59129aSraghus case P_NEPTUNE_ATLAS_4PORT: 66812e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 66822e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 6683d81011f0Ssbehera case P_NEPTUNE_ALONSO: 66842e59129aSraghus nports = 4; 66852e59129aSraghus break; 66862e59129aSraghus default: 66872e59129aSraghus break; 66882e59129aSraghus } 668959ac0c16Sdavemq break; 669059ac0c16Sdavemq } 669159ac0c16Sdavemq 669259ac0c16Sdavemq return (nports); 669359ac0c16Sdavemq } 6694ec090658Sml 6695ec090658Sml /* 6696ec090658Sml * The following two functions are to support 6697ec090658Sml * PSARC/2007/453 MSI-X interrupt limit override. 6698ec090658Sml */ 6699ec090658Sml static int 6700ec090658Sml nxge_create_msi_property(p_nxge_t nxgep) 6701ec090658Sml { 6702ec090658Sml int nmsi; 6703ec090658Sml extern int ncpus; 6704ec090658Sml 6705ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==>nxge_create_msi_property")); 6706ec090658Sml 6707ec090658Sml switch (nxgep->mac.portmode) { 6708ec090658Sml case PORT_10G_COPPER: 6709ec090658Sml case PORT_10G_FIBER: 671000161856Syc case PORT_10G_TN1010: 6711ec090658Sml (void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip, 6712ec090658Sml DDI_PROP_CANSLEEP, "#msix-request", NULL, 0); 6713ec090658Sml /* 6714ec090658Sml * The maximum MSI-X requested will be 8. 6715ec090658Sml * If the # of CPUs is less than 8, we will reqeust 6716ec090658Sml * # MSI-X based on the # of CPUs. 6717ec090658Sml */ 6718ec090658Sml if (ncpus >= NXGE_MSIX_REQUEST_10G) { 6719ec090658Sml nmsi = NXGE_MSIX_REQUEST_10G; 6720ec090658Sml } else { 6721ec090658Sml nmsi = ncpus; 6722ec090658Sml } 6723ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6724ec090658Sml "==>nxge_create_msi_property(10G): exists 0x%x (nmsi %d)", 6725ec090658Sml ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 6726ec090658Sml DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 6727ec090658Sml break; 6728ec090658Sml 6729ec090658Sml default: 6730ec090658Sml nmsi = NXGE_MSIX_REQUEST_1G; 6731ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6732ec090658Sml "==>nxge_create_msi_property(1G): exists 0x%x (nmsi %d)", 6733ec090658Sml ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 6734ec090658Sml DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 6735ec090658Sml break; 6736ec090658Sml } 6737ec090658Sml 6738ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<==nxge_create_msi_property")); 6739ec090658Sml return (nmsi); 6740ec090658Sml } 67414045d941Ssowmini 67424045d941Ssowmini /* ARGSUSED */ 67434045d941Ssowmini static int 67444045d941Ssowmini nxge_get_def_val(nxge_t *nxgep, mac_prop_id_t pr_num, uint_t pr_valsize, 67454045d941Ssowmini void *pr_val) 67464045d941Ssowmini { 67474045d941Ssowmini int err = 0; 67484045d941Ssowmini link_flowctrl_t fl; 67494045d941Ssowmini 67504045d941Ssowmini switch (pr_num) { 67513fd94f8cSam case MAC_PROP_AUTONEG: 67524045d941Ssowmini *(uint8_t *)pr_val = 1; 67534045d941Ssowmini break; 67543fd94f8cSam case MAC_PROP_FLOWCTRL: 67554045d941Ssowmini if (pr_valsize < sizeof (link_flowctrl_t)) 67564045d941Ssowmini return (EINVAL); 67574045d941Ssowmini fl = LINK_FLOWCTRL_RX; 67584045d941Ssowmini bcopy(&fl, pr_val, sizeof (fl)); 67594045d941Ssowmini break; 67603fd94f8cSam case MAC_PROP_ADV_1000FDX_CAP: 67613fd94f8cSam case MAC_PROP_EN_1000FDX_CAP: 67624045d941Ssowmini *(uint8_t *)pr_val = 1; 67634045d941Ssowmini break; 67643fd94f8cSam case MAC_PROP_ADV_100FDX_CAP: 67653fd94f8cSam case MAC_PROP_EN_100FDX_CAP: 67664045d941Ssowmini *(uint8_t *)pr_val = 1; 67674045d941Ssowmini break; 67684045d941Ssowmini default: 67694045d941Ssowmini err = ENOTSUP; 67704045d941Ssowmini break; 67714045d941Ssowmini } 67724045d941Ssowmini return (err); 67734045d941Ssowmini } 67746f157acbSml 67756f157acbSml 67766f157acbSml /* 67776f157acbSml * The following is a software around for the Neptune hardware's 67786f157acbSml * interrupt bugs; The Neptune hardware may generate spurious interrupts when 67796f157acbSml * an interrupr handler is removed. 67806f157acbSml */ 67816f157acbSml #define NXGE_PCI_PORT_LOGIC_OFFSET 0x98 67826f157acbSml #define NXGE_PIM_RESET (1ULL << 29) 67836f157acbSml #define NXGE_GLU_RESET (1ULL << 30) 67846f157acbSml #define NXGE_NIU_RESET (1ULL << 31) 67856f157acbSml #define NXGE_PCI_RESET_ALL (NXGE_PIM_RESET | \ 67866f157acbSml NXGE_GLU_RESET | \ 67876f157acbSml NXGE_NIU_RESET) 67886f157acbSml 67896f157acbSml #define NXGE_WAIT_QUITE_TIME 200000 67906f157acbSml #define NXGE_WAIT_QUITE_RETRY 40 67916f157acbSml #define NXGE_PCI_RESET_WAIT 1000000 /* one second */ 67926f157acbSml 67936f157acbSml static void 67946f157acbSml nxge_niu_peu_reset(p_nxge_t nxgep) 67956f157acbSml { 67966f157acbSml uint32_t rvalue; 67976f157acbSml p_nxge_hw_list_t hw_p; 67986f157acbSml p_nxge_t fnxgep; 67996f157acbSml int i, j; 68006f157acbSml 68016f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_niu_peu_reset")); 68026f157acbSml if ((hw_p = nxgep->nxge_hw_p) == NULL) { 68036f157acbSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 68046f157acbSml "==> nxge_niu_peu_reset: NULL hardware pointer")); 68056f157acbSml return; 68066f157acbSml } 68076f157acbSml 68086f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 68096f157acbSml "==> nxge_niu_peu_reset: flags 0x%x link timer id %d timer id %d", 68106f157acbSml hw_p->flags, nxgep->nxge_link_poll_timerid, 68116f157acbSml nxgep->nxge_timerid)); 68126f157acbSml 68136f157acbSml MUTEX_ENTER(&hw_p->nxge_cfg_lock); 68146f157acbSml /* 68156f157acbSml * Make sure other instances from the same hardware 68166f157acbSml * stop sending PIO and in quiescent state. 68176f157acbSml */ 68186f157acbSml for (i = 0; i < NXGE_MAX_PORTS; i++) { 68196f157acbSml fnxgep = hw_p->nxge_p[i]; 68206f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 68216f157acbSml "==> nxge_niu_peu_reset: checking entry %d " 68226f157acbSml "nxgep $%p", i, fnxgep)); 68236f157acbSml #ifdef NXGE_DEBUG 68246f157acbSml if (fnxgep) { 68256f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 68266f157acbSml "==> nxge_niu_peu_reset: entry %d (function %d) " 68276f157acbSml "link timer id %d hw timer id %d", 68286f157acbSml i, fnxgep->function_num, 68296f157acbSml fnxgep->nxge_link_poll_timerid, 68306f157acbSml fnxgep->nxge_timerid)); 68316f157acbSml } 68326f157acbSml #endif 68336f157acbSml if (fnxgep && fnxgep != nxgep && 68346f157acbSml (fnxgep->nxge_timerid || fnxgep->nxge_link_poll_timerid)) { 68356f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 68366f157acbSml "==> nxge_niu_peu_reset: checking $%p " 68376f157acbSml "(function %d) timer ids", 68386f157acbSml fnxgep, fnxgep->function_num)); 68396f157acbSml for (j = 0; j < NXGE_WAIT_QUITE_RETRY; j++) { 68406f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 68416f157acbSml "==> nxge_niu_peu_reset: waiting")); 68426f157acbSml NXGE_DELAY(NXGE_WAIT_QUITE_TIME); 68436f157acbSml if (!fnxgep->nxge_timerid && 68446f157acbSml !fnxgep->nxge_link_poll_timerid) { 68456f157acbSml break; 68466f157acbSml } 68476f157acbSml } 68486f157acbSml NXGE_DELAY(NXGE_WAIT_QUITE_TIME); 68496f157acbSml if (fnxgep->nxge_timerid || 68506f157acbSml fnxgep->nxge_link_poll_timerid) { 68516f157acbSml MUTEX_EXIT(&hw_p->nxge_cfg_lock); 68526f157acbSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 68536f157acbSml "<== nxge_niu_peu_reset: cannot reset " 68546f157acbSml "hardware (devices are still in use)")); 68556f157acbSml return; 68566f157acbSml } 68576f157acbSml } 68586f157acbSml } 68596f157acbSml 68606f157acbSml if ((hw_p->flags & COMMON_RESET_NIU_PCI) != COMMON_RESET_NIU_PCI) { 68616f157acbSml hw_p->flags |= COMMON_RESET_NIU_PCI; 68626f157acbSml rvalue = pci_config_get32(nxgep->dev_regs->nxge_pciregh, 68636f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET); 68646f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 68656f157acbSml "nxge_niu_peu_reset: read offset 0x%x (%d) " 68666f157acbSml "(data 0x%x)", 68676f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, 68686f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, 68696f157acbSml rvalue)); 68706f157acbSml 68716f157acbSml rvalue |= NXGE_PCI_RESET_ALL; 68726f157acbSml pci_config_put32(nxgep->dev_regs->nxge_pciregh, 68736f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, rvalue); 68746f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 68756f157acbSml "nxge_niu_peu_reset: RESETTING NIU: write NIU reset 0x%x", 68766f157acbSml rvalue)); 68776f157acbSml 68786f157acbSml NXGE_DELAY(NXGE_PCI_RESET_WAIT); 68796f157acbSml } 68806f157acbSml 68816f157acbSml MUTEX_EXIT(&hw_p->nxge_cfg_lock); 68826f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_niu_peu_reset")); 68836f157acbSml } 6884d6d3405fSml 6885d6d3405fSml static void 6886d6d3405fSml nxge_set_pci_replay_timeout(p_nxge_t nxgep) 6887d6d3405fSml { 6888d6d3405fSml p_dev_regs_t dev_regs; 6889d6d3405fSml uint32_t value; 6890d6d3405fSml 6891d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_set_pci_replay_timeout")); 6892d6d3405fSml 6893d6d3405fSml if (!nxge_set_replay_timer) { 6894d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 6895d6d3405fSml "==> nxge_set_pci_replay_timeout: will not change " 6896d6d3405fSml "the timeout")); 6897d6d3405fSml return; 6898d6d3405fSml } 6899d6d3405fSml 6900d6d3405fSml dev_regs = nxgep->dev_regs; 6901d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 6902d6d3405fSml "==> nxge_set_pci_replay_timeout: dev_regs 0x%p pcireg 0x%p", 6903d6d3405fSml dev_regs, dev_regs->nxge_pciregh)); 6904d6d3405fSml 6905d6d3405fSml if (dev_regs == NULL || (dev_regs->nxge_pciregh == NULL)) { 6906f720bc57Syc NXGE_DEBUG_MSG((nxgep, DDI_CTL, 6907d6d3405fSml "==> nxge_set_pci_replay_timeout: NULL dev_regs $%p or " 6908d6d3405fSml "no PCI handle", 6909d6d3405fSml dev_regs)); 6910d6d3405fSml return; 6911d6d3405fSml } 6912d6d3405fSml value = (pci_config_get32(dev_regs->nxge_pciregh, 6913d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET) | 6914d6d3405fSml (nxge_replay_timeout << PCI_REPLAY_TIMEOUT_SHIFT)); 6915d6d3405fSml 6916d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 6917d6d3405fSml "nxge_set_pci_replay_timeout: replay timeout value before set 0x%x " 6918d6d3405fSml "(timeout value to set 0x%x at offset 0x%x) value 0x%x", 6919d6d3405fSml pci_config_get32(dev_regs->nxge_pciregh, 6920d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET), nxge_replay_timeout, 6921d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET, value)); 6922d6d3405fSml 6923d6d3405fSml pci_config_put32(dev_regs->nxge_pciregh, PCI_REPLAY_TIMEOUT_CFG_OFFSET, 6924d6d3405fSml value); 6925d6d3405fSml 6926d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 6927d6d3405fSml "nxge_set_pci_replay_timeout: replay timeout value after set 0x%x", 6928d6d3405fSml pci_config_get32(dev_regs->nxge_pciregh, 6929d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET))); 6930d6d3405fSml 6931d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_set_pci_replay_timeout")); 6932d6d3405fSml } 693319397407SSherry Moore 693419397407SSherry Moore /* 693519397407SSherry Moore * quiesce(9E) entry point. 693619397407SSherry Moore * 693719397407SSherry Moore * This function is called when the system is single-threaded at high 693819397407SSherry Moore * PIL with preemption disabled. Therefore, this function must not be 693919397407SSherry Moore * blocked. 694019397407SSherry Moore * 694119397407SSherry Moore * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 694219397407SSherry Moore * DDI_FAILURE indicates an error condition and should almost never happen. 694319397407SSherry Moore */ 694419397407SSherry Moore static int 694519397407SSherry Moore nxge_quiesce(dev_info_t *dip) 694619397407SSherry Moore { 694719397407SSherry Moore int instance = ddi_get_instance(dip); 694819397407SSherry Moore p_nxge_t nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 694919397407SSherry Moore 695019397407SSherry Moore if (nxgep == NULL) 695119397407SSherry Moore return (DDI_FAILURE); 695219397407SSherry Moore 695319397407SSherry Moore /* Turn off debugging */ 695419397407SSherry Moore nxge_debug_level = NO_DEBUG; 695519397407SSherry Moore nxgep->nxge_debug_level = NO_DEBUG; 695619397407SSherry Moore npi_debug_level = NO_DEBUG; 695719397407SSherry Moore 695819397407SSherry Moore /* 695919397407SSherry Moore * Stop link monitor only when linkchkmod is interrupt based 696019397407SSherry Moore */ 696119397407SSherry Moore if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 696219397407SSherry Moore (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 696319397407SSherry Moore } 696419397407SSherry Moore 696519397407SSherry Moore (void) nxge_intr_hw_disable(nxgep); 696619397407SSherry Moore 696719397407SSherry Moore /* 696819397407SSherry Moore * Reset the receive MAC side. 696919397407SSherry Moore */ 697019397407SSherry Moore (void) nxge_rx_mac_disable(nxgep); 697119397407SSherry Moore 697219397407SSherry Moore /* Disable and soft reset the IPP */ 697319397407SSherry Moore if (!isLDOMguest(nxgep)) 697419397407SSherry Moore (void) nxge_ipp_disable(nxgep); 697519397407SSherry Moore 697619397407SSherry Moore /* 697719397407SSherry Moore * Reset the transmit/receive DMA side. 697819397407SSherry Moore */ 697919397407SSherry Moore (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 698019397407SSherry Moore (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 698119397407SSherry Moore 698219397407SSherry Moore /* 698319397407SSherry Moore * Reset the transmit MAC side. 698419397407SSherry Moore */ 698519397407SSherry Moore (void) nxge_tx_mac_disable(nxgep); 698619397407SSherry Moore 698719397407SSherry Moore return (DDI_SUCCESS); 698819397407SSherry Moore } 6989