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 /* 12244961713Sgirish * Add tunable to reduce the amount of time spent in the 12344961713Sgirish * ISR doing Rx Processing. 12444961713Sgirish */ 12544961713Sgirish uint32_t nxge_max_rx_pkts = 1024; 12644961713Sgirish 12744961713Sgirish /* 12844961713Sgirish * Tunables to manage the receive buffer blocks. 12944961713Sgirish * 13044961713Sgirish * nxge_rx_threshold_hi: copy all buffers. 13144961713Sgirish * nxge_rx_bcopy_size_type: receive buffer block size type. 13244961713Sgirish * nxge_rx_threshold_lo: copy only up to tunable block size type. 13344961713Sgirish */ 13444961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_hi = NXGE_RX_COPY_6; 13544961713Sgirish nxge_rxbuf_type_t nxge_rx_buf_size_type = RCR_PKTBUFSZ_0; 13644961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_lo = NXGE_RX_COPY_3; 13744961713Sgirish 138678453a8Sspeer /* Use kmem_alloc() to allocate data buffers. */ 139b1000363Sml #if defined(_BIG_ENDIAN) 140d00f30bbSspeer uint32_t nxge_use_kmem_alloc = 1; 141678453a8Sspeer #else 142d00f30bbSspeer uint32_t nxge_use_kmem_alloc = 0; 143678453a8Sspeer #endif 144678453a8Sspeer 14544961713Sgirish rtrace_t npi_rtracebuf; 14644961713Sgirish 147d6d3405fSml /* 148d6d3405fSml * The hardware sometimes fails to allow enough time for the link partner 149d6d3405fSml * to send an acknowledgement for packets that the hardware sent to it. The 150d6d3405fSml * hardware resends the packets earlier than it should be in those instances. 151d6d3405fSml * This behavior caused some switches to acknowledge the wrong packets 152d6d3405fSml * and it triggered the fatal error. 153d6d3405fSml * This software workaround is to set the replay timer to a value 154d6d3405fSml * suggested by the hardware team. 155d6d3405fSml * 156d6d3405fSml * PCI config space replay timer register: 157d6d3405fSml * The following replay timeout value is 0xc 158d6d3405fSml * for bit 14:18. 159d6d3405fSml */ 160d6d3405fSml #define PCI_REPLAY_TIMEOUT_CFG_OFFSET 0xb8 161d6d3405fSml #define PCI_REPLAY_TIMEOUT_SHIFT 14 162d6d3405fSml 163d6d3405fSml uint32_t nxge_set_replay_timer = 1; 164d6d3405fSml uint32_t nxge_replay_timeout = 0xc; 165d6d3405fSml 166cf020df9Sml /* 167cf020df9Sml * The transmit serialization sometimes causes 168cf020df9Sml * longer sleep before calling the driver transmit 169cf020df9Sml * function as it sleeps longer than it should. 170cf020df9Sml * The performace group suggests that a time wait tunable 171cf020df9Sml * can be used to set the maximum wait time when needed 172cf020df9Sml * and the default is set to 1 tick. 173cf020df9Sml */ 174cf020df9Sml uint32_t nxge_tx_serial_maxsleep = 1; 175cf020df9Sml 17644961713Sgirish #if defined(sun4v) 17744961713Sgirish /* 17844961713Sgirish * Hypervisor N2/NIU services information. 17944961713Sgirish */ 18044961713Sgirish static hsvc_info_t niu_hsvc = { 18144961713Sgirish HSVC_REV_1, NULL, HSVC_GROUP_NIU, NIU_MAJOR_VER, 18244961713Sgirish NIU_MINOR_VER, "nxge" 18344961713Sgirish }; 184678453a8Sspeer 185678453a8Sspeer static int nxge_hsvc_register(p_nxge_t); 18644961713Sgirish #endif 18744961713Sgirish 18844961713Sgirish /* 18944961713Sgirish * Function Prototypes 19044961713Sgirish */ 19144961713Sgirish static int nxge_attach(dev_info_t *, ddi_attach_cmd_t); 19244961713Sgirish static int nxge_detach(dev_info_t *, ddi_detach_cmd_t); 19344961713Sgirish static void nxge_unattach(p_nxge_t); 19419397407SSherry Moore static int nxge_quiesce(dev_info_t *); 19544961713Sgirish 19644961713Sgirish #if NXGE_PROPERTY 19744961713Sgirish static void nxge_remove_hard_properties(p_nxge_t); 19844961713Sgirish #endif 19944961713Sgirish 200678453a8Sspeer /* 201678453a8Sspeer * These two functions are required by nxge_hio.c 202678453a8Sspeer */ 203*da14cebeSEric Cheng extern int nxge_m_mmac_remove(void *arg, int slot); 204651ce697SMichael Speer extern void nxge_grp_cleanup(p_nxge_t nxge); 205678453a8Sspeer 20644961713Sgirish static nxge_status_t nxge_setup_system_dma_pages(p_nxge_t); 20744961713Sgirish 20844961713Sgirish static nxge_status_t nxge_setup_mutexes(p_nxge_t); 20944961713Sgirish static void nxge_destroy_mutexes(p_nxge_t); 21044961713Sgirish 21144961713Sgirish static nxge_status_t nxge_map_regs(p_nxge_t nxgep); 21244961713Sgirish static void nxge_unmap_regs(p_nxge_t nxgep); 21344961713Sgirish #ifdef NXGE_DEBUG 21444961713Sgirish static void nxge_test_map_regs(p_nxge_t nxgep); 21544961713Sgirish #endif 21644961713Sgirish 21744961713Sgirish static nxge_status_t nxge_add_intrs(p_nxge_t nxgep); 21844961713Sgirish static void nxge_remove_intrs(p_nxge_t nxgep); 21944961713Sgirish 22044961713Sgirish static nxge_status_t nxge_add_intrs_adv(p_nxge_t nxgep); 22144961713Sgirish static nxge_status_t nxge_add_intrs_adv_type(p_nxge_t, uint32_t); 22244961713Sgirish static nxge_status_t nxge_add_intrs_adv_type_fix(p_nxge_t, uint32_t); 22344961713Sgirish static void nxge_intrs_enable(p_nxge_t nxgep); 22444961713Sgirish static void nxge_intrs_disable(p_nxge_t nxgep); 22544961713Sgirish 22644961713Sgirish static void nxge_suspend(p_nxge_t); 22744961713Sgirish static nxge_status_t nxge_resume(p_nxge_t); 22844961713Sgirish 22944961713Sgirish static nxge_status_t nxge_setup_dev(p_nxge_t); 23044961713Sgirish static void nxge_destroy_dev(p_nxge_t); 23144961713Sgirish 23244961713Sgirish static nxge_status_t nxge_alloc_mem_pool(p_nxge_t); 23344961713Sgirish static void nxge_free_mem_pool(p_nxge_t); 23444961713Sgirish 235678453a8Sspeer nxge_status_t nxge_alloc_rx_mem_pool(p_nxge_t); 23644961713Sgirish static void nxge_free_rx_mem_pool(p_nxge_t); 23744961713Sgirish 238678453a8Sspeer nxge_status_t nxge_alloc_tx_mem_pool(p_nxge_t); 23944961713Sgirish static void nxge_free_tx_mem_pool(p_nxge_t); 24044961713Sgirish 24144961713Sgirish static nxge_status_t nxge_dma_mem_alloc(p_nxge_t, dma_method_t, 24244961713Sgirish struct ddi_dma_attr *, 24344961713Sgirish size_t, ddi_device_acc_attr_t *, uint_t, 24444961713Sgirish p_nxge_dma_common_t); 24544961713Sgirish 24644961713Sgirish static void nxge_dma_mem_free(p_nxge_dma_common_t); 247678453a8Sspeer static void nxge_dma_free_rx_data_buf(p_nxge_dma_common_t); 24844961713Sgirish 24944961713Sgirish static nxge_status_t nxge_alloc_rx_buf_dma(p_nxge_t, uint16_t, 25044961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 25144961713Sgirish static void nxge_free_rx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 25244961713Sgirish 25344961713Sgirish static nxge_status_t nxge_alloc_rx_cntl_dma(p_nxge_t, uint16_t, 25444961713Sgirish p_nxge_dma_common_t *, size_t); 25544961713Sgirish static void nxge_free_rx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 25644961713Sgirish 257678453a8Sspeer extern nxge_status_t nxge_alloc_tx_buf_dma(p_nxge_t, uint16_t, 25844961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 25944961713Sgirish static void nxge_free_tx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 26044961713Sgirish 261678453a8Sspeer extern nxge_status_t nxge_alloc_tx_cntl_dma(p_nxge_t, uint16_t, 26244961713Sgirish p_nxge_dma_common_t *, 26344961713Sgirish size_t); 26444961713Sgirish static void nxge_free_tx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 26544961713Sgirish 26644961713Sgirish static int nxge_init_common_dev(p_nxge_t); 26744961713Sgirish static void nxge_uninit_common_dev(p_nxge_t); 2684045d941Ssowmini extern int nxge_param_set_mac(p_nxge_t, queue_t *, mblk_t *, 2694045d941Ssowmini char *, caddr_t); 27044961713Sgirish 27144961713Sgirish /* 27244961713Sgirish * The next declarations are for the GLDv3 interface. 27344961713Sgirish */ 27444961713Sgirish static int nxge_m_start(void *); 27544961713Sgirish static void nxge_m_stop(void *); 27644961713Sgirish static int nxge_m_multicst(void *, boolean_t, const uint8_t *); 27744961713Sgirish static int nxge_m_promisc(void *, boolean_t); 27844961713Sgirish static void nxge_m_ioctl(void *, queue_t *, mblk_t *); 27944961713Sgirish static nxge_status_t nxge_mac_register(p_nxge_t); 280*da14cebeSEric Cheng static int nxge_altmac_set(p_nxge_t nxgep, uint8_t *mac_addr, 281*da14cebeSEric Cheng int slot, int rdctbl, boolean_t usetbl); 282*da14cebeSEric Cheng void nxge_mmac_kstat_update(p_nxge_t nxgep, int slot, 28358324dfcSspeer boolean_t factory); 284*da14cebeSEric Cheng #if defined(sun4v) 285*da14cebeSEric Cheng extern mblk_t *nxge_m_tx(void *arg, mblk_t *mp); 286*da14cebeSEric Cheng #endif 287*da14cebeSEric Cheng 288*da14cebeSEric Cheng static void nxge_m_getfactaddr(void *, uint_t, uint8_t *); 2891bd6825cSml static boolean_t nxge_m_getcapab(void *, mac_capab_t, void *); 2901bd6825cSml static int nxge_m_setprop(void *, const char *, mac_prop_id_t, 2911bd6825cSml uint_t, const void *); 2921bd6825cSml static int nxge_m_getprop(void *, const char *, mac_prop_id_t, 293afdda45fSVasumathi Sundaram - Sun Microsystems uint_t, uint_t, void *, uint_t *); 2941bd6825cSml static int nxge_set_priv_prop(nxge_t *, const char *, uint_t, 2951bd6825cSml const void *); 2964045d941Ssowmini static int nxge_get_priv_prop(nxge_t *, const char *, uint_t, uint_t, 297afdda45fSVasumathi Sundaram - Sun Microsystems void *, uint_t *); 2984045d941Ssowmini static int nxge_get_def_val(nxge_t *, mac_prop_id_t, uint_t, void *); 299*da14cebeSEric Cheng static void nxge_fill_ring(void *, mac_ring_type_t, const int, const int, 300*da14cebeSEric Cheng mac_ring_info_t *, mac_ring_handle_t); 301*da14cebeSEric Cheng static void nxge_group_add_ring(mac_group_driver_t, mac_ring_driver_t, 302*da14cebeSEric Cheng mac_ring_type_t); 303*da14cebeSEric Cheng static void nxge_group_rem_ring(mac_group_driver_t, mac_ring_driver_t, 304*da14cebeSEric Cheng mac_ring_type_t); 3054045d941Ssowmini 3066f157acbSml static void nxge_niu_peu_reset(p_nxge_t nxgep); 307d6d3405fSml static void nxge_set_pci_replay_timeout(nxge_t *); 3084045d941Ssowmini 3094045d941Ssowmini mac_priv_prop_t nxge_priv_props[] = { 3104045d941Ssowmini {"_adv_10gfdx_cap", MAC_PROP_PERM_RW}, 3114045d941Ssowmini {"_adv_pause_cap", MAC_PROP_PERM_RW}, 3124045d941Ssowmini {"_function_number", MAC_PROP_PERM_READ}, 3134045d941Ssowmini {"_fw_version", MAC_PROP_PERM_READ}, 3144045d941Ssowmini {"_port_mode", MAC_PROP_PERM_READ}, 3154045d941Ssowmini {"_hot_swap_phy", MAC_PROP_PERM_READ}, 3164045d941Ssowmini {"_accept_jumbo", MAC_PROP_PERM_RW}, 3174045d941Ssowmini {"_rxdma_intr_time", MAC_PROP_PERM_RW}, 3184045d941Ssowmini {"_rxdma_intr_pkts", MAC_PROP_PERM_RW}, 3194045d941Ssowmini {"_class_opt_ipv4_tcp", MAC_PROP_PERM_RW}, 3204045d941Ssowmini {"_class_opt_ipv4_udp", MAC_PROP_PERM_RW}, 3214045d941Ssowmini {"_class_opt_ipv4_ah", MAC_PROP_PERM_RW}, 3224045d941Ssowmini {"_class_opt_ipv4_sctp", MAC_PROP_PERM_RW}, 3234045d941Ssowmini {"_class_opt_ipv6_tcp", MAC_PROP_PERM_RW}, 3244045d941Ssowmini {"_class_opt_ipv6_udp", MAC_PROP_PERM_RW}, 3254045d941Ssowmini {"_class_opt_ipv6_ah", MAC_PROP_PERM_RW}, 3264045d941Ssowmini {"_class_opt_ipv6_sctp", MAC_PROP_PERM_RW}, 3274045d941Ssowmini {"_soft_lso_enable", MAC_PROP_PERM_RW} 3284045d941Ssowmini }; 3294045d941Ssowmini 3304045d941Ssowmini #define NXGE_MAX_PRIV_PROPS \ 3314045d941Ssowmini (sizeof (nxge_priv_props)/sizeof (mac_priv_prop_t)) 3321bd6825cSml 33344961713Sgirish #define NXGE_NEPTUNE_MAGIC 0x4E584745UL 33444961713Sgirish #define MAX_DUMP_SZ 256 33544961713Sgirish 3361bd6825cSml #define NXGE_M_CALLBACK_FLAGS \ 337*da14cebeSEric Cheng (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP) 33844961713Sgirish 339678453a8Sspeer mac_callbacks_t nxge_m_callbacks = { 34044961713Sgirish NXGE_M_CALLBACK_FLAGS, 34144961713Sgirish nxge_m_stat, 34244961713Sgirish nxge_m_start, 34344961713Sgirish nxge_m_stop, 34444961713Sgirish nxge_m_promisc, 34544961713Sgirish nxge_m_multicst, 346*da14cebeSEric Cheng NULL, 347*da14cebeSEric Cheng NULL, 34844961713Sgirish nxge_m_ioctl, 3491bd6825cSml nxge_m_getcapab, 3501bd6825cSml NULL, 3511bd6825cSml NULL, 3521bd6825cSml nxge_m_setprop, 3531bd6825cSml nxge_m_getprop 35444961713Sgirish }; 35544961713Sgirish 35644961713Sgirish void 35744961713Sgirish nxge_err_inject(p_nxge_t, queue_t *, mblk_t *); 35844961713Sgirish 359ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override. */ 360ec090658Sml #define NXGE_MSIX_REQUEST_10G 8 361ec090658Sml #define NXGE_MSIX_REQUEST_1G 2 362ec090658Sml static int nxge_create_msi_property(p_nxge_t); 363ec090658Sml 36444961713Sgirish /* 36544961713Sgirish * These global variables control the message 36644961713Sgirish * output. 36744961713Sgirish */ 36844961713Sgirish out_dbgmsg_t nxge_dbgmsg_out = DBG_CONSOLE | STR_LOG; 369678453a8Sspeer uint64_t nxge_debug_level; 37044961713Sgirish 37144961713Sgirish /* 37244961713Sgirish * This list contains the instance structures for the Neptune 37344961713Sgirish * devices present in the system. The lock exists to guarantee 37444961713Sgirish * mutually exclusive access to the list. 37544961713Sgirish */ 37644961713Sgirish void *nxge_list = NULL; 37744961713Sgirish 37844961713Sgirish void *nxge_hw_list = NULL; 37944961713Sgirish nxge_os_mutex_t nxge_common_lock; 38044961713Sgirish 38144961713Sgirish extern uint64_t npi_debug_level; 38244961713Sgirish 38344961713Sgirish extern nxge_status_t nxge_ldgv_init(p_nxge_t, int *, int *); 38444961713Sgirish extern nxge_status_t nxge_ldgv_init_n2(p_nxge_t, int *, int *); 38544961713Sgirish extern nxge_status_t nxge_ldgv_uninit(p_nxge_t); 38644961713Sgirish extern nxge_status_t nxge_intr_ldgv_init(p_nxge_t); 38744961713Sgirish extern void nxge_fm_init(p_nxge_t, 38844961713Sgirish ddi_device_acc_attr_t *, 38944961713Sgirish ddi_device_acc_attr_t *, 39044961713Sgirish ddi_dma_attr_t *); 39144961713Sgirish extern void nxge_fm_fini(p_nxge_t); 39258324dfcSspeer extern npi_status_t npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t); 39344961713Sgirish 39444961713Sgirish /* 39544961713Sgirish * Count used to maintain the number of buffers being used 39644961713Sgirish * by Neptune instances and loaned up to the upper layers. 39744961713Sgirish */ 39844961713Sgirish uint32_t nxge_mblks_pending = 0; 39944961713Sgirish 40044961713Sgirish /* 40144961713Sgirish * Device register access attributes for PIO. 40244961713Sgirish */ 40344961713Sgirish static ddi_device_acc_attr_t nxge_dev_reg_acc_attr = { 40444961713Sgirish DDI_DEVICE_ATTR_V0, 40544961713Sgirish DDI_STRUCTURE_LE_ACC, 40644961713Sgirish DDI_STRICTORDER_ACC, 40744961713Sgirish }; 40844961713Sgirish 40944961713Sgirish /* 41044961713Sgirish * Device descriptor access attributes for DMA. 41144961713Sgirish */ 41244961713Sgirish static ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr = { 41344961713Sgirish DDI_DEVICE_ATTR_V0, 41444961713Sgirish DDI_STRUCTURE_LE_ACC, 41544961713Sgirish DDI_STRICTORDER_ACC 41644961713Sgirish }; 41744961713Sgirish 41844961713Sgirish /* 41944961713Sgirish * Device buffer access attributes for DMA. 42044961713Sgirish */ 42144961713Sgirish static ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr = { 42244961713Sgirish DDI_DEVICE_ATTR_V0, 42344961713Sgirish DDI_STRUCTURE_BE_ACC, 42444961713Sgirish DDI_STRICTORDER_ACC 42544961713Sgirish }; 42644961713Sgirish 42744961713Sgirish ddi_dma_attr_t nxge_desc_dma_attr = { 42844961713Sgirish DMA_ATTR_V0, /* version number. */ 42944961713Sgirish 0, /* low address */ 43044961713Sgirish 0xffffffffffffffff, /* high address */ 43144961713Sgirish 0xffffffffffffffff, /* address counter max */ 43244961713Sgirish #ifndef NIU_PA_WORKAROUND 43344961713Sgirish 0x100000, /* alignment */ 43444961713Sgirish #else 43544961713Sgirish 0x2000, 43644961713Sgirish #endif 43744961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 43844961713Sgirish 0x1, /* minimum transfer size */ 43944961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 44044961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 44144961713Sgirish 1, /* scatter/gather list length */ 44244961713Sgirish (unsigned int) 1, /* granularity */ 44344961713Sgirish 0 /* attribute flags */ 44444961713Sgirish }; 44544961713Sgirish 44644961713Sgirish ddi_dma_attr_t nxge_tx_dma_attr = { 44744961713Sgirish DMA_ATTR_V0, /* version number. */ 44844961713Sgirish 0, /* low address */ 44944961713Sgirish 0xffffffffffffffff, /* high address */ 45044961713Sgirish 0xffffffffffffffff, /* address counter max */ 45144961713Sgirish #if defined(_BIG_ENDIAN) 45244961713Sgirish 0x2000, /* alignment */ 45344961713Sgirish #else 45444961713Sgirish 0x1000, /* alignment */ 45544961713Sgirish #endif 45644961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 45744961713Sgirish 0x1, /* minimum transfer size */ 45844961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 45944961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 46044961713Sgirish 5, /* scatter/gather list length */ 46144961713Sgirish (unsigned int) 1, /* granularity */ 46244961713Sgirish 0 /* attribute flags */ 46344961713Sgirish }; 46444961713Sgirish 46544961713Sgirish ddi_dma_attr_t nxge_rx_dma_attr = { 46644961713Sgirish DMA_ATTR_V0, /* version number. */ 46744961713Sgirish 0, /* low address */ 46844961713Sgirish 0xffffffffffffffff, /* high address */ 46944961713Sgirish 0xffffffffffffffff, /* address counter max */ 47044961713Sgirish 0x2000, /* alignment */ 47144961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 47244961713Sgirish 0x1, /* minimum transfer size */ 47344961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 47444961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 47544961713Sgirish 1, /* scatter/gather list length */ 47644961713Sgirish (unsigned int) 1, /* granularity */ 4770e2bd521Ssbehera DDI_DMA_RELAXED_ORDERING /* attribute flags */ 47844961713Sgirish }; 47944961713Sgirish 48044961713Sgirish ddi_dma_lim_t nxge_dma_limits = { 48144961713Sgirish (uint_t)0, /* dlim_addr_lo */ 48244961713Sgirish (uint_t)0xffffffff, /* dlim_addr_hi */ 48344961713Sgirish (uint_t)0xffffffff, /* dlim_cntr_max */ 48444961713Sgirish (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */ 48544961713Sgirish 0x1, /* dlim_minxfer */ 48644961713Sgirish 1024 /* dlim_speed */ 48744961713Sgirish }; 48844961713Sgirish 48944961713Sgirish dma_method_t nxge_force_dma = DVMA; 49044961713Sgirish 49144961713Sgirish /* 49244961713Sgirish * dma chunk sizes. 49344961713Sgirish * 49444961713Sgirish * Try to allocate the largest possible size 49544961713Sgirish * so that fewer number of dma chunks would be managed 49644961713Sgirish */ 49744961713Sgirish #ifdef NIU_PA_WORKAROUND 49844961713Sgirish size_t alloc_sizes [] = {0x2000}; 49944961713Sgirish #else 50044961713Sgirish size_t alloc_sizes [] = {0x1000, 0x2000, 0x4000, 0x8000, 50144961713Sgirish 0x10000, 0x20000, 0x40000, 0x80000, 50230ac2e7bSml 0x100000, 0x200000, 0x400000, 0x800000, 50330ac2e7bSml 0x1000000, 0x2000000, 0x4000000}; 50444961713Sgirish #endif 50544961713Sgirish 50644961713Sgirish /* 50744961713Sgirish * Translate "dev_t" to a pointer to the associated "dev_info_t". 50844961713Sgirish */ 50944961713Sgirish 510678453a8Sspeer extern void nxge_get_environs(nxge_t *); 511678453a8Sspeer 51244961713Sgirish static int 51344961713Sgirish nxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 51444961713Sgirish { 51544961713Sgirish p_nxge_t nxgep = NULL; 51644961713Sgirish int instance; 51744961713Sgirish int status = DDI_SUCCESS; 51844961713Sgirish uint8_t portn; 51958324dfcSspeer nxge_mmac_t *mmac_info; 5207b1f684aSSriharsha Basavapatna p_nxge_param_t param_arr; 52144961713Sgirish 52244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_attach")); 52344961713Sgirish 52444961713Sgirish /* 52544961713Sgirish * Get the device instance since we'll need to setup 52644961713Sgirish * or retrieve a soft state for this instance. 52744961713Sgirish */ 52844961713Sgirish instance = ddi_get_instance(dip); 52944961713Sgirish 53044961713Sgirish switch (cmd) { 53144961713Sgirish case DDI_ATTACH: 53244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_ATTACH")); 53344961713Sgirish break; 53444961713Sgirish 53544961713Sgirish case DDI_RESUME: 53644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_RESUME")); 53744961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 53844961713Sgirish if (nxgep == NULL) { 53944961713Sgirish status = DDI_FAILURE; 54044961713Sgirish break; 54144961713Sgirish } 54244961713Sgirish if (nxgep->dip != dip) { 54344961713Sgirish status = DDI_FAILURE; 54444961713Sgirish break; 54544961713Sgirish } 54644961713Sgirish if (nxgep->suspended == DDI_PM_SUSPEND) { 54744961713Sgirish status = ddi_dev_is_needed(nxgep->dip, 0, 1); 54844961713Sgirish } else { 54956d930aeSspeer status = nxge_resume(nxgep); 55044961713Sgirish } 55144961713Sgirish goto nxge_attach_exit; 55244961713Sgirish 55344961713Sgirish case DDI_PM_RESUME: 55444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_RESUME")); 55544961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 55644961713Sgirish if (nxgep == NULL) { 55744961713Sgirish status = DDI_FAILURE; 55844961713Sgirish break; 55944961713Sgirish } 56044961713Sgirish if (nxgep->dip != dip) { 56144961713Sgirish status = DDI_FAILURE; 56244961713Sgirish break; 56344961713Sgirish } 56456d930aeSspeer status = nxge_resume(nxgep); 56544961713Sgirish goto nxge_attach_exit; 56644961713Sgirish 56744961713Sgirish default: 56844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing unknown")); 56944961713Sgirish status = DDI_FAILURE; 57044961713Sgirish goto nxge_attach_exit; 57144961713Sgirish } 57244961713Sgirish 57344961713Sgirish 57444961713Sgirish if (ddi_soft_state_zalloc(nxge_list, instance) == DDI_FAILURE) { 57544961713Sgirish status = DDI_FAILURE; 57644961713Sgirish goto nxge_attach_exit; 57744961713Sgirish } 57844961713Sgirish 57944961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance); 58044961713Sgirish if (nxgep == NULL) { 5812e59129aSraghus status = NXGE_ERROR; 5822e59129aSraghus goto nxge_attach_fail2; 58344961713Sgirish } 58444961713Sgirish 58598ecde52Stm nxgep->nxge_magic = NXGE_MAGIC; 58698ecde52Stm 58744961713Sgirish nxgep->drv_state = 0; 58844961713Sgirish nxgep->dip = dip; 58944961713Sgirish nxgep->instance = instance; 59044961713Sgirish nxgep->p_dip = ddi_get_parent(dip); 59144961713Sgirish nxgep->nxge_debug_level = nxge_debug_level; 59244961713Sgirish npi_debug_level = nxge_debug_level; 59344961713Sgirish 594678453a8Sspeer /* Are we a guest running in a Hybrid I/O environment? */ 595678453a8Sspeer nxge_get_environs(nxgep); 59644961713Sgirish 59744961713Sgirish status = nxge_map_regs(nxgep); 598678453a8Sspeer 59944961713Sgirish if (status != NXGE_OK) { 60044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_map_regs failed")); 6012e59129aSraghus goto nxge_attach_fail3; 60244961713Sgirish } 60344961713Sgirish 604678453a8Sspeer nxge_fm_init(nxgep, &nxge_dev_reg_acc_attr, 605678453a8Sspeer &nxge_dev_desc_dma_acc_attr, 606678453a8Sspeer &nxge_rx_dma_attr); 607678453a8Sspeer 608678453a8Sspeer /* Create & initialize the per-Neptune data structure */ 609678453a8Sspeer /* (even if we're a guest). */ 61044961713Sgirish status = nxge_init_common_dev(nxgep); 61144961713Sgirish if (status != NXGE_OK) { 61244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6134045d941Ssowmini "nxge_init_common_dev failed")); 6142e59129aSraghus goto nxge_attach_fail4; 61544961713Sgirish } 61644961713Sgirish 617d6d3405fSml /* 618d6d3405fSml * Software workaround: set the replay timer. 619d6d3405fSml */ 620d6d3405fSml if (nxgep->niu_type != N2_NIU) { 621d6d3405fSml nxge_set_pci_replay_timeout(nxgep); 622d6d3405fSml } 623*da14cebeSEric Cheng #if defined(sun4v) 624*da14cebeSEric Cheng if (isLDOMguest(nxgep)) { 625*da14cebeSEric Cheng nxge_m_callbacks.mc_tx = nxge_m_tx; 626*da14cebeSEric Cheng } 627*da14cebeSEric Cheng #endif 628d6d3405fSml 629678453a8Sspeer #if defined(sun4v) 630678453a8Sspeer /* This is required by nxge_hio_init(), which follows. */ 631678453a8Sspeer if ((status = nxge_hsvc_register(nxgep)) != DDI_SUCCESS) 6329d5b8bc5SMichael Speer goto nxge_attach_fail4; 633678453a8Sspeer #endif 634678453a8Sspeer 635678453a8Sspeer if ((status = nxge_hio_init(nxgep)) != NXGE_OK) { 636678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6374045d941Ssowmini "nxge_hio_init failed")); 638678453a8Sspeer goto nxge_attach_fail4; 639678453a8Sspeer } 640678453a8Sspeer 64159ac0c16Sdavemq if (nxgep->niu_type == NEPTUNE_2_10GF) { 64259ac0c16Sdavemq if (nxgep->function_num > 1) { 6434202ea4bSsbehera NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Unsupported" 64459ac0c16Sdavemq " function %d. Only functions 0 and 1 are " 64559ac0c16Sdavemq "supported for this card.", nxgep->function_num)); 64659ac0c16Sdavemq status = NXGE_ERROR; 6472e59129aSraghus goto nxge_attach_fail4; 64859ac0c16Sdavemq } 64959ac0c16Sdavemq } 65059ac0c16Sdavemq 651678453a8Sspeer if (isLDOMguest(nxgep)) { 652678453a8Sspeer /* 653678453a8Sspeer * Use the function number here. 654678453a8Sspeer */ 655678453a8Sspeer nxgep->mac.portnum = nxgep->function_num; 656678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_LOGICAL; 657678453a8Sspeer 658678453a8Sspeer /* XXX We'll set the MAC address counts to 1 for now. */ 659678453a8Sspeer mmac_info = &nxgep->nxge_mmac_info; 660678453a8Sspeer mmac_info->num_mmac = 1; 661678453a8Sspeer mmac_info->naddrfree = 1; 66258324dfcSspeer } else { 663678453a8Sspeer portn = NXGE_GET_PORT_NUM(nxgep->function_num); 664678453a8Sspeer nxgep->mac.portnum = portn; 665678453a8Sspeer if ((portn == 0) || (portn == 1)) 666678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_XMAC; 667678453a8Sspeer else 668678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_BMAC; 669678453a8Sspeer /* 670678453a8Sspeer * Neptune has 4 ports, the first 2 ports use XMAC (10G MAC) 671678453a8Sspeer * internally, the rest 2 ports use BMAC (1G "Big" MAC). 672678453a8Sspeer * The two types of MACs have different characterizations. 673678453a8Sspeer */ 674678453a8Sspeer mmac_info = &nxgep->nxge_mmac_info; 675678453a8Sspeer if (nxgep->function_num < 2) { 676678453a8Sspeer mmac_info->num_mmac = XMAC_MAX_ALT_ADDR_ENTRY; 677678453a8Sspeer mmac_info->naddrfree = XMAC_MAX_ALT_ADDR_ENTRY; 678678453a8Sspeer } else { 679678453a8Sspeer mmac_info->num_mmac = BMAC_MAX_ALT_ADDR_ENTRY; 680678453a8Sspeer mmac_info->naddrfree = BMAC_MAX_ALT_ADDR_ENTRY; 681678453a8Sspeer } 68258324dfcSspeer } 68344961713Sgirish /* 68444961713Sgirish * Setup the Ndd parameters for the this instance. 68544961713Sgirish */ 68644961713Sgirish nxge_init_param(nxgep); 68744961713Sgirish 68844961713Sgirish /* 68944961713Sgirish * Setup Register Tracing Buffer. 69044961713Sgirish */ 69144961713Sgirish npi_rtrace_buf_init((rtrace_t *)&npi_rtracebuf); 69244961713Sgirish 69344961713Sgirish /* init stats ptr */ 69444961713Sgirish nxge_init_statsp(nxgep); 69556d930aeSspeer 6962e59129aSraghus /* 697678453a8Sspeer * Copy the vpd info from eeprom to a local data 698678453a8Sspeer * structure, and then check its validity. 6992e59129aSraghus */ 700678453a8Sspeer if (!isLDOMguest(nxgep)) { 701678453a8Sspeer int *regp; 702678453a8Sspeer uint_t reglen; 703678453a8Sspeer int rv; 70456d930aeSspeer 705678453a8Sspeer nxge_vpd_info_get(nxgep); 70644961713Sgirish 707678453a8Sspeer /* Find the NIU config handle. */ 708678453a8Sspeer rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, 709678453a8Sspeer ddi_get_parent(nxgep->dip), DDI_PROP_DONTPASS, 710678453a8Sspeer "reg", ®p, ®len); 711678453a8Sspeer 712678453a8Sspeer if (rv != DDI_PROP_SUCCESS) { 713678453a8Sspeer goto nxge_attach_fail5; 714678453a8Sspeer } 715678453a8Sspeer /* 716678453a8Sspeer * The address_hi, that is the first int, in the reg 717678453a8Sspeer * property consists of config handle, but need to remove 718678453a8Sspeer * the bits 28-31 which are OBP specific info. 719678453a8Sspeer */ 720678453a8Sspeer nxgep->niu_cfg_hdl = (*regp) & 0xFFFFFFF; 721678453a8Sspeer ddi_prop_free(regp); 72244961713Sgirish } 72344961713Sgirish 724678453a8Sspeer if (isLDOMguest(nxgep)) { 725678453a8Sspeer uchar_t *prop_val; 726678453a8Sspeer uint_t prop_len; 7277b1f684aSSriharsha Basavapatna uint32_t max_frame_size; 72844961713Sgirish 729678453a8Sspeer extern void nxge_get_logical_props(p_nxge_t); 730678453a8Sspeer 731678453a8Sspeer nxgep->statsp->mac_stats.xcvr_inuse = LOGICAL_XCVR; 732678453a8Sspeer nxgep->mac.portmode = PORT_LOGICAL; 733678453a8Sspeer (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 734678453a8Sspeer "phy-type", "virtual transceiver"); 735678453a8Sspeer 736678453a8Sspeer nxgep->nports = 1; 737678453a8Sspeer nxgep->board_ver = 0; /* XXX What? */ 738678453a8Sspeer 739678453a8Sspeer /* 740678453a8Sspeer * local-mac-address property gives us info on which 741678453a8Sspeer * specific MAC address the Hybrid resource is associated 742678453a8Sspeer * with. 743678453a8Sspeer */ 744678453a8Sspeer if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0, 745678453a8Sspeer "local-mac-address", &prop_val, 746678453a8Sspeer &prop_len) != DDI_PROP_SUCCESS) { 747678453a8Sspeer goto nxge_attach_fail5; 748678453a8Sspeer } 749678453a8Sspeer if (prop_len != ETHERADDRL) { 750678453a8Sspeer ddi_prop_free(prop_val); 751678453a8Sspeer goto nxge_attach_fail5; 752678453a8Sspeer } 753678453a8Sspeer ether_copy(prop_val, nxgep->hio_mac_addr); 754678453a8Sspeer ddi_prop_free(prop_val); 755678453a8Sspeer nxge_get_logical_props(nxgep); 756678453a8Sspeer 7577b1f684aSSriharsha Basavapatna /* 7587b1f684aSSriharsha Basavapatna * Enable Jumbo property based on the "max-frame-size" 7597b1f684aSSriharsha Basavapatna * property value. 7607b1f684aSSriharsha Basavapatna */ 7617b1f684aSSriharsha Basavapatna max_frame_size = ddi_prop_get_int(DDI_DEV_T_ANY, 7627b1f684aSSriharsha Basavapatna nxgep->dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 7637b1f684aSSriharsha Basavapatna "max-frame-size", NXGE_MTU_DEFAULT_MAX); 7647b1f684aSSriharsha Basavapatna if ((max_frame_size > NXGE_MTU_DEFAULT_MAX) && 7657b1f684aSSriharsha Basavapatna (max_frame_size <= TX_JUMBO_MTU)) { 7667b1f684aSSriharsha Basavapatna param_arr = nxgep->param_arr; 7677b1f684aSSriharsha Basavapatna 7687b1f684aSSriharsha Basavapatna param_arr[param_accept_jumbo].value = 1; 7697b1f684aSSriharsha Basavapatna nxgep->mac.is_jumbo = B_TRUE; 7707b1f684aSSriharsha Basavapatna nxgep->mac.maxframesize = (uint16_t)max_frame_size; 7717b1f684aSSriharsha Basavapatna nxgep->mac.default_mtu = nxgep->mac.maxframesize - 7727b1f684aSSriharsha Basavapatna NXGE_EHEADER_VLAN_CRC; 7737b1f684aSSriharsha Basavapatna } 774678453a8Sspeer } else { 775678453a8Sspeer status = nxge_xcvr_find(nxgep); 776678453a8Sspeer 777678453a8Sspeer if (status != NXGE_OK) { 778678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_attach: " 7794045d941Ssowmini " Couldn't determine card type" 7804045d941Ssowmini " .... exit ")); 781678453a8Sspeer goto nxge_attach_fail5; 782678453a8Sspeer } 783678453a8Sspeer 784678453a8Sspeer status = nxge_get_config_properties(nxgep); 785678453a8Sspeer 786678453a8Sspeer if (status != NXGE_OK) { 787678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7884045d941Ssowmini "get_hw create failed")); 789678453a8Sspeer goto nxge_attach_fail; 790678453a8Sspeer } 79144961713Sgirish } 79244961713Sgirish 79344961713Sgirish /* 79444961713Sgirish * Setup the Kstats for the driver. 79544961713Sgirish */ 79644961713Sgirish nxge_setup_kstats(nxgep); 79744961713Sgirish 798678453a8Sspeer if (!isLDOMguest(nxgep)) 799678453a8Sspeer nxge_setup_param(nxgep); 80044961713Sgirish 80144961713Sgirish status = nxge_setup_system_dma_pages(nxgep); 80244961713Sgirish if (status != NXGE_OK) { 80344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "set dma page failed")); 80444961713Sgirish goto nxge_attach_fail; 80544961713Sgirish } 80644961713Sgirish 80744961713Sgirish nxge_hw_id_init(nxgep); 808678453a8Sspeer 809678453a8Sspeer if (!isLDOMguest(nxgep)) 810678453a8Sspeer nxge_hw_init_niu_common(nxgep); 81144961713Sgirish 81244961713Sgirish status = nxge_setup_mutexes(nxgep); 81344961713Sgirish if (status != NXGE_OK) { 81444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set mutex failed")); 81544961713Sgirish goto nxge_attach_fail; 81644961713Sgirish } 81744961713Sgirish 818678453a8Sspeer #if defined(sun4v) 819678453a8Sspeer if (isLDOMguest(nxgep)) { 820678453a8Sspeer /* Find our VR & channel sets. */ 821678453a8Sspeer status = nxge_hio_vr_add(nxgep); 822330cd344SMichael Speer if (status != NXGE_OK) { 823330cd344SMichael Speer NXGE_DEBUG_MSG((nxgep, DDI_CTL, 824330cd344SMichael Speer "nxge_hio_vr_add failed")); 825330cd344SMichael Speer (void) hsvc_unregister(&nxgep->niu_hsvc); 826330cd344SMichael Speer nxgep->niu_hsvc_available = B_FALSE; 827330cd344SMichael Speer } 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 } 843330cd344SMichael Speer 84400161856Syc /* If a guest, register with vio_net instead. */ 8452e59129aSraghus if ((status = nxge_mac_register(nxgep)) != NXGE_OK) { 84644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 847678453a8Sspeer "unable to register to mac layer (%d)", status)); 84844961713Sgirish goto nxge_attach_fail; 84944961713Sgirish } 85044961713Sgirish 85144961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_UNKNOWN); 85244961713Sgirish 853678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DDI_CTL, 854678453a8Sspeer "registered to mac (instance %d)", instance)); 85544961713Sgirish 85600161856Syc /* nxge_link_monitor calls xcvr.check_link recursively */ 85744961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 85844961713Sgirish 85944961713Sgirish goto nxge_attach_exit; 86044961713Sgirish 86144961713Sgirish nxge_attach_fail: 86244961713Sgirish nxge_unattach(nxgep); 8632e59129aSraghus goto nxge_attach_fail1; 8642e59129aSraghus 8652e59129aSraghus nxge_attach_fail5: 8662e59129aSraghus /* 8672e59129aSraghus * Tear down the ndd parameters setup. 8682e59129aSraghus */ 8692e59129aSraghus nxge_destroy_param(nxgep); 8702e59129aSraghus 8712e59129aSraghus /* 8722e59129aSraghus * Tear down the kstat setup. 8732e59129aSraghus */ 8742e59129aSraghus nxge_destroy_kstats(nxgep); 8752e59129aSraghus 8762e59129aSraghus nxge_attach_fail4: 8772e59129aSraghus if (nxgep->nxge_hw_p) { 8782e59129aSraghus nxge_uninit_common_dev(nxgep); 8792e59129aSraghus nxgep->nxge_hw_p = NULL; 8802e59129aSraghus } 8812e59129aSraghus 8822e59129aSraghus nxge_attach_fail3: 8832e59129aSraghus /* 8842e59129aSraghus * Unmap the register setup. 8852e59129aSraghus */ 8862e59129aSraghus nxge_unmap_regs(nxgep); 8872e59129aSraghus 8882e59129aSraghus nxge_fm_fini(nxgep); 8892e59129aSraghus 8902e59129aSraghus nxge_attach_fail2: 8912e59129aSraghus ddi_soft_state_free(nxge_list, nxgep->instance); 8922e59129aSraghus 8932e59129aSraghus nxge_attach_fail1: 89456d930aeSspeer if (status != NXGE_OK) 89556d930aeSspeer status = (NXGE_ERROR | NXGE_DDI_FAILED); 89644961713Sgirish nxgep = NULL; 89744961713Sgirish 89844961713Sgirish nxge_attach_exit: 89944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_attach status = 0x%08x", 9004045d941Ssowmini status)); 90144961713Sgirish 90244961713Sgirish return (status); 90344961713Sgirish } 90444961713Sgirish 90544961713Sgirish static int 90644961713Sgirish nxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 90744961713Sgirish { 90844961713Sgirish int status = DDI_SUCCESS; 90944961713Sgirish int instance; 91044961713Sgirish p_nxge_t nxgep = NULL; 91144961713Sgirish 91244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_detach")); 91344961713Sgirish instance = ddi_get_instance(dip); 91444961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance); 91544961713Sgirish if (nxgep == NULL) { 91644961713Sgirish status = DDI_FAILURE; 91744961713Sgirish goto nxge_detach_exit; 91844961713Sgirish } 91944961713Sgirish 92044961713Sgirish switch (cmd) { 92144961713Sgirish case DDI_DETACH: 92244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_DETACH")); 92344961713Sgirish break; 92444961713Sgirish 92544961713Sgirish case DDI_PM_SUSPEND: 92644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_SUSPEND")); 92744961713Sgirish nxgep->suspended = DDI_PM_SUSPEND; 92844961713Sgirish nxge_suspend(nxgep); 92944961713Sgirish break; 93044961713Sgirish 93144961713Sgirish case DDI_SUSPEND: 93244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_SUSPEND")); 93344961713Sgirish if (nxgep->suspended != DDI_PM_SUSPEND) { 93444961713Sgirish nxgep->suspended = DDI_SUSPEND; 93544961713Sgirish nxge_suspend(nxgep); 93644961713Sgirish } 93744961713Sgirish break; 93844961713Sgirish 93944961713Sgirish default: 94044961713Sgirish status = DDI_FAILURE; 94144961713Sgirish } 94244961713Sgirish 94344961713Sgirish if (cmd != DDI_DETACH) 94444961713Sgirish goto nxge_detach_exit; 94544961713Sgirish 94644961713Sgirish /* 94744961713Sgirish * Stop the xcvr polling. 94844961713Sgirish */ 94944961713Sgirish nxgep->suspended = cmd; 95044961713Sgirish 95144961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 95244961713Sgirish 953678453a8Sspeer if (isLDOMguest(nxgep)) { 954d7cf53fcSmisaki Miyashita if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) 955d7cf53fcSmisaki Miyashita nxge_m_stop((void *)nxgep); 956678453a8Sspeer nxge_hio_unregister(nxgep); 957678453a8Sspeer } else if (nxgep->mach && (status = mac_unregister(nxgep->mach)) != 0) { 95844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 9594045d941Ssowmini "<== nxge_detach status = 0x%08X", status)); 96044961713Sgirish return (DDI_FAILURE); 96144961713Sgirish } 96244961713Sgirish 96344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 9644045d941Ssowmini "<== nxge_detach (mac_unregister) status = 0x%08X", status)); 96544961713Sgirish 96644961713Sgirish nxge_unattach(nxgep); 96744961713Sgirish nxgep = NULL; 96844961713Sgirish 96944961713Sgirish nxge_detach_exit: 97044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_detach status = 0x%08X", 9714045d941Ssowmini status)); 97244961713Sgirish 97344961713Sgirish return (status); 97444961713Sgirish } 97544961713Sgirish 97644961713Sgirish static void 97744961713Sgirish nxge_unattach(p_nxge_t nxgep) 97844961713Sgirish { 97944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unattach")); 98044961713Sgirish 98144961713Sgirish if (nxgep == NULL || nxgep->dev_regs == NULL) { 98244961713Sgirish return; 98344961713Sgirish } 98444961713Sgirish 98598ecde52Stm nxgep->nxge_magic = 0; 98698ecde52Stm 98744961713Sgirish if (nxgep->nxge_timerid) { 98844961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 98944961713Sgirish nxgep->nxge_timerid = 0; 99044961713Sgirish } 99144961713Sgirish 9926f157acbSml /* 9936f157acbSml * If this flag is set, it will affect the Neptune 9946f157acbSml * only. 9956f157acbSml */ 9966f157acbSml if ((nxgep->niu_type != N2_NIU) && nxge_peu_reset_enable) { 9976f157acbSml nxge_niu_peu_reset(nxgep); 9986f157acbSml } 9996f157acbSml 1000678453a8Sspeer #if defined(sun4v) 1001678453a8Sspeer if (isLDOMguest(nxgep)) { 1002d00f30bbSspeer (void) nxge_hio_vr_release(nxgep); 1003678453a8Sspeer } 1004678453a8Sspeer #endif 1005678453a8Sspeer 100653560810Ssbehera if (nxgep->nxge_hw_p) { 100753560810Ssbehera nxge_uninit_common_dev(nxgep); 100853560810Ssbehera nxgep->nxge_hw_p = NULL; 100953560810Ssbehera } 101053560810Ssbehera 101144961713Sgirish #if defined(sun4v) 101244961713Sgirish if (nxgep->niu_type == N2_NIU && nxgep->niu_hsvc_available == B_TRUE) { 101344961713Sgirish (void) hsvc_unregister(&nxgep->niu_hsvc); 101444961713Sgirish nxgep->niu_hsvc_available = B_FALSE; 101544961713Sgirish } 101644961713Sgirish #endif 101744961713Sgirish /* 101844961713Sgirish * Stop any further interrupts. 101944961713Sgirish */ 102044961713Sgirish nxge_remove_intrs(nxgep); 102144961713Sgirish 102244961713Sgirish /* 102344961713Sgirish * Stop the device and free resources. 102444961713Sgirish */ 1025678453a8Sspeer if (!isLDOMguest(nxgep)) { 1026678453a8Sspeer nxge_destroy_dev(nxgep); 1027678453a8Sspeer } 102844961713Sgirish 102944961713Sgirish /* 103044961713Sgirish * Tear down the ndd parameters setup. 103144961713Sgirish */ 103244961713Sgirish nxge_destroy_param(nxgep); 103344961713Sgirish 103444961713Sgirish /* 103544961713Sgirish * Tear down the kstat setup. 103644961713Sgirish */ 103744961713Sgirish nxge_destroy_kstats(nxgep); 103844961713Sgirish 103944961713Sgirish /* 104044961713Sgirish * Destroy all mutexes. 104144961713Sgirish */ 104244961713Sgirish nxge_destroy_mutexes(nxgep); 104344961713Sgirish 104444961713Sgirish /* 104544961713Sgirish * Remove the list of ndd parameters which 104644961713Sgirish * were setup during attach. 104744961713Sgirish */ 104844961713Sgirish if (nxgep->dip) { 104944961713Sgirish NXGE_DEBUG_MSG((nxgep, OBP_CTL, 10504045d941Ssowmini " nxge_unattach: remove all properties")); 105144961713Sgirish 105244961713Sgirish (void) ddi_prop_remove_all(nxgep->dip); 105344961713Sgirish } 105444961713Sgirish 105544961713Sgirish #if NXGE_PROPERTY 105644961713Sgirish nxge_remove_hard_properties(nxgep); 105744961713Sgirish #endif 105844961713Sgirish 105944961713Sgirish /* 106044961713Sgirish * Unmap the register setup. 106144961713Sgirish */ 106244961713Sgirish nxge_unmap_regs(nxgep); 106344961713Sgirish 106444961713Sgirish nxge_fm_fini(nxgep); 106544961713Sgirish 106644961713Sgirish ddi_soft_state_free(nxge_list, nxgep->instance); 106744961713Sgirish 106844961713Sgirish NXGE_DEBUG_MSG((NULL, DDI_CTL, "<== nxge_unattach")); 106944961713Sgirish } 107044961713Sgirish 1071678453a8Sspeer #if defined(sun4v) 1072678453a8Sspeer int 10739d5b8bc5SMichael Speer nxge_hsvc_register(nxge_t *nxgep) 1074678453a8Sspeer { 1075678453a8Sspeer nxge_status_t status; 1076678453a8Sspeer 1077678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 1078678453a8Sspeer nxgep->niu_hsvc_available = B_FALSE; 1079678453a8Sspeer bcopy(&niu_hsvc, &nxgep->niu_hsvc, sizeof (hsvc_info_t)); 1080678453a8Sspeer if ((status = hsvc_register(&nxgep->niu_hsvc, 1081678453a8Sspeer &nxgep->niu_min_ver)) != 0) { 1082678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1083678453a8Sspeer "nxge_attach: %s: cannot negotiate " 1084678453a8Sspeer "hypervisor services revision %d group: 0x%lx " 1085678453a8Sspeer "major: 0x%lx minor: 0x%lx errno: %d", 1086678453a8Sspeer niu_hsvc.hsvc_modname, niu_hsvc.hsvc_rev, 1087678453a8Sspeer niu_hsvc.hsvc_group, niu_hsvc.hsvc_major, 1088678453a8Sspeer niu_hsvc.hsvc_minor, status)); 1089678453a8Sspeer return (DDI_FAILURE); 1090678453a8Sspeer } 1091678453a8Sspeer nxgep->niu_hsvc_available = B_TRUE; 1092678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DDI_CTL, 10934045d941Ssowmini "NIU Hypervisor service enabled")); 1094678453a8Sspeer } 1095678453a8Sspeer 1096678453a8Sspeer return (DDI_SUCCESS); 1097678453a8Sspeer } 1098678453a8Sspeer #endif 1099678453a8Sspeer 110044961713Sgirish static char n2_siu_name[] = "niu"; 110144961713Sgirish 110244961713Sgirish static nxge_status_t 110344961713Sgirish nxge_map_regs(p_nxge_t nxgep) 110444961713Sgirish { 110544961713Sgirish int ddi_status = DDI_SUCCESS; 110644961713Sgirish p_dev_regs_t dev_regs; 110744961713Sgirish char buf[MAXPATHLEN + 1]; 110844961713Sgirish char *devname; 110944961713Sgirish #ifdef NXGE_DEBUG 111044961713Sgirish char *sysname; 111144961713Sgirish #endif 111244961713Sgirish off_t regsize; 111344961713Sgirish nxge_status_t status = NXGE_OK; 111414ea4bb7Ssd #if !defined(_BIG_ENDIAN) 111514ea4bb7Ssd off_t pci_offset; 111614ea4bb7Ssd uint16_t pcie_devctl; 111714ea4bb7Ssd #endif 111844961713Sgirish 1119678453a8Sspeer if (isLDOMguest(nxgep)) { 1120678453a8Sspeer return (nxge_guest_regs_map(nxgep)); 1121678453a8Sspeer } 1122678453a8Sspeer 112344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_map_regs")); 112444961713Sgirish nxgep->dev_regs = NULL; 112544961713Sgirish dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP); 112644961713Sgirish dev_regs->nxge_regh = NULL; 112744961713Sgirish dev_regs->nxge_pciregh = NULL; 112844961713Sgirish dev_regs->nxge_msix_regh = NULL; 112944961713Sgirish dev_regs->nxge_vir_regh = NULL; 113044961713Sgirish dev_regs->nxge_vir2_regh = NULL; 113159ac0c16Sdavemq nxgep->niu_type = NIU_TYPE_NONE; 113244961713Sgirish 113344961713Sgirish devname = ddi_pathname(nxgep->dip, buf); 113444961713Sgirish ASSERT(strlen(devname) > 0); 113544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11364045d941Ssowmini "nxge_map_regs: pathname devname %s", devname)); 113744961713Sgirish 113800161856Syc /* 113900161856Syc * The driver is running on a N2-NIU system if devname is something 114000161856Syc * like "/niu@80/network@0" 114100161856Syc */ 114244961713Sgirish if (strstr(devname, n2_siu_name)) { 114344961713Sgirish /* N2/NIU */ 114444961713Sgirish nxgep->niu_type = N2_NIU; 114544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11464045d941Ssowmini "nxge_map_regs: N2/NIU devname %s", devname)); 114744961713Sgirish /* get function number */ 114844961713Sgirish nxgep->function_num = 11494045d941Ssowmini (devname[strlen(devname) -1] == '1' ? 1 : 0); 115044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11514045d941Ssowmini "nxge_map_regs: N2/NIU function number %d", 11524045d941Ssowmini nxgep->function_num)); 115344961713Sgirish } else { 115444961713Sgirish int *prop_val; 115544961713Sgirish uint_t prop_len; 115644961713Sgirish uint8_t func_num; 115744961713Sgirish 115844961713Sgirish if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 11594045d941Ssowmini 0, "reg", 11604045d941Ssowmini &prop_val, &prop_len) != DDI_PROP_SUCCESS) { 116144961713Sgirish NXGE_DEBUG_MSG((nxgep, VPD_CTL, 11624045d941Ssowmini "Reg property not found")); 116344961713Sgirish ddi_status = DDI_FAILURE; 116444961713Sgirish goto nxge_map_regs_fail0; 116544961713Sgirish 116644961713Sgirish } else { 116744961713Sgirish func_num = (prop_val[0] >> 8) & 0x7; 116844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11694045d941Ssowmini "Reg property found: fun # %d", 11704045d941Ssowmini func_num)); 117144961713Sgirish nxgep->function_num = func_num; 1172678453a8Sspeer if (isLDOMguest(nxgep)) { 1173678453a8Sspeer nxgep->function_num /= 2; 1174678453a8Sspeer return (NXGE_OK); 1175678453a8Sspeer } 117644961713Sgirish ddi_prop_free(prop_val); 117744961713Sgirish } 117844961713Sgirish } 117944961713Sgirish 118044961713Sgirish switch (nxgep->niu_type) { 118144961713Sgirish default: 118244961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 0, ®size); 118344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11844045d941Ssowmini "nxge_map_regs: pci config size 0x%x", regsize)); 118544961713Sgirish 118644961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 0, 11874045d941Ssowmini (caddr_t *)&(dev_regs->nxge_pciregp), 0, 0, 11884045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_pciregh); 118944961713Sgirish if (ddi_status != DDI_SUCCESS) { 119044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 11914045d941Ssowmini "ddi_map_regs, nxge bus config regs failed")); 119244961713Sgirish goto nxge_map_regs_fail0; 119344961713Sgirish } 119444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11954045d941Ssowmini "nxge_map_reg: PCI config addr 0x%0llx " 11964045d941Ssowmini " handle 0x%0llx", dev_regs->nxge_pciregp, 11974045d941Ssowmini dev_regs->nxge_pciregh)); 119844961713Sgirish /* 119944961713Sgirish * IMP IMP 120044961713Sgirish * workaround for bit swapping bug in HW 120144961713Sgirish * which ends up in no-snoop = yes 120244961713Sgirish * resulting, in DMA not synched properly 120344961713Sgirish */ 120444961713Sgirish #if !defined(_BIG_ENDIAN) 120514ea4bb7Ssd /* workarounds for x86 systems */ 120614ea4bb7Ssd pci_offset = 0x80 + PCIE_DEVCTL; 120714ea4bb7Ssd pcie_devctl = 0x0; 120814ea4bb7Ssd pcie_devctl &= PCIE_DEVCTL_ENABLE_NO_SNOOP; 120914ea4bb7Ssd pcie_devctl |= PCIE_DEVCTL_RO_EN; 121014ea4bb7Ssd pci_config_put16(dev_regs->nxge_pciregh, pci_offset, 12114045d941Ssowmini pcie_devctl); 121244961713Sgirish #endif 121314ea4bb7Ssd 121444961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 121544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12164045d941Ssowmini "nxge_map_regs: pio size 0x%x", regsize)); 121744961713Sgirish /* set up the device mapped register */ 121844961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 12194045d941Ssowmini (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 12204045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 122144961713Sgirish if (ddi_status != DDI_SUCCESS) { 122244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12234045d941Ssowmini "ddi_map_regs for Neptune global reg failed")); 122444961713Sgirish goto nxge_map_regs_fail1; 122544961713Sgirish } 122644961713Sgirish 122744961713Sgirish /* set up the msi/msi-x mapped register */ 122844961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 122944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12304045d941Ssowmini "nxge_map_regs: msix size 0x%x", regsize)); 123144961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 12324045d941Ssowmini (caddr_t *)&(dev_regs->nxge_msix_regp), 0, 0, 12334045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_msix_regh); 123444961713Sgirish if (ddi_status != DDI_SUCCESS) { 123544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12364045d941Ssowmini "ddi_map_regs for msi reg failed")); 123744961713Sgirish goto nxge_map_regs_fail2; 123844961713Sgirish } 123944961713Sgirish 124044961713Sgirish /* set up the vio region mapped register */ 124144961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 124244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12434045d941Ssowmini "nxge_map_regs: vio size 0x%x", regsize)); 124444961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 12454045d941Ssowmini (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 12464045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 124744961713Sgirish 124844961713Sgirish if (ddi_status != DDI_SUCCESS) { 124944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12504045d941Ssowmini "ddi_map_regs for nxge vio reg failed")); 125144961713Sgirish goto nxge_map_regs_fail3; 125244961713Sgirish } 125344961713Sgirish nxgep->dev_regs = dev_regs; 125444961713Sgirish 125544961713Sgirish NPI_PCI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_pciregh); 125644961713Sgirish NPI_PCI_ADD_HANDLE_SET(nxgep, 12574045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_pciregp); 125844961713Sgirish NPI_MSI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_msix_regh); 125944961713Sgirish NPI_MSI_ADD_HANDLE_SET(nxgep, 12604045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_msix_regp); 126144961713Sgirish 126244961713Sgirish NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 126344961713Sgirish NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 126444961713Sgirish 126544961713Sgirish NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 126644961713Sgirish NPI_REG_ADD_HANDLE_SET(nxgep, 12674045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_regp); 126844961713Sgirish 126944961713Sgirish NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 127044961713Sgirish NPI_VREG_ADD_HANDLE_SET(nxgep, 12714045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 127244961713Sgirish 127344961713Sgirish break; 127444961713Sgirish 127544961713Sgirish case N2_NIU: 127644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "ddi_map_regs, NIU")); 127744961713Sgirish /* 127844961713Sgirish * Set up the device mapped register (FWARC 2006/556) 127944961713Sgirish * (changed back to 1: reg starts at 1!) 128044961713Sgirish */ 128144961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 128244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12834045d941Ssowmini "nxge_map_regs: dev size 0x%x", regsize)); 128444961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 12854045d941Ssowmini (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 12864045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 128744961713Sgirish 128844961713Sgirish if (ddi_status != DDI_SUCCESS) { 128944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12904045d941Ssowmini "ddi_map_regs for N2/NIU, global reg failed ")); 129144961713Sgirish goto nxge_map_regs_fail1; 129244961713Sgirish } 129344961713Sgirish 1294678453a8Sspeer /* set up the first vio region mapped register */ 129544961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 129644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12974045d941Ssowmini "nxge_map_regs: vio (1) size 0x%x", regsize)); 129844961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 12994045d941Ssowmini (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 13004045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 130144961713Sgirish 130244961713Sgirish if (ddi_status != DDI_SUCCESS) { 130344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13044045d941Ssowmini "ddi_map_regs for nxge vio reg failed")); 130544961713Sgirish goto nxge_map_regs_fail2; 130644961713Sgirish } 1307678453a8Sspeer /* set up the second vio region mapped register */ 130844961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 130944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13104045d941Ssowmini "nxge_map_regs: vio (3) size 0x%x", regsize)); 131144961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 13124045d941Ssowmini (caddr_t *)&(dev_regs->nxge_vir2_regp), 0, 0, 13134045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir2_regh); 131444961713Sgirish 131544961713Sgirish if (ddi_status != DDI_SUCCESS) { 131644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13174045d941Ssowmini "ddi_map_regs for nxge vio2 reg failed")); 131844961713Sgirish goto nxge_map_regs_fail3; 131944961713Sgirish } 132044961713Sgirish nxgep->dev_regs = dev_regs; 132144961713Sgirish 132244961713Sgirish NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 132344961713Sgirish NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 132444961713Sgirish 132544961713Sgirish NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 132644961713Sgirish NPI_REG_ADD_HANDLE_SET(nxgep, 13274045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_regp); 132844961713Sgirish 132944961713Sgirish NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 133044961713Sgirish NPI_VREG_ADD_HANDLE_SET(nxgep, 13314045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 133244961713Sgirish 133344961713Sgirish NPI_V2REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir2_regh); 133444961713Sgirish NPI_V2REG_ADD_HANDLE_SET(nxgep, 13354045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_vir2_regp); 133644961713Sgirish 133744961713Sgirish break; 133844961713Sgirish } 133944961713Sgirish 134044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "nxge_map_reg: hardware addr 0x%0llx " 13414045d941Ssowmini " handle 0x%0llx", dev_regs->nxge_regp, dev_regs->nxge_regh)); 134244961713Sgirish 134344961713Sgirish goto nxge_map_regs_exit; 134444961713Sgirish nxge_map_regs_fail3: 134544961713Sgirish if (dev_regs->nxge_msix_regh) { 134644961713Sgirish ddi_regs_map_free(&dev_regs->nxge_msix_regh); 134744961713Sgirish } 134844961713Sgirish if (dev_regs->nxge_vir_regh) { 134944961713Sgirish ddi_regs_map_free(&dev_regs->nxge_regh); 135044961713Sgirish } 135144961713Sgirish nxge_map_regs_fail2: 135244961713Sgirish if (dev_regs->nxge_regh) { 135344961713Sgirish ddi_regs_map_free(&dev_regs->nxge_regh); 135444961713Sgirish } 135544961713Sgirish nxge_map_regs_fail1: 135644961713Sgirish if (dev_regs->nxge_pciregh) { 135744961713Sgirish ddi_regs_map_free(&dev_regs->nxge_pciregh); 135844961713Sgirish } 135944961713Sgirish nxge_map_regs_fail0: 136044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Freeing register set memory")); 136144961713Sgirish kmem_free(dev_regs, sizeof (dev_regs_t)); 136244961713Sgirish 136344961713Sgirish nxge_map_regs_exit: 136444961713Sgirish if (ddi_status != DDI_SUCCESS) 136544961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 136644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_map_regs")); 136744961713Sgirish return (status); 136844961713Sgirish } 136944961713Sgirish 137044961713Sgirish static void 137144961713Sgirish nxge_unmap_regs(p_nxge_t nxgep) 137244961713Sgirish { 137344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unmap_regs")); 1374678453a8Sspeer 1375678453a8Sspeer if (isLDOMguest(nxgep)) { 1376678453a8Sspeer nxge_guest_regs_map_free(nxgep); 1377678453a8Sspeer return; 1378678453a8Sspeer } 1379678453a8Sspeer 138044961713Sgirish if (nxgep->dev_regs) { 138144961713Sgirish if (nxgep->dev_regs->nxge_pciregh) { 138244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13834045d941Ssowmini "==> nxge_unmap_regs: bus")); 138444961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_pciregh); 138544961713Sgirish nxgep->dev_regs->nxge_pciregh = NULL; 138644961713Sgirish } 138744961713Sgirish if (nxgep->dev_regs->nxge_regh) { 138844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13894045d941Ssowmini "==> nxge_unmap_regs: device registers")); 139044961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_regh); 139144961713Sgirish nxgep->dev_regs->nxge_regh = NULL; 139244961713Sgirish } 139344961713Sgirish if (nxgep->dev_regs->nxge_msix_regh) { 139444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13954045d941Ssowmini "==> nxge_unmap_regs: device interrupts")); 139644961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_msix_regh); 139744961713Sgirish nxgep->dev_regs->nxge_msix_regh = NULL; 139844961713Sgirish } 139944961713Sgirish if (nxgep->dev_regs->nxge_vir_regh) { 140044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 14014045d941Ssowmini "==> nxge_unmap_regs: vio region")); 140244961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_vir_regh); 140344961713Sgirish nxgep->dev_regs->nxge_vir_regh = NULL; 140444961713Sgirish } 140544961713Sgirish if (nxgep->dev_regs->nxge_vir2_regh) { 140644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 14074045d941Ssowmini "==> nxge_unmap_regs: vio2 region")); 140844961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_vir2_regh); 140944961713Sgirish nxgep->dev_regs->nxge_vir2_regh = NULL; 141044961713Sgirish } 141144961713Sgirish 141244961713Sgirish kmem_free(nxgep->dev_regs, sizeof (dev_regs_t)); 141344961713Sgirish nxgep->dev_regs = NULL; 141444961713Sgirish } 141544961713Sgirish 141644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_unmap_regs")); 141744961713Sgirish } 141844961713Sgirish 141944961713Sgirish static nxge_status_t 142044961713Sgirish nxge_setup_mutexes(p_nxge_t nxgep) 142144961713Sgirish { 142244961713Sgirish int ddi_status = DDI_SUCCESS; 142344961713Sgirish nxge_status_t status = NXGE_OK; 142444961713Sgirish nxge_classify_t *classify_ptr; 142544961713Sgirish int partition; 142644961713Sgirish 142744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_mutexes")); 142844961713Sgirish 142944961713Sgirish /* 143044961713Sgirish * Get the interrupt cookie so the mutexes can be 143158324dfcSspeer * Initialized. 143244961713Sgirish */ 1433678453a8Sspeer if (isLDOMguest(nxgep)) { 1434678453a8Sspeer nxgep->interrupt_cookie = 0; 1435678453a8Sspeer } else { 1436678453a8Sspeer ddi_status = ddi_get_iblock_cookie(nxgep->dip, 0, 1437678453a8Sspeer &nxgep->interrupt_cookie); 1438678453a8Sspeer 1439678453a8Sspeer if (ddi_status != DDI_SUCCESS) { 1440678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1441678453a8Sspeer "<== nxge_setup_mutexes: failed 0x%x", 1442678453a8Sspeer ddi_status)); 1443678453a8Sspeer goto nxge_setup_mutexes_exit; 1444678453a8Sspeer } 144544961713Sgirish } 144644961713Sgirish 144798ecde52Stm cv_init(&nxgep->poll_cv, NULL, CV_DRIVER, NULL); 144898ecde52Stm MUTEX_INIT(&nxgep->poll_lock, NULL, 144998ecde52Stm MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 145098ecde52Stm 145144961713Sgirish /* 145298ecde52Stm * Initialize mutexes for this device. 145344961713Sgirish */ 145444961713Sgirish MUTEX_INIT(nxgep->genlock, NULL, 14554045d941Ssowmini MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 145644961713Sgirish MUTEX_INIT(&nxgep->ouraddr_lock, NULL, 14574045d941Ssowmini MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 145844961713Sgirish MUTEX_INIT(&nxgep->mif_lock, NULL, 14594045d941Ssowmini MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 1460678453a8Sspeer MUTEX_INIT(&nxgep->group_lock, NULL, 1461678453a8Sspeer MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 146244961713Sgirish RW_INIT(&nxgep->filter_lock, NULL, 14634045d941Ssowmini RW_DRIVER, (void *)nxgep->interrupt_cookie); 146444961713Sgirish 146544961713Sgirish classify_ptr = &nxgep->classifier; 146644961713Sgirish /* 146744961713Sgirish * FFLP Mutexes are never used in interrupt context 146844961713Sgirish * as fflp operation can take very long time to 146944961713Sgirish * complete and hence not suitable to invoke from interrupt 147044961713Sgirish * handlers. 147144961713Sgirish */ 147244961713Sgirish MUTEX_INIT(&classify_ptr->tcam_lock, NULL, 147359ac0c16Sdavemq NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 14742e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 147544961713Sgirish MUTEX_INIT(&classify_ptr->fcram_lock, NULL, 147659ac0c16Sdavemq NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 147744961713Sgirish for (partition = 0; partition < MAX_PARTITION; partition++) { 147844961713Sgirish MUTEX_INIT(&classify_ptr->hash_lock[partition], NULL, 147944961713Sgirish NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 148044961713Sgirish } 148144961713Sgirish } 148244961713Sgirish 148344961713Sgirish nxge_setup_mutexes_exit: 148444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 148559ac0c16Sdavemq "<== nxge_setup_mutexes status = %x", status)); 148644961713Sgirish 148744961713Sgirish if (ddi_status != DDI_SUCCESS) 148844961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 148944961713Sgirish 149044961713Sgirish return (status); 149144961713Sgirish } 149244961713Sgirish 149344961713Sgirish static void 149444961713Sgirish nxge_destroy_mutexes(p_nxge_t nxgep) 149544961713Sgirish { 149644961713Sgirish int partition; 149744961713Sgirish nxge_classify_t *classify_ptr; 149844961713Sgirish 149944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_mutexes")); 150044961713Sgirish RW_DESTROY(&nxgep->filter_lock); 1501678453a8Sspeer MUTEX_DESTROY(&nxgep->group_lock); 150244961713Sgirish MUTEX_DESTROY(&nxgep->mif_lock); 150344961713Sgirish MUTEX_DESTROY(&nxgep->ouraddr_lock); 150444961713Sgirish MUTEX_DESTROY(nxgep->genlock); 150544961713Sgirish 150644961713Sgirish classify_ptr = &nxgep->classifier; 150744961713Sgirish MUTEX_DESTROY(&classify_ptr->tcam_lock); 150844961713Sgirish 150998ecde52Stm /* Destroy all polling resources. */ 151098ecde52Stm MUTEX_DESTROY(&nxgep->poll_lock); 151198ecde52Stm cv_destroy(&nxgep->poll_cv); 151298ecde52Stm 151398ecde52Stm /* free data structures, based on HW type */ 15142e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 151544961713Sgirish MUTEX_DESTROY(&classify_ptr->fcram_lock); 151644961713Sgirish for (partition = 0; partition < MAX_PARTITION; partition++) { 151744961713Sgirish MUTEX_DESTROY(&classify_ptr->hash_lock[partition]); 151844961713Sgirish } 151944961713Sgirish } 152044961713Sgirish 152144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_mutexes")); 152244961713Sgirish } 152344961713Sgirish 152444961713Sgirish nxge_status_t 152544961713Sgirish nxge_init(p_nxge_t nxgep) 152644961713Sgirish { 1527678453a8Sspeer nxge_status_t status = NXGE_OK; 152844961713Sgirish 152944961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_init")); 153044961713Sgirish 153114ea4bb7Ssd if (nxgep->drv_state & STATE_HW_INITIALIZED) { 153214ea4bb7Ssd return (status); 153314ea4bb7Ssd } 153414ea4bb7Ssd 153544961713Sgirish /* 153644961713Sgirish * Allocate system memory for the receive/transmit buffer blocks 153744961713Sgirish * and receive/transmit descriptor rings. 153844961713Sgirish */ 153944961713Sgirish status = nxge_alloc_mem_pool(nxgep); 154044961713Sgirish if (status != NXGE_OK) { 154144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "alloc mem failed\n")); 154244961713Sgirish goto nxge_init_fail1; 154344961713Sgirish } 154444961713Sgirish 1545678453a8Sspeer if (!isLDOMguest(nxgep)) { 1546678453a8Sspeer /* 1547678453a8Sspeer * Initialize and enable the TXC registers. 1548678453a8Sspeer * (Globally enable the Tx controller, 1549678453a8Sspeer * enable the port, configure the dma channel bitmap, 1550678453a8Sspeer * configure the max burst size). 1551678453a8Sspeer */ 1552678453a8Sspeer status = nxge_txc_init(nxgep); 1553678453a8Sspeer if (status != NXGE_OK) { 1554678453a8Sspeer NXGE_ERROR_MSG((nxgep, 1555678453a8Sspeer NXGE_ERR_CTL, "init txc failed\n")); 1556678453a8Sspeer goto nxge_init_fail2; 1557678453a8Sspeer } 155844961713Sgirish } 155944961713Sgirish 156044961713Sgirish /* 156144961713Sgirish * Initialize and enable TXDMA channels. 156244961713Sgirish */ 156344961713Sgirish status = nxge_init_txdma_channels(nxgep); 156444961713Sgirish if (status != NXGE_OK) { 156544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txdma failed\n")); 156644961713Sgirish goto nxge_init_fail3; 156744961713Sgirish } 156844961713Sgirish 156944961713Sgirish /* 157044961713Sgirish * Initialize and enable RXDMA channels. 157144961713Sgirish */ 157244961713Sgirish status = nxge_init_rxdma_channels(nxgep); 157344961713Sgirish if (status != NXGE_OK) { 157444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init rxdma failed\n")); 157544961713Sgirish goto nxge_init_fail4; 157644961713Sgirish } 157744961713Sgirish 1578678453a8Sspeer /* 1579678453a8Sspeer * The guest domain is now done. 1580678453a8Sspeer */ 1581678453a8Sspeer if (isLDOMguest(nxgep)) { 1582678453a8Sspeer nxgep->drv_state |= STATE_HW_INITIALIZED; 1583678453a8Sspeer goto nxge_init_exit; 1584678453a8Sspeer } 1585678453a8Sspeer 158644961713Sgirish /* 158744961713Sgirish * Initialize TCAM and FCRAM (Neptune). 158844961713Sgirish */ 158944961713Sgirish status = nxge_classify_init(nxgep); 159044961713Sgirish if (status != NXGE_OK) { 159144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init classify failed\n")); 159244961713Sgirish goto nxge_init_fail5; 159344961713Sgirish } 159444961713Sgirish 159544961713Sgirish /* 159644961713Sgirish * Initialize ZCP 159744961713Sgirish */ 159844961713Sgirish status = nxge_zcp_init(nxgep); 159944961713Sgirish if (status != NXGE_OK) { 160044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init ZCP failed\n")); 160144961713Sgirish goto nxge_init_fail5; 160244961713Sgirish } 160344961713Sgirish 160444961713Sgirish /* 160544961713Sgirish * Initialize IPP. 160644961713Sgirish */ 160744961713Sgirish status = nxge_ipp_init(nxgep); 160844961713Sgirish if (status != NXGE_OK) { 160944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init IPP failed\n")); 161044961713Sgirish goto nxge_init_fail5; 161144961713Sgirish } 161244961713Sgirish 161344961713Sgirish /* 161444961713Sgirish * Initialize the MAC block. 161544961713Sgirish */ 161644961713Sgirish status = nxge_mac_init(nxgep); 161744961713Sgirish if (status != NXGE_OK) { 161844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init MAC failed\n")); 161944961713Sgirish goto nxge_init_fail5; 162044961713Sgirish } 162144961713Sgirish 1622678453a8Sspeer nxge_intrs_enable(nxgep); /* XXX What changes do I need to make here? */ 162344961713Sgirish 162444961713Sgirish /* 162544961713Sgirish * Enable hardware interrupts. 162644961713Sgirish */ 162744961713Sgirish nxge_intr_hw_enable(nxgep); 162844961713Sgirish nxgep->drv_state |= STATE_HW_INITIALIZED; 162944961713Sgirish 163044961713Sgirish goto nxge_init_exit; 163144961713Sgirish 163244961713Sgirish nxge_init_fail5: 163344961713Sgirish nxge_uninit_rxdma_channels(nxgep); 163444961713Sgirish nxge_init_fail4: 163544961713Sgirish nxge_uninit_txdma_channels(nxgep); 163644961713Sgirish nxge_init_fail3: 1637678453a8Sspeer if (!isLDOMguest(nxgep)) { 1638678453a8Sspeer (void) nxge_txc_uninit(nxgep); 1639678453a8Sspeer } 164044961713Sgirish nxge_init_fail2: 164144961713Sgirish nxge_free_mem_pool(nxgep); 164244961713Sgirish nxge_init_fail1: 164344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16444045d941Ssowmini "<== nxge_init status (failed) = 0x%08x", status)); 164544961713Sgirish return (status); 164644961713Sgirish 164744961713Sgirish nxge_init_exit: 164844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_init status = 0x%08x", 16494045d941Ssowmini status)); 165044961713Sgirish return (status); 165144961713Sgirish } 165244961713Sgirish 165344961713Sgirish 165444961713Sgirish timeout_id_t 165544961713Sgirish nxge_start_timer(p_nxge_t nxgep, fptrv_t func, int msec) 165644961713Sgirish { 16574045d941Ssowmini if ((nxgep->suspended == 0) || (nxgep->suspended == DDI_RESUME)) { 165844961713Sgirish return (timeout(func, (caddr_t)nxgep, 16594045d941Ssowmini drv_usectohz(1000 * msec))); 166044961713Sgirish } 166144961713Sgirish return (NULL); 166244961713Sgirish } 166344961713Sgirish 166444961713Sgirish /*ARGSUSED*/ 166544961713Sgirish void 166644961713Sgirish nxge_stop_timer(p_nxge_t nxgep, timeout_id_t timerid) 166744961713Sgirish { 166844961713Sgirish if (timerid) { 166944961713Sgirish (void) untimeout(timerid); 167044961713Sgirish } 167144961713Sgirish } 167244961713Sgirish 167344961713Sgirish void 167444961713Sgirish nxge_uninit(p_nxge_t nxgep) 167544961713Sgirish { 167644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_uninit")); 167744961713Sgirish 167844961713Sgirish if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 167944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 16804045d941Ssowmini "==> nxge_uninit: not initialized")); 168144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 16824045d941Ssowmini "<== nxge_uninit")); 168344961713Sgirish return; 168444961713Sgirish } 168544961713Sgirish 168644961713Sgirish /* stop timer */ 168744961713Sgirish if (nxgep->nxge_timerid) { 168844961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 168944961713Sgirish nxgep->nxge_timerid = 0; 169044961713Sgirish } 169144961713Sgirish 169244961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 169344961713Sgirish (void) nxge_intr_hw_disable(nxgep); 169444961713Sgirish 169544961713Sgirish /* 169644961713Sgirish * Reset the receive MAC side. 169744961713Sgirish */ 169844961713Sgirish (void) nxge_rx_mac_disable(nxgep); 169944961713Sgirish 170044961713Sgirish /* Disable and soft reset the IPP */ 1701678453a8Sspeer if (!isLDOMguest(nxgep)) 1702678453a8Sspeer (void) nxge_ipp_disable(nxgep); 170344961713Sgirish 1704a3c5bd6dSspeer /* Free classification resources */ 1705a3c5bd6dSspeer (void) nxge_classify_uninit(nxgep); 1706a3c5bd6dSspeer 170744961713Sgirish /* 170844961713Sgirish * Reset the transmit/receive DMA side. 170944961713Sgirish */ 171044961713Sgirish (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 171144961713Sgirish (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 171244961713Sgirish 171344961713Sgirish nxge_uninit_txdma_channels(nxgep); 171444961713Sgirish nxge_uninit_rxdma_channels(nxgep); 171544961713Sgirish 171644961713Sgirish /* 171744961713Sgirish * Reset the transmit MAC side. 171844961713Sgirish */ 171944961713Sgirish (void) nxge_tx_mac_disable(nxgep); 172044961713Sgirish 172144961713Sgirish nxge_free_mem_pool(nxgep); 172244961713Sgirish 17236f157acbSml /* 17246f157acbSml * Start the timer if the reset flag is not set. 17256f157acbSml * If this reset flag is set, the link monitor 17266f157acbSml * will not be started in order to stop furthur bus 17276f157acbSml * activities coming from this interface. 17286f157acbSml * The driver will start the monitor function 17296f157acbSml * if the interface was initialized again later. 17306f157acbSml */ 17316f157acbSml if (!nxge_peu_reset_enable) { 17326f157acbSml (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 17336f157acbSml } 173444961713Sgirish 173544961713Sgirish nxgep->drv_state &= ~STATE_HW_INITIALIZED; 173644961713Sgirish 173744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_uninit: " 17384045d941Ssowmini "nxge_mblks_pending %d", nxge_mblks_pending)); 173944961713Sgirish } 174044961713Sgirish 174144961713Sgirish void 174244961713Sgirish nxge_get64(p_nxge_t nxgep, p_mblk_t mp) 174344961713Sgirish { 1744adfcba55Sjoycey #if defined(__i386) 1745adfcba55Sjoycey size_t reg; 1746adfcba55Sjoycey #else 174744961713Sgirish uint64_t reg; 1748adfcba55Sjoycey #endif 174944961713Sgirish uint64_t regdata; 175044961713Sgirish int i, retry; 175144961713Sgirish 175244961713Sgirish bcopy((char *)mp->b_rptr, (char *)®, sizeof (uint64_t)); 175344961713Sgirish regdata = 0; 175444961713Sgirish retry = 1; 175544961713Sgirish 175644961713Sgirish for (i = 0; i < retry; i++) { 175744961713Sgirish NXGE_REG_RD64(nxgep->npi_handle, reg, ®data); 175844961713Sgirish } 175944961713Sgirish bcopy((char *)®data, (char *)mp->b_rptr, sizeof (uint64_t)); 176044961713Sgirish } 176144961713Sgirish 176244961713Sgirish void 176344961713Sgirish nxge_put64(p_nxge_t nxgep, p_mblk_t mp) 176444961713Sgirish { 1765adfcba55Sjoycey #if defined(__i386) 1766adfcba55Sjoycey size_t reg; 1767adfcba55Sjoycey #else 176844961713Sgirish uint64_t reg; 1769adfcba55Sjoycey #endif 177044961713Sgirish uint64_t buf[2]; 177144961713Sgirish 177244961713Sgirish bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t)); 17737a8b1321Sjoycey #if defined(__i386) 17747a8b1321Sjoycey reg = (size_t)buf[0]; 17757a8b1321Sjoycey #else 177644961713Sgirish reg = buf[0]; 17777a8b1321Sjoycey #endif 177844961713Sgirish 177944961713Sgirish NXGE_NPI_PIO_WRITE64(nxgep->npi_handle, reg, buf[1]); 178044961713Sgirish } 178144961713Sgirish 178244961713Sgirish 178344961713Sgirish nxge_os_mutex_t nxgedebuglock; 178444961713Sgirish int nxge_debug_init = 0; 178544961713Sgirish 178644961713Sgirish /*ARGSUSED*/ 178744961713Sgirish /*VARARGS*/ 178844961713Sgirish void 178944961713Sgirish nxge_debug_msg(p_nxge_t nxgep, uint64_t level, char *fmt, ...) 179044961713Sgirish { 179144961713Sgirish char msg_buffer[1048]; 179244961713Sgirish char prefix_buffer[32]; 179344961713Sgirish int instance; 179444961713Sgirish uint64_t debug_level; 179544961713Sgirish int cmn_level = CE_CONT; 179644961713Sgirish va_list ap; 179744961713Sgirish 1798678453a8Sspeer if (nxgep && nxgep->nxge_debug_level != nxge_debug_level) { 1799678453a8Sspeer /* In case a developer has changed nxge_debug_level. */ 1800678453a8Sspeer if (nxgep->nxge_debug_level != nxge_debug_level) 1801678453a8Sspeer nxgep->nxge_debug_level = nxge_debug_level; 1802678453a8Sspeer } 1803678453a8Sspeer 180444961713Sgirish debug_level = (nxgep == NULL) ? nxge_debug_level : 18054045d941Ssowmini nxgep->nxge_debug_level; 180644961713Sgirish 180744961713Sgirish if ((level & debug_level) || 18084045d941Ssowmini (level == NXGE_NOTE) || 18094045d941Ssowmini (level == NXGE_ERR_CTL)) { 181044961713Sgirish /* do the msg processing */ 181144961713Sgirish if (nxge_debug_init == 0) { 181244961713Sgirish MUTEX_INIT(&nxgedebuglock, NULL, MUTEX_DRIVER, NULL); 181344961713Sgirish nxge_debug_init = 1; 181444961713Sgirish } 181544961713Sgirish 181644961713Sgirish MUTEX_ENTER(&nxgedebuglock); 181744961713Sgirish 181844961713Sgirish if ((level & NXGE_NOTE)) { 181944961713Sgirish cmn_level = CE_NOTE; 182044961713Sgirish } 182144961713Sgirish 182244961713Sgirish if (level & NXGE_ERR_CTL) { 182344961713Sgirish cmn_level = CE_WARN; 182444961713Sgirish } 182544961713Sgirish 182644961713Sgirish va_start(ap, fmt); 182744961713Sgirish (void) vsprintf(msg_buffer, fmt, ap); 182844961713Sgirish va_end(ap); 182944961713Sgirish if (nxgep == NULL) { 183044961713Sgirish instance = -1; 183144961713Sgirish (void) sprintf(prefix_buffer, "%s :", "nxge"); 183244961713Sgirish } else { 183344961713Sgirish instance = nxgep->instance; 183444961713Sgirish (void) sprintf(prefix_buffer, 18354045d941Ssowmini "%s%d :", "nxge", instance); 183644961713Sgirish } 183744961713Sgirish 183844961713Sgirish MUTEX_EXIT(&nxgedebuglock); 183944961713Sgirish cmn_err(cmn_level, "!%s %s\n", 18404045d941Ssowmini prefix_buffer, msg_buffer); 184144961713Sgirish 184244961713Sgirish } 184344961713Sgirish } 184444961713Sgirish 184544961713Sgirish char * 184644961713Sgirish nxge_dump_packet(char *addr, int size) 184744961713Sgirish { 184844961713Sgirish uchar_t *ap = (uchar_t *)addr; 184944961713Sgirish int i; 185044961713Sgirish static char etherbuf[1024]; 185144961713Sgirish char *cp = etherbuf; 185244961713Sgirish char digits[] = "0123456789abcdef"; 185344961713Sgirish 185444961713Sgirish if (!size) 185544961713Sgirish size = 60; 185644961713Sgirish 185744961713Sgirish if (size > MAX_DUMP_SZ) { 185844961713Sgirish /* Dump the leading bytes */ 185944961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 186044961713Sgirish if (*ap > 0x0f) 186144961713Sgirish *cp++ = digits[*ap >> 4]; 186244961713Sgirish *cp++ = digits[*ap++ & 0xf]; 186344961713Sgirish *cp++ = ':'; 186444961713Sgirish } 186544961713Sgirish for (i = 0; i < 20; i++) 186644961713Sgirish *cp++ = '.'; 186744961713Sgirish /* Dump the last MAX_DUMP_SZ/2 bytes */ 186844961713Sgirish ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ/2)); 186944961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 187044961713Sgirish if (*ap > 0x0f) 187144961713Sgirish *cp++ = digits[*ap >> 4]; 187244961713Sgirish *cp++ = digits[*ap++ & 0xf]; 187344961713Sgirish *cp++ = ':'; 187444961713Sgirish } 187544961713Sgirish } else { 187644961713Sgirish for (i = 0; i < size; i++) { 187744961713Sgirish if (*ap > 0x0f) 187844961713Sgirish *cp++ = digits[*ap >> 4]; 187944961713Sgirish *cp++ = digits[*ap++ & 0xf]; 188044961713Sgirish *cp++ = ':'; 188144961713Sgirish } 188244961713Sgirish } 188344961713Sgirish *--cp = 0; 188444961713Sgirish return (etherbuf); 188544961713Sgirish } 188644961713Sgirish 188744961713Sgirish #ifdef NXGE_DEBUG 188844961713Sgirish static void 188944961713Sgirish nxge_test_map_regs(p_nxge_t nxgep) 189044961713Sgirish { 189144961713Sgirish ddi_acc_handle_t cfg_handle; 189244961713Sgirish p_pci_cfg_t cfg_ptr; 189344961713Sgirish ddi_acc_handle_t dev_handle; 189444961713Sgirish char *dev_ptr; 189544961713Sgirish ddi_acc_handle_t pci_config_handle; 189644961713Sgirish uint32_t regval; 189744961713Sgirish int i; 189844961713Sgirish 189944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_test_map_regs")); 190044961713Sgirish 190144961713Sgirish dev_handle = nxgep->dev_regs->nxge_regh; 190244961713Sgirish dev_ptr = (char *)nxgep->dev_regs->nxge_regp; 190344961713Sgirish 19042e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 190544961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 190644961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 190744961713Sgirish 190844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 190959ac0c16Sdavemq "Neptune PCI regp cfg_ptr 0x%llx", (char *)cfg_ptr)); 191044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 191159ac0c16Sdavemq "Neptune PCI cfg_ptr vendor id ptr 0x%llx", 191259ac0c16Sdavemq &cfg_ptr->vendorid)); 191344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 191459ac0c16Sdavemq "\tvendorid 0x%x devid 0x%x", 191559ac0c16Sdavemq NXGE_PIO_READ16(cfg_handle, &cfg_ptr->vendorid, 0), 191659ac0c16Sdavemq NXGE_PIO_READ16(cfg_handle, &cfg_ptr->devid, 0))); 191744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 191859ac0c16Sdavemq "PCI BAR: base 0x%x base14 0x%x base 18 0x%x " 191959ac0c16Sdavemq "bar1c 0x%x", 192059ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base, 0), 192159ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base14, 0), 192259ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base18, 0), 192359ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base1c, 0))); 192444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 192559ac0c16Sdavemq "\nNeptune PCI BAR: base20 0x%x base24 0x%x " 192659ac0c16Sdavemq "base 28 0x%x bar2c 0x%x\n", 192759ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base20, 0), 192859ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base24, 0), 192959ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base28, 0), 193059ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base2c, 0))); 193144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 193259ac0c16Sdavemq "\nNeptune PCI BAR: base30 0x%x\n", 193359ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base30, 0))); 193444961713Sgirish 193544961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 193644961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 193744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 193859ac0c16Sdavemq "first 0x%llx second 0x%llx third 0x%llx " 193959ac0c16Sdavemq "last 0x%llx ", 194059ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 194159ac0c16Sdavemq (uint64_t *)(dev_ptr + 0), 0), 194259ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 194359ac0c16Sdavemq (uint64_t *)(dev_ptr + 8), 0), 194459ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 194559ac0c16Sdavemq (uint64_t *)(dev_ptr + 16), 0), 194659ac0c16Sdavemq NXGE_PIO_READ64(cfg_handle, 194759ac0c16Sdavemq (uint64_t *)(dev_ptr + 24), 0))); 194844961713Sgirish } 194944961713Sgirish } 195044961713Sgirish 195144961713Sgirish #endif 195244961713Sgirish 195344961713Sgirish static void 195444961713Sgirish nxge_suspend(p_nxge_t nxgep) 195544961713Sgirish { 195644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_suspend")); 195744961713Sgirish 195844961713Sgirish nxge_intrs_disable(nxgep); 195944961713Sgirish nxge_destroy_dev(nxgep); 196044961713Sgirish 196144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_suspend")); 196244961713Sgirish } 196344961713Sgirish 196444961713Sgirish static nxge_status_t 196544961713Sgirish nxge_resume(p_nxge_t nxgep) 196644961713Sgirish { 196744961713Sgirish nxge_status_t status = NXGE_OK; 196844961713Sgirish 196944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_resume")); 197044961713Sgirish 197191c98b31Sjoycey nxgep->suspended = DDI_RESUME; 197291c98b31Sjoycey (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 197391c98b31Sjoycey (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_START); 197491c98b31Sjoycey (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START); 197591c98b31Sjoycey (void) nxge_rx_mac_enable(nxgep); 197691c98b31Sjoycey (void) nxge_tx_mac_enable(nxgep); 197791c98b31Sjoycey nxge_intrs_enable(nxgep); 197844961713Sgirish nxgep->suspended = 0; 197944961713Sgirish 198044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 19814045d941Ssowmini "<== nxge_resume status = 0x%x", status)); 198244961713Sgirish return (status); 198344961713Sgirish } 198444961713Sgirish 198544961713Sgirish static nxge_status_t 198644961713Sgirish nxge_setup_dev(p_nxge_t nxgep) 198744961713Sgirish { 198844961713Sgirish nxge_status_t status = NXGE_OK; 198944961713Sgirish 199044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_dev port %d", 199159ac0c16Sdavemq nxgep->mac.portnum)); 199244961713Sgirish 199344961713Sgirish status = nxge_link_init(nxgep); 199414ea4bb7Ssd 199514ea4bb7Ssd if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) { 199614ea4bb7Ssd NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 19974045d941Ssowmini "port%d Bad register acc handle", nxgep->mac.portnum)); 199814ea4bb7Ssd status = NXGE_ERROR; 199914ea4bb7Ssd } 200014ea4bb7Ssd 200144961713Sgirish if (status != NXGE_OK) { 200244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20034045d941Ssowmini " nxge_setup_dev status " 20044045d941Ssowmini "(xcvr init 0x%08x)", status)); 200544961713Sgirish goto nxge_setup_dev_exit; 200644961713Sgirish } 200744961713Sgirish 200844961713Sgirish nxge_setup_dev_exit: 200944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20104045d941Ssowmini "<== nxge_setup_dev port %d status = 0x%08x", 20114045d941Ssowmini nxgep->mac.portnum, status)); 201244961713Sgirish 201344961713Sgirish return (status); 201444961713Sgirish } 201544961713Sgirish 201644961713Sgirish static void 201744961713Sgirish nxge_destroy_dev(p_nxge_t nxgep) 201844961713Sgirish { 201944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_dev")); 202044961713Sgirish 202144961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 202244961713Sgirish 202344961713Sgirish (void) nxge_hw_stop(nxgep); 202444961713Sgirish 202544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_dev")); 202644961713Sgirish } 202744961713Sgirish 202844961713Sgirish static nxge_status_t 202944961713Sgirish nxge_setup_system_dma_pages(p_nxge_t nxgep) 203044961713Sgirish { 203144961713Sgirish int ddi_status = DDI_SUCCESS; 203244961713Sgirish uint_t count; 203344961713Sgirish ddi_dma_cookie_t cookie; 203444961713Sgirish uint_t iommu_pagesize; 203544961713Sgirish nxge_status_t status = NXGE_OK; 203644961713Sgirish 2037678453a8Sspeer NXGE_ERROR_MSG((nxgep, DDI_CTL, "==> nxge_setup_system_dma_pages")); 203844961713Sgirish nxgep->sys_page_sz = ddi_ptob(nxgep->dip, (ulong_t)1); 203944961713Sgirish if (nxgep->niu_type != N2_NIU) { 204044961713Sgirish iommu_pagesize = dvma_pagesize(nxgep->dip); 204144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20424045d941Ssowmini " nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 20434045d941Ssowmini " default_block_size %d iommu_pagesize %d", 20444045d941Ssowmini nxgep->sys_page_sz, 20454045d941Ssowmini ddi_ptob(nxgep->dip, (ulong_t)1), 20464045d941Ssowmini nxgep->rx_default_block_size, 20474045d941Ssowmini iommu_pagesize)); 204844961713Sgirish 204944961713Sgirish if (iommu_pagesize != 0) { 205044961713Sgirish if (nxgep->sys_page_sz == iommu_pagesize) { 205144961713Sgirish if (iommu_pagesize > 0x4000) 205244961713Sgirish nxgep->sys_page_sz = 0x4000; 205344961713Sgirish } else { 205444961713Sgirish if (nxgep->sys_page_sz > iommu_pagesize) 205544961713Sgirish nxgep->sys_page_sz = iommu_pagesize; 205644961713Sgirish } 205744961713Sgirish } 205844961713Sgirish } 205944961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 206044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20614045d941Ssowmini "==> nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 20624045d941Ssowmini "default_block_size %d page mask %d", 20634045d941Ssowmini nxgep->sys_page_sz, 20644045d941Ssowmini ddi_ptob(nxgep->dip, (ulong_t)1), 20654045d941Ssowmini nxgep->rx_default_block_size, 20664045d941Ssowmini nxgep->sys_page_mask)); 206744961713Sgirish 206844961713Sgirish 206944961713Sgirish switch (nxgep->sys_page_sz) { 207044961713Sgirish default: 207144961713Sgirish nxgep->sys_page_sz = 0x1000; 207244961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 207344961713Sgirish nxgep->rx_default_block_size = 0x1000; 207444961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 207544961713Sgirish break; 207644961713Sgirish case 0x1000: 207744961713Sgirish nxgep->rx_default_block_size = 0x1000; 207844961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 207944961713Sgirish break; 208044961713Sgirish case 0x2000: 208144961713Sgirish nxgep->rx_default_block_size = 0x2000; 208244961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 208344961713Sgirish break; 208444961713Sgirish case 0x4000: 208544961713Sgirish nxgep->rx_default_block_size = 0x4000; 208644961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_16K; 208744961713Sgirish break; 208844961713Sgirish case 0x8000: 208944961713Sgirish nxgep->rx_default_block_size = 0x8000; 209044961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_32K; 209144961713Sgirish break; 209244961713Sgirish } 209344961713Sgirish 209444961713Sgirish #ifndef USE_RX_BIG_BUF 209544961713Sgirish nxge_rx_dma_attr.dma_attr_align = nxgep->sys_page_sz; 209644961713Sgirish #else 209744961713Sgirish nxgep->rx_default_block_size = 0x2000; 209844961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 209944961713Sgirish #endif 210044961713Sgirish /* 210144961713Sgirish * Get the system DMA burst size. 210244961713Sgirish */ 210344961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr, 21044045d941Ssowmini DDI_DMA_DONTWAIT, 0, 21054045d941Ssowmini &nxgep->dmasparehandle); 210644961713Sgirish if (ddi_status != DDI_SUCCESS) { 210744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 21084045d941Ssowmini "ddi_dma_alloc_handle: failed " 21094045d941Ssowmini " status 0x%x", ddi_status)); 211044961713Sgirish goto nxge_get_soft_properties_exit; 211144961713Sgirish } 211244961713Sgirish 211344961713Sgirish ddi_status = ddi_dma_addr_bind_handle(nxgep->dmasparehandle, NULL, 21144045d941Ssowmini (caddr_t)nxgep->dmasparehandle, 21154045d941Ssowmini sizeof (nxgep->dmasparehandle), 21164045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 21174045d941Ssowmini DDI_DMA_DONTWAIT, 0, 21184045d941Ssowmini &cookie, &count); 211944961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 212044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 21214045d941Ssowmini "Binding spare handle to find system" 21224045d941Ssowmini " burstsize failed.")); 212344961713Sgirish ddi_status = DDI_FAILURE; 212444961713Sgirish goto nxge_get_soft_properties_fail1; 212544961713Sgirish } 212644961713Sgirish 212744961713Sgirish nxgep->sys_burst_sz = ddi_dma_burstsizes(nxgep->dmasparehandle); 212844961713Sgirish (void) ddi_dma_unbind_handle(nxgep->dmasparehandle); 212944961713Sgirish 213044961713Sgirish nxge_get_soft_properties_fail1: 213144961713Sgirish ddi_dma_free_handle(&nxgep->dmasparehandle); 213244961713Sgirish 213344961713Sgirish nxge_get_soft_properties_exit: 213444961713Sgirish 213544961713Sgirish if (ddi_status != DDI_SUCCESS) 213644961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 213744961713Sgirish 213844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 21394045d941Ssowmini "<== nxge_setup_system_dma_pages status = 0x%08x", status)); 214044961713Sgirish return (status); 214144961713Sgirish } 214244961713Sgirish 214344961713Sgirish static nxge_status_t 214444961713Sgirish nxge_alloc_mem_pool(p_nxge_t nxgep) 214544961713Sgirish { 214644961713Sgirish nxge_status_t status = NXGE_OK; 214744961713Sgirish 214844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_alloc_mem_pool")); 214944961713Sgirish 215044961713Sgirish status = nxge_alloc_rx_mem_pool(nxgep); 215144961713Sgirish if (status != NXGE_OK) { 215244961713Sgirish return (NXGE_ERROR); 215344961713Sgirish } 215444961713Sgirish 215544961713Sgirish status = nxge_alloc_tx_mem_pool(nxgep); 215644961713Sgirish if (status != NXGE_OK) { 215744961713Sgirish nxge_free_rx_mem_pool(nxgep); 215844961713Sgirish return (NXGE_ERROR); 215944961713Sgirish } 216044961713Sgirish 216144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_alloc_mem_pool")); 216244961713Sgirish return (NXGE_OK); 216344961713Sgirish } 216444961713Sgirish 216544961713Sgirish static void 216644961713Sgirish nxge_free_mem_pool(p_nxge_t nxgep) 216744961713Sgirish { 216844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_mem_pool")); 216944961713Sgirish 217044961713Sgirish nxge_free_rx_mem_pool(nxgep); 217144961713Sgirish nxge_free_tx_mem_pool(nxgep); 217244961713Sgirish 217344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_mem_pool")); 217444961713Sgirish } 217544961713Sgirish 2176678453a8Sspeer nxge_status_t 217744961713Sgirish nxge_alloc_rx_mem_pool(p_nxge_t nxgep) 217844961713Sgirish { 2179678453a8Sspeer uint32_t rdc_max; 218044961713Sgirish p_nxge_dma_pt_cfg_t p_all_cfgp; 218144961713Sgirish p_nxge_hw_pt_cfg_t p_cfgp; 218244961713Sgirish p_nxge_dma_pool_t dma_poolp; 218344961713Sgirish p_nxge_dma_common_t *dma_buf_p; 218444961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 218544961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 218644961713Sgirish uint32_t *num_chunks; /* per dma */ 218744961713Sgirish nxge_status_t status = NXGE_OK; 218844961713Sgirish 218944961713Sgirish uint32_t nxge_port_rbr_size; 219044961713Sgirish uint32_t nxge_port_rbr_spare_size; 219144961713Sgirish uint32_t nxge_port_rcr_size; 2192678453a8Sspeer uint32_t rx_cntl_alloc_size; 219344961713Sgirish 219444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_mem_pool")); 219544961713Sgirish 219644961713Sgirish p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 219744961713Sgirish p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 2198678453a8Sspeer rdc_max = NXGE_MAX_RDCS; 219944961713Sgirish 220044961713Sgirish /* 2201678453a8Sspeer * Allocate memory for the common DMA data structures. 220244961713Sgirish */ 220344961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 22044045d941Ssowmini KM_SLEEP); 220544961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 22064045d941Ssowmini sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP); 220744961713Sgirish 220844961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 22094045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 221044961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 22114045d941Ssowmini sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP); 221244961713Sgirish 221344961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 22144045d941Ssowmini sizeof (uint32_t) * rdc_max, KM_SLEEP); 221544961713Sgirish 221644961713Sgirish /* 2217678453a8Sspeer * Assume that each DMA channel will be configured with 2218678453a8Sspeer * the default block size. 2219678453a8Sspeer * rbr block counts are modulo the batch count (16). 222044961713Sgirish */ 222144961713Sgirish nxge_port_rbr_size = p_all_cfgp->rbr_size; 222244961713Sgirish nxge_port_rcr_size = p_all_cfgp->rcr_size; 222344961713Sgirish 222444961713Sgirish if (!nxge_port_rbr_size) { 222544961713Sgirish nxge_port_rbr_size = NXGE_RBR_RBB_DEFAULT; 222644961713Sgirish } 222744961713Sgirish if (nxge_port_rbr_size % NXGE_RXDMA_POST_BATCH) { 222844961713Sgirish nxge_port_rbr_size = (NXGE_RXDMA_POST_BATCH * 22294045d941Ssowmini (nxge_port_rbr_size / NXGE_RXDMA_POST_BATCH + 1)); 223044961713Sgirish } 223144961713Sgirish 223244961713Sgirish p_all_cfgp->rbr_size = nxge_port_rbr_size; 223344961713Sgirish nxge_port_rbr_spare_size = nxge_rbr_spare_size; 223444961713Sgirish 223544961713Sgirish if (nxge_port_rbr_spare_size % NXGE_RXDMA_POST_BATCH) { 223644961713Sgirish nxge_port_rbr_spare_size = (NXGE_RXDMA_POST_BATCH * 22374045d941Ssowmini (nxge_port_rbr_spare_size / NXGE_RXDMA_POST_BATCH + 1)); 223844961713Sgirish } 223930ac2e7bSml if (nxge_port_rbr_size > RBR_DEFAULT_MAX_BLKS) { 224030ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 224130ac2e7bSml "nxge_alloc_rx_mem_pool: RBR size too high %d, " 224230ac2e7bSml "set to default %d", 224330ac2e7bSml nxge_port_rbr_size, RBR_DEFAULT_MAX_BLKS)); 224430ac2e7bSml nxge_port_rbr_size = RBR_DEFAULT_MAX_BLKS; 224530ac2e7bSml } 224630ac2e7bSml if (nxge_port_rcr_size > RCR_DEFAULT_MAX) { 224730ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 224830ac2e7bSml "nxge_alloc_rx_mem_pool: RCR too high %d, " 224930ac2e7bSml "set to default %d", 225030ac2e7bSml nxge_port_rcr_size, RCR_DEFAULT_MAX)); 225130ac2e7bSml nxge_port_rcr_size = RCR_DEFAULT_MAX; 225230ac2e7bSml } 225344961713Sgirish 225444961713Sgirish /* 225544961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 225644961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 225744961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 225844961713Sgirish * function). 225944961713Sgirish */ 226044961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 226144961713Sgirish if (nxgep->niu_type == N2_NIU) { 226244961713Sgirish nxge_port_rbr_spare_size = 0; 226344961713Sgirish if ((nxge_port_rbr_size > NXGE_NIU_CONTIG_RBR_MAX) || 22644045d941Ssowmini (!ISP2(nxge_port_rbr_size))) { 226544961713Sgirish nxge_port_rbr_size = NXGE_NIU_CONTIG_RBR_MAX; 226644961713Sgirish } 226744961713Sgirish if ((nxge_port_rcr_size > NXGE_NIU_CONTIG_RCR_MAX) || 22684045d941Ssowmini (!ISP2(nxge_port_rcr_size))) { 226944961713Sgirish nxge_port_rcr_size = NXGE_NIU_CONTIG_RCR_MAX; 227044961713Sgirish } 227144961713Sgirish } 227244961713Sgirish #endif 227344961713Sgirish 227444961713Sgirish /* 227544961713Sgirish * Addresses of receive block ring, receive completion ring and the 227644961713Sgirish * mailbox must be all cache-aligned (64 bytes). 227744961713Sgirish */ 227844961713Sgirish rx_cntl_alloc_size = nxge_port_rbr_size + nxge_port_rbr_spare_size; 227944961713Sgirish rx_cntl_alloc_size *= (sizeof (rx_desc_t)); 228044961713Sgirish rx_cntl_alloc_size += (sizeof (rcr_entry_t) * nxge_port_rcr_size); 228144961713Sgirish rx_cntl_alloc_size += sizeof (rxdma_mailbox_t); 228244961713Sgirish 228344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_alloc_rx_mem_pool: " 22844045d941Ssowmini "nxge_port_rbr_size = %d nxge_port_rbr_spare_size = %d " 22854045d941Ssowmini "nxge_port_rcr_size = %d " 22864045d941Ssowmini "rx_cntl_alloc_size = %d", 22874045d941Ssowmini nxge_port_rbr_size, nxge_port_rbr_spare_size, 22884045d941Ssowmini nxge_port_rcr_size, 22894045d941Ssowmini rx_cntl_alloc_size)); 229044961713Sgirish 229144961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 229244961713Sgirish if (nxgep->niu_type == N2_NIU) { 2293678453a8Sspeer uint32_t rx_buf_alloc_size = (nxgep->rx_default_block_size * 2294678453a8Sspeer (nxge_port_rbr_size + nxge_port_rbr_spare_size)); 2295678453a8Sspeer 229644961713Sgirish if (!ISP2(rx_buf_alloc_size)) { 229744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 22984045d941Ssowmini "==> nxge_alloc_rx_mem_pool: " 22994045d941Ssowmini " must be power of 2")); 230044961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 230144961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 230244961713Sgirish } 230344961713Sgirish 230444961713Sgirish if (rx_buf_alloc_size > (1 << 22)) { 230544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 23064045d941Ssowmini "==> nxge_alloc_rx_mem_pool: " 23074045d941Ssowmini " limit size to 4M")); 230844961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 230944961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 231044961713Sgirish } 231144961713Sgirish 231244961713Sgirish if (rx_cntl_alloc_size < 0x2000) { 231344961713Sgirish rx_cntl_alloc_size = 0x2000; 231444961713Sgirish } 231544961713Sgirish } 231644961713Sgirish #endif 231744961713Sgirish nxgep->nxge_port_rbr_size = nxge_port_rbr_size; 231844961713Sgirish nxgep->nxge_port_rcr_size = nxge_port_rcr_size; 2319678453a8Sspeer nxgep->nxge_port_rbr_spare_size = nxge_port_rbr_spare_size; 2320678453a8Sspeer nxgep->nxge_port_rx_cntl_alloc_size = rx_cntl_alloc_size; 232144961713Sgirish 2322678453a8Sspeer dma_poolp->ndmas = p_cfgp->max_rdcs; 232344961713Sgirish dma_poolp->num_chunks = num_chunks; 232444961713Sgirish dma_poolp->buf_allocated = B_TRUE; 232544961713Sgirish nxgep->rx_buf_pool_p = dma_poolp; 232644961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 232744961713Sgirish 2328678453a8Sspeer dma_cntl_poolp->ndmas = p_cfgp->max_rdcs; 232944961713Sgirish dma_cntl_poolp->buf_allocated = B_TRUE; 233044961713Sgirish nxgep->rx_cntl_pool_p = dma_cntl_poolp; 233144961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 233244961713Sgirish 2333678453a8Sspeer /* Allocate the receive rings, too. */ 2334678453a8Sspeer nxgep->rx_rbr_rings = 23354045d941Ssowmini KMEM_ZALLOC(sizeof (rx_rbr_rings_t), KM_SLEEP); 2336678453a8Sspeer nxgep->rx_rbr_rings->rbr_rings = 23374045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_rbr_ring_t) * rdc_max, KM_SLEEP); 2338678453a8Sspeer nxgep->rx_rcr_rings = 23394045d941Ssowmini KMEM_ZALLOC(sizeof (rx_rcr_rings_t), KM_SLEEP); 2340678453a8Sspeer nxgep->rx_rcr_rings->rcr_rings = 23414045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_rcr_ring_t) * rdc_max, KM_SLEEP); 2342678453a8Sspeer nxgep->rx_mbox_areas_p = 23434045d941Ssowmini KMEM_ZALLOC(sizeof (rx_mbox_areas_t), KM_SLEEP); 2344678453a8Sspeer nxgep->rx_mbox_areas_p->rxmbox_areas = 23454045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_mbox_t) * rdc_max, KM_SLEEP); 2346678453a8Sspeer 2347678453a8Sspeer nxgep->rx_rbr_rings->ndmas = nxgep->rx_rcr_rings->ndmas = 2348678453a8Sspeer p_cfgp->max_rdcs; 234944961713Sgirish 235044961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 23514045d941Ssowmini "<== nxge_alloc_rx_mem_pool:status 0x%08x", status)); 235244961713Sgirish 2353678453a8Sspeer nxge_alloc_rx_mem_pool_exit: 2354678453a8Sspeer return (status); 2355678453a8Sspeer } 2356678453a8Sspeer 2357678453a8Sspeer /* 2358678453a8Sspeer * nxge_alloc_rxb 2359678453a8Sspeer * 2360678453a8Sspeer * Allocate buffers for an RDC. 2361678453a8Sspeer * 2362678453a8Sspeer * Arguments: 2363678453a8Sspeer * nxgep 2364678453a8Sspeer * channel The channel to map into our kernel space. 2365678453a8Sspeer * 2366678453a8Sspeer * Notes: 2367678453a8Sspeer * 2368678453a8Sspeer * NPI function calls: 2369678453a8Sspeer * 2370678453a8Sspeer * NXGE function calls: 2371678453a8Sspeer * 2372678453a8Sspeer * Registers accessed: 2373678453a8Sspeer * 2374678453a8Sspeer * Context: 2375678453a8Sspeer * 2376678453a8Sspeer * Taking apart: 2377678453a8Sspeer * 2378678453a8Sspeer * Open questions: 2379678453a8Sspeer * 2380678453a8Sspeer */ 2381678453a8Sspeer nxge_status_t 2382678453a8Sspeer nxge_alloc_rxb( 2383678453a8Sspeer p_nxge_t nxgep, 2384678453a8Sspeer int channel) 2385678453a8Sspeer { 2386678453a8Sspeer size_t rx_buf_alloc_size; 2387678453a8Sspeer nxge_status_t status = NXGE_OK; 2388678453a8Sspeer 2389678453a8Sspeer nxge_dma_common_t **data; 2390678453a8Sspeer nxge_dma_common_t **control; 2391678453a8Sspeer uint32_t *num_chunks; 2392678453a8Sspeer 2393678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb")); 2394678453a8Sspeer 2395678453a8Sspeer /* 2396678453a8Sspeer * Allocate memory for the receive buffers and descriptor rings. 2397678453a8Sspeer * Replace these allocation functions with the interface functions 2398678453a8Sspeer * provided by the partition manager if/when they are available. 2399678453a8Sspeer */ 2400678453a8Sspeer 2401678453a8Sspeer /* 2402678453a8Sspeer * Allocate memory for the receive buffer blocks. 2403678453a8Sspeer */ 2404678453a8Sspeer rx_buf_alloc_size = (nxgep->rx_default_block_size * 24054045d941Ssowmini (nxgep->nxge_port_rbr_size + nxgep->nxge_port_rbr_spare_size)); 2406678453a8Sspeer 2407678453a8Sspeer data = &nxgep->rx_buf_pool_p->dma_buf_pool_p[channel]; 2408678453a8Sspeer num_chunks = &nxgep->rx_buf_pool_p->num_chunks[channel]; 2409678453a8Sspeer 2410678453a8Sspeer if ((status = nxge_alloc_rx_buf_dma( 2411678453a8Sspeer nxgep, channel, data, rx_buf_alloc_size, 2412678453a8Sspeer nxgep->rx_default_block_size, num_chunks)) != NXGE_OK) { 2413678453a8Sspeer return (status); 241444961713Sgirish } 241544961713Sgirish 2416678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_alloc_rxb(): " 2417678453a8Sspeer "dma %d dma_buf_p %llx &dma_buf_p %llx", channel, *data, data)); 2418678453a8Sspeer 2419678453a8Sspeer /* 2420678453a8Sspeer * Allocate memory for descriptor rings and mailbox. 2421678453a8Sspeer */ 2422678453a8Sspeer control = &nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel]; 2423678453a8Sspeer 2424678453a8Sspeer if ((status = nxge_alloc_rx_cntl_dma( 2425678453a8Sspeer nxgep, channel, control, nxgep->nxge_port_rx_cntl_alloc_size)) 2426678453a8Sspeer != NXGE_OK) { 2427678453a8Sspeer nxge_free_rx_cntl_dma(nxgep, *control); 2428678453a8Sspeer (*data)->buf_alloc_state |= BUF_ALLOCATED_WAIT_FREE; 2429678453a8Sspeer nxge_free_rx_buf_dma(nxgep, *data, *num_chunks); 2430678453a8Sspeer return (status); 2431678453a8Sspeer } 243244961713Sgirish 243344961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 2434678453a8Sspeer "<== nxge_alloc_rx_mem_pool:status 0x%08x", status)); 243544961713Sgirish 243644961713Sgirish return (status); 243744961713Sgirish } 243844961713Sgirish 2439678453a8Sspeer void 2440678453a8Sspeer nxge_free_rxb( 2441678453a8Sspeer p_nxge_t nxgep, 2442678453a8Sspeer int channel) 2443678453a8Sspeer { 2444678453a8Sspeer nxge_dma_common_t *data; 2445678453a8Sspeer nxge_dma_common_t *control; 2446678453a8Sspeer uint32_t num_chunks; 2447678453a8Sspeer 2448678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb")); 2449678453a8Sspeer 2450678453a8Sspeer data = nxgep->rx_buf_pool_p->dma_buf_pool_p[channel]; 2451678453a8Sspeer num_chunks = nxgep->rx_buf_pool_p->num_chunks[channel]; 2452678453a8Sspeer nxge_free_rx_buf_dma(nxgep, data, num_chunks); 2453678453a8Sspeer 2454678453a8Sspeer nxgep->rx_buf_pool_p->dma_buf_pool_p[channel] = 0; 2455678453a8Sspeer nxgep->rx_buf_pool_p->num_chunks[channel] = 0; 2456678453a8Sspeer 2457678453a8Sspeer control = nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel]; 2458678453a8Sspeer nxge_free_rx_cntl_dma(nxgep, control); 2459678453a8Sspeer 2460678453a8Sspeer nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel] = 0; 2461678453a8Sspeer 2462678453a8Sspeer KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 2463678453a8Sspeer KMEM_FREE(control, sizeof (nxge_dma_common_t)); 2464678453a8Sspeer 2465678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_alloc_rbb")); 2466678453a8Sspeer } 2467678453a8Sspeer 246844961713Sgirish static void 246944961713Sgirish nxge_free_rx_mem_pool(p_nxge_t nxgep) 247044961713Sgirish { 2471678453a8Sspeer int rdc_max = NXGE_MAX_RDCS; 247244961713Sgirish 247344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_mem_pool")); 247444961713Sgirish 2475678453a8Sspeer if (!nxgep->rx_buf_pool_p || !nxgep->rx_buf_pool_p->buf_allocated) { 247644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 24774045d941Ssowmini "<== nxge_free_rx_mem_pool " 24784045d941Ssowmini "(null rx buf pool or buf not allocated")); 247944961713Sgirish return; 248044961713Sgirish } 2481678453a8Sspeer if (!nxgep->rx_cntl_pool_p || !nxgep->rx_cntl_pool_p->buf_allocated) { 248244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 24834045d941Ssowmini "<== nxge_free_rx_mem_pool " 24844045d941Ssowmini "(null rx cntl buf pool or cntl buf not allocated")); 248544961713Sgirish return; 248644961713Sgirish } 248744961713Sgirish 2488678453a8Sspeer KMEM_FREE(nxgep->rx_cntl_pool_p->dma_buf_pool_p, 2489678453a8Sspeer sizeof (p_nxge_dma_common_t) * rdc_max); 2490678453a8Sspeer KMEM_FREE(nxgep->rx_cntl_pool_p, sizeof (nxge_dma_pool_t)); 249144961713Sgirish 2492678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p->num_chunks, 2493678453a8Sspeer sizeof (uint32_t) * rdc_max); 2494678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p->dma_buf_pool_p, 2495678453a8Sspeer sizeof (p_nxge_dma_common_t) * rdc_max); 2496678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p, sizeof (nxge_dma_pool_t)); 249744961713Sgirish 2498678453a8Sspeer nxgep->rx_buf_pool_p = 0; 2499678453a8Sspeer nxgep->rx_cntl_pool_p = 0; 250044961713Sgirish 2501678453a8Sspeer KMEM_FREE(nxgep->rx_rbr_rings->rbr_rings, 2502678453a8Sspeer sizeof (p_rx_rbr_ring_t) * rdc_max); 2503678453a8Sspeer KMEM_FREE(nxgep->rx_rbr_rings, sizeof (rx_rbr_rings_t)); 2504678453a8Sspeer KMEM_FREE(nxgep->rx_rcr_rings->rcr_rings, 2505678453a8Sspeer sizeof (p_rx_rcr_ring_t) * rdc_max); 2506678453a8Sspeer KMEM_FREE(nxgep->rx_rcr_rings, sizeof (rx_rcr_rings_t)); 2507678453a8Sspeer KMEM_FREE(nxgep->rx_mbox_areas_p->rxmbox_areas, 2508678453a8Sspeer sizeof (p_rx_mbox_t) * rdc_max); 2509678453a8Sspeer KMEM_FREE(nxgep->rx_mbox_areas_p, sizeof (rx_mbox_areas_t)); 251044961713Sgirish 2511678453a8Sspeer nxgep->rx_rbr_rings = 0; 2512678453a8Sspeer nxgep->rx_rcr_rings = 0; 2513678453a8Sspeer nxgep->rx_mbox_areas_p = 0; 251444961713Sgirish 251544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_rx_mem_pool")); 251644961713Sgirish } 251744961713Sgirish 251844961713Sgirish 251944961713Sgirish static nxge_status_t 252044961713Sgirish nxge_alloc_rx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 252144961713Sgirish p_nxge_dma_common_t *dmap, 252244961713Sgirish size_t alloc_size, size_t block_size, uint32_t *num_chunks) 252344961713Sgirish { 252444961713Sgirish p_nxge_dma_common_t rx_dmap; 252544961713Sgirish nxge_status_t status = NXGE_OK; 252644961713Sgirish size_t total_alloc_size; 252744961713Sgirish size_t allocated = 0; 252844961713Sgirish int i, size_index, array_size; 2529678453a8Sspeer boolean_t use_kmem_alloc = B_FALSE; 253044961713Sgirish 253144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_buf_dma")); 253244961713Sgirish 253344961713Sgirish rx_dmap = (p_nxge_dma_common_t) 25344045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 25354045d941Ssowmini KM_SLEEP); 253644961713Sgirish 253744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 25384045d941Ssowmini " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ", 25394045d941Ssowmini dma_channel, alloc_size, block_size, dmap)); 254044961713Sgirish 254144961713Sgirish total_alloc_size = alloc_size; 254244961713Sgirish 254344961713Sgirish #if defined(RX_USE_RECLAIM_POST) 254444961713Sgirish total_alloc_size = alloc_size + alloc_size/4; 254544961713Sgirish #endif 254644961713Sgirish 254744961713Sgirish i = 0; 254844961713Sgirish size_index = 0; 254944961713Sgirish array_size = sizeof (alloc_sizes)/sizeof (size_t); 255044961713Sgirish while ((alloc_sizes[size_index] < alloc_size) && 25514045d941Ssowmini (size_index < array_size)) 25524045d941Ssowmini size_index++; 255344961713Sgirish if (size_index >= array_size) { 255444961713Sgirish size_index = array_size - 1; 255544961713Sgirish } 255644961713Sgirish 2557678453a8Sspeer /* For Neptune, use kmem_alloc if the kmem flag is set. */ 2558678453a8Sspeer if (nxgep->niu_type != N2_NIU && nxge_use_kmem_alloc) { 2559678453a8Sspeer use_kmem_alloc = B_TRUE; 2560678453a8Sspeer #if defined(__i386) || defined(__amd64) 2561678453a8Sspeer size_index = 0; 2562678453a8Sspeer #endif 2563678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2564678453a8Sspeer "==> nxge_alloc_rx_buf_dma: " 2565678453a8Sspeer "Neptune use kmem_alloc() - size_index %d", 2566678453a8Sspeer size_index)); 2567678453a8Sspeer } 2568678453a8Sspeer 256944961713Sgirish while ((allocated < total_alloc_size) && 25704045d941Ssowmini (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 257144961713Sgirish rx_dmap[i].dma_chunk_index = i; 257244961713Sgirish rx_dmap[i].block_size = block_size; 257344961713Sgirish rx_dmap[i].alength = alloc_sizes[size_index]; 257444961713Sgirish rx_dmap[i].orig_alength = rx_dmap[i].alength; 257544961713Sgirish rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 257644961713Sgirish rx_dmap[i].dma_channel = dma_channel; 257744961713Sgirish rx_dmap[i].contig_alloc_type = B_FALSE; 2578678453a8Sspeer rx_dmap[i].kmem_alloc_type = B_FALSE; 2579678453a8Sspeer rx_dmap[i].buf_alloc_type = DDI_MEM_ALLOC; 258044961713Sgirish 258144961713Sgirish /* 258244961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 258344961713Sgirish * needs to call Hypervisor api to set up 258444961713Sgirish * logical pages. 258544961713Sgirish */ 258644961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 258744961713Sgirish rx_dmap[i].contig_alloc_type = B_TRUE; 2588678453a8Sspeer rx_dmap[i].buf_alloc_type = CONTIG_MEM_ALLOC; 2589678453a8Sspeer } else if (use_kmem_alloc) { 2590678453a8Sspeer /* For Neptune, use kmem_alloc */ 2591678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2592678453a8Sspeer "==> nxge_alloc_rx_buf_dma: " 2593678453a8Sspeer "Neptune use kmem_alloc()")); 2594678453a8Sspeer rx_dmap[i].kmem_alloc_type = B_TRUE; 2595678453a8Sspeer rx_dmap[i].buf_alloc_type = KMEM_ALLOC; 259644961713Sgirish } 259744961713Sgirish 259844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 25994045d941Ssowmini "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x " 26004045d941Ssowmini "i %d nblocks %d alength %d", 26014045d941Ssowmini dma_channel, i, &rx_dmap[i], block_size, 26024045d941Ssowmini i, rx_dmap[i].nblocks, 26034045d941Ssowmini rx_dmap[i].alength)); 260444961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 26054045d941Ssowmini &nxge_rx_dma_attr, 26064045d941Ssowmini rx_dmap[i].alength, 26074045d941Ssowmini &nxge_dev_buf_dma_acc_attr, 26084045d941Ssowmini DDI_DMA_READ | DDI_DMA_STREAMING, 26094045d941Ssowmini (p_nxge_dma_common_t)(&rx_dmap[i])); 261044961713Sgirish if (status != NXGE_OK) { 261144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2612678453a8Sspeer "nxge_alloc_rx_buf_dma: Alloc Failed: " 2613678453a8Sspeer "dma %d size_index %d size requested %d", 2614678453a8Sspeer dma_channel, 2615678453a8Sspeer size_index, 2616678453a8Sspeer rx_dmap[i].alength)); 261744961713Sgirish size_index--; 261844961713Sgirish } else { 2619678453a8Sspeer rx_dmap[i].buf_alloc_state = BUF_ALLOCATED; 2620678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2621678453a8Sspeer " nxge_alloc_rx_buf_dma DONE alloc mem: " 2622678453a8Sspeer "dma %d dma_buf_p $%p kaddrp $%p alength %d " 2623678453a8Sspeer "buf_alloc_state %d alloc_type %d", 2624678453a8Sspeer dma_channel, 2625678453a8Sspeer &rx_dmap[i], 2626678453a8Sspeer rx_dmap[i].kaddrp, 2627678453a8Sspeer rx_dmap[i].alength, 2628678453a8Sspeer rx_dmap[i].buf_alloc_state, 2629678453a8Sspeer rx_dmap[i].buf_alloc_type)); 2630678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2631678453a8Sspeer " alloc_rx_buf_dma allocated rdc %d " 2632678453a8Sspeer "chunk %d size %x dvma %x bufp %llx kaddrp $%p", 2633678453a8Sspeer dma_channel, i, rx_dmap[i].alength, 2634678453a8Sspeer rx_dmap[i].ioaddr_pp, &rx_dmap[i], 2635678453a8Sspeer rx_dmap[i].kaddrp)); 263644961713Sgirish i++; 263744961713Sgirish allocated += alloc_sizes[size_index]; 263844961713Sgirish } 263944961713Sgirish } 264044961713Sgirish 264144961713Sgirish if (allocated < total_alloc_size) { 264230ac2e7bSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2643678453a8Sspeer "==> nxge_alloc_rx_buf_dma: not enough for channel %d " 264430ac2e7bSml "allocated 0x%x requested 0x%x", 264530ac2e7bSml dma_channel, 264630ac2e7bSml allocated, total_alloc_size)); 264730ac2e7bSml status = NXGE_ERROR; 264844961713Sgirish goto nxge_alloc_rx_mem_fail1; 264944961713Sgirish } 265044961713Sgirish 265130ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2652678453a8Sspeer "==> nxge_alloc_rx_buf_dma: Allocated for channel %d " 265330ac2e7bSml "allocated 0x%x requested 0x%x", 265430ac2e7bSml dma_channel, 265530ac2e7bSml allocated, total_alloc_size)); 265630ac2e7bSml 265744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 26584045d941Ssowmini " alloc_rx_buf_dma rdc %d allocated %d chunks", 26594045d941Ssowmini dma_channel, i)); 266044961713Sgirish *num_chunks = i; 266144961713Sgirish *dmap = rx_dmap; 266244961713Sgirish 266344961713Sgirish goto nxge_alloc_rx_mem_exit; 266444961713Sgirish 266544961713Sgirish nxge_alloc_rx_mem_fail1: 266644961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 266744961713Sgirish 266844961713Sgirish nxge_alloc_rx_mem_exit: 266944961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 26704045d941Ssowmini "<== nxge_alloc_rx_buf_dma status 0x%08x", status)); 267144961713Sgirish 267244961713Sgirish return (status); 267344961713Sgirish } 267444961713Sgirish 267544961713Sgirish /*ARGSUSED*/ 267644961713Sgirish static void 267744961713Sgirish nxge_free_rx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 267844961713Sgirish uint32_t num_chunks) 267944961713Sgirish { 268044961713Sgirish int i; 268144961713Sgirish 268244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 26834045d941Ssowmini "==> nxge_free_rx_buf_dma: # of chunks %d", num_chunks)); 268444961713Sgirish 2685678453a8Sspeer if (dmap == 0) 2686678453a8Sspeer return; 2687678453a8Sspeer 268844961713Sgirish for (i = 0; i < num_chunks; i++) { 268944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 26904045d941Ssowmini "==> nxge_free_rx_buf_dma: chunk %d dmap 0x%llx", 26914045d941Ssowmini i, dmap)); 2692678453a8Sspeer nxge_dma_free_rx_data_buf(dmap++); 269344961713Sgirish } 269444961713Sgirish 269544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_buf_dma")); 269644961713Sgirish } 269744961713Sgirish 269844961713Sgirish /*ARGSUSED*/ 269944961713Sgirish static nxge_status_t 270044961713Sgirish nxge_alloc_rx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 270144961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 270244961713Sgirish { 270344961713Sgirish p_nxge_dma_common_t rx_dmap; 270444961713Sgirish nxge_status_t status = NXGE_OK; 270544961713Sgirish 270644961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_cntl_dma")); 270744961713Sgirish 270844961713Sgirish rx_dmap = (p_nxge_dma_common_t) 27094045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 271044961713Sgirish 271144961713Sgirish rx_dmap->contig_alloc_type = B_FALSE; 2712678453a8Sspeer rx_dmap->kmem_alloc_type = B_FALSE; 271344961713Sgirish 271444961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 27154045d941Ssowmini &nxge_desc_dma_attr, 27164045d941Ssowmini size, 27174045d941Ssowmini &nxge_dev_desc_dma_acc_attr, 27184045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 27194045d941Ssowmini rx_dmap); 272044961713Sgirish if (status != NXGE_OK) { 272144961713Sgirish goto nxge_alloc_rx_cntl_dma_fail1; 272244961713Sgirish } 272344961713Sgirish 272444961713Sgirish *dmap = rx_dmap; 272544961713Sgirish goto nxge_alloc_rx_cntl_dma_exit; 272644961713Sgirish 272744961713Sgirish nxge_alloc_rx_cntl_dma_fail1: 272844961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t)); 272944961713Sgirish 273044961713Sgirish nxge_alloc_rx_cntl_dma_exit: 273144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 27324045d941Ssowmini "<== nxge_alloc_rx_cntl_dma status 0x%08x", status)); 273344961713Sgirish 2734678453a8Sspeer return (status); 2735678453a8Sspeer } 2736678453a8Sspeer 2737678453a8Sspeer /*ARGSUSED*/ 2738678453a8Sspeer static void 2739678453a8Sspeer nxge_free_rx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 2740678453a8Sspeer { 2741678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_rx_cntl_dma")); 2742678453a8Sspeer 2743678453a8Sspeer if (dmap == 0) 2744678453a8Sspeer return; 2745678453a8Sspeer 2746678453a8Sspeer nxge_dma_mem_free(dmap); 2747678453a8Sspeer 2748678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_rx_cntl_dma")); 2749678453a8Sspeer } 2750678453a8Sspeer 2751678453a8Sspeer typedef struct { 2752678453a8Sspeer size_t tx_size; 2753678453a8Sspeer size_t cr_size; 2754678453a8Sspeer size_t threshhold; 2755678453a8Sspeer } nxge_tdc_sizes_t; 2756678453a8Sspeer 2757678453a8Sspeer static 2758678453a8Sspeer nxge_status_t 2759678453a8Sspeer nxge_tdc_sizes( 2760678453a8Sspeer nxge_t *nxgep, 2761678453a8Sspeer nxge_tdc_sizes_t *sizes) 2762678453a8Sspeer { 2763678453a8Sspeer uint32_t threshhold; /* The bcopy() threshhold */ 2764678453a8Sspeer size_t tx_size; /* Transmit buffer size */ 2765678453a8Sspeer size_t cr_size; /* Completion ring size */ 2766678453a8Sspeer 2767678453a8Sspeer /* 2768678453a8Sspeer * Assume that each DMA channel will be configured with the 2769678453a8Sspeer * default transmit buffer size for copying transmit data. 2770678453a8Sspeer * (If a packet is bigger than this, it will not be copied.) 2771678453a8Sspeer */ 2772678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 2773678453a8Sspeer threshhold = TX_BCOPY_SIZE; 2774678453a8Sspeer } else { 2775678453a8Sspeer threshhold = nxge_bcopy_thresh; 2776678453a8Sspeer } 2777678453a8Sspeer tx_size = nxge_tx_ring_size * threshhold; 2778678453a8Sspeer 2779678453a8Sspeer cr_size = nxge_tx_ring_size * sizeof (tx_desc_t); 2780678453a8Sspeer cr_size += sizeof (txdma_mailbox_t); 2781678453a8Sspeer 2782678453a8Sspeer #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 2783678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 2784678453a8Sspeer if (!ISP2(tx_size)) { 2785678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27864045d941Ssowmini "==> nxge_tdc_sizes: Tx size" 27874045d941Ssowmini " must be power of 2")); 2788678453a8Sspeer return (NXGE_ERROR); 2789678453a8Sspeer } 2790678453a8Sspeer 2791678453a8Sspeer if (tx_size > (1 << 22)) { 2792678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27934045d941Ssowmini "==> nxge_tdc_sizes: Tx size" 27944045d941Ssowmini " limited to 4M")); 2795678453a8Sspeer return (NXGE_ERROR); 2796678453a8Sspeer } 2797678453a8Sspeer 2798678453a8Sspeer if (cr_size < 0x2000) 2799678453a8Sspeer cr_size = 0x2000; 2800678453a8Sspeer } 2801678453a8Sspeer #endif 2802678453a8Sspeer 2803678453a8Sspeer sizes->threshhold = threshhold; 2804678453a8Sspeer sizes->tx_size = tx_size; 2805678453a8Sspeer sizes->cr_size = cr_size; 2806678453a8Sspeer 2807678453a8Sspeer return (NXGE_OK); 2808678453a8Sspeer } 2809678453a8Sspeer /* 2810678453a8Sspeer * nxge_alloc_txb 2811678453a8Sspeer * 2812678453a8Sspeer * Allocate buffers for an TDC. 2813678453a8Sspeer * 2814678453a8Sspeer * Arguments: 2815678453a8Sspeer * nxgep 2816678453a8Sspeer * channel The channel to map into our kernel space. 2817678453a8Sspeer * 2818678453a8Sspeer * Notes: 2819678453a8Sspeer * 2820678453a8Sspeer * NPI function calls: 2821678453a8Sspeer * 2822678453a8Sspeer * NXGE function calls: 2823678453a8Sspeer * 2824678453a8Sspeer * Registers accessed: 2825678453a8Sspeer * 2826678453a8Sspeer * Context: 2827678453a8Sspeer * 2828678453a8Sspeer * Taking apart: 2829678453a8Sspeer * 2830678453a8Sspeer * Open questions: 2831678453a8Sspeer * 2832678453a8Sspeer */ 2833678453a8Sspeer nxge_status_t 2834678453a8Sspeer nxge_alloc_txb( 2835678453a8Sspeer p_nxge_t nxgep, 2836678453a8Sspeer int channel) 2837678453a8Sspeer { 2838678453a8Sspeer nxge_dma_common_t **dma_buf_p; 2839678453a8Sspeer nxge_dma_common_t **dma_cntl_p; 2840678453a8Sspeer uint32_t *num_chunks; 2841678453a8Sspeer nxge_status_t status = NXGE_OK; 2842678453a8Sspeer 2843678453a8Sspeer nxge_tdc_sizes_t sizes; 2844678453a8Sspeer 2845678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tbb")); 2846678453a8Sspeer 2847678453a8Sspeer if (nxge_tdc_sizes(nxgep, &sizes) != NXGE_OK) 2848678453a8Sspeer return (NXGE_ERROR); 2849678453a8Sspeer 2850678453a8Sspeer /* 2851678453a8Sspeer * Allocate memory for transmit buffers and descriptor rings. 2852678453a8Sspeer * Replace these allocation functions with the interface functions 2853678453a8Sspeer * provided by the partition manager Real Soon Now. 2854678453a8Sspeer */ 2855678453a8Sspeer dma_buf_p = &nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2856678453a8Sspeer num_chunks = &nxgep->tx_buf_pool_p->num_chunks[channel]; 2857678453a8Sspeer 2858678453a8Sspeer dma_cntl_p = &nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2859678453a8Sspeer 2860678453a8Sspeer /* 2861678453a8Sspeer * Allocate memory for transmit buffers and descriptor rings. 2862678453a8Sspeer * Replace allocation functions with interface functions provided 2863678453a8Sspeer * by the partition manager when it is available. 2864678453a8Sspeer * 2865678453a8Sspeer * Allocate memory for the transmit buffer pool. 2866678453a8Sspeer */ 2867678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 28684045d941Ssowmini "sizes: tx: %ld, cr:%ld, th:%ld", 28694045d941Ssowmini sizes.tx_size, sizes.cr_size, sizes.threshhold)); 2870678453a8Sspeer 2871678453a8Sspeer *num_chunks = 0; 2872678453a8Sspeer status = nxge_alloc_tx_buf_dma(nxgep, channel, dma_buf_p, 2873678453a8Sspeer sizes.tx_size, sizes.threshhold, num_chunks); 2874678453a8Sspeer if (status != NXGE_OK) { 2875678453a8Sspeer cmn_err(CE_NOTE, "nxge_alloc_tx_buf_dma failed!"); 2876678453a8Sspeer return (status); 2877678453a8Sspeer } 2878678453a8Sspeer 2879678453a8Sspeer /* 2880678453a8Sspeer * Allocate memory for descriptor rings and mailbox. 2881678453a8Sspeer */ 2882678453a8Sspeer status = nxge_alloc_tx_cntl_dma(nxgep, channel, dma_cntl_p, 2883678453a8Sspeer sizes.cr_size); 2884678453a8Sspeer if (status != NXGE_OK) { 2885678453a8Sspeer nxge_free_tx_buf_dma(nxgep, *dma_buf_p, *num_chunks); 2886678453a8Sspeer cmn_err(CE_NOTE, "nxge_alloc_tx_cntl_dma failed!"); 2887678453a8Sspeer return (status); 2888678453a8Sspeer } 2889678453a8Sspeer 2890678453a8Sspeer return (NXGE_OK); 2891678453a8Sspeer } 2892678453a8Sspeer 2893678453a8Sspeer void 2894678453a8Sspeer nxge_free_txb( 2895678453a8Sspeer p_nxge_t nxgep, 2896678453a8Sspeer int channel) 2897678453a8Sspeer { 2898678453a8Sspeer nxge_dma_common_t *data; 2899678453a8Sspeer nxge_dma_common_t *control; 2900678453a8Sspeer uint32_t num_chunks; 2901678453a8Sspeer 2902678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_txb")); 2903678453a8Sspeer 2904678453a8Sspeer data = nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2905678453a8Sspeer num_chunks = nxgep->tx_buf_pool_p->num_chunks[channel]; 2906678453a8Sspeer nxge_free_tx_buf_dma(nxgep, data, num_chunks); 2907678453a8Sspeer 2908678453a8Sspeer nxgep->tx_buf_pool_p->dma_buf_pool_p[channel] = 0; 2909678453a8Sspeer nxgep->tx_buf_pool_p->num_chunks[channel] = 0; 2910678453a8Sspeer 2911678453a8Sspeer control = nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2912678453a8Sspeer nxge_free_tx_cntl_dma(nxgep, control); 291344961713Sgirish 2914678453a8Sspeer nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel] = 0; 291544961713Sgirish 2916678453a8Sspeer KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 2917678453a8Sspeer KMEM_FREE(control, sizeof (nxge_dma_common_t)); 291844961713Sgirish 2919678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_txb")); 292044961713Sgirish } 292144961713Sgirish 2922678453a8Sspeer /* 2923678453a8Sspeer * nxge_alloc_tx_mem_pool 2924678453a8Sspeer * 2925678453a8Sspeer * This function allocates all of the per-port TDC control data structures. 2926678453a8Sspeer * The per-channel (TDC) data structures are allocated when needed. 2927678453a8Sspeer * 2928678453a8Sspeer * Arguments: 2929678453a8Sspeer * nxgep 2930678453a8Sspeer * 2931678453a8Sspeer * Notes: 2932678453a8Sspeer * 2933678453a8Sspeer * Context: 2934678453a8Sspeer * Any domain 2935678453a8Sspeer */ 2936678453a8Sspeer nxge_status_t 293744961713Sgirish nxge_alloc_tx_mem_pool(p_nxge_t nxgep) 293844961713Sgirish { 2939678453a8Sspeer nxge_hw_pt_cfg_t *p_cfgp; 2940678453a8Sspeer nxge_dma_pool_t *dma_poolp; 2941678453a8Sspeer nxge_dma_common_t **dma_buf_p; 2942678453a8Sspeer nxge_dma_pool_t *dma_cntl_poolp; 2943678453a8Sspeer nxge_dma_common_t **dma_cntl_p; 294444961713Sgirish uint32_t *num_chunks; /* per dma */ 2945678453a8Sspeer int tdc_max; 294644961713Sgirish 294744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool")); 294844961713Sgirish 2949678453a8Sspeer p_cfgp = &nxgep->pt_config.hw_config; 2950678453a8Sspeer tdc_max = NXGE_MAX_TDCS; 295144961713Sgirish 295244961713Sgirish /* 295344961713Sgirish * Allocate memory for each transmit DMA channel. 295444961713Sgirish */ 295544961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 29564045d941Ssowmini KM_SLEEP); 295744961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 29584045d941Ssowmini sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP); 295944961713Sgirish 296044961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 29614045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 296244961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 29634045d941Ssowmini sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP); 296444961713Sgirish 296530ac2e7bSml if (nxge_tx_ring_size > TDC_DEFAULT_MAX) { 296630ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 296730ac2e7bSml "nxge_alloc_tx_mem_pool: TDC too high %d, " 296830ac2e7bSml "set to default %d", 296930ac2e7bSml nxge_tx_ring_size, TDC_DEFAULT_MAX)); 297030ac2e7bSml nxge_tx_ring_size = TDC_DEFAULT_MAX; 297130ac2e7bSml } 297230ac2e7bSml 297344961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 297444961713Sgirish /* 297544961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 297644961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 297744961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 297844961713Sgirish * function). The transmit ring is limited to 8K (includes the 297944961713Sgirish * mailbox). 298044961713Sgirish */ 298144961713Sgirish if (nxgep->niu_type == N2_NIU) { 298244961713Sgirish if ((nxge_tx_ring_size > NXGE_NIU_CONTIG_TX_MAX) || 29834045d941Ssowmini (!ISP2(nxge_tx_ring_size))) { 298444961713Sgirish nxge_tx_ring_size = NXGE_NIU_CONTIG_TX_MAX; 298544961713Sgirish } 298644961713Sgirish } 298744961713Sgirish #endif 298844961713Sgirish 298944961713Sgirish nxgep->nxge_port_tx_ring_size = nxge_tx_ring_size; 299044961713Sgirish 299144961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 29924045d941Ssowmini sizeof (uint32_t) * tdc_max, KM_SLEEP); 299344961713Sgirish 2994678453a8Sspeer dma_poolp->ndmas = p_cfgp->tdc.owned; 299544961713Sgirish dma_poolp->num_chunks = num_chunks; 299644961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 299744961713Sgirish nxgep->tx_buf_pool_p = dma_poolp; 299844961713Sgirish 2999678453a8Sspeer dma_poolp->buf_allocated = B_TRUE; 3000678453a8Sspeer 3001678453a8Sspeer dma_cntl_poolp->ndmas = p_cfgp->tdc.owned; 300244961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 300344961713Sgirish nxgep->tx_cntl_pool_p = dma_cntl_poolp; 300444961713Sgirish 3005678453a8Sspeer dma_cntl_poolp->buf_allocated = B_TRUE; 300644961713Sgirish 3007678453a8Sspeer nxgep->tx_rings = 3008678453a8Sspeer KMEM_ZALLOC(sizeof (tx_rings_t), KM_SLEEP); 3009678453a8Sspeer nxgep->tx_rings->rings = 3010678453a8Sspeer KMEM_ZALLOC(sizeof (p_tx_ring_t) * tdc_max, KM_SLEEP); 3011678453a8Sspeer nxgep->tx_mbox_areas_p = 3012678453a8Sspeer KMEM_ZALLOC(sizeof (tx_mbox_areas_t), KM_SLEEP); 3013678453a8Sspeer nxgep->tx_mbox_areas_p->txmbox_areas_p = 3014678453a8Sspeer KMEM_ZALLOC(sizeof (p_tx_mbox_t) * tdc_max, KM_SLEEP); 301544961713Sgirish 3016678453a8Sspeer nxgep->tx_rings->ndmas = p_cfgp->tdc.owned; 301744961713Sgirish 301844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, 30194045d941Ssowmini "==> nxge_alloc_tx_mem_pool: ndmas %d poolp->ndmas %d", 30204045d941Ssowmini tdc_max, dma_poolp->ndmas)); 302144961713Sgirish 3022678453a8Sspeer return (NXGE_OK); 302344961713Sgirish } 302444961713Sgirish 3025678453a8Sspeer nxge_status_t 302644961713Sgirish nxge_alloc_tx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 302744961713Sgirish p_nxge_dma_common_t *dmap, size_t alloc_size, 302844961713Sgirish size_t block_size, uint32_t *num_chunks) 302944961713Sgirish { 303044961713Sgirish p_nxge_dma_common_t tx_dmap; 303144961713Sgirish nxge_status_t status = NXGE_OK; 303244961713Sgirish size_t total_alloc_size; 303344961713Sgirish size_t allocated = 0; 303444961713Sgirish int i, size_index, array_size; 303544961713Sgirish 303644961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_buf_dma")); 303744961713Sgirish 303844961713Sgirish tx_dmap = (p_nxge_dma_common_t) 30394045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 30404045d941Ssowmini KM_SLEEP); 304144961713Sgirish 304244961713Sgirish total_alloc_size = alloc_size; 304344961713Sgirish i = 0; 304444961713Sgirish size_index = 0; 304544961713Sgirish array_size = sizeof (alloc_sizes) / sizeof (size_t); 304644961713Sgirish while ((alloc_sizes[size_index] < alloc_size) && 30474045d941Ssowmini (size_index < array_size)) 304844961713Sgirish size_index++; 304944961713Sgirish if (size_index >= array_size) { 305044961713Sgirish size_index = array_size - 1; 305144961713Sgirish } 305244961713Sgirish 305344961713Sgirish while ((allocated < total_alloc_size) && 30544045d941Ssowmini (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 305544961713Sgirish 305644961713Sgirish tx_dmap[i].dma_chunk_index = i; 305744961713Sgirish tx_dmap[i].block_size = block_size; 305844961713Sgirish tx_dmap[i].alength = alloc_sizes[size_index]; 305944961713Sgirish tx_dmap[i].orig_alength = tx_dmap[i].alength; 306044961713Sgirish tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 306144961713Sgirish tx_dmap[i].dma_channel = dma_channel; 306244961713Sgirish tx_dmap[i].contig_alloc_type = B_FALSE; 3063678453a8Sspeer tx_dmap[i].kmem_alloc_type = B_FALSE; 306444961713Sgirish 306544961713Sgirish /* 306644961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 306744961713Sgirish * needs to call Hypervisor api to set up 306844961713Sgirish * logical pages. 306944961713Sgirish */ 307044961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 307144961713Sgirish tx_dmap[i].contig_alloc_type = B_TRUE; 307244961713Sgirish } 307344961713Sgirish 307444961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 30754045d941Ssowmini &nxge_tx_dma_attr, 30764045d941Ssowmini tx_dmap[i].alength, 30774045d941Ssowmini &nxge_dev_buf_dma_acc_attr, 30784045d941Ssowmini DDI_DMA_WRITE | DDI_DMA_STREAMING, 30794045d941Ssowmini (p_nxge_dma_common_t)(&tx_dmap[i])); 308044961713Sgirish if (status != NXGE_OK) { 308144961713Sgirish size_index--; 308244961713Sgirish } else { 308344961713Sgirish i++; 308444961713Sgirish allocated += alloc_sizes[size_index]; 308544961713Sgirish } 308644961713Sgirish } 308744961713Sgirish 308844961713Sgirish if (allocated < total_alloc_size) { 308930ac2e7bSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 309030ac2e7bSml "==> nxge_alloc_tx_buf_dma: not enough channel %d: " 309130ac2e7bSml "allocated 0x%x requested 0x%x", 309230ac2e7bSml dma_channel, 309330ac2e7bSml allocated, total_alloc_size)); 309430ac2e7bSml status = NXGE_ERROR; 309544961713Sgirish goto nxge_alloc_tx_mem_fail1; 309644961713Sgirish } 309744961713Sgirish 309830ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 309930ac2e7bSml "==> nxge_alloc_tx_buf_dma: Allocated for channel %d: " 310030ac2e7bSml "allocated 0x%x requested 0x%x", 310130ac2e7bSml dma_channel, 310230ac2e7bSml allocated, total_alloc_size)); 310330ac2e7bSml 310444961713Sgirish *num_chunks = i; 310544961713Sgirish *dmap = tx_dmap; 310644961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 31074045d941Ssowmini "==> nxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d", 31084045d941Ssowmini *dmap, i)); 310944961713Sgirish goto nxge_alloc_tx_mem_exit; 311044961713Sgirish 311144961713Sgirish nxge_alloc_tx_mem_fail1: 311244961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 311344961713Sgirish 311444961713Sgirish nxge_alloc_tx_mem_exit: 311544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 31164045d941Ssowmini "<== nxge_alloc_tx_buf_dma status 0x%08x", status)); 311744961713Sgirish 311844961713Sgirish return (status); 311944961713Sgirish } 312044961713Sgirish 312144961713Sgirish /*ARGSUSED*/ 312244961713Sgirish static void 312344961713Sgirish nxge_free_tx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 312444961713Sgirish uint32_t num_chunks) 312544961713Sgirish { 312644961713Sgirish int i; 312744961713Sgirish 312844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_tx_buf_dma")); 312944961713Sgirish 3130678453a8Sspeer if (dmap == 0) 3131678453a8Sspeer return; 3132678453a8Sspeer 313344961713Sgirish for (i = 0; i < num_chunks; i++) { 313444961713Sgirish nxge_dma_mem_free(dmap++); 313544961713Sgirish } 313644961713Sgirish 313744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_tx_buf_dma")); 313844961713Sgirish } 313944961713Sgirish 314044961713Sgirish /*ARGSUSED*/ 3141678453a8Sspeer nxge_status_t 314244961713Sgirish nxge_alloc_tx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 314344961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 314444961713Sgirish { 314544961713Sgirish p_nxge_dma_common_t tx_dmap; 314644961713Sgirish nxge_status_t status = NXGE_OK; 314744961713Sgirish 314844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_cntl_dma")); 314944961713Sgirish tx_dmap = (p_nxge_dma_common_t) 31504045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 315144961713Sgirish 315244961713Sgirish tx_dmap->contig_alloc_type = B_FALSE; 3153678453a8Sspeer tx_dmap->kmem_alloc_type = B_FALSE; 315444961713Sgirish 315544961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 31564045d941Ssowmini &nxge_desc_dma_attr, 31574045d941Ssowmini size, 31584045d941Ssowmini &nxge_dev_desc_dma_acc_attr, 31594045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 31604045d941Ssowmini tx_dmap); 316144961713Sgirish if (status != NXGE_OK) { 316244961713Sgirish goto nxge_alloc_tx_cntl_dma_fail1; 316344961713Sgirish } 316444961713Sgirish 316544961713Sgirish *dmap = tx_dmap; 316644961713Sgirish goto nxge_alloc_tx_cntl_dma_exit; 316744961713Sgirish 316844961713Sgirish nxge_alloc_tx_cntl_dma_fail1: 316944961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t)); 317044961713Sgirish 317144961713Sgirish nxge_alloc_tx_cntl_dma_exit: 317244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 31734045d941Ssowmini "<== nxge_alloc_tx_cntl_dma status 0x%08x", status)); 317444961713Sgirish 317544961713Sgirish return (status); 317644961713Sgirish } 317744961713Sgirish 317844961713Sgirish /*ARGSUSED*/ 317944961713Sgirish static void 318044961713Sgirish nxge_free_tx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 318144961713Sgirish { 318244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_tx_cntl_dma")); 318344961713Sgirish 3184678453a8Sspeer if (dmap == 0) 3185678453a8Sspeer return; 3186678453a8Sspeer 318744961713Sgirish nxge_dma_mem_free(dmap); 318844961713Sgirish 318944961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_tx_cntl_dma")); 319044961713Sgirish } 319144961713Sgirish 3192678453a8Sspeer /* 3193678453a8Sspeer * nxge_free_tx_mem_pool 3194678453a8Sspeer * 3195678453a8Sspeer * This function frees all of the per-port TDC control data structures. 3196678453a8Sspeer * The per-channel (TDC) data structures are freed when the channel 3197678453a8Sspeer * is stopped. 3198678453a8Sspeer * 3199678453a8Sspeer * Arguments: 3200678453a8Sspeer * nxgep 3201678453a8Sspeer * 3202678453a8Sspeer * Notes: 3203678453a8Sspeer * 3204678453a8Sspeer * Context: 3205678453a8Sspeer * Any domain 3206678453a8Sspeer */ 320744961713Sgirish static void 320844961713Sgirish nxge_free_tx_mem_pool(p_nxge_t nxgep) 320944961713Sgirish { 3210678453a8Sspeer int tdc_max = NXGE_MAX_TDCS; 321144961713Sgirish 3212678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_tx_mem_pool")); 321344961713Sgirish 3214678453a8Sspeer if (!nxgep->tx_buf_pool_p || !nxgep->tx_buf_pool_p->buf_allocated) { 3215678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 32164045d941Ssowmini "<== nxge_free_tx_mem_pool " 32174045d941Ssowmini "(null tx buf pool or buf not allocated")); 321844961713Sgirish return; 321944961713Sgirish } 3220678453a8Sspeer if (!nxgep->tx_cntl_pool_p || !nxgep->tx_cntl_pool_p->buf_allocated) { 3221678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 32224045d941Ssowmini "<== nxge_free_tx_mem_pool " 32234045d941Ssowmini "(null tx cntl buf pool or cntl buf not allocated")); 322444961713Sgirish return; 322544961713Sgirish } 322644961713Sgirish 3227678453a8Sspeer /* 1. Free the mailboxes. */ 3228678453a8Sspeer KMEM_FREE(nxgep->tx_mbox_areas_p->txmbox_areas_p, 3229678453a8Sspeer sizeof (p_tx_mbox_t) * tdc_max); 3230678453a8Sspeer KMEM_FREE(nxgep->tx_mbox_areas_p, sizeof (tx_mbox_areas_t)); 323144961713Sgirish 3232678453a8Sspeer nxgep->tx_mbox_areas_p = 0; 323344961713Sgirish 3234678453a8Sspeer /* 2. Free the transmit ring arrays. */ 3235678453a8Sspeer KMEM_FREE(nxgep->tx_rings->rings, 3236678453a8Sspeer sizeof (p_tx_ring_t) * tdc_max); 3237678453a8Sspeer KMEM_FREE(nxgep->tx_rings, sizeof (tx_rings_t)); 323844961713Sgirish 3239678453a8Sspeer nxgep->tx_rings = 0; 324044961713Sgirish 3241678453a8Sspeer /* 3. Free the completion ring data structures. */ 3242678453a8Sspeer KMEM_FREE(nxgep->tx_cntl_pool_p->dma_buf_pool_p, 3243678453a8Sspeer sizeof (p_nxge_dma_common_t) * tdc_max); 3244678453a8Sspeer KMEM_FREE(nxgep->tx_cntl_pool_p, sizeof (nxge_dma_pool_t)); 324544961713Sgirish 3246678453a8Sspeer nxgep->tx_cntl_pool_p = 0; 324744961713Sgirish 3248678453a8Sspeer /* 4. Free the data ring data structures. */ 3249678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p->num_chunks, 3250678453a8Sspeer sizeof (uint32_t) * tdc_max); 3251678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p->dma_buf_pool_p, 3252678453a8Sspeer sizeof (p_nxge_dma_common_t) * tdc_max); 3253678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p, sizeof (nxge_dma_pool_t)); 325444961713Sgirish 3255678453a8Sspeer nxgep->tx_buf_pool_p = 0; 3256678453a8Sspeer 3257678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_tx_mem_pool")); 325844961713Sgirish } 325944961713Sgirish 326044961713Sgirish /*ARGSUSED*/ 326144961713Sgirish static nxge_status_t 326244961713Sgirish nxge_dma_mem_alloc(p_nxge_t nxgep, dma_method_t method, 326344961713Sgirish struct ddi_dma_attr *dma_attrp, 326444961713Sgirish size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags, 326544961713Sgirish p_nxge_dma_common_t dma_p) 326644961713Sgirish { 326744961713Sgirish caddr_t kaddrp; 326844961713Sgirish int ddi_status = DDI_SUCCESS; 326944961713Sgirish boolean_t contig_alloc_type; 3270678453a8Sspeer boolean_t kmem_alloc_type; 327144961713Sgirish 327244961713Sgirish contig_alloc_type = dma_p->contig_alloc_type; 327344961713Sgirish 327444961713Sgirish if (contig_alloc_type && (nxgep->niu_type != N2_NIU)) { 327544961713Sgirish /* 327644961713Sgirish * contig_alloc_type for contiguous memory only allowed 327744961713Sgirish * for N2/NIU. 327844961713Sgirish */ 327944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 32804045d941Ssowmini "nxge_dma_mem_alloc: alloc type not allowed (%d)", 32814045d941Ssowmini dma_p->contig_alloc_type)); 328244961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 328344961713Sgirish } 328444961713Sgirish 328544961713Sgirish dma_p->dma_handle = NULL; 328644961713Sgirish dma_p->acc_handle = NULL; 328744961713Sgirish dma_p->kaddrp = dma_p->last_kaddrp = NULL; 328844961713Sgirish dma_p->first_ioaddr_pp = dma_p->last_ioaddr_pp = NULL; 328944961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, dma_attrp, 32904045d941Ssowmini DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle); 329144961713Sgirish if (ddi_status != DDI_SUCCESS) { 329244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 32934045d941Ssowmini "nxge_dma_mem_alloc:ddi_dma_alloc_handle failed.")); 329444961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 329544961713Sgirish } 329644961713Sgirish 3297678453a8Sspeer kmem_alloc_type = dma_p->kmem_alloc_type; 3298678453a8Sspeer 329944961713Sgirish switch (contig_alloc_type) { 330044961713Sgirish case B_FALSE: 3301678453a8Sspeer switch (kmem_alloc_type) { 3302678453a8Sspeer case B_FALSE: 3303678453a8Sspeer ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, 33044045d941Ssowmini length, 33054045d941Ssowmini acc_attr_p, 33064045d941Ssowmini xfer_flags, 33074045d941Ssowmini DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength, 33084045d941Ssowmini &dma_p->acc_handle); 3309678453a8Sspeer if (ddi_status != DDI_SUCCESS) { 3310678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3311678453a8Sspeer "nxge_dma_mem_alloc: " 3312678453a8Sspeer "ddi_dma_mem_alloc failed")); 3313678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3314678453a8Sspeer dma_p->dma_handle = NULL; 3315678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3316678453a8Sspeer } 3317678453a8Sspeer if (dma_p->alength < length) { 3318678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3319678453a8Sspeer "nxge_dma_mem_alloc:di_dma_mem_alloc " 3320678453a8Sspeer "< length.")); 332144961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 3322678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 332344961713Sgirish dma_p->acc_handle = NULL; 3324678453a8Sspeer dma_p->dma_handle = NULL; 3325678453a8Sspeer return (NXGE_ERROR); 332644961713Sgirish } 332744961713Sgirish 3328678453a8Sspeer ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, 3329678453a8Sspeer NULL, 3330678453a8Sspeer kaddrp, dma_p->alength, xfer_flags, 3331678453a8Sspeer DDI_DMA_DONTWAIT, 3332678453a8Sspeer 0, &dma_p->dma_cookie, &dma_p->ncookies); 3333678453a8Sspeer if (ddi_status != DDI_DMA_MAPPED) { 3334678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3335678453a8Sspeer "nxge_dma_mem_alloc: ddi_dma_addr_bind " 3336678453a8Sspeer "failed " 3337678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 3338678453a8Sspeer dma_p->ncookies)); 3339678453a8Sspeer if (dma_p->acc_handle) { 3340678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3341678453a8Sspeer dma_p->acc_handle = NULL; 3342678453a8Sspeer } 3343678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3344678453a8Sspeer dma_p->dma_handle = NULL; 3345678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3346678453a8Sspeer } 3347678453a8Sspeer 3348678453a8Sspeer if (dma_p->ncookies != 1) { 3349678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 3350678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind " 3351678453a8Sspeer "> 1 cookie" 3352678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 3353678453a8Sspeer dma_p->ncookies)); 3354330cd344SMichael Speer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3355678453a8Sspeer if (dma_p->acc_handle) { 3356678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3357678453a8Sspeer dma_p->acc_handle = NULL; 3358678453a8Sspeer } 3359678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3360678453a8Sspeer dma_p->dma_handle = NULL; 3361330cd344SMichael Speer dma_p->acc_handle = NULL; 3362678453a8Sspeer return (NXGE_ERROR); 3363678453a8Sspeer } 3364678453a8Sspeer break; 3365678453a8Sspeer 3366678453a8Sspeer case B_TRUE: 3367678453a8Sspeer kaddrp = KMEM_ALLOC(length, KM_NOSLEEP); 3368678453a8Sspeer if (kaddrp == NULL) { 3369678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3370678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_mem_alloc " 3371678453a8Sspeer "kmem alloc failed")); 3372678453a8Sspeer return (NXGE_ERROR); 3373678453a8Sspeer } 3374678453a8Sspeer 3375678453a8Sspeer dma_p->alength = length; 3376678453a8Sspeer ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, 3377678453a8Sspeer NULL, kaddrp, dma_p->alength, xfer_flags, 3378678453a8Sspeer DDI_DMA_DONTWAIT, 0, 3379678453a8Sspeer &dma_p->dma_cookie, &dma_p->ncookies); 3380678453a8Sspeer if (ddi_status != DDI_DMA_MAPPED) { 3381678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3382678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind: " 3383678453a8Sspeer "(kmem_alloc) failed kaddrp $%p length %d " 3384678453a8Sspeer "(staus 0x%x (%d) ncookies %d.)", 3385678453a8Sspeer kaddrp, length, 3386678453a8Sspeer ddi_status, ddi_status, dma_p->ncookies)); 3387678453a8Sspeer KMEM_FREE(kaddrp, length); 3388678453a8Sspeer dma_p->acc_handle = NULL; 3389678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3390678453a8Sspeer dma_p->dma_handle = NULL; 3391678453a8Sspeer dma_p->kaddrp = NULL; 3392678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3393678453a8Sspeer } 3394678453a8Sspeer 3395678453a8Sspeer if (dma_p->ncookies != 1) { 3396678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 3397678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind " 3398678453a8Sspeer "(kmem_alloc) > 1 cookie" 3399678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 34004045d941Ssowmini dma_p->ncookies)); 3401678453a8Sspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3402330cd344SMichael Speer KMEM_FREE(kaddrp, length); 3403678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3404678453a8Sspeer dma_p->dma_handle = NULL; 3405330cd344SMichael Speer dma_p->acc_handle = NULL; 3406678453a8Sspeer dma_p->kaddrp = NULL; 3407678453a8Sspeer return (NXGE_ERROR); 340844961713Sgirish } 3409678453a8Sspeer 3410678453a8Sspeer dma_p->kaddrp = kaddrp; 3411678453a8Sspeer 3412678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 34134045d941Ssowmini "nxge_dma_mem_alloc: kmem_alloc dmap $%p " 34144045d941Ssowmini "kaddr $%p alength %d", 34154045d941Ssowmini dma_p, 34164045d941Ssowmini kaddrp, 34174045d941Ssowmini dma_p->alength)); 3418678453a8Sspeer break; 341944961713Sgirish } 342044961713Sgirish break; 342144961713Sgirish 342244961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 342344961713Sgirish case B_TRUE: 342444961713Sgirish kaddrp = (caddr_t)contig_mem_alloc(length); 342544961713Sgirish if (kaddrp == NULL) { 342644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34274045d941Ssowmini "nxge_dma_mem_alloc:contig_mem_alloc failed.")); 342844961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 342944961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 343044961713Sgirish } 343144961713Sgirish 343244961713Sgirish dma_p->alength = length; 343344961713Sgirish ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL, 34344045d941Ssowmini kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0, 34354045d941Ssowmini &dma_p->dma_cookie, &dma_p->ncookies); 343644961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 343744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34384045d941Ssowmini "nxge_dma_mem_alloc:di_dma_addr_bind failed " 34394045d941Ssowmini "(status 0x%x ncookies %d.)", ddi_status, 34404045d941Ssowmini dma_p->ncookies)); 344144961713Sgirish 344244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 34434045d941Ssowmini "==> nxge_dma_mem_alloc: (not mapped)" 34444045d941Ssowmini "length %lu (0x%x) " 34454045d941Ssowmini "free contig kaddrp $%p " 34464045d941Ssowmini "va_to_pa $%p", 34474045d941Ssowmini length, length, 34484045d941Ssowmini kaddrp, 34494045d941Ssowmini va_to_pa(kaddrp))); 345044961713Sgirish 345144961713Sgirish 345244961713Sgirish contig_mem_free((void *)kaddrp, length); 345344961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 345444961713Sgirish 345544961713Sgirish dma_p->dma_handle = NULL; 345644961713Sgirish dma_p->acc_handle = NULL; 345744961713Sgirish dma_p->alength = NULL; 345844961713Sgirish dma_p->kaddrp = NULL; 345944961713Sgirish 346044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 346144961713Sgirish } 346244961713Sgirish 346344961713Sgirish if (dma_p->ncookies != 1 || 34644045d941Ssowmini (dma_p->dma_cookie.dmac_laddress == NULL)) { 346544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34664045d941Ssowmini "nxge_dma_mem_alloc:di_dma_addr_bind > 1 " 34674045d941Ssowmini "cookie or " 34684045d941Ssowmini "dmac_laddress is NULL $%p size %d " 34694045d941Ssowmini " (status 0x%x ncookies %d.)", 34704045d941Ssowmini ddi_status, 34714045d941Ssowmini dma_p->dma_cookie.dmac_laddress, 34724045d941Ssowmini dma_p->dma_cookie.dmac_size, 34734045d941Ssowmini dma_p->ncookies)); 347444961713Sgirish 347544961713Sgirish contig_mem_free((void *)kaddrp, length); 347656d930aeSspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 347744961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 347844961713Sgirish 347944961713Sgirish dma_p->alength = 0; 348044961713Sgirish dma_p->dma_handle = NULL; 348144961713Sgirish dma_p->acc_handle = NULL; 348244961713Sgirish dma_p->kaddrp = NULL; 348344961713Sgirish 348444961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 348544961713Sgirish } 348644961713Sgirish break; 348744961713Sgirish 348844961713Sgirish #else 348944961713Sgirish case B_TRUE: 349044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34914045d941Ssowmini "nxge_dma_mem_alloc: invalid alloc type for !sun4v")); 349244961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 349344961713Sgirish #endif 349444961713Sgirish } 349544961713Sgirish 349644961713Sgirish dma_p->kaddrp = kaddrp; 349744961713Sgirish dma_p->last_kaddrp = (unsigned char *)kaddrp + 34984045d941Ssowmini dma_p->alength - RXBUF_64B_ALIGNED; 3499adfcba55Sjoycey #if defined(__i386) 3500adfcba55Sjoycey dma_p->ioaddr_pp = 35014045d941Ssowmini (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress; 3502adfcba55Sjoycey #else 350344961713Sgirish dma_p->ioaddr_pp = (unsigned char *)dma_p->dma_cookie.dmac_laddress; 3504adfcba55Sjoycey #endif 350544961713Sgirish dma_p->last_ioaddr_pp = 3506adfcba55Sjoycey #if defined(__i386) 35074045d941Ssowmini (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress + 3508adfcba55Sjoycey #else 35094045d941Ssowmini (unsigned char *)dma_p->dma_cookie.dmac_laddress + 3510adfcba55Sjoycey #endif 35114045d941Ssowmini dma_p->alength - RXBUF_64B_ALIGNED; 351244961713Sgirish 351344961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle); 351444961713Sgirish 351544961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 351644961713Sgirish dma_p->orig_ioaddr_pp = 35174045d941Ssowmini (unsigned char *)dma_p->dma_cookie.dmac_laddress; 351844961713Sgirish dma_p->orig_alength = length; 351944961713Sgirish dma_p->orig_kaddrp = kaddrp; 352044961713Sgirish dma_p->orig_vatopa = (uint64_t)va_to_pa(kaddrp); 352144961713Sgirish #endif 352244961713Sgirish 352344961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_dma_mem_alloc: " 35244045d941Ssowmini "dma buffer allocated: dma_p $%p " 35254045d941Ssowmini "return dmac_ladress from cookie $%p cookie dmac_size %d " 35264045d941Ssowmini "dma_p->ioaddr_p $%p " 35274045d941Ssowmini "dma_p->orig_ioaddr_p $%p " 35284045d941Ssowmini "orig_vatopa $%p " 35294045d941Ssowmini "alength %d (0x%x) " 35304045d941Ssowmini "kaddrp $%p " 35314045d941Ssowmini "length %d (0x%x)", 35324045d941Ssowmini dma_p, 35334045d941Ssowmini dma_p->dma_cookie.dmac_laddress, dma_p->dma_cookie.dmac_size, 35344045d941Ssowmini dma_p->ioaddr_pp, 35354045d941Ssowmini dma_p->orig_ioaddr_pp, 35364045d941Ssowmini dma_p->orig_vatopa, 35374045d941Ssowmini dma_p->alength, dma_p->alength, 35384045d941Ssowmini kaddrp, 35394045d941Ssowmini length, length)); 354044961713Sgirish 354144961713Sgirish return (NXGE_OK); 354244961713Sgirish } 354344961713Sgirish 354444961713Sgirish static void 354544961713Sgirish nxge_dma_mem_free(p_nxge_dma_common_t dma_p) 354644961713Sgirish { 354744961713Sgirish if (dma_p->dma_handle != NULL) { 354844961713Sgirish if (dma_p->ncookies) { 354944961713Sgirish (void) ddi_dma_unbind_handle(dma_p->dma_handle); 355044961713Sgirish dma_p->ncookies = 0; 355144961713Sgirish } 355244961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 355344961713Sgirish dma_p->dma_handle = NULL; 355444961713Sgirish } 355544961713Sgirish 355644961713Sgirish if (dma_p->acc_handle != NULL) { 355744961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 355844961713Sgirish dma_p->acc_handle = NULL; 355944961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 356044961713Sgirish } 356144961713Sgirish 356244961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 356344961713Sgirish if (dma_p->contig_alloc_type && 35644045d941Ssowmini dma_p->orig_kaddrp && dma_p->orig_alength) { 356544961713Sgirish NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_mem_free: " 35664045d941Ssowmini "kaddrp $%p (orig_kaddrp $%p)" 35674045d941Ssowmini "mem type %d ", 35684045d941Ssowmini "orig_alength %d " 35694045d941Ssowmini "alength 0x%x (%d)", 35704045d941Ssowmini dma_p->kaddrp, 35714045d941Ssowmini dma_p->orig_kaddrp, 35724045d941Ssowmini dma_p->contig_alloc_type, 35734045d941Ssowmini dma_p->orig_alength, 35744045d941Ssowmini dma_p->alength, dma_p->alength)); 357544961713Sgirish 357644961713Sgirish contig_mem_free(dma_p->orig_kaddrp, dma_p->orig_alength); 357744961713Sgirish dma_p->orig_alength = NULL; 357844961713Sgirish dma_p->orig_kaddrp = NULL; 357944961713Sgirish dma_p->contig_alloc_type = B_FALSE; 358044961713Sgirish } 358144961713Sgirish #endif 358244961713Sgirish dma_p->kaddrp = NULL; 358344961713Sgirish dma_p->alength = NULL; 358444961713Sgirish } 358544961713Sgirish 3586678453a8Sspeer static void 3587678453a8Sspeer nxge_dma_free_rx_data_buf(p_nxge_dma_common_t dma_p) 3588678453a8Sspeer { 3589678453a8Sspeer uint64_t kaddr; 3590678453a8Sspeer uint32_t buf_size; 3591678453a8Sspeer 3592678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "==> nxge_dma_free_rx_data_buf")); 3593678453a8Sspeer 3594678453a8Sspeer if (dma_p->dma_handle != NULL) { 3595678453a8Sspeer if (dma_p->ncookies) { 3596678453a8Sspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3597678453a8Sspeer dma_p->ncookies = 0; 3598678453a8Sspeer } 3599678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3600678453a8Sspeer dma_p->dma_handle = NULL; 3601678453a8Sspeer } 3602678453a8Sspeer 3603678453a8Sspeer if (dma_p->acc_handle != NULL) { 3604678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3605678453a8Sspeer dma_p->acc_handle = NULL; 3606678453a8Sspeer NPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 3607678453a8Sspeer } 3608678453a8Sspeer 3609678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3610678453a8Sspeer "==> nxge_dma_free_rx_data_buf: dmap $%p buf_alloc_state %d", 3611678453a8Sspeer dma_p, 3612678453a8Sspeer dma_p->buf_alloc_state)); 3613678453a8Sspeer 3614678453a8Sspeer if (!(dma_p->buf_alloc_state & BUF_ALLOCATED_WAIT_FREE)) { 3615678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3616678453a8Sspeer "<== nxge_dma_free_rx_data_buf: " 3617678453a8Sspeer "outstanding data buffers")); 3618678453a8Sspeer return; 3619678453a8Sspeer } 3620678453a8Sspeer 3621678453a8Sspeer #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 3622678453a8Sspeer if (dma_p->contig_alloc_type && 36234045d941Ssowmini dma_p->orig_kaddrp && dma_p->orig_alength) { 3624678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_free_rx_data_buf: " 3625678453a8Sspeer "kaddrp $%p (orig_kaddrp $%p)" 3626678453a8Sspeer "mem type %d ", 3627678453a8Sspeer "orig_alength %d " 3628678453a8Sspeer "alength 0x%x (%d)", 3629678453a8Sspeer dma_p->kaddrp, 3630678453a8Sspeer dma_p->orig_kaddrp, 3631678453a8Sspeer dma_p->contig_alloc_type, 3632678453a8Sspeer dma_p->orig_alength, 3633678453a8Sspeer dma_p->alength, dma_p->alength)); 3634678453a8Sspeer 3635678453a8Sspeer kaddr = (uint64_t)dma_p->orig_kaddrp; 3636678453a8Sspeer buf_size = dma_p->orig_alength; 3637678453a8Sspeer nxge_free_buf(CONTIG_MEM_ALLOC, kaddr, buf_size); 3638678453a8Sspeer dma_p->orig_alength = NULL; 3639678453a8Sspeer dma_p->orig_kaddrp = NULL; 3640678453a8Sspeer dma_p->contig_alloc_type = B_FALSE; 3641678453a8Sspeer dma_p->kaddrp = NULL; 3642678453a8Sspeer dma_p->alength = NULL; 3643678453a8Sspeer return; 3644678453a8Sspeer } 3645678453a8Sspeer #endif 3646678453a8Sspeer 3647678453a8Sspeer if (dma_p->kmem_alloc_type) { 3648678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3649678453a8Sspeer "nxge_dma_free_rx_data_buf: free kmem " 36504045d941Ssowmini "kaddrp $%p (orig_kaddrp $%p)" 36514045d941Ssowmini "alloc type %d " 36524045d941Ssowmini "orig_alength %d " 36534045d941Ssowmini "alength 0x%x (%d)", 36544045d941Ssowmini dma_p->kaddrp, 36554045d941Ssowmini dma_p->orig_kaddrp, 36564045d941Ssowmini dma_p->kmem_alloc_type, 36574045d941Ssowmini dma_p->orig_alength, 36584045d941Ssowmini dma_p->alength, dma_p->alength)); 3659678453a8Sspeer #if defined(__i386) 3660678453a8Sspeer kaddr = (uint64_t)(uint32_t)dma_p->kaddrp; 3661678453a8Sspeer #else 3662678453a8Sspeer kaddr = (uint64_t)dma_p->kaddrp; 3663678453a8Sspeer #endif 3664678453a8Sspeer buf_size = dma_p->orig_alength; 3665678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3666678453a8Sspeer "nxge_dma_free_rx_data_buf: free dmap $%p " 3667678453a8Sspeer "kaddr $%p buf_size %d", 3668678453a8Sspeer dma_p, 3669678453a8Sspeer kaddr, buf_size)); 3670678453a8Sspeer nxge_free_buf(KMEM_ALLOC, kaddr, buf_size); 3671678453a8Sspeer dma_p->alength = 0; 3672678453a8Sspeer dma_p->orig_alength = 0; 3673678453a8Sspeer dma_p->kaddrp = NULL; 3674678453a8Sspeer dma_p->kmem_alloc_type = B_FALSE; 3675678453a8Sspeer } 3676678453a8Sspeer 3677678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_dma_free_rx_data_buf")); 3678678453a8Sspeer } 3679678453a8Sspeer 368044961713Sgirish /* 368144961713Sgirish * nxge_m_start() -- start transmitting and receiving. 368244961713Sgirish * 368344961713Sgirish * This function is called by the MAC layer when the first 368444961713Sgirish * stream is open to prepare the hardware ready for sending 368544961713Sgirish * and transmitting packets. 368644961713Sgirish */ 368744961713Sgirish static int 368844961713Sgirish nxge_m_start(void *arg) 368944961713Sgirish { 369044961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 369144961713Sgirish 369244961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_start")); 369344961713Sgirish 36946f157acbSml if (nxge_peu_reset_enable && !nxgep->nxge_link_poll_timerid) { 36956f157acbSml (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 36966f157acbSml } 36976f157acbSml 369844961713Sgirish MUTEX_ENTER(nxgep->genlock); 369914ea4bb7Ssd if (nxge_init(nxgep) != NXGE_OK) { 370044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 37014045d941Ssowmini "<== nxge_m_start: initialization failed")); 370244961713Sgirish MUTEX_EXIT(nxgep->genlock); 370344961713Sgirish return (EIO); 370444961713Sgirish } 370544961713Sgirish 370614ea4bb7Ssd if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) 370714ea4bb7Ssd goto nxge_m_start_exit; 370844961713Sgirish /* 370944961713Sgirish * Start timer to check the system error and tx hangs 371044961713Sgirish */ 3711678453a8Sspeer if (!isLDOMguest(nxgep)) 3712678453a8Sspeer nxgep->nxge_timerid = nxge_start_timer(nxgep, 3713678453a8Sspeer nxge_check_hw_state, NXGE_CHECK_TIMER); 3714678453a8Sspeer #if defined(sun4v) 3715678453a8Sspeer else 3716678453a8Sspeer nxge_hio_start_timer(nxgep); 3717678453a8Sspeer #endif 371844961713Sgirish 3719a3c5bd6dSspeer nxgep->link_notify = B_TRUE; 3720a3c5bd6dSspeer 372144961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STARTED; 372244961713Sgirish 372314ea4bb7Ssd nxge_m_start_exit: 372444961713Sgirish MUTEX_EXIT(nxgep->genlock); 372544961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_start")); 372644961713Sgirish return (0); 372744961713Sgirish } 372844961713Sgirish 3729*da14cebeSEric Cheng 3730*da14cebeSEric Cheng static boolean_t 3731*da14cebeSEric Cheng nxge_check_groups_stopped(p_nxge_t nxgep) 3732*da14cebeSEric Cheng { 3733*da14cebeSEric Cheng int i; 3734*da14cebeSEric Cheng 3735*da14cebeSEric Cheng for (i = 0; i < NXGE_MAX_RDC_GROUPS; i++) { 3736*da14cebeSEric Cheng if (nxgep->rx_hio_groups[i].started) 3737*da14cebeSEric Cheng return (B_FALSE); 3738*da14cebeSEric Cheng } 3739*da14cebeSEric Cheng 3740*da14cebeSEric Cheng return (B_TRUE); 3741*da14cebeSEric Cheng } 3742*da14cebeSEric Cheng 374344961713Sgirish /* 374444961713Sgirish * nxge_m_stop(): stop transmitting and receiving. 374544961713Sgirish */ 374644961713Sgirish static void 374744961713Sgirish nxge_m_stop(void *arg) 374844961713Sgirish { 374944961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 3750*da14cebeSEric Cheng boolean_t groups_stopped; 375144961713Sgirish 375244961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_stop")); 375344961713Sgirish 3754*da14cebeSEric Cheng groups_stopped = nxge_check_groups_stopped(nxgep); 3755*da14cebeSEric Cheng #ifdef later 3756*da14cebeSEric Cheng ASSERT(groups_stopped == B_FALSE); 3757*da14cebeSEric Cheng #endif 3758*da14cebeSEric Cheng 3759*da14cebeSEric Cheng if (!groups_stopped) { 3760*da14cebeSEric Cheng cmn_err(CE_WARN, "nxge(%d): groups are not stopped!\n", 3761*da14cebeSEric Cheng nxgep->instance); 3762*da14cebeSEric Cheng return; 3763*da14cebeSEric Cheng } 3764*da14cebeSEric Cheng 3765d7cf53fcSmisaki Miyashita MUTEX_ENTER(nxgep->genlock); 3766d7cf53fcSmisaki Miyashita nxgep->nxge_mac_state = NXGE_MAC_STOPPING; 3767d7cf53fcSmisaki Miyashita 376844961713Sgirish if (nxgep->nxge_timerid) { 376944961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 377044961713Sgirish nxgep->nxge_timerid = 0; 377144961713Sgirish } 3772a3c5bd6dSspeer 377344961713Sgirish nxge_uninit(nxgep); 377444961713Sgirish 377544961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STOPPED; 377644961713Sgirish 377744961713Sgirish MUTEX_EXIT(nxgep->genlock); 377844961713Sgirish 377944961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_stop")); 378044961713Sgirish } 378144961713Sgirish 378244961713Sgirish static int 378344961713Sgirish nxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 378444961713Sgirish { 378544961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 378644961713Sgirish struct ether_addr addrp; 378744961713Sgirish 378844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 37894045d941Ssowmini "==> nxge_m_multicst: add %d", add)); 379044961713Sgirish 379144961713Sgirish bcopy(mca, (uint8_t *)&addrp, ETHERADDRL); 379244961713Sgirish if (add) { 379344961713Sgirish if (nxge_add_mcast_addr(nxgep, &addrp)) { 379444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 37954045d941Ssowmini "<== nxge_m_multicst: add multicast failed")); 379644961713Sgirish return (EINVAL); 379744961713Sgirish } 379844961713Sgirish } else { 379944961713Sgirish if (nxge_del_mcast_addr(nxgep, &addrp)) { 380044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 38014045d941Ssowmini "<== nxge_m_multicst: del multicast failed")); 380244961713Sgirish return (EINVAL); 380344961713Sgirish } 380444961713Sgirish } 380544961713Sgirish 380644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_multicst")); 380744961713Sgirish 380844961713Sgirish return (0); 380944961713Sgirish } 381044961713Sgirish 381144961713Sgirish static int 381244961713Sgirish nxge_m_promisc(void *arg, boolean_t on) 381344961713Sgirish { 381444961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 381544961713Sgirish 381644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38174045d941Ssowmini "==> nxge_m_promisc: on %d", on)); 381844961713Sgirish 381944961713Sgirish if (nxge_set_promisc(nxgep, on)) { 382044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 38214045d941Ssowmini "<== nxge_m_promisc: set promisc failed")); 382244961713Sgirish return (EINVAL); 382344961713Sgirish } 382444961713Sgirish 382544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38264045d941Ssowmini "<== nxge_m_promisc: on %d", on)); 382744961713Sgirish 382844961713Sgirish return (0); 382944961713Sgirish } 383044961713Sgirish 383144961713Sgirish static void 383244961713Sgirish nxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 383344961713Sgirish { 383444961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 383556d930aeSspeer struct iocblk *iocp; 383644961713Sgirish boolean_t need_privilege; 383744961713Sgirish int err; 383844961713Sgirish int cmd; 383944961713Sgirish 384044961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl")); 384144961713Sgirish 384244961713Sgirish iocp = (struct iocblk *)mp->b_rptr; 384344961713Sgirish iocp->ioc_error = 0; 384444961713Sgirish need_privilege = B_TRUE; 384544961713Sgirish cmd = iocp->ioc_cmd; 384644961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl: cmd 0x%08x", cmd)); 384744961713Sgirish switch (cmd) { 384844961713Sgirish default: 384944961713Sgirish miocnak(wq, mp, 0, EINVAL); 385044961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl: invalid")); 385144961713Sgirish return; 385244961713Sgirish 385344961713Sgirish case LB_GET_INFO_SIZE: 385444961713Sgirish case LB_GET_INFO: 385544961713Sgirish case LB_GET_MODE: 385644961713Sgirish need_privilege = B_FALSE; 385744961713Sgirish break; 385844961713Sgirish case LB_SET_MODE: 385944961713Sgirish break; 386044961713Sgirish 386144961713Sgirish 386244961713Sgirish case NXGE_GET_MII: 386344961713Sgirish case NXGE_PUT_MII: 386444961713Sgirish case NXGE_GET64: 386544961713Sgirish case NXGE_PUT64: 386644961713Sgirish case NXGE_GET_TX_RING_SZ: 386744961713Sgirish case NXGE_GET_TX_DESC: 386844961713Sgirish case NXGE_TX_SIDE_RESET: 386944961713Sgirish case NXGE_RX_SIDE_RESET: 387044961713Sgirish case NXGE_GLOBAL_RESET: 387144961713Sgirish case NXGE_RESET_MAC: 387244961713Sgirish case NXGE_TX_REGS_DUMP: 387344961713Sgirish case NXGE_RX_REGS_DUMP: 387444961713Sgirish case NXGE_INT_REGS_DUMP: 387544961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 387644961713Sgirish case NXGE_PUT_TCAM: 387744961713Sgirish case NXGE_GET_TCAM: 387844961713Sgirish case NXGE_RTRACE: 387944961713Sgirish case NXGE_RDUMP: 388044961713Sgirish 388144961713Sgirish need_privilege = B_FALSE; 388244961713Sgirish break; 388344961713Sgirish case NXGE_INJECT_ERR: 388444961713Sgirish cmn_err(CE_NOTE, "!nxge_m_ioctl: Inject error\n"); 388544961713Sgirish nxge_err_inject(nxgep, wq, mp); 388644961713Sgirish break; 388744961713Sgirish } 388844961713Sgirish 388944961713Sgirish if (need_privilege) { 389056d930aeSspeer err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 389144961713Sgirish if (err != 0) { 389244961713Sgirish miocnak(wq, mp, 0, err); 389344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 38944045d941Ssowmini "<== nxge_m_ioctl: no priv")); 389544961713Sgirish return; 389644961713Sgirish } 389744961713Sgirish } 389844961713Sgirish 389944961713Sgirish switch (cmd) { 390044961713Sgirish 390144961713Sgirish case LB_GET_MODE: 390244961713Sgirish case LB_SET_MODE: 390344961713Sgirish case LB_GET_INFO_SIZE: 390444961713Sgirish case LB_GET_INFO: 390544961713Sgirish nxge_loopback_ioctl(nxgep, wq, mp, iocp); 390644961713Sgirish break; 390744961713Sgirish 390844961713Sgirish case NXGE_GET_MII: 390944961713Sgirish case NXGE_PUT_MII: 391044961713Sgirish case NXGE_PUT_TCAM: 391144961713Sgirish case NXGE_GET_TCAM: 391244961713Sgirish case NXGE_GET64: 391344961713Sgirish case NXGE_PUT64: 391444961713Sgirish case NXGE_GET_TX_RING_SZ: 391544961713Sgirish case NXGE_GET_TX_DESC: 391644961713Sgirish case NXGE_TX_SIDE_RESET: 391744961713Sgirish case NXGE_RX_SIDE_RESET: 391844961713Sgirish case NXGE_GLOBAL_RESET: 391944961713Sgirish case NXGE_RESET_MAC: 392044961713Sgirish case NXGE_TX_REGS_DUMP: 392144961713Sgirish case NXGE_RX_REGS_DUMP: 392244961713Sgirish case NXGE_INT_REGS_DUMP: 392344961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 392444961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 39254045d941Ssowmini "==> nxge_m_ioctl: cmd 0x%x", cmd)); 392644961713Sgirish nxge_hw_ioctl(nxgep, wq, mp, iocp); 392744961713Sgirish break; 392844961713Sgirish } 392944961713Sgirish 393044961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl")); 393144961713Sgirish } 393244961713Sgirish 393344961713Sgirish extern void nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count); 393444961713Sgirish 3935678453a8Sspeer void 3936*da14cebeSEric Cheng nxge_mmac_kstat_update(p_nxge_t nxgep, int slot, boolean_t factory) 393758324dfcSspeer { 393858324dfcSspeer p_nxge_mmac_stats_t mmac_stats; 393958324dfcSspeer int i; 394058324dfcSspeer nxge_mmac_t *mmac_info; 394158324dfcSspeer 394258324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 394358324dfcSspeer 394458324dfcSspeer mmac_stats = &nxgep->statsp->mmac_stats; 394558324dfcSspeer mmac_stats->mmac_max_cnt = mmac_info->num_mmac; 394658324dfcSspeer mmac_stats->mmac_avail_cnt = mmac_info->naddrfree; 394758324dfcSspeer 394858324dfcSspeer for (i = 0; i < ETHERADDRL; i++) { 394958324dfcSspeer if (factory) { 395058324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 39514045d941Ssowmini = mmac_info->factory_mac_pool[slot][ 39524045d941Ssowmini (ETHERADDRL-1) - i]; 395358324dfcSspeer } else { 395458324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 39554045d941Ssowmini = mmac_info->mac_pool[slot].addr[ 39564045d941Ssowmini (ETHERADDRL - 1) - i]; 395758324dfcSspeer } 395858324dfcSspeer } 395958324dfcSspeer } 396058324dfcSspeer 396158324dfcSspeer /* 396258324dfcSspeer * nxge_altmac_set() -- Set an alternate MAC address 396358324dfcSspeer */ 3964*da14cebeSEric Cheng static int 3965*da14cebeSEric Cheng nxge_altmac_set(p_nxge_t nxgep, uint8_t *maddr, int slot, 3966*da14cebeSEric Cheng int rdctbl, boolean_t usetbl) 396758324dfcSspeer { 396858324dfcSspeer uint8_t addrn; 396958324dfcSspeer uint8_t portn; 397058324dfcSspeer npi_mac_addr_t altmac; 39717b9fa28bSspeer hostinfo_t mac_rdc; 39727b9fa28bSspeer p_nxge_class_pt_cfg_t clscfgp; 397358324dfcSspeer 3974*da14cebeSEric Cheng 397558324dfcSspeer altmac.w2 = ((uint16_t)maddr[0] << 8) | ((uint16_t)maddr[1] & 0x0ff); 397658324dfcSspeer altmac.w1 = ((uint16_t)maddr[2] << 8) | ((uint16_t)maddr[3] & 0x0ff); 397758324dfcSspeer altmac.w0 = ((uint16_t)maddr[4] << 8) | ((uint16_t)maddr[5] & 0x0ff); 397858324dfcSspeer 397958324dfcSspeer portn = nxgep->mac.portnum; 398058324dfcSspeer addrn = (uint8_t)slot - 1; 398158324dfcSspeer 3982*da14cebeSEric Cheng if (npi_mac_altaddr_entry(nxgep->npi_handle, OP_SET, 3983*da14cebeSEric Cheng nxgep->function_num, addrn, &altmac) != NPI_SUCCESS) 398458324dfcSspeer return (EIO); 39857b9fa28bSspeer 39867b9fa28bSspeer /* 39877b9fa28bSspeer * Set the rdc table number for the host info entry 39887b9fa28bSspeer * for this mac address slot. 39897b9fa28bSspeer */ 39907b9fa28bSspeer clscfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config; 39917b9fa28bSspeer mac_rdc.value = 0; 3992*da14cebeSEric Cheng if (usetbl) 3993*da14cebeSEric Cheng mac_rdc.bits.w0.rdc_tbl_num = rdctbl; 3994*da14cebeSEric Cheng else 3995*da14cebeSEric Cheng mac_rdc.bits.w0.rdc_tbl_num = 3996*da14cebeSEric Cheng clscfgp->mac_host_info[addrn].rdctbl; 39977b9fa28bSspeer mac_rdc.bits.w0.mac_pref = clscfgp->mac_host_info[addrn].mpr_npr; 39987b9fa28bSspeer 39997b9fa28bSspeer if (npi_mac_hostinfo_entry(nxgep->npi_handle, OP_SET, 40007b9fa28bSspeer nxgep->function_num, addrn, &mac_rdc) != NPI_SUCCESS) { 40017b9fa28bSspeer return (EIO); 40027b9fa28bSspeer } 40037b9fa28bSspeer 400458324dfcSspeer /* 400558324dfcSspeer * Enable comparison with the alternate MAC address. 400658324dfcSspeer * While the first alternate addr is enabled by bit 1 of register 400758324dfcSspeer * BMAC_ALTAD_CMPEN, it is enabled by bit 0 of register 400858324dfcSspeer * XMAC_ADDR_CMPEN, so slot needs to be converted to addrn 400958324dfcSspeer * accordingly before calling npi_mac_altaddr_entry. 401058324dfcSspeer */ 401158324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 401258324dfcSspeer addrn = (uint8_t)slot - 1; 401358324dfcSspeer else 401458324dfcSspeer addrn = (uint8_t)slot; 401558324dfcSspeer 4016*da14cebeSEric Cheng if (npi_mac_altaddr_enable(nxgep->npi_handle, 4017*da14cebeSEric Cheng nxgep->function_num, addrn) != NPI_SUCCESS) { 401858324dfcSspeer return (EIO); 4019*da14cebeSEric Cheng } 4020*da14cebeSEric Cheng 402158324dfcSspeer return (0); 402258324dfcSspeer } 402358324dfcSspeer 402458324dfcSspeer /* 4025*da14cebeSEric Cheng * nxeg_m_mmac_add_g() - find an unused address slot, set the address 402658324dfcSspeer * value to the one specified, enable the port to start filtering on 402758324dfcSspeer * the new MAC address. Returns 0 on success. 402858324dfcSspeer */ 4029678453a8Sspeer int 4030*da14cebeSEric Cheng nxge_m_mmac_add_g(void *arg, const uint8_t *maddr, int rdctbl, 4031*da14cebeSEric Cheng boolean_t usetbl) 403258324dfcSspeer { 403358324dfcSspeer p_nxge_t nxgep = arg; 4034*da14cebeSEric Cheng int slot; 403558324dfcSspeer nxge_mmac_t *mmac_info; 403658324dfcSspeer int err; 403758324dfcSspeer nxge_status_t status; 403858324dfcSspeer 403958324dfcSspeer mutex_enter(nxgep->genlock); 404058324dfcSspeer 404158324dfcSspeer /* 404258324dfcSspeer * Make sure that nxge is initialized, if _start() has 404358324dfcSspeer * not been called. 404458324dfcSspeer */ 404558324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 404658324dfcSspeer status = nxge_init(nxgep); 404758324dfcSspeer if (status != NXGE_OK) { 404858324dfcSspeer mutex_exit(nxgep->genlock); 404958324dfcSspeer return (ENXIO); 405058324dfcSspeer } 405158324dfcSspeer } 405258324dfcSspeer 405358324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 405458324dfcSspeer if (mmac_info->naddrfree == 0) { 405558324dfcSspeer mutex_exit(nxgep->genlock); 405658324dfcSspeer return (ENOSPC); 405758324dfcSspeer } 4058*da14cebeSEric Cheng 405958324dfcSspeer /* 406058324dfcSspeer * Search for the first available slot. Because naddrfree 406158324dfcSspeer * is not zero, we are guaranteed to find one. 406258324dfcSspeer * Each of the first two ports of Neptune has 16 alternate 4063678453a8Sspeer * MAC slots but only the first 7 (of 15) slots have assigned factory 406458324dfcSspeer * MAC addresses. We first search among the slots without bundled 406558324dfcSspeer * factory MACs. If we fail to find one in that range, then we 406658324dfcSspeer * search the slots with bundled factory MACs. A factory MAC 406758324dfcSspeer * will be wasted while the slot is used with a user MAC address. 406858324dfcSspeer * But the slot could be used by factory MAC again after calling 406958324dfcSspeer * nxge_m_mmac_remove and nxge_m_mmac_reserve. 407058324dfcSspeer */ 4071*da14cebeSEric Cheng for (slot = 0; slot <= mmac_info->num_mmac; slot++) { 4072*da14cebeSEric Cheng if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 4073*da14cebeSEric Cheng break; 407458324dfcSspeer } 4075*da14cebeSEric Cheng 407658324dfcSspeer ASSERT(slot <= mmac_info->num_mmac); 4077e857d0f3SMichael Speer 4078*da14cebeSEric Cheng if ((err = nxge_altmac_set(nxgep, (uint8_t *)maddr, slot, rdctbl, 4079*da14cebeSEric Cheng usetbl)) != 0) { 408058324dfcSspeer mutex_exit(nxgep->genlock); 408158324dfcSspeer return (err); 408258324dfcSspeer } 4083e857d0f3SMichael Speer 4084*da14cebeSEric Cheng bcopy(maddr, mmac_info->mac_pool[slot].addr, ETHERADDRL); 408558324dfcSspeer mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED; 408658324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR; 408758324dfcSspeer mmac_info->naddrfree--; 408858324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 408958324dfcSspeer 409058324dfcSspeer mutex_exit(nxgep->genlock); 409158324dfcSspeer return (0); 409258324dfcSspeer } 409358324dfcSspeer 409458324dfcSspeer /* 409558324dfcSspeer * Remove the specified mac address and update the HW not to filter 409658324dfcSspeer * the mac address anymore. 409758324dfcSspeer */ 4098678453a8Sspeer int 4099*da14cebeSEric Cheng nxge_m_mmac_remove(void *arg, int slot) 410058324dfcSspeer { 410158324dfcSspeer p_nxge_t nxgep = arg; 410258324dfcSspeer nxge_mmac_t *mmac_info; 410358324dfcSspeer uint8_t addrn; 410458324dfcSspeer uint8_t portn; 410558324dfcSspeer int err = 0; 410658324dfcSspeer nxge_status_t status; 410758324dfcSspeer 410858324dfcSspeer mutex_enter(nxgep->genlock); 410958324dfcSspeer 411058324dfcSspeer /* 411158324dfcSspeer * Make sure that nxge is initialized, if _start() has 411258324dfcSspeer * not been called. 411358324dfcSspeer */ 411458324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 411558324dfcSspeer status = nxge_init(nxgep); 411658324dfcSspeer if (status != NXGE_OK) { 411758324dfcSspeer mutex_exit(nxgep->genlock); 411858324dfcSspeer return (ENXIO); 411958324dfcSspeer } 412058324dfcSspeer } 412158324dfcSspeer 412258324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 412358324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 412458324dfcSspeer mutex_exit(nxgep->genlock); 412558324dfcSspeer return (EINVAL); 412658324dfcSspeer } 412758324dfcSspeer 412858324dfcSspeer portn = nxgep->mac.portnum; 412958324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 413058324dfcSspeer addrn = (uint8_t)slot - 1; 413158324dfcSspeer else 413258324dfcSspeer addrn = (uint8_t)slot; 413358324dfcSspeer 413458324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 413558324dfcSspeer if (npi_mac_altaddr_disable(nxgep->npi_handle, portn, addrn) 41364045d941Ssowmini == NPI_SUCCESS) { 413758324dfcSspeer mmac_info->naddrfree++; 413858324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_SLOT_USED; 413958324dfcSspeer /* 414058324dfcSspeer * Regardless if the MAC we just stopped filtering 414158324dfcSspeer * is a user addr or a facory addr, we must set 414258324dfcSspeer * the MMAC_VENDOR_ADDR flag if this slot has an 414358324dfcSspeer * associated factory MAC to indicate that a factory 414458324dfcSspeer * MAC is available. 414558324dfcSspeer */ 414658324dfcSspeer if (slot <= mmac_info->num_factory_mmac) { 414758324dfcSspeer mmac_info->mac_pool[slot].flags 41484045d941Ssowmini |= MMAC_VENDOR_ADDR; 414958324dfcSspeer } 415058324dfcSspeer /* 415158324dfcSspeer * Clear mac_pool[slot].addr so that kstat shows 0 415258324dfcSspeer * alternate MAC address if the slot is not used. 415358324dfcSspeer * (But nxge_m_mmac_get returns the factory MAC even 415458324dfcSspeer * when the slot is not used!) 415558324dfcSspeer */ 415658324dfcSspeer bzero(mmac_info->mac_pool[slot].addr, ETHERADDRL); 415758324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 415858324dfcSspeer } else { 415958324dfcSspeer err = EIO; 416058324dfcSspeer } 416158324dfcSspeer } else { 416258324dfcSspeer err = EINVAL; 416358324dfcSspeer } 416458324dfcSspeer 416558324dfcSspeer mutex_exit(nxgep->genlock); 416658324dfcSspeer return (err); 416758324dfcSspeer } 416858324dfcSspeer 416958324dfcSspeer /* 4170*da14cebeSEric Cheng * The callback to query all the factory addresses. naddr must be the same as 4171*da14cebeSEric Cheng * the number of factory addresses (returned by MAC_CAPAB_MULTIFACTADDR), and 4172*da14cebeSEric Cheng * mcm_addr is the space allocated for keep all the addresses, whose size is 4173*da14cebeSEric Cheng * naddr * MAXMACADDRLEN. 417458324dfcSspeer */ 4175*da14cebeSEric Cheng static void 4176*da14cebeSEric Cheng nxge_m_getfactaddr(void *arg, uint_t naddr, uint8_t *addr) 417758324dfcSspeer { 4178*da14cebeSEric Cheng nxge_t *nxgep = arg; 4179*da14cebeSEric Cheng nxge_mmac_t *mmac_info; 4180*da14cebeSEric Cheng int i; 418158324dfcSspeer 418258324dfcSspeer mutex_enter(nxgep->genlock); 418358324dfcSspeer 418458324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 4185*da14cebeSEric Cheng ASSERT(naddr == mmac_info->num_factory_mmac); 418658324dfcSspeer 4187*da14cebeSEric Cheng for (i = 0; i < naddr; i++) { 4188*da14cebeSEric Cheng bcopy(mmac_info->factory_mac_pool[i + 1], 4189*da14cebeSEric Cheng addr + i * MAXMACADDRLEN, ETHERADDRL); 419058324dfcSspeer } 419158324dfcSspeer 419258324dfcSspeer mutex_exit(nxgep->genlock); 419358324dfcSspeer } 419458324dfcSspeer 4195*da14cebeSEric Cheng 419644961713Sgirish static boolean_t 419744961713Sgirish nxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 419844961713Sgirish { 419958324dfcSspeer nxge_t *nxgep = arg; 420058324dfcSspeer uint32_t *txflags = cap_data; 420144961713Sgirish 420258324dfcSspeer switch (cap) { 420358324dfcSspeer case MAC_CAPAB_HCKSUM: 4204678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4205b4d05839Sml "==> nxge_m_getcapab: checksum %d", nxge_cksum_offload)); 4206b4d05839Sml if (nxge_cksum_offload <= 1) { 4207678453a8Sspeer *txflags = HCKSUM_INET_PARTIAL; 4208678453a8Sspeer } 420944961713Sgirish break; 4210678453a8Sspeer 4211*da14cebeSEric Cheng case MAC_CAPAB_MULTIFACTADDR: { 4212*da14cebeSEric Cheng mac_capab_multifactaddr_t *mfacp = cap_data; 421344961713Sgirish 421458324dfcSspeer mutex_enter(nxgep->genlock); 4215*da14cebeSEric Cheng mfacp->mcm_naddr = nxgep->nxge_mmac_info.num_factory_mmac; 4216*da14cebeSEric Cheng mfacp->mcm_getaddr = nxge_m_getfactaddr; 421758324dfcSspeer mutex_exit(nxgep->genlock); 421858324dfcSspeer break; 4219*da14cebeSEric Cheng } 4220678453a8Sspeer 422130ac2e7bSml case MAC_CAPAB_LSO: { 422230ac2e7bSml mac_capab_lso_t *cap_lso = cap_data; 422330ac2e7bSml 42243d16f8e7Sml if (nxgep->soft_lso_enable) { 4225b4d05839Sml if (nxge_cksum_offload <= 1) { 4226b4d05839Sml cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 4227b4d05839Sml if (nxge_lso_max > NXGE_LSO_MAXLEN) { 4228b4d05839Sml nxge_lso_max = NXGE_LSO_MAXLEN; 4229b4d05839Sml } 4230b4d05839Sml cap_lso->lso_basic_tcp_ipv4.lso_max = 4231b4d05839Sml nxge_lso_max; 423230ac2e7bSml } 423330ac2e7bSml break; 423430ac2e7bSml } else { 423530ac2e7bSml return (B_FALSE); 423630ac2e7bSml } 423730ac2e7bSml } 423830ac2e7bSml 4239678453a8Sspeer case MAC_CAPAB_RINGS: { 4240*da14cebeSEric Cheng mac_capab_rings_t *cap_rings = cap_data; 4241*da14cebeSEric Cheng p_nxge_hw_pt_cfg_t p_cfgp = &nxgep->pt_config.hw_config; 4242678453a8Sspeer 4243*da14cebeSEric Cheng mutex_enter(nxgep->genlock); 4244*da14cebeSEric Cheng if (cap_rings->mr_type == MAC_RING_TYPE_RX) { 4245*da14cebeSEric Cheng cap_rings->mr_group_type = MAC_GROUP_TYPE_DYNAMIC; 4246*da14cebeSEric Cheng cap_rings->mr_rnum = p_cfgp->max_rdcs; 4247*da14cebeSEric Cheng cap_rings->mr_rget = nxge_fill_ring; 4248*da14cebeSEric Cheng cap_rings->mr_gnum = p_cfgp->max_rdc_grpids; 4249*da14cebeSEric Cheng cap_rings->mr_gget = nxge_hio_group_get; 4250*da14cebeSEric Cheng cap_rings->mr_gaddring = nxge_group_add_ring; 4251*da14cebeSEric Cheng cap_rings->mr_gremring = nxge_group_rem_ring; 4252*da14cebeSEric Cheng 4253*da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, RX_CTL, 4254*da14cebeSEric Cheng "==> nxge_m_getcapab: rx nrings[%d] ngroups[%d]", 4255*da14cebeSEric Cheng p_cfgp->max_rdcs, p_cfgp->max_rdc_grpids)); 4256*da14cebeSEric Cheng } else { 4257*da14cebeSEric Cheng cap_rings->mr_group_type = MAC_GROUP_TYPE_DYNAMIC; 4258*da14cebeSEric Cheng cap_rings->mr_rnum = p_cfgp->tdc.count; 4259*da14cebeSEric Cheng cap_rings->mr_rget = nxge_fill_ring; 4260*da14cebeSEric Cheng if (isLDOMservice(nxgep)) { 4261*da14cebeSEric Cheng /* share capable */ 4262*da14cebeSEric Cheng /* Do not report the default ring: hence -1 */ 4263*da14cebeSEric Cheng cap_rings->mr_gnum = 4264*da14cebeSEric Cheng NXGE_MAX_TDC_GROUPS / nxgep->nports - 1; 4265678453a8Sspeer } else { 4266*da14cebeSEric Cheng cap_rings->mr_gnum = 0; 4267678453a8Sspeer } 4268*da14cebeSEric Cheng 4269*da14cebeSEric Cheng cap_rings->mr_gget = nxge_hio_group_get; 4270*da14cebeSEric Cheng cap_rings->mr_gaddring = nxge_group_add_ring; 4271*da14cebeSEric Cheng cap_rings->mr_gremring = nxge_group_rem_ring; 4272*da14cebeSEric Cheng 4273*da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, TX_CTL, 4274*da14cebeSEric Cheng "==> nxge_m_getcapab: tx rings # of rings %d", 4275*da14cebeSEric Cheng p_cfgp->tdc.count)); 4276*da14cebeSEric Cheng } 4277*da14cebeSEric Cheng mutex_exit(nxgep->genlock); 4278678453a8Sspeer break; 4279678453a8Sspeer } 4280678453a8Sspeer 4281*da14cebeSEric Cheng #if defined(sun4v) 4282678453a8Sspeer case MAC_CAPAB_SHARES: { 4283678453a8Sspeer mac_capab_share_t *mshares = (mac_capab_share_t *)cap_data; 4284678453a8Sspeer 4285678453a8Sspeer /* 4286678453a8Sspeer * Only the service domain driver responds to 4287678453a8Sspeer * this capability request. 4288678453a8Sspeer */ 4289*da14cebeSEric Cheng mutex_enter(nxgep->genlock); 4290678453a8Sspeer if (isLDOMservice(nxgep)) { 4291678453a8Sspeer mshares->ms_snum = 3; 4292678453a8Sspeer mshares->ms_handle = (void *)nxgep; 4293678453a8Sspeer mshares->ms_salloc = nxge_hio_share_alloc; 4294678453a8Sspeer mshares->ms_sfree = nxge_hio_share_free; 4295*da14cebeSEric Cheng mshares->ms_sadd = nxge_hio_share_add_group; 4296*da14cebeSEric Cheng mshares->ms_sremove = nxge_hio_share_rem_group; 4297678453a8Sspeer mshares->ms_squery = nxge_hio_share_query; 4298*da14cebeSEric Cheng mshares->ms_sbind = nxge_hio_share_bind; 4299*da14cebeSEric Cheng mshares->ms_sunbind = nxge_hio_share_unbind; 4300*da14cebeSEric Cheng mutex_exit(nxgep->genlock); 4301*da14cebeSEric Cheng } else { 4302*da14cebeSEric Cheng mutex_exit(nxgep->genlock); 4303678453a8Sspeer return (B_FALSE); 4304*da14cebeSEric Cheng } 4305678453a8Sspeer break; 4306678453a8Sspeer } 4307678453a8Sspeer #endif 430844961713Sgirish default: 430944961713Sgirish return (B_FALSE); 431044961713Sgirish } 431144961713Sgirish return (B_TRUE); 431244961713Sgirish } 431344961713Sgirish 43141bd6825cSml static boolean_t 43151bd6825cSml nxge_param_locked(mac_prop_id_t pr_num) 43161bd6825cSml { 43171bd6825cSml /* 43181bd6825cSml * All adv_* parameters are locked (read-only) while 43191bd6825cSml * the device is in any sort of loopback mode ... 43201bd6825cSml */ 43211bd6825cSml switch (pr_num) { 43223fd94f8cSam case MAC_PROP_ADV_1000FDX_CAP: 43233fd94f8cSam case MAC_PROP_EN_1000FDX_CAP: 43243fd94f8cSam case MAC_PROP_ADV_1000HDX_CAP: 43253fd94f8cSam case MAC_PROP_EN_1000HDX_CAP: 43263fd94f8cSam case MAC_PROP_ADV_100FDX_CAP: 43273fd94f8cSam case MAC_PROP_EN_100FDX_CAP: 43283fd94f8cSam case MAC_PROP_ADV_100HDX_CAP: 43293fd94f8cSam case MAC_PROP_EN_100HDX_CAP: 43303fd94f8cSam case MAC_PROP_ADV_10FDX_CAP: 43313fd94f8cSam case MAC_PROP_EN_10FDX_CAP: 43323fd94f8cSam case MAC_PROP_ADV_10HDX_CAP: 43333fd94f8cSam case MAC_PROP_EN_10HDX_CAP: 43343fd94f8cSam case MAC_PROP_AUTONEG: 43353fd94f8cSam case MAC_PROP_FLOWCTRL: 43361bd6825cSml return (B_TRUE); 43371bd6825cSml } 43381bd6825cSml return (B_FALSE); 43391bd6825cSml } 43401bd6825cSml 43411bd6825cSml /* 43421bd6825cSml * callback functions for set/get of properties 43431bd6825cSml */ 43441bd6825cSml static int 43451bd6825cSml nxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 43461bd6825cSml uint_t pr_valsize, const void *pr_val) 43471bd6825cSml { 43481bd6825cSml nxge_t *nxgep = barg; 43491bd6825cSml p_nxge_param_t param_arr; 43501bd6825cSml p_nxge_stats_t statsp; 43511bd6825cSml int err = 0; 43521bd6825cSml uint8_t val; 43531bd6825cSml uint32_t cur_mtu, new_mtu, old_framesize; 43541bd6825cSml link_flowctrl_t fl; 43551bd6825cSml 43561bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_setprop")); 43571bd6825cSml param_arr = nxgep->param_arr; 43581bd6825cSml statsp = nxgep->statsp; 43591bd6825cSml mutex_enter(nxgep->genlock); 43601bd6825cSml if (statsp->port_stats.lb_mode != nxge_lb_normal && 43611bd6825cSml nxge_param_locked(pr_num)) { 43621bd6825cSml /* 43631bd6825cSml * All adv_* parameters are locked (read-only) 43641bd6825cSml * while the device is in any sort of loopback mode. 43651bd6825cSml */ 43661bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 43671bd6825cSml "==> nxge_m_setprop: loopback mode: read only")); 43681bd6825cSml mutex_exit(nxgep->genlock); 43691bd6825cSml return (EBUSY); 43701bd6825cSml } 43711bd6825cSml 43721bd6825cSml val = *(uint8_t *)pr_val; 43731bd6825cSml switch (pr_num) { 43743fd94f8cSam case MAC_PROP_EN_1000FDX_CAP: 43751bd6825cSml nxgep->param_en_1000fdx = val; 43761bd6825cSml param_arr[param_anar_1000fdx].value = val; 43771bd6825cSml 43781bd6825cSml goto reprogram; 43791bd6825cSml 43803fd94f8cSam case MAC_PROP_EN_100FDX_CAP: 43811bd6825cSml nxgep->param_en_100fdx = val; 43821bd6825cSml param_arr[param_anar_100fdx].value = val; 43831bd6825cSml 43841bd6825cSml goto reprogram; 43851bd6825cSml 43863fd94f8cSam case MAC_PROP_EN_10FDX_CAP: 43871bd6825cSml nxgep->param_en_10fdx = val; 43881bd6825cSml param_arr[param_anar_10fdx].value = val; 43891bd6825cSml 43901bd6825cSml goto reprogram; 43911bd6825cSml 43923fd94f8cSam case MAC_PROP_EN_1000HDX_CAP: 43933fd94f8cSam case MAC_PROP_EN_100HDX_CAP: 43943fd94f8cSam case MAC_PROP_EN_10HDX_CAP: 43953fd94f8cSam case MAC_PROP_ADV_1000FDX_CAP: 43963fd94f8cSam case MAC_PROP_ADV_1000HDX_CAP: 43973fd94f8cSam case MAC_PROP_ADV_100FDX_CAP: 43983fd94f8cSam case MAC_PROP_ADV_100HDX_CAP: 43993fd94f8cSam case MAC_PROP_ADV_10FDX_CAP: 44003fd94f8cSam case MAC_PROP_ADV_10HDX_CAP: 44013fd94f8cSam case MAC_PROP_STATUS: 44023fd94f8cSam case MAC_PROP_SPEED: 44033fd94f8cSam case MAC_PROP_DUPLEX: 44041bd6825cSml err = EINVAL; /* cannot set read-only properties */ 44051bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 44061bd6825cSml "==> nxge_m_setprop: read only property %d", 44071bd6825cSml pr_num)); 44081bd6825cSml break; 44091bd6825cSml 44103fd94f8cSam case MAC_PROP_AUTONEG: 44111bd6825cSml param_arr[param_autoneg].value = val; 44121bd6825cSml 44131bd6825cSml goto reprogram; 44141bd6825cSml 44153fd94f8cSam case MAC_PROP_MTU: 44161bd6825cSml cur_mtu = nxgep->mac.default_mtu; 44171bd6825cSml bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 44181bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 44191bd6825cSml "==> nxge_m_setprop: set MTU: %d is_jumbo %d", 44201bd6825cSml new_mtu, nxgep->mac.is_jumbo)); 44211bd6825cSml 44221bd6825cSml if (new_mtu == cur_mtu) { 44231bd6825cSml err = 0; 44241bd6825cSml break; 44251bd6825cSml } 4426afdda45fSVasumathi Sundaram - Sun Microsystems if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 4427afdda45fSVasumathi Sundaram - Sun Microsystems err = EBUSY; 4428afdda45fSVasumathi Sundaram - Sun Microsystems break; 4429afdda45fSVasumathi Sundaram - Sun Microsystems } 44301bd6825cSml if (new_mtu < NXGE_DEFAULT_MTU || 44311bd6825cSml new_mtu > NXGE_MAXIMUM_MTU) { 44321bd6825cSml err = EINVAL; 44331bd6825cSml break; 44341bd6825cSml } 44351bd6825cSml 44361bd6825cSml if ((new_mtu > NXGE_DEFAULT_MTU) && 44371bd6825cSml !nxgep->mac.is_jumbo) { 44381bd6825cSml err = EINVAL; 44391bd6825cSml break; 44401bd6825cSml } 44411bd6825cSml 44421bd6825cSml old_framesize = (uint32_t)nxgep->mac.maxframesize; 44431bd6825cSml nxgep->mac.maxframesize = (uint16_t) 44441bd6825cSml (new_mtu + NXGE_EHEADER_VLAN_CRC); 44451bd6825cSml if (nxge_mac_set_framesize(nxgep)) { 4446c2d37b8bSml nxgep->mac.maxframesize = 4447c2d37b8bSml (uint16_t)old_framesize; 44481bd6825cSml err = EINVAL; 44491bd6825cSml break; 44501bd6825cSml } 44511bd6825cSml 44521bd6825cSml err = mac_maxsdu_update(nxgep->mach, new_mtu); 44531bd6825cSml if (err) { 4454c2d37b8bSml nxgep->mac.maxframesize = 4455c2d37b8bSml (uint16_t)old_framesize; 44561bd6825cSml err = EINVAL; 44571bd6825cSml break; 44581bd6825cSml } 44591bd6825cSml 44601bd6825cSml nxgep->mac.default_mtu = new_mtu; 44611bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 44621bd6825cSml "==> nxge_m_setprop: set MTU: %d maxframe %d", 44631bd6825cSml new_mtu, nxgep->mac.maxframesize)); 44641bd6825cSml break; 44651bd6825cSml 44663fd94f8cSam case MAC_PROP_FLOWCTRL: 44671bd6825cSml bcopy(pr_val, &fl, sizeof (fl)); 44681bd6825cSml switch (fl) { 44691bd6825cSml default: 44701bd6825cSml err = EINVAL; 44711bd6825cSml break; 44721bd6825cSml 44731bd6825cSml case LINK_FLOWCTRL_NONE: 44741bd6825cSml param_arr[param_anar_pause].value = 0; 44751bd6825cSml break; 44761bd6825cSml 44771bd6825cSml case LINK_FLOWCTRL_RX: 44781bd6825cSml param_arr[param_anar_pause].value = 1; 44791bd6825cSml break; 44801bd6825cSml 44811bd6825cSml case LINK_FLOWCTRL_TX: 44821bd6825cSml case LINK_FLOWCTRL_BI: 44831bd6825cSml err = EINVAL; 44841bd6825cSml break; 44851bd6825cSml } 44861bd6825cSml 44871bd6825cSml reprogram: 44881bd6825cSml if (err == 0) { 44891bd6825cSml if (!nxge_param_link_update(nxgep)) { 44901bd6825cSml err = EINVAL; 44911bd6825cSml } 44921bd6825cSml } 44931bd6825cSml break; 44943fd94f8cSam case MAC_PROP_PRIVATE: 44951bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 44961bd6825cSml "==> nxge_m_setprop: private property")); 44971bd6825cSml err = nxge_set_priv_prop(nxgep, pr_name, pr_valsize, 44981bd6825cSml pr_val); 44991bd6825cSml break; 45004045d941Ssowmini 45014045d941Ssowmini default: 45024045d941Ssowmini err = ENOTSUP; 45034045d941Ssowmini break; 45041bd6825cSml } 45051bd6825cSml 45061bd6825cSml mutex_exit(nxgep->genlock); 45071bd6825cSml 45081bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 45091bd6825cSml "<== nxge_m_setprop (return %d)", err)); 45101bd6825cSml return (err); 45111bd6825cSml } 45121bd6825cSml 45131bd6825cSml static int 45141bd6825cSml nxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 4515afdda45fSVasumathi Sundaram - Sun Microsystems uint_t pr_flags, uint_t pr_valsize, void *pr_val, uint_t *perm) 45161bd6825cSml { 45171bd6825cSml nxge_t *nxgep = barg; 45181bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 45191bd6825cSml p_nxge_stats_t statsp = nxgep->statsp; 45201bd6825cSml int err = 0; 45211bd6825cSml link_flowctrl_t fl; 45221bd6825cSml uint64_t tmp = 0; 45234045d941Ssowmini link_state_t ls; 45243fd94f8cSam boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT); 45251bd6825cSml 45261bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 45271bd6825cSml "==> nxge_m_getprop: pr_num %d", pr_num)); 45284045d941Ssowmini 45294045d941Ssowmini if (pr_valsize == 0) 45304045d941Ssowmini return (EINVAL); 45314045d941Ssowmini 4532afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_RW; 4533afdda45fSVasumathi Sundaram - Sun Microsystems 45343fd94f8cSam if ((is_default) && (pr_num != MAC_PROP_PRIVATE)) { 45354045d941Ssowmini err = nxge_get_def_val(nxgep, pr_num, pr_valsize, pr_val); 45364045d941Ssowmini return (err); 45374045d941Ssowmini } 45384045d941Ssowmini 45391bd6825cSml bzero(pr_val, pr_valsize); 45401bd6825cSml switch (pr_num) { 45413fd94f8cSam case MAC_PROP_DUPLEX: 4542afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 45431bd6825cSml *(uint8_t *)pr_val = statsp->mac_stats.link_duplex; 45441bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 45451bd6825cSml "==> nxge_m_getprop: duplex mode %d", 45461bd6825cSml *(uint8_t *)pr_val)); 45471bd6825cSml break; 45481bd6825cSml 45493fd94f8cSam case MAC_PROP_SPEED: 45501bd6825cSml if (pr_valsize < sizeof (uint64_t)) 45511bd6825cSml return (EINVAL); 4552afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 45531bd6825cSml tmp = statsp->mac_stats.link_speed * 1000000ull; 45541bd6825cSml bcopy(&tmp, pr_val, sizeof (tmp)); 45551bd6825cSml break; 45561bd6825cSml 45573fd94f8cSam case MAC_PROP_STATUS: 45584045d941Ssowmini if (pr_valsize < sizeof (link_state_t)) 45591bd6825cSml return (EINVAL); 4560afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 45614045d941Ssowmini if (!statsp->mac_stats.link_up) 45624045d941Ssowmini ls = LINK_STATE_DOWN; 45634045d941Ssowmini else 45644045d941Ssowmini ls = LINK_STATE_UP; 45654045d941Ssowmini bcopy(&ls, pr_val, sizeof (ls)); 45661bd6825cSml break; 45671bd6825cSml 45683fd94f8cSam case MAC_PROP_AUTONEG: 45691bd6825cSml *(uint8_t *)pr_val = 45701bd6825cSml param_arr[param_autoneg].value; 45711bd6825cSml break; 45721bd6825cSml 45733fd94f8cSam case MAC_PROP_FLOWCTRL: 45741bd6825cSml if (pr_valsize < sizeof (link_flowctrl_t)) 45751bd6825cSml return (EINVAL); 45761bd6825cSml 45771bd6825cSml fl = LINK_FLOWCTRL_NONE; 45781bd6825cSml if (param_arr[param_anar_pause].value) { 45791bd6825cSml fl = LINK_FLOWCTRL_RX; 45801bd6825cSml } 45811bd6825cSml bcopy(&fl, pr_val, sizeof (fl)); 45821bd6825cSml break; 45831bd6825cSml 45843fd94f8cSam case MAC_PROP_ADV_1000FDX_CAP: 4585afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 45861bd6825cSml *(uint8_t *)pr_val = 45871bd6825cSml param_arr[param_anar_1000fdx].value; 45881bd6825cSml break; 45891bd6825cSml 45903fd94f8cSam case MAC_PROP_EN_1000FDX_CAP: 45911bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_1000fdx; 45921bd6825cSml break; 45931bd6825cSml 45943fd94f8cSam case MAC_PROP_ADV_100FDX_CAP: 4595afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 45961bd6825cSml *(uint8_t *)pr_val = 45971bd6825cSml param_arr[param_anar_100fdx].value; 45981bd6825cSml break; 45991bd6825cSml 46003fd94f8cSam case MAC_PROP_EN_100FDX_CAP: 46011bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_100fdx; 46021bd6825cSml break; 46031bd6825cSml 46043fd94f8cSam case MAC_PROP_ADV_10FDX_CAP: 4605afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 46061bd6825cSml *(uint8_t *)pr_val = 46071bd6825cSml param_arr[param_anar_10fdx].value; 46081bd6825cSml break; 46091bd6825cSml 46103fd94f8cSam case MAC_PROP_EN_10FDX_CAP: 46111bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_10fdx; 46121bd6825cSml break; 46131bd6825cSml 46143fd94f8cSam case MAC_PROP_EN_1000HDX_CAP: 46153fd94f8cSam case MAC_PROP_EN_100HDX_CAP: 46163fd94f8cSam case MAC_PROP_EN_10HDX_CAP: 46173fd94f8cSam case MAC_PROP_ADV_1000HDX_CAP: 46183fd94f8cSam case MAC_PROP_ADV_100HDX_CAP: 46193fd94f8cSam case MAC_PROP_ADV_10HDX_CAP: 46204045d941Ssowmini err = ENOTSUP; 46211bd6825cSml break; 46221bd6825cSml 46233fd94f8cSam case MAC_PROP_PRIVATE: 46244045d941Ssowmini err = nxge_get_priv_prop(nxgep, pr_name, pr_flags, 4625afdda45fSVasumathi Sundaram - Sun Microsystems pr_valsize, pr_val, perm); 46264045d941Ssowmini break; 46271bd6825cSml default: 46284045d941Ssowmini err = EINVAL; 46294045d941Ssowmini break; 46301bd6825cSml } 46311bd6825cSml 46321bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_getprop")); 46331bd6825cSml 46341bd6825cSml return (err); 46351bd6825cSml } 46361bd6825cSml 46371bd6825cSml /* ARGSUSED */ 46381bd6825cSml static int 46391bd6825cSml nxge_set_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_valsize, 46401bd6825cSml const void *pr_val) 46411bd6825cSml { 46421bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 46431bd6825cSml int err = 0; 46441bd6825cSml long result; 46451bd6825cSml 46461bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46471bd6825cSml "==> nxge_set_priv_prop: name %s", pr_name)); 46481bd6825cSml 46491bd6825cSml if (strcmp(pr_name, "_accept_jumbo") == 0) { 46501bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 46511bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46521bd6825cSml "<== nxge_set_priv_prop: name %s " 46531bd6825cSml "pr_val %s result %d " 46541bd6825cSml "param %d is_jumbo %d", 46551bd6825cSml pr_name, pr_val, result, 46561bd6825cSml param_arr[param_accept_jumbo].value, 46571bd6825cSml nxgep->mac.is_jumbo)); 46581bd6825cSml 46591bd6825cSml if (result > 1 || result < 0) { 46601bd6825cSml err = EINVAL; 46611bd6825cSml } else { 46621bd6825cSml if (nxgep->mac.is_jumbo == 46631bd6825cSml (uint32_t)result) { 46641bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46651bd6825cSml "no change (%d %d)", 46661bd6825cSml nxgep->mac.is_jumbo, 46671bd6825cSml result)); 46681bd6825cSml return (0); 46691bd6825cSml } 46701bd6825cSml } 46711bd6825cSml 46721bd6825cSml param_arr[param_accept_jumbo].value = result; 46731bd6825cSml nxgep->mac.is_jumbo = B_FALSE; 46741bd6825cSml if (result) { 46751bd6825cSml nxgep->mac.is_jumbo = B_TRUE; 46761bd6825cSml } 46771bd6825cSml 46781bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46791bd6825cSml "<== nxge_set_priv_prop: name %s (value %d) is_jumbo %d", 46801bd6825cSml pr_name, result, nxgep->mac.is_jumbo)); 46811bd6825cSml 46821bd6825cSml return (err); 46831bd6825cSml } 46841bd6825cSml 46851bd6825cSml /* Blanking */ 46861bd6825cSml if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 46871bd6825cSml err = nxge_param_rx_intr_time(nxgep, NULL, NULL, 46881bd6825cSml (char *)pr_val, 46891bd6825cSml (caddr_t)¶m_arr[param_rxdma_intr_time]); 46901bd6825cSml if (err) { 46911bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46921bd6825cSml "<== nxge_set_priv_prop: " 46931bd6825cSml "unable to set (%s)", pr_name)); 46941bd6825cSml err = EINVAL; 46951bd6825cSml } else { 46961bd6825cSml err = 0; 46971bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46981bd6825cSml "<== nxge_set_priv_prop: " 46991bd6825cSml "set (%s)", pr_name)); 47001bd6825cSml } 47011bd6825cSml 47021bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47031bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 47041bd6825cSml pr_name, result)); 47051bd6825cSml 47061bd6825cSml return (err); 47071bd6825cSml } 47081bd6825cSml 47091bd6825cSml if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 47101bd6825cSml err = nxge_param_rx_intr_pkts(nxgep, NULL, NULL, 47111bd6825cSml (char *)pr_val, 47121bd6825cSml (caddr_t)¶m_arr[param_rxdma_intr_pkts]); 47131bd6825cSml if (err) { 47141bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47151bd6825cSml "<== nxge_set_priv_prop: " 47161bd6825cSml "unable to set (%s)", pr_name)); 47171bd6825cSml err = EINVAL; 47181bd6825cSml } else { 47191bd6825cSml err = 0; 47201bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47211bd6825cSml "<== nxge_set_priv_prop: " 47221bd6825cSml "set (%s)", pr_name)); 47231bd6825cSml } 47241bd6825cSml 47251bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47261bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 47271bd6825cSml pr_name, result)); 47281bd6825cSml 47291bd6825cSml return (err); 47301bd6825cSml } 47311bd6825cSml 47321bd6825cSml /* Classification */ 47331bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 47341bd6825cSml if (pr_val == NULL) { 47351bd6825cSml err = EINVAL; 47361bd6825cSml return (err); 47371bd6825cSml } 47381bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 47391bd6825cSml 47401bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 47411bd6825cSml NULL, (char *)pr_val, 47421bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 47431bd6825cSml 47441bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47451bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 47461bd6825cSml pr_name, result)); 47471bd6825cSml 47481bd6825cSml return (err); 47491bd6825cSml } 47501bd6825cSml 47511bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 47521bd6825cSml if (pr_val == NULL) { 47531bd6825cSml err = EINVAL; 47541bd6825cSml return (err); 47551bd6825cSml } 47561bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 47571bd6825cSml 47581bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 47591bd6825cSml NULL, (char *)pr_val, 47601bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 47611bd6825cSml 47621bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47631bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 47641bd6825cSml pr_name, result)); 47651bd6825cSml 47661bd6825cSml return (err); 47671bd6825cSml } 47681bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 47691bd6825cSml if (pr_val == NULL) { 47701bd6825cSml err = EINVAL; 47711bd6825cSml return (err); 47721bd6825cSml } 47731bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 47741bd6825cSml 47751bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 47761bd6825cSml NULL, (char *)pr_val, 47771bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 47781bd6825cSml 47791bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47801bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 47811bd6825cSml pr_name, result)); 47821bd6825cSml 47831bd6825cSml return (err); 47841bd6825cSml } 47851bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 47861bd6825cSml if (pr_val == NULL) { 47871bd6825cSml err = EINVAL; 47881bd6825cSml return (err); 47891bd6825cSml } 47901bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 47911bd6825cSml 47921bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 47931bd6825cSml NULL, (char *)pr_val, 47941bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 47951bd6825cSml 47961bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47971bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 47981bd6825cSml pr_name, result)); 47991bd6825cSml 48001bd6825cSml return (err); 48011bd6825cSml } 48021bd6825cSml 48031bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 48041bd6825cSml if (pr_val == NULL) { 48051bd6825cSml err = EINVAL; 48061bd6825cSml return (err); 48071bd6825cSml } 48081bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 48091bd6825cSml 48101bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 48111bd6825cSml NULL, (char *)pr_val, 48121bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 48131bd6825cSml 48141bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48151bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 48161bd6825cSml pr_name, result)); 48171bd6825cSml 48181bd6825cSml return (err); 48191bd6825cSml } 48201bd6825cSml 48211bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 48221bd6825cSml if (pr_val == NULL) { 48231bd6825cSml err = EINVAL; 48241bd6825cSml return (err); 48251bd6825cSml } 48261bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 48271bd6825cSml 48281bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 48291bd6825cSml NULL, (char *)pr_val, 48301bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 48311bd6825cSml 48321bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48331bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 48341bd6825cSml pr_name, result)); 48351bd6825cSml 48361bd6825cSml return (err); 48371bd6825cSml } 48381bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 48391bd6825cSml if (pr_val == NULL) { 48401bd6825cSml err = EINVAL; 48411bd6825cSml return (err); 48421bd6825cSml } 48431bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 48441bd6825cSml 48451bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 48461bd6825cSml NULL, (char *)pr_val, 48471bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 48481bd6825cSml 48491bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48501bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 48511bd6825cSml pr_name, result)); 48521bd6825cSml 48531bd6825cSml return (err); 48541bd6825cSml } 48551bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 48561bd6825cSml if (pr_val == NULL) { 48571bd6825cSml err = EINVAL; 48581bd6825cSml return (err); 48591bd6825cSml } 48601bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 48611bd6825cSml 48621bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 48631bd6825cSml NULL, (char *)pr_val, 48641bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 48651bd6825cSml 48661bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48671bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 48681bd6825cSml pr_name, result)); 48691bd6825cSml 48701bd6825cSml return (err); 48711bd6825cSml } 48721bd6825cSml 48731bd6825cSml if (strcmp(pr_name, "_soft_lso_enable") == 0) { 48741bd6825cSml if (pr_val == NULL) { 48751bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48761bd6825cSml "==> nxge_set_priv_prop: name %s (null)", pr_name)); 48771bd6825cSml err = EINVAL; 48781bd6825cSml return (err); 48791bd6825cSml } 48801bd6825cSml 48811bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 48821bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48831bd6825cSml "<== nxge_set_priv_prop: name %s " 48841bd6825cSml "(lso %d pr_val %s value %d)", 48851bd6825cSml pr_name, nxgep->soft_lso_enable, pr_val, result)); 48861bd6825cSml 48871bd6825cSml if (result > 1 || result < 0) { 48881bd6825cSml err = EINVAL; 48891bd6825cSml } else { 48901bd6825cSml if (nxgep->soft_lso_enable == (uint32_t)result) { 48911bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48921bd6825cSml "no change (%d %d)", 48931bd6825cSml nxgep->soft_lso_enable, result)); 48941bd6825cSml return (0); 48951bd6825cSml } 48961bd6825cSml } 48971bd6825cSml 48981bd6825cSml nxgep->soft_lso_enable = (int)result; 48991bd6825cSml 49001bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49011bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 49021bd6825cSml pr_name, result)); 49031bd6825cSml 49041bd6825cSml return (err); 49051bd6825cSml } 490600161856Syc /* 490700161856Syc * Commands like "ndd -set /dev/nxge0 adv_10gfdx_cap 1" cause the 490800161856Syc * following code to be executed. 490900161856Syc */ 49104045d941Ssowmini if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) { 49114045d941Ssowmini err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val, 49124045d941Ssowmini (caddr_t)¶m_arr[param_anar_10gfdx]); 49134045d941Ssowmini return (err); 49144045d941Ssowmini } 49154045d941Ssowmini if (strcmp(pr_name, "_adv_pause_cap") == 0) { 49164045d941Ssowmini err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val, 49174045d941Ssowmini (caddr_t)¶m_arr[param_anar_pause]); 49184045d941Ssowmini return (err); 49194045d941Ssowmini } 49201bd6825cSml 49211bd6825cSml return (EINVAL); 49221bd6825cSml } 49231bd6825cSml 49241bd6825cSml static int 49254045d941Ssowmini nxge_get_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_flags, 4926afdda45fSVasumathi Sundaram - Sun Microsystems uint_t pr_valsize, void *pr_val, uint_t *perm) 49271bd6825cSml { 49281bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 49291bd6825cSml char valstr[MAXNAMELEN]; 49301bd6825cSml int err = EINVAL; 49311bd6825cSml uint_t strsize; 49323fd94f8cSam boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT); 49331bd6825cSml 49341bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49351bd6825cSml "==> nxge_get_priv_prop: property %s", pr_name)); 49361bd6825cSml 49371bd6825cSml /* function number */ 49381bd6825cSml if (strcmp(pr_name, "_function_number") == 0) { 49394045d941Ssowmini if (is_default) 49404045d941Ssowmini return (ENOTSUP); 4941afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 49424045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 49434045d941Ssowmini nxgep->function_num); 49441bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49451bd6825cSml "==> nxge_get_priv_prop: name %s " 49461bd6825cSml "(value %d valstr %s)", 49471bd6825cSml pr_name, nxgep->function_num, valstr)); 49481bd6825cSml 49491bd6825cSml err = 0; 49501bd6825cSml goto done; 49511bd6825cSml } 49521bd6825cSml 49531bd6825cSml /* Neptune firmware version */ 49541bd6825cSml if (strcmp(pr_name, "_fw_version") == 0) { 49554045d941Ssowmini if (is_default) 49564045d941Ssowmini return (ENOTSUP); 4957afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 49584045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%s", 49594045d941Ssowmini nxgep->vpd_info.ver); 49601bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49611bd6825cSml "==> nxge_get_priv_prop: name %s " 49621bd6825cSml "(value %d valstr %s)", 49631bd6825cSml pr_name, nxgep->vpd_info.ver, valstr)); 49641bd6825cSml 49651bd6825cSml err = 0; 49661bd6825cSml goto done; 49671bd6825cSml } 49681bd6825cSml 49691bd6825cSml /* port PHY mode */ 49701bd6825cSml if (strcmp(pr_name, "_port_mode") == 0) { 49714045d941Ssowmini if (is_default) 49724045d941Ssowmini return (ENOTSUP); 4973afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 49741bd6825cSml switch (nxgep->mac.portmode) { 49751bd6825cSml case PORT_1G_COPPER: 49764045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G copper %s", 49771bd6825cSml nxgep->hot_swappable_phy ? 49781bd6825cSml "[Hot Swappable]" : ""); 49791bd6825cSml break; 49801bd6825cSml case PORT_1G_FIBER: 49814045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G fiber %s", 49821bd6825cSml nxgep->hot_swappable_phy ? 49831bd6825cSml "[hot swappable]" : ""); 49841bd6825cSml break; 49851bd6825cSml case PORT_10G_COPPER: 49864045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 49874045d941Ssowmini "10G copper %s", 49881bd6825cSml nxgep->hot_swappable_phy ? 49891bd6825cSml "[hot swappable]" : ""); 49901bd6825cSml break; 49911bd6825cSml case PORT_10G_FIBER: 49924045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "10G fiber %s", 49931bd6825cSml nxgep->hot_swappable_phy ? 49941bd6825cSml "[hot swappable]" : ""); 49951bd6825cSml break; 49961bd6825cSml case PORT_10G_SERDES: 49974045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 49984045d941Ssowmini "10G serdes %s", nxgep->hot_swappable_phy ? 49991bd6825cSml "[hot swappable]" : ""); 50001bd6825cSml break; 50011bd6825cSml case PORT_1G_SERDES: 50024045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G serdes %s", 50031bd6825cSml nxgep->hot_swappable_phy ? 50041bd6825cSml "[hot swappable]" : ""); 50051bd6825cSml break; 500600161856Syc case PORT_1G_TN1010: 500700161856Syc (void) snprintf(valstr, sizeof (valstr), 500800161856Syc "1G TN1010 copper %s", nxgep->hot_swappable_phy ? 500900161856Syc "[hot swappable]" : ""); 501000161856Syc break; 501100161856Syc case PORT_10G_TN1010: 501200161856Syc (void) snprintf(valstr, sizeof (valstr), 501300161856Syc "10G TN1010 copper %s", nxgep->hot_swappable_phy ? 501400161856Syc "[hot swappable]" : ""); 501500161856Syc break; 50161bd6825cSml case PORT_1G_RGMII_FIBER: 50174045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 50184045d941Ssowmini "1G rgmii fiber %s", nxgep->hot_swappable_phy ? 50191bd6825cSml "[hot swappable]" : ""); 50201bd6825cSml break; 50211bd6825cSml case PORT_HSP_MODE: 50224045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 5023c2d37b8bSml "phy not present[hot swappable]"); 50241bd6825cSml break; 50251bd6825cSml default: 50264045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "unknown %s", 50271bd6825cSml nxgep->hot_swappable_phy ? 50281bd6825cSml "[hot swappable]" : ""); 50291bd6825cSml break; 50301bd6825cSml } 50311bd6825cSml 50321bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50331bd6825cSml "==> nxge_get_priv_prop: name %s (value %s)", 50341bd6825cSml pr_name, valstr)); 50351bd6825cSml 50361bd6825cSml err = 0; 50371bd6825cSml goto done; 50381bd6825cSml } 50391bd6825cSml 50401bd6825cSml /* Hot swappable PHY */ 50411bd6825cSml if (strcmp(pr_name, "_hot_swap_phy") == 0) { 50424045d941Ssowmini if (is_default) 50434045d941Ssowmini return (ENOTSUP); 5044afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 50454045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%s", 50461bd6825cSml nxgep->hot_swappable_phy ? 50471bd6825cSml "yes" : "no"); 50481bd6825cSml 50491bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50501bd6825cSml "==> nxge_get_priv_prop: name %s " 50511bd6825cSml "(value %d valstr %s)", 50521bd6825cSml pr_name, nxgep->hot_swappable_phy, valstr)); 50531bd6825cSml 50541bd6825cSml err = 0; 50551bd6825cSml goto done; 50561bd6825cSml } 50571bd6825cSml 50581bd6825cSml 50591bd6825cSml /* accept jumbo */ 50601bd6825cSml if (strcmp(pr_name, "_accept_jumbo") == 0) { 50614045d941Ssowmini if (is_default) 50624045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 50634045d941Ssowmini else 50644045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 50654045d941Ssowmini "%d", nxgep->mac.is_jumbo); 50661bd6825cSml err = 0; 50671bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50681bd6825cSml "==> nxge_get_priv_prop: name %s (value %d (%d, %d))", 50691bd6825cSml pr_name, 50701bd6825cSml (uint32_t)param_arr[param_accept_jumbo].value, 50711bd6825cSml nxgep->mac.is_jumbo, 50721bd6825cSml nxge_jumbo_enable)); 50731bd6825cSml 50741bd6825cSml goto done; 50751bd6825cSml } 50761bd6825cSml 50771bd6825cSml /* Receive Interrupt Blanking Parameters */ 50781bd6825cSml if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 50794045d941Ssowmini err = 0; 50804045d941Ssowmini if (is_default) { 50814045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 50824045d941Ssowmini "%d", RXDMA_RCR_TO_DEFAULT); 50834045d941Ssowmini goto done; 50844045d941Ssowmini } 50854045d941Ssowmini 50864045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 50874045d941Ssowmini nxgep->intr_timeout); 50881bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50891bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 50901bd6825cSml pr_name, 50911bd6825cSml (uint32_t)nxgep->intr_timeout)); 50921bd6825cSml goto done; 50931bd6825cSml } 50941bd6825cSml 50951bd6825cSml if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 50964045d941Ssowmini err = 0; 50974045d941Ssowmini if (is_default) { 50984045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 50994045d941Ssowmini "%d", RXDMA_RCR_PTHRES_DEFAULT); 51004045d941Ssowmini goto done; 51014045d941Ssowmini } 51024045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 51034045d941Ssowmini nxgep->intr_threshold); 51041bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51051bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 51061bd6825cSml pr_name, (uint32_t)nxgep->intr_threshold)); 51071bd6825cSml 51081bd6825cSml goto done; 51091bd6825cSml } 51101bd6825cSml 51111bd6825cSml /* Classification and Load Distribution Configuration */ 51121bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 51134045d941Ssowmini if (is_default) { 51144045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 51154045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 51164045d941Ssowmini err = 0; 51174045d941Ssowmini goto done; 51184045d941Ssowmini } 51191bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 51201bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 51211bd6825cSml 51224045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 51231bd6825cSml (int)param_arr[param_class_opt_ipv4_tcp].value); 51241bd6825cSml 51251bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51261bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 51271bd6825cSml goto done; 51281bd6825cSml } 51291bd6825cSml 51301bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 51314045d941Ssowmini if (is_default) { 51324045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 51334045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 51344045d941Ssowmini err = 0; 51354045d941Ssowmini goto done; 51364045d941Ssowmini } 51371bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 51381bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 51391bd6825cSml 51404045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 51411bd6825cSml (int)param_arr[param_class_opt_ipv4_udp].value); 51421bd6825cSml 51431bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51441bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 51451bd6825cSml goto done; 51461bd6825cSml } 51471bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 51484045d941Ssowmini if (is_default) { 51494045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 51504045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 51514045d941Ssowmini err = 0; 51524045d941Ssowmini goto done; 51534045d941Ssowmini } 51541bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 51551bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 51561bd6825cSml 51574045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 51581bd6825cSml (int)param_arr[param_class_opt_ipv4_ah].value); 51591bd6825cSml 51601bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51611bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 51621bd6825cSml goto done; 51631bd6825cSml } 51641bd6825cSml 51651bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 51664045d941Ssowmini if (is_default) { 51674045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 51684045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 51694045d941Ssowmini err = 0; 51704045d941Ssowmini goto done; 51714045d941Ssowmini } 51721bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 51731bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 51741bd6825cSml 51754045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 51761bd6825cSml (int)param_arr[param_class_opt_ipv4_sctp].value); 51771bd6825cSml 51781bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51791bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 51801bd6825cSml goto done; 51811bd6825cSml } 51821bd6825cSml 51831bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 51844045d941Ssowmini if (is_default) { 51854045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 51864045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 51874045d941Ssowmini err = 0; 51884045d941Ssowmini goto done; 51894045d941Ssowmini } 51901bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 51911bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 51921bd6825cSml 51934045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 51941bd6825cSml (int)param_arr[param_class_opt_ipv6_tcp].value); 51951bd6825cSml 51961bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51971bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 51981bd6825cSml goto done; 51991bd6825cSml } 52001bd6825cSml 52011bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 52024045d941Ssowmini if (is_default) { 52034045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52044045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 52054045d941Ssowmini err = 0; 52064045d941Ssowmini goto done; 52074045d941Ssowmini } 52081bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 52091bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 52101bd6825cSml 52114045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52121bd6825cSml (int)param_arr[param_class_opt_ipv6_udp].value); 52131bd6825cSml 52141bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52151bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 52161bd6825cSml goto done; 52171bd6825cSml } 52181bd6825cSml 52191bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 52204045d941Ssowmini if (is_default) { 52214045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52224045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 52234045d941Ssowmini err = 0; 52244045d941Ssowmini goto done; 52254045d941Ssowmini } 52261bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 52271bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 52281bd6825cSml 52294045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52301bd6825cSml (int)param_arr[param_class_opt_ipv6_ah].value); 52311bd6825cSml 52321bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52331bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 52341bd6825cSml goto done; 52351bd6825cSml } 52361bd6825cSml 52371bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 52384045d941Ssowmini if (is_default) { 52394045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52404045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 52414045d941Ssowmini err = 0; 52424045d941Ssowmini goto done; 52434045d941Ssowmini } 52441bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 52451bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 52461bd6825cSml 52474045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52481bd6825cSml (int)param_arr[param_class_opt_ipv6_sctp].value); 52491bd6825cSml 52501bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52511bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 52521bd6825cSml goto done; 52531bd6825cSml } 52541bd6825cSml 52551bd6825cSml /* Software LSO */ 52561bd6825cSml if (strcmp(pr_name, "_soft_lso_enable") == 0) { 52574045d941Ssowmini if (is_default) { 52584045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 52594045d941Ssowmini err = 0; 52604045d941Ssowmini goto done; 52614045d941Ssowmini } 52624045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 52634045d941Ssowmini "%d", nxgep->soft_lso_enable); 52641bd6825cSml err = 0; 52651bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52661bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 52671bd6825cSml pr_name, nxgep->soft_lso_enable)); 52681bd6825cSml 52691bd6825cSml goto done; 52701bd6825cSml } 52714045d941Ssowmini if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) { 52724045d941Ssowmini err = 0; 52734045d941Ssowmini if (is_default || 52744045d941Ssowmini nxgep->param_arr[param_anar_10gfdx].value != 0) { 52754045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 1); 52764045d941Ssowmini goto done; 52774045d941Ssowmini } else { 52784045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 52794045d941Ssowmini goto done; 52804045d941Ssowmini } 52814045d941Ssowmini } 52824045d941Ssowmini if (strcmp(pr_name, "_adv_pause_cap") == 0) { 52834045d941Ssowmini err = 0; 52844045d941Ssowmini if (is_default || 52854045d941Ssowmini nxgep->param_arr[param_anar_pause].value != 0) { 52864045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 1); 52874045d941Ssowmini goto done; 52884045d941Ssowmini } else { 52894045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 52904045d941Ssowmini goto done; 52914045d941Ssowmini } 52924045d941Ssowmini } 52931bd6825cSml 52941bd6825cSml done: 52951bd6825cSml if (err == 0) { 52961bd6825cSml strsize = (uint_t)strlen(valstr); 52971bd6825cSml if (pr_valsize < strsize) { 52981bd6825cSml err = ENOBUFS; 52991bd6825cSml } else { 53001bd6825cSml (void) strlcpy(pr_val, valstr, pr_valsize); 53011bd6825cSml } 53021bd6825cSml } 53031bd6825cSml 53041bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53051bd6825cSml "<== nxge_get_priv_prop: return %d", err)); 53061bd6825cSml return (err); 53071bd6825cSml } 53081bd6825cSml 530944961713Sgirish /* 531044961713Sgirish * Module loading and removing entry points. 531144961713Sgirish */ 531244961713Sgirish 53136f157acbSml DDI_DEFINE_STREAM_OPS(nxge_dev_ops, nulldev, nulldev, nxge_attach, nxge_detach, 531419397407SSherry Moore nodev, NULL, D_MP, NULL, nxge_quiesce); 531544961713Sgirish 53162e59129aSraghus #define NXGE_DESC_VER "Sun NIU 10Gb Ethernet" 531744961713Sgirish 531844961713Sgirish /* 531944961713Sgirish * Module linkage information for the kernel. 532044961713Sgirish */ 532144961713Sgirish static struct modldrv nxge_modldrv = { 532244961713Sgirish &mod_driverops, 532344961713Sgirish NXGE_DESC_VER, 532444961713Sgirish &nxge_dev_ops 532544961713Sgirish }; 532644961713Sgirish 532744961713Sgirish static struct modlinkage modlinkage = { 532844961713Sgirish MODREV_1, (void *) &nxge_modldrv, NULL 532944961713Sgirish }; 533044961713Sgirish 533144961713Sgirish int 533244961713Sgirish _init(void) 533344961713Sgirish { 533444961713Sgirish int status; 533544961713Sgirish 533644961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init")); 533744961713Sgirish mac_init_ops(&nxge_dev_ops, "nxge"); 533844961713Sgirish status = ddi_soft_state_init(&nxge_list, sizeof (nxge_t), 0); 533944961713Sgirish if (status != 0) { 534044961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, 53414045d941Ssowmini "failed to init device soft state")); 534244961713Sgirish goto _init_exit; 534344961713Sgirish } 534444961713Sgirish status = mod_install(&modlinkage); 534544961713Sgirish if (status != 0) { 534644961713Sgirish ddi_soft_state_fini(&nxge_list); 534744961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, "Mod install failed")); 534844961713Sgirish goto _init_exit; 534944961713Sgirish } 535044961713Sgirish 535144961713Sgirish MUTEX_INIT(&nxge_common_lock, NULL, MUTEX_DRIVER, NULL); 535244961713Sgirish 535344961713Sgirish _init_exit: 535444961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "_init status = 0x%X", status)); 535544961713Sgirish 535644961713Sgirish return (status); 535744961713Sgirish } 535844961713Sgirish 535944961713Sgirish int 536044961713Sgirish _fini(void) 536144961713Sgirish { 536244961713Sgirish int status; 536344961713Sgirish 536444961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini")); 536544961713Sgirish 536644961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove")); 5367a3c5bd6dSspeer 5368a3c5bd6dSspeer if (nxge_mblks_pending) 5369a3c5bd6dSspeer return (EBUSY); 5370a3c5bd6dSspeer 537144961713Sgirish status = mod_remove(&modlinkage); 537244961713Sgirish if (status != DDI_SUCCESS) { 537344961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, 53744045d941Ssowmini "Module removal failed 0x%08x", 53754045d941Ssowmini status)); 537644961713Sgirish goto _fini_exit; 537744961713Sgirish } 537844961713Sgirish 537944961713Sgirish mac_fini_ops(&nxge_dev_ops); 538044961713Sgirish 538144961713Sgirish ddi_soft_state_fini(&nxge_list); 538244961713Sgirish 538344961713Sgirish MUTEX_DESTROY(&nxge_common_lock); 538444961713Sgirish _fini_exit: 538544961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "_fini status = 0x%08x", status)); 538644961713Sgirish 538744961713Sgirish return (status); 538844961713Sgirish } 538944961713Sgirish 539044961713Sgirish int 539144961713Sgirish _info(struct modinfo *modinfop) 539244961713Sgirish { 539344961713Sgirish int status; 539444961713Sgirish 539544961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info")); 539644961713Sgirish status = mod_info(&modlinkage, modinfop); 539744961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status)); 539844961713Sgirish 539944961713Sgirish return (status); 540044961713Sgirish } 540144961713Sgirish 5402*da14cebeSEric Cheng /*ARGSUSED*/ 5403*da14cebeSEric Cheng static int 5404*da14cebeSEric Cheng nxge_tx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num) 5405*da14cebeSEric Cheng { 5406*da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5407*da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5408*da14cebeSEric Cheng uint32_t channel; 5409*da14cebeSEric Cheng p_tx_ring_t ring; 5410*da14cebeSEric Cheng 5411*da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.tdc.start + rhp->index; 5412*da14cebeSEric Cheng ring = nxgep->tx_rings->rings[channel]; 5413*da14cebeSEric Cheng 5414*da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 5415*da14cebeSEric Cheng ring->tx_ring_handle = rhp->ring_handle; 5416*da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5417*da14cebeSEric Cheng 5418*da14cebeSEric Cheng return (0); 5419*da14cebeSEric Cheng } 5420*da14cebeSEric Cheng 5421*da14cebeSEric Cheng static void 5422*da14cebeSEric Cheng nxge_tx_ring_stop(mac_ring_driver_t rdriver) 5423*da14cebeSEric Cheng { 5424*da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5425*da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5426*da14cebeSEric Cheng uint32_t channel; 5427*da14cebeSEric Cheng p_tx_ring_t ring; 5428*da14cebeSEric Cheng 5429*da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.tdc.start + rhp->index; 5430*da14cebeSEric Cheng ring = nxgep->tx_rings->rings[channel]; 5431*da14cebeSEric Cheng 5432*da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 5433*da14cebeSEric Cheng ring->tx_ring_handle = (mac_ring_handle_t)NULL; 5434*da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5435*da14cebeSEric Cheng } 5436*da14cebeSEric Cheng 5437*da14cebeSEric Cheng static int 5438*da14cebeSEric Cheng nxge_rx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num) 5439*da14cebeSEric Cheng { 5440*da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5441*da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5442*da14cebeSEric Cheng uint32_t channel; 5443*da14cebeSEric Cheng p_rx_rcr_ring_t ring; 5444*da14cebeSEric Cheng int i; 5445*da14cebeSEric Cheng 5446*da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.start_rdc + rhp->index; 5447*da14cebeSEric Cheng ring = nxgep->rx_rcr_rings->rcr_rings[channel]; 5448*da14cebeSEric Cheng 5449*da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 5450*da14cebeSEric Cheng 5451*da14cebeSEric Cheng if (nxgep->rx_channel_started[channel] == B_TRUE) { 5452*da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5453*da14cebeSEric Cheng return (0); 5454*da14cebeSEric Cheng } 5455*da14cebeSEric Cheng 5456*da14cebeSEric Cheng /* set rcr_ring */ 5457*da14cebeSEric Cheng for (i = 0; i < nxgep->ldgvp->maxldvs; i++) { 5458*da14cebeSEric Cheng if ((nxgep->ldgvp->ldvp[i].is_rxdma == 1) && 5459*da14cebeSEric Cheng (nxgep->ldgvp->ldvp[i].channel == channel)) { 5460*da14cebeSEric Cheng ring->ldvp = &nxgep->ldgvp->ldvp[i]; 5461*da14cebeSEric Cheng ring->ldgp = nxgep->ldgvp->ldvp[i].ldgp; 5462*da14cebeSEric Cheng } 5463*da14cebeSEric Cheng } 5464*da14cebeSEric Cheng 5465*da14cebeSEric Cheng nxgep->rx_channel_started[channel] = B_TRUE; 5466*da14cebeSEric Cheng ring->rcr_mac_handle = rhp->ring_handle; 5467*da14cebeSEric Cheng ring->rcr_gen_num = mr_gen_num; 5468*da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5469*da14cebeSEric Cheng 5470*da14cebeSEric Cheng return (0); 5471*da14cebeSEric Cheng } 5472*da14cebeSEric Cheng 5473*da14cebeSEric Cheng static void 5474*da14cebeSEric Cheng nxge_rx_ring_stop(mac_ring_driver_t rdriver) 5475*da14cebeSEric Cheng { 5476*da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5477*da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5478*da14cebeSEric Cheng uint32_t channel; 5479*da14cebeSEric Cheng p_rx_rcr_ring_t ring; 5480*da14cebeSEric Cheng 5481*da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.start_rdc + rhp->index; 5482*da14cebeSEric Cheng ring = nxgep->rx_rcr_rings->rcr_rings[channel]; 5483*da14cebeSEric Cheng 5484*da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 5485*da14cebeSEric Cheng nxgep->rx_channel_started[channel] = B_FALSE; 5486*da14cebeSEric Cheng ring->rcr_mac_handle = NULL; 5487*da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5488*da14cebeSEric Cheng } 5489*da14cebeSEric Cheng 5490*da14cebeSEric Cheng /* 5491*da14cebeSEric Cheng * Callback funtion for MAC layer to register all rings. 5492*da14cebeSEric Cheng */ 5493*da14cebeSEric Cheng static void 5494*da14cebeSEric Cheng nxge_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index, 5495*da14cebeSEric Cheng const int index, mac_ring_info_t *infop, mac_ring_handle_t rh) 5496*da14cebeSEric Cheng { 5497*da14cebeSEric Cheng p_nxge_t nxgep = (p_nxge_t)arg; 5498*da14cebeSEric Cheng p_nxge_hw_pt_cfg_t p_cfgp = &nxgep->pt_config.hw_config; 5499*da14cebeSEric Cheng 5500*da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, TX_CTL, 5501*da14cebeSEric Cheng "==> nxge_fill_ring 0x%x index %d", rtype, index)); 5502*da14cebeSEric Cheng 5503*da14cebeSEric Cheng switch (rtype) { 5504*da14cebeSEric Cheng case MAC_RING_TYPE_TX: { 5505*da14cebeSEric Cheng p_nxge_ring_handle_t rhandlep; 5506*da14cebeSEric Cheng 5507*da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, TX_CTL, 5508*da14cebeSEric Cheng "==> nxge_fill_ring (TX) 0x%x index %d ntdcs %d", 5509*da14cebeSEric Cheng rtype, index, p_cfgp->tdc.count)); 5510*da14cebeSEric Cheng 5511*da14cebeSEric Cheng ASSERT((index >= 0) && (index < p_cfgp->tdc.count)); 5512*da14cebeSEric Cheng rhandlep = &nxgep->tx_ring_handles[index]; 5513*da14cebeSEric Cheng rhandlep->nxgep = nxgep; 5514*da14cebeSEric Cheng rhandlep->index = index; 5515*da14cebeSEric Cheng rhandlep->ring_handle = rh; 5516*da14cebeSEric Cheng 5517*da14cebeSEric Cheng infop->mri_driver = (mac_ring_driver_t)rhandlep; 5518*da14cebeSEric Cheng infop->mri_start = nxge_tx_ring_start; 5519*da14cebeSEric Cheng infop->mri_stop = nxge_tx_ring_stop; 5520*da14cebeSEric Cheng infop->mri_tx = nxge_tx_ring_send; 5521*da14cebeSEric Cheng 5522*da14cebeSEric Cheng break; 5523*da14cebeSEric Cheng } 5524*da14cebeSEric Cheng case MAC_RING_TYPE_RX: { 5525*da14cebeSEric Cheng p_nxge_ring_handle_t rhandlep; 5526*da14cebeSEric Cheng int nxge_rindex; 5527*da14cebeSEric Cheng mac_intr_t nxge_mac_intr; 5528*da14cebeSEric Cheng 5529*da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, RX_CTL, 5530*da14cebeSEric Cheng "==> nxge_fill_ring (RX) 0x%x index %d nrdcs %d", 5531*da14cebeSEric Cheng rtype, index, p_cfgp->max_rdcs)); 5532*da14cebeSEric Cheng 5533*da14cebeSEric Cheng /* 5534*da14cebeSEric Cheng * 'index' is the ring index within the group. 5535*da14cebeSEric Cheng * Find the ring index in the nxge instance. 5536*da14cebeSEric Cheng */ 5537*da14cebeSEric Cheng nxge_rindex = nxge_get_rxring_index(nxgep, rg_index, index); 5538*da14cebeSEric Cheng 5539*da14cebeSEric Cheng ASSERT((nxge_rindex >= 0) && (nxge_rindex < p_cfgp->max_rdcs)); 5540*da14cebeSEric Cheng rhandlep = &nxgep->rx_ring_handles[nxge_rindex]; 5541*da14cebeSEric Cheng rhandlep->nxgep = nxgep; 5542*da14cebeSEric Cheng rhandlep->index = nxge_rindex; 5543*da14cebeSEric Cheng rhandlep->ring_handle = rh; 5544*da14cebeSEric Cheng 5545*da14cebeSEric Cheng /* 5546*da14cebeSEric Cheng * Entrypoint to enable interrupt (disable poll) and 5547*da14cebeSEric Cheng * disable interrupt (enable poll). 5548*da14cebeSEric Cheng */ 5549*da14cebeSEric Cheng nxge_mac_intr.mi_handle = (mac_intr_handle_t)rhandlep; 5550*da14cebeSEric Cheng nxge_mac_intr.mi_enable = (mac_intr_enable_t)nxge_disable_poll; 5551*da14cebeSEric Cheng nxge_mac_intr.mi_disable = (mac_intr_disable_t)nxge_enable_poll; 5552*da14cebeSEric Cheng infop->mri_driver = (mac_ring_driver_t)rhandlep; 5553*da14cebeSEric Cheng infop->mri_start = nxge_rx_ring_start; 5554*da14cebeSEric Cheng infop->mri_stop = nxge_rx_ring_stop; 5555*da14cebeSEric Cheng infop->mri_intr = nxge_mac_intr; /* ??? */ 5556*da14cebeSEric Cheng infop->mri_poll = nxge_rx_poll; 5557*da14cebeSEric Cheng 5558*da14cebeSEric Cheng break; 5559*da14cebeSEric Cheng } 5560*da14cebeSEric Cheng default: 5561*da14cebeSEric Cheng break; 5562*da14cebeSEric Cheng } 5563*da14cebeSEric Cheng 5564*da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_fill_ring 0x%x", 5565*da14cebeSEric Cheng rtype)); 5566*da14cebeSEric Cheng } 5567*da14cebeSEric Cheng 5568*da14cebeSEric Cheng static void 5569*da14cebeSEric Cheng nxge_group_add_ring(mac_group_driver_t gh, mac_ring_driver_t rh, 5570*da14cebeSEric Cheng mac_ring_type_t type) 5571*da14cebeSEric Cheng { 5572*da14cebeSEric Cheng nxge_ring_group_t *rgroup = (nxge_ring_group_t *)gh; 5573*da14cebeSEric Cheng nxge_ring_handle_t *rhandle = (nxge_ring_handle_t *)rh; 5574*da14cebeSEric Cheng nxge_t *nxge; 5575*da14cebeSEric Cheng nxge_grp_t *grp; 5576*da14cebeSEric Cheng nxge_rdc_grp_t *rdc_grp; 5577*da14cebeSEric Cheng uint16_t channel; /* device-wise ring id */ 5578*da14cebeSEric Cheng int dev_gindex; 5579*da14cebeSEric Cheng int rv; 5580*da14cebeSEric Cheng 5581*da14cebeSEric Cheng nxge = rgroup->nxgep; 5582*da14cebeSEric Cheng 5583*da14cebeSEric Cheng switch (type) { 5584*da14cebeSEric Cheng case MAC_RING_TYPE_TX: 5585*da14cebeSEric Cheng /* 5586*da14cebeSEric Cheng * nxge_grp_dc_add takes a channel number which is a 5587*da14cebeSEric Cheng * "devise" ring ID. 5588*da14cebeSEric Cheng */ 5589*da14cebeSEric Cheng channel = nxge->pt_config.hw_config.tdc.start + rhandle->index; 5590*da14cebeSEric Cheng 5591*da14cebeSEric Cheng /* 5592*da14cebeSEric Cheng * Remove the ring from the default group 5593*da14cebeSEric Cheng */ 5594*da14cebeSEric Cheng if (rgroup->gindex != 0) { 5595*da14cebeSEric Cheng (void) nxge_grp_dc_remove(nxge, VP_BOUND_TX, channel); 5596*da14cebeSEric Cheng } 5597*da14cebeSEric Cheng 5598*da14cebeSEric Cheng /* 5599*da14cebeSEric Cheng * nxge->tx_set.group[] is an array of groups indexed by 5600*da14cebeSEric Cheng * a "port" group ID. 5601*da14cebeSEric Cheng */ 5602*da14cebeSEric Cheng grp = nxge->tx_set.group[rgroup->gindex]; 5603*da14cebeSEric Cheng rv = nxge_grp_dc_add(nxge, grp, VP_BOUND_TX, channel); 5604*da14cebeSEric Cheng if (rv != 0) { 5605*da14cebeSEric Cheng NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 5606*da14cebeSEric Cheng "nxge_group_add_ring: nxge_grp_dc_add failed")); 5607*da14cebeSEric Cheng } 5608*da14cebeSEric Cheng break; 5609*da14cebeSEric Cheng 5610*da14cebeSEric Cheng case MAC_RING_TYPE_RX: 5611*da14cebeSEric Cheng /* 5612*da14cebeSEric Cheng * nxge->rx_set.group[] is an array of groups indexed by 5613*da14cebeSEric Cheng * a "port" group ID. 5614*da14cebeSEric Cheng */ 5615*da14cebeSEric Cheng grp = nxge->rx_set.group[rgroup->gindex]; 5616*da14cebeSEric Cheng 5617*da14cebeSEric Cheng dev_gindex = nxge->pt_config.hw_config.def_mac_rxdma_grpid + 5618*da14cebeSEric Cheng rgroup->gindex; 5619*da14cebeSEric Cheng rdc_grp = &nxge->pt_config.rdc_grps[dev_gindex]; 5620*da14cebeSEric Cheng 5621*da14cebeSEric Cheng /* 5622*da14cebeSEric Cheng * nxge_grp_dc_add takes a channel number which is a 5623*da14cebeSEric Cheng * "devise" ring ID. 5624*da14cebeSEric Cheng */ 5625*da14cebeSEric Cheng channel = nxge->pt_config.hw_config.start_rdc + rhandle->index; 5626*da14cebeSEric Cheng rv = nxge_grp_dc_add(nxge, grp, VP_BOUND_RX, channel); 5627*da14cebeSEric Cheng if (rv != 0) { 5628*da14cebeSEric Cheng NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 5629*da14cebeSEric Cheng "nxge_group_add_ring: nxge_grp_dc_add failed")); 5630*da14cebeSEric Cheng } 5631*da14cebeSEric Cheng 5632*da14cebeSEric Cheng rdc_grp->map |= (1 << channel); 5633*da14cebeSEric Cheng rdc_grp->max_rdcs++; 5634*da14cebeSEric Cheng 5635*da14cebeSEric Cheng (void) nxge_init_fzc_rdc_tbl(nxge, rgroup->rdctbl); 5636*da14cebeSEric Cheng break; 5637*da14cebeSEric Cheng } 5638*da14cebeSEric Cheng } 5639*da14cebeSEric Cheng 5640*da14cebeSEric Cheng static void 5641*da14cebeSEric Cheng nxge_group_rem_ring(mac_group_driver_t gh, mac_ring_driver_t rh, 5642*da14cebeSEric Cheng mac_ring_type_t type) 5643*da14cebeSEric Cheng { 5644*da14cebeSEric Cheng nxge_ring_group_t *rgroup = (nxge_ring_group_t *)gh; 5645*da14cebeSEric Cheng nxge_ring_handle_t *rhandle = (nxge_ring_handle_t *)rh; 5646*da14cebeSEric Cheng nxge_t *nxge; 5647*da14cebeSEric Cheng uint16_t channel; /* device-wise ring id */ 5648*da14cebeSEric Cheng nxge_rdc_grp_t *rdc_grp; 5649*da14cebeSEric Cheng int dev_gindex; 5650*da14cebeSEric Cheng 5651*da14cebeSEric Cheng nxge = rgroup->nxgep; 5652*da14cebeSEric Cheng 5653*da14cebeSEric Cheng switch (type) { 5654*da14cebeSEric Cheng case MAC_RING_TYPE_TX: 5655*da14cebeSEric Cheng dev_gindex = nxge->pt_config.hw_config.def_mac_txdma_grpid + 5656*da14cebeSEric Cheng rgroup->gindex; 5657*da14cebeSEric Cheng channel = nxge->pt_config.hw_config.tdc.start + rhandle->index; 5658*da14cebeSEric Cheng nxge_grp_dc_remove(nxge, VP_BOUND_TX, channel); 5659*da14cebeSEric Cheng 5660*da14cebeSEric Cheng /* 5661*da14cebeSEric Cheng * Add the ring back to the default group 5662*da14cebeSEric Cheng */ 5663*da14cebeSEric Cheng if (rgroup->gindex != 0) { 5664*da14cebeSEric Cheng nxge_grp_t *grp; 5665*da14cebeSEric Cheng grp = nxge->tx_set.group[0]; 5666*da14cebeSEric Cheng (void) nxge_grp_dc_add(nxge, grp, VP_BOUND_TX, channel); 5667*da14cebeSEric Cheng } 5668*da14cebeSEric Cheng break; 5669*da14cebeSEric Cheng 5670*da14cebeSEric Cheng case MAC_RING_TYPE_RX: 5671*da14cebeSEric Cheng dev_gindex = nxge->pt_config.hw_config.def_mac_rxdma_grpid + 5672*da14cebeSEric Cheng rgroup->gindex; 5673*da14cebeSEric Cheng rdc_grp = &nxge->pt_config.rdc_grps[dev_gindex]; 5674*da14cebeSEric Cheng channel = rdc_grp->start_rdc + rhandle->index; 5675*da14cebeSEric Cheng nxge_grp_dc_remove(nxge, VP_BOUND_RX, channel); 5676*da14cebeSEric Cheng 5677*da14cebeSEric Cheng rdc_grp->map &= ~(1 << channel); 5678*da14cebeSEric Cheng rdc_grp->max_rdcs--; 5679*da14cebeSEric Cheng 5680*da14cebeSEric Cheng (void) nxge_init_fzc_rdc_tbl(nxge, rgroup->rdctbl); 5681*da14cebeSEric Cheng break; 5682*da14cebeSEric Cheng } 5683*da14cebeSEric Cheng } 5684*da14cebeSEric Cheng 5685*da14cebeSEric Cheng 568644961713Sgirish /*ARGSUSED*/ 568744961713Sgirish static nxge_status_t 568844961713Sgirish nxge_add_intrs(p_nxge_t nxgep) 568944961713Sgirish { 569044961713Sgirish 569144961713Sgirish int intr_types; 569244961713Sgirish int type = 0; 569344961713Sgirish int ddi_status = DDI_SUCCESS; 569444961713Sgirish nxge_status_t status = NXGE_OK; 569544961713Sgirish 569644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs")); 569744961713Sgirish 569844961713Sgirish nxgep->nxge_intr_type.intr_registered = B_FALSE; 569944961713Sgirish nxgep->nxge_intr_type.intr_enabled = B_FALSE; 570044961713Sgirish nxgep->nxge_intr_type.msi_intx_cnt = 0; 570144961713Sgirish nxgep->nxge_intr_type.intr_added = 0; 570244961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_FALSE; 570344961713Sgirish nxgep->nxge_intr_type.intr_type = 0; 570444961713Sgirish 570544961713Sgirish if (nxgep->niu_type == N2_NIU) { 570644961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 570744961713Sgirish } else if (nxge_msi_enable) { 570844961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 570944961713Sgirish } 571044961713Sgirish 571144961713Sgirish /* Get the supported interrupt types */ 571244961713Sgirish if ((ddi_status = ddi_intr_get_supported_types(nxgep->dip, &intr_types)) 57134045d941Ssowmini != DDI_SUCCESS) { 571444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_intrs: " 57154045d941Ssowmini "ddi_intr_get_supported_types failed: status 0x%08x", 57164045d941Ssowmini ddi_status)); 571744961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 571844961713Sgirish } 571944961713Sgirish nxgep->nxge_intr_type.intr_types = intr_types; 572044961713Sgirish 572144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 57224045d941Ssowmini "ddi_intr_get_supported_types: 0x%08x", intr_types)); 572344961713Sgirish 572444961713Sgirish /* 572544961713Sgirish * Solaris MSIX is not supported yet. use MSI for now. 572644961713Sgirish * nxge_msi_enable (1): 572744961713Sgirish * 1 - MSI 2 - MSI-X others - FIXED 572844961713Sgirish */ 572944961713Sgirish switch (nxge_msi_enable) { 573044961713Sgirish default: 573144961713Sgirish type = DDI_INTR_TYPE_FIXED; 573244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 57334045d941Ssowmini "use fixed (intx emulation) type %08x", 57344045d941Ssowmini type)); 573544961713Sgirish break; 573644961713Sgirish 573744961713Sgirish case 2: 573844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 57394045d941Ssowmini "ddi_intr_get_supported_types: 0x%08x", intr_types)); 574044961713Sgirish if (intr_types & DDI_INTR_TYPE_MSIX) { 574144961713Sgirish type = DDI_INTR_TYPE_MSIX; 574244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 57434045d941Ssowmini "ddi_intr_get_supported_types: MSIX 0x%08x", 57444045d941Ssowmini type)); 574544961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSI) { 574644961713Sgirish type = DDI_INTR_TYPE_MSI; 574744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 57484045d941Ssowmini "ddi_intr_get_supported_types: MSI 0x%08x", 57494045d941Ssowmini type)); 575044961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 575144961713Sgirish type = DDI_INTR_TYPE_FIXED; 575244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 57534045d941Ssowmini "ddi_intr_get_supported_types: MSXED0x%08x", 57544045d941Ssowmini type)); 575544961713Sgirish } 575644961713Sgirish break; 575744961713Sgirish 575844961713Sgirish case 1: 575944961713Sgirish if (intr_types & DDI_INTR_TYPE_MSI) { 576044961713Sgirish type = DDI_INTR_TYPE_MSI; 576144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 57624045d941Ssowmini "ddi_intr_get_supported_types: MSI 0x%08x", 57634045d941Ssowmini type)); 576444961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSIX) { 576544961713Sgirish type = DDI_INTR_TYPE_MSIX; 576644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 57674045d941Ssowmini "ddi_intr_get_supported_types: MSIX 0x%08x", 57684045d941Ssowmini type)); 576944961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 577044961713Sgirish type = DDI_INTR_TYPE_FIXED; 577144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 57724045d941Ssowmini "ddi_intr_get_supported_types: MSXED0x%08x", 57734045d941Ssowmini type)); 577444961713Sgirish } 577544961713Sgirish } 577644961713Sgirish 577744961713Sgirish nxgep->nxge_intr_type.intr_type = type; 577844961713Sgirish if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI || 57794045d941Ssowmini type == DDI_INTR_TYPE_FIXED) && 57804045d941Ssowmini nxgep->nxge_intr_type.niu_msi_enable) { 578144961713Sgirish if ((status = nxge_add_intrs_adv(nxgep)) != DDI_SUCCESS) { 578244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 57834045d941Ssowmini " nxge_add_intrs: " 57844045d941Ssowmini " nxge_add_intrs_adv failed: status 0x%08x", 57854045d941Ssowmini status)); 578644961713Sgirish return (status); 578744961713Sgirish } else { 578844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 57894045d941Ssowmini "interrupts registered : type %d", type)); 579044961713Sgirish nxgep->nxge_intr_type.intr_registered = B_TRUE; 579144961713Sgirish 579244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 57934045d941Ssowmini "\nAdded advanced nxge add_intr_adv " 57944045d941Ssowmini "intr type 0x%x\n", type)); 579544961713Sgirish 579644961713Sgirish return (status); 579744961713Sgirish } 579844961713Sgirish } 579944961713Sgirish 580044961713Sgirish if (!nxgep->nxge_intr_type.intr_registered) { 580144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_add_intrs: " 58024045d941Ssowmini "failed to register interrupts")); 580344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 580444961713Sgirish } 580544961713Sgirish 580644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_add_intrs")); 580744961713Sgirish return (status); 580844961713Sgirish } 580944961713Sgirish 581044961713Sgirish static nxge_status_t 581144961713Sgirish nxge_add_intrs_adv(p_nxge_t nxgep) 581244961713Sgirish { 581344961713Sgirish int intr_type; 581444961713Sgirish p_nxge_intr_t intrp; 581544961713Sgirish 581644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv")); 581744961713Sgirish 581844961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 581944961713Sgirish intr_type = intrp->intr_type; 582044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv: type 0x%x", 58214045d941Ssowmini intr_type)); 582244961713Sgirish 582344961713Sgirish switch (intr_type) { 582444961713Sgirish case DDI_INTR_TYPE_MSI: /* 0x2 */ 582544961713Sgirish case DDI_INTR_TYPE_MSIX: /* 0x4 */ 582644961713Sgirish return (nxge_add_intrs_adv_type(nxgep, intr_type)); 582744961713Sgirish 582844961713Sgirish case DDI_INTR_TYPE_FIXED: /* 0x1 */ 582944961713Sgirish return (nxge_add_intrs_adv_type_fix(nxgep, intr_type)); 583044961713Sgirish 583144961713Sgirish default: 583244961713Sgirish return (NXGE_ERROR); 583344961713Sgirish } 583444961713Sgirish } 583544961713Sgirish 583644961713Sgirish 583744961713Sgirish /*ARGSUSED*/ 583844961713Sgirish static nxge_status_t 583944961713Sgirish nxge_add_intrs_adv_type(p_nxge_t nxgep, uint32_t int_type) 584044961713Sgirish { 584144961713Sgirish dev_info_t *dip = nxgep->dip; 584244961713Sgirish p_nxge_ldg_t ldgp; 584344961713Sgirish p_nxge_intr_t intrp; 584444961713Sgirish uint_t *inthandler; 584544961713Sgirish void *arg1, *arg2; 584644961713Sgirish int behavior; 5847ec090658Sml int nintrs, navail, nrequest; 584844961713Sgirish int nactual, nrequired; 584944961713Sgirish int inum = 0; 585044961713Sgirish int x, y; 585144961713Sgirish int ddi_status = DDI_SUCCESS; 585244961713Sgirish nxge_status_t status = NXGE_OK; 585344961713Sgirish 585444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type")); 585544961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 585644961713Sgirish intrp->start_inum = 0; 585744961713Sgirish 585844961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 585944961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 586044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58614045d941Ssowmini "ddi_intr_get_nintrs() failed, status: 0x%x%, " 58624045d941Ssowmini "nintrs: %d", ddi_status, nintrs)); 586344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 586444961713Sgirish } 586544961713Sgirish 586644961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 586744961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 586844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58694045d941Ssowmini "ddi_intr_get_navail() failed, status: 0x%x%, " 58704045d941Ssowmini "nintrs: %d", ddi_status, navail)); 587144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 587244961713Sgirish } 587344961713Sgirish 587444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 58754045d941Ssowmini "ddi_intr_get_navail() returned: nintrs %d, navail %d", 58764045d941Ssowmini nintrs, navail)); 587744961713Sgirish 5878ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override */ 5879ec090658Sml if (int_type == DDI_INTR_TYPE_MSIX) { 5880ec090658Sml nrequest = nxge_create_msi_property(nxgep); 5881ec090658Sml if (nrequest < navail) { 5882ec090658Sml navail = nrequest; 5883ec090658Sml NXGE_DEBUG_MSG((nxgep, INT_CTL, 5884ec090658Sml "nxge_add_intrs_adv_type: nintrs %d " 5885ec090658Sml "navail %d (nrequest %d)", 5886ec090658Sml nintrs, navail, nrequest)); 5887ec090658Sml } 5888ec090658Sml } 5889ec090658Sml 589044961713Sgirish if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) { 589144961713Sgirish /* MSI must be power of 2 */ 589244961713Sgirish if ((navail & 16) == 16) { 589344961713Sgirish navail = 16; 589444961713Sgirish } else if ((navail & 8) == 8) { 589544961713Sgirish navail = 8; 589644961713Sgirish } else if ((navail & 4) == 4) { 589744961713Sgirish navail = 4; 589844961713Sgirish } else if ((navail & 2) == 2) { 589944961713Sgirish navail = 2; 590044961713Sgirish } else { 590144961713Sgirish navail = 1; 590244961713Sgirish } 590344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 59044045d941Ssowmini "ddi_intr_get_navail(): (msi power of 2) nintrs %d, " 59054045d941Ssowmini "navail %d", nintrs, navail)); 590644961713Sgirish } 590744961713Sgirish 590844961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 59094045d941Ssowmini DDI_INTR_ALLOC_NORMAL); 591044961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 591144961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 591244961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 59134045d941Ssowmini navail, &nactual, behavior); 591444961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 591544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59164045d941Ssowmini " ddi_intr_alloc() failed: %d", 59174045d941Ssowmini ddi_status)); 591844961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 591944961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 592044961713Sgirish } 592144961713Sgirish 592244961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 59234045d941Ssowmini (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 592444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59254045d941Ssowmini " ddi_intr_get_pri() failed: %d", 59264045d941Ssowmini ddi_status)); 592744961713Sgirish /* Free already allocated interrupts */ 592844961713Sgirish for (y = 0; y < nactual; y++) { 592944961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 593044961713Sgirish } 593144961713Sgirish 593244961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 593344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 593444961713Sgirish } 593544961713Sgirish 593644961713Sgirish nrequired = 0; 593744961713Sgirish switch (nxgep->niu_type) { 593844961713Sgirish default: 593944961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 594044961713Sgirish break; 594144961713Sgirish 594244961713Sgirish case N2_NIU: 594344961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 594444961713Sgirish break; 594544961713Sgirish } 594644961713Sgirish 594744961713Sgirish if (status != NXGE_OK) { 594844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59494045d941Ssowmini "nxge_add_intrs_adv_typ:nxge_ldgv_init " 59504045d941Ssowmini "failed: 0x%x", status)); 595144961713Sgirish /* Free already allocated interrupts */ 595244961713Sgirish for (y = 0; y < nactual; y++) { 595344961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 595444961713Sgirish } 595544961713Sgirish 595644961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 595744961713Sgirish return (status); 595844961713Sgirish } 595944961713Sgirish 596044961713Sgirish ldgp = nxgep->ldgvp->ldgp; 596144961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 596244961713Sgirish ldgp->vector = (uint8_t)x; 596344961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 596444961713Sgirish arg1 = ldgp->ldvp; 596544961713Sgirish arg2 = nxgep; 596644961713Sgirish if (ldgp->nldvs == 1) { 596744961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 596844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 59694045d941Ssowmini "nxge_add_intrs_adv_type: " 59704045d941Ssowmini "arg1 0x%x arg2 0x%x: " 59714045d941Ssowmini "1-1 int handler (entry %d intdata 0x%x)\n", 59724045d941Ssowmini arg1, arg2, 59734045d941Ssowmini x, ldgp->intdata)); 597444961713Sgirish } else if (ldgp->nldvs > 1) { 597544961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 597644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 59774045d941Ssowmini "nxge_add_intrs_adv_type: " 59784045d941Ssowmini "arg1 0x%x arg2 0x%x: " 59794045d941Ssowmini "nldevs %d int handler " 59804045d941Ssowmini "(entry %d intdata 0x%x)\n", 59814045d941Ssowmini arg1, arg2, 59824045d941Ssowmini ldgp->nldvs, x, ldgp->intdata)); 598344961713Sgirish } 598444961713Sgirish 598544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 59864045d941Ssowmini "==> nxge_add_intrs_adv_type: ddi_add_intr(inum) #%d " 59874045d941Ssowmini "htable 0x%llx", x, intrp->htable[x])); 598844961713Sgirish 598944961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 59904045d941Ssowmini (ddi_intr_handler_t *)inthandler, arg1, arg2)) 59914045d941Ssowmini != DDI_SUCCESS) { 599244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59934045d941Ssowmini "==> nxge_add_intrs_adv_type: failed #%d " 59944045d941Ssowmini "status 0x%x", x, ddi_status)); 599544961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 599644961713Sgirish (void) ddi_intr_remove_handler( 59974045d941Ssowmini intrp->htable[y]); 599844961713Sgirish } 599944961713Sgirish /* Free already allocated intr */ 600044961713Sgirish for (y = 0; y < nactual; y++) { 600144961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 600244961713Sgirish } 600344961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 600444961713Sgirish 600544961713Sgirish (void) nxge_ldgv_uninit(nxgep); 600644961713Sgirish 600744961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 600844961713Sgirish } 600944961713Sgirish intrp->intr_added++; 601044961713Sgirish } 601144961713Sgirish 601244961713Sgirish intrp->msi_intx_cnt = nactual; 601344961713Sgirish 601444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 60154045d941Ssowmini "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d", 60164045d941Ssowmini navail, nactual, 60174045d941Ssowmini intrp->msi_intx_cnt, 60184045d941Ssowmini intrp->intr_added)); 601944961713Sgirish 602044961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 602144961713Sgirish 602244961713Sgirish (void) nxge_intr_ldgv_init(nxgep); 602344961713Sgirish 602444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type")); 602544961713Sgirish 602644961713Sgirish return (status); 602744961713Sgirish } 602844961713Sgirish 602944961713Sgirish /*ARGSUSED*/ 603044961713Sgirish static nxge_status_t 603144961713Sgirish nxge_add_intrs_adv_type_fix(p_nxge_t nxgep, uint32_t int_type) 603244961713Sgirish { 603344961713Sgirish dev_info_t *dip = nxgep->dip; 603444961713Sgirish p_nxge_ldg_t ldgp; 603544961713Sgirish p_nxge_intr_t intrp; 603644961713Sgirish uint_t *inthandler; 603744961713Sgirish void *arg1, *arg2; 603844961713Sgirish int behavior; 603944961713Sgirish int nintrs, navail; 604044961713Sgirish int nactual, nrequired; 604144961713Sgirish int inum = 0; 604244961713Sgirish int x, y; 604344961713Sgirish int ddi_status = DDI_SUCCESS; 604444961713Sgirish nxge_status_t status = NXGE_OK; 604544961713Sgirish 604644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type_fix")); 604744961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 604844961713Sgirish intrp->start_inum = 0; 604944961713Sgirish 605044961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 605144961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 605244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 60534045d941Ssowmini "ddi_intr_get_nintrs() failed, status: 0x%x%, " 60544045d941Ssowmini "nintrs: %d", status, nintrs)); 605544961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 605644961713Sgirish } 605744961713Sgirish 605844961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 605944961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 606044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60614045d941Ssowmini "ddi_intr_get_navail() failed, status: 0x%x%, " 60624045d941Ssowmini "nintrs: %d", ddi_status, navail)); 606344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 606444961713Sgirish } 606544961713Sgirish 606644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 60674045d941Ssowmini "ddi_intr_get_navail() returned: nintrs %d, naavail %d", 60684045d941Ssowmini nintrs, navail)); 606944961713Sgirish 607044961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 60714045d941Ssowmini DDI_INTR_ALLOC_NORMAL); 607244961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 607344961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 607444961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 60754045d941Ssowmini navail, &nactual, behavior); 607644961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 607744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60784045d941Ssowmini " ddi_intr_alloc() failed: %d", 60794045d941Ssowmini ddi_status)); 608044961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 608144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 608244961713Sgirish } 608344961713Sgirish 608444961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 60854045d941Ssowmini (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 608644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60874045d941Ssowmini " ddi_intr_get_pri() failed: %d", 60884045d941Ssowmini ddi_status)); 608944961713Sgirish /* Free already allocated interrupts */ 609044961713Sgirish for (y = 0; y < nactual; y++) { 609144961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 609244961713Sgirish } 609344961713Sgirish 609444961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 609544961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 609644961713Sgirish } 609744961713Sgirish 609844961713Sgirish nrequired = 0; 609944961713Sgirish switch (nxgep->niu_type) { 610044961713Sgirish default: 610144961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 610244961713Sgirish break; 610344961713Sgirish 610444961713Sgirish case N2_NIU: 610544961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 610644961713Sgirish break; 610744961713Sgirish } 610844961713Sgirish 610944961713Sgirish if (status != NXGE_OK) { 611044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61114045d941Ssowmini "nxge_add_intrs_adv_type_fix:nxge_ldgv_init " 61124045d941Ssowmini "failed: 0x%x", status)); 611344961713Sgirish /* Free already allocated interrupts */ 611444961713Sgirish for (y = 0; y < nactual; y++) { 611544961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 611644961713Sgirish } 611744961713Sgirish 611844961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 611944961713Sgirish return (status); 612044961713Sgirish } 612144961713Sgirish 612244961713Sgirish ldgp = nxgep->ldgvp->ldgp; 612344961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 612444961713Sgirish ldgp->vector = (uint8_t)x; 612544961713Sgirish if (nxgep->niu_type != N2_NIU) { 612644961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 612744961713Sgirish } 612844961713Sgirish 612944961713Sgirish arg1 = ldgp->ldvp; 613044961713Sgirish arg2 = nxgep; 613144961713Sgirish if (ldgp->nldvs == 1) { 613244961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 613344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 61344045d941Ssowmini "nxge_add_intrs_adv_type_fix: " 61354045d941Ssowmini "1-1 int handler(%d) ldg %d ldv %d " 61364045d941Ssowmini "arg1 $%p arg2 $%p\n", 61374045d941Ssowmini x, ldgp->ldg, ldgp->ldvp->ldv, 61384045d941Ssowmini arg1, arg2)); 613944961713Sgirish } else if (ldgp->nldvs > 1) { 614044961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 614144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 61424045d941Ssowmini "nxge_add_intrs_adv_type_fix: " 61434045d941Ssowmini "shared ldv %d int handler(%d) ldv %d ldg %d" 61444045d941Ssowmini "arg1 0x%016llx arg2 0x%016llx\n", 61454045d941Ssowmini x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv, 61464045d941Ssowmini arg1, arg2)); 614744961713Sgirish } 614844961713Sgirish 614944961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 61504045d941Ssowmini (ddi_intr_handler_t *)inthandler, arg1, arg2)) 61514045d941Ssowmini != DDI_SUCCESS) { 615244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61534045d941Ssowmini "==> nxge_add_intrs_adv_type_fix: failed #%d " 61544045d941Ssowmini "status 0x%x", x, ddi_status)); 615544961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 615644961713Sgirish (void) ddi_intr_remove_handler( 61574045d941Ssowmini intrp->htable[y]); 615844961713Sgirish } 615944961713Sgirish for (y = 0; y < nactual; y++) { 616044961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 616144961713Sgirish } 616244961713Sgirish /* Free already allocated intr */ 616344961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 616444961713Sgirish 616544961713Sgirish (void) nxge_ldgv_uninit(nxgep); 616644961713Sgirish 616744961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 616844961713Sgirish } 616944961713Sgirish intrp->intr_added++; 617044961713Sgirish } 617144961713Sgirish 617244961713Sgirish intrp->msi_intx_cnt = nactual; 617344961713Sgirish 617444961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 617544961713Sgirish 617644961713Sgirish status = nxge_intr_ldgv_init(nxgep); 617744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type_fix")); 617844961713Sgirish 617944961713Sgirish return (status); 618044961713Sgirish } 618144961713Sgirish 618244961713Sgirish static void 618344961713Sgirish nxge_remove_intrs(p_nxge_t nxgep) 618444961713Sgirish { 618544961713Sgirish int i, inum; 618644961713Sgirish p_nxge_intr_t intrp; 618744961713Sgirish 618844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs")); 618944961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 619044961713Sgirish if (!intrp->intr_registered) { 619144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 61924045d941Ssowmini "<== nxge_remove_intrs: interrupts not registered")); 619344961713Sgirish return; 619444961713Sgirish } 619544961713Sgirish 619644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs:advanced")); 619744961713Sgirish 619844961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 619944961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 62004045d941Ssowmini intrp->intr_added); 620144961713Sgirish } else { 620244961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 620344961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 620444961713Sgirish } 620544961713Sgirish } 620644961713Sgirish 620744961713Sgirish for (inum = 0; inum < intrp->intr_added; inum++) { 620844961713Sgirish if (intrp->htable[inum]) { 620944961713Sgirish (void) ddi_intr_remove_handler(intrp->htable[inum]); 621044961713Sgirish } 621144961713Sgirish } 621244961713Sgirish 621344961713Sgirish for (inum = 0; inum < intrp->msi_intx_cnt; inum++) { 621444961713Sgirish if (intrp->htable[inum]) { 621544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 62164045d941Ssowmini "nxge_remove_intrs: ddi_intr_free inum %d " 62174045d941Ssowmini "msi_intx_cnt %d intr_added %d", 62184045d941Ssowmini inum, 62194045d941Ssowmini intrp->msi_intx_cnt, 62204045d941Ssowmini intrp->intr_added)); 622144961713Sgirish 622244961713Sgirish (void) ddi_intr_free(intrp->htable[inum]); 622344961713Sgirish } 622444961713Sgirish } 622544961713Sgirish 622644961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 622744961713Sgirish intrp->intr_registered = B_FALSE; 622844961713Sgirish intrp->intr_enabled = B_FALSE; 622944961713Sgirish intrp->msi_intx_cnt = 0; 623044961713Sgirish intrp->intr_added = 0; 623144961713Sgirish 6232a3c5bd6dSspeer (void) nxge_ldgv_uninit(nxgep); 6233a3c5bd6dSspeer 6234ec090658Sml (void) ddi_prop_remove(DDI_DEV_T_NONE, nxgep->dip, 6235ec090658Sml "#msix-request"); 6236ec090658Sml 623744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_intrs")); 623844961713Sgirish } 623944961713Sgirish 624044961713Sgirish /*ARGSUSED*/ 624144961713Sgirish static void 624244961713Sgirish nxge_intrs_enable(p_nxge_t nxgep) 624344961713Sgirish { 624444961713Sgirish p_nxge_intr_t intrp; 624544961713Sgirish int i; 624644961713Sgirish int status; 624744961713Sgirish 624844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable")); 624944961713Sgirish 625044961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 625144961713Sgirish 625244961713Sgirish if (!intrp->intr_registered) { 625344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_intrs_enable: " 62544045d941Ssowmini "interrupts are not registered")); 625544961713Sgirish return; 625644961713Sgirish } 625744961713Sgirish 625844961713Sgirish if (intrp->intr_enabled) { 625944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 62604045d941Ssowmini "<== nxge_intrs_enable: already enabled")); 626144961713Sgirish return; 626244961713Sgirish } 626344961713Sgirish 626444961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 626544961713Sgirish status = ddi_intr_block_enable(intrp->htable, 62664045d941Ssowmini intrp->intr_added); 626744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 62684045d941Ssowmini "block enable - status 0x%x total inums #%d\n", 62694045d941Ssowmini status, intrp->intr_added)); 627044961713Sgirish } else { 627144961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 627244961713Sgirish status = ddi_intr_enable(intrp->htable[i]); 627344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 62744045d941Ssowmini "ddi_intr_enable:enable - status 0x%x " 62754045d941Ssowmini "total inums %d enable inum #%d\n", 62764045d941Ssowmini status, intrp->intr_added, i)); 627744961713Sgirish if (status == DDI_SUCCESS) { 627844961713Sgirish intrp->intr_enabled = B_TRUE; 627944961713Sgirish } 628044961713Sgirish } 628144961713Sgirish } 628244961713Sgirish 628344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_enable")); 628444961713Sgirish } 628544961713Sgirish 628644961713Sgirish /*ARGSUSED*/ 628744961713Sgirish static void 628844961713Sgirish nxge_intrs_disable(p_nxge_t nxgep) 628944961713Sgirish { 629044961713Sgirish p_nxge_intr_t intrp; 629144961713Sgirish int i; 629244961713Sgirish 629344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_disable")); 629444961713Sgirish 629544961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 629644961713Sgirish 629744961713Sgirish if (!intrp->intr_registered) { 629844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable: " 62994045d941Ssowmini "interrupts are not registered")); 630044961713Sgirish return; 630144961713Sgirish } 630244961713Sgirish 630344961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 630444961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 63054045d941Ssowmini intrp->intr_added); 630644961713Sgirish } else { 630744961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 630844961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 630944961713Sgirish } 631044961713Sgirish } 631144961713Sgirish 631244961713Sgirish intrp->intr_enabled = B_FALSE; 631344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable")); 631444961713Sgirish } 631544961713Sgirish 631644961713Sgirish static nxge_status_t 631744961713Sgirish nxge_mac_register(p_nxge_t nxgep) 631844961713Sgirish { 631944961713Sgirish mac_register_t *macp; 632044961713Sgirish int status; 632144961713Sgirish 632244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_mac_register")); 632344961713Sgirish 632444961713Sgirish if ((macp = mac_alloc(MAC_VERSION)) == NULL) 632544961713Sgirish return (NXGE_ERROR); 632644961713Sgirish 632744961713Sgirish macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 632844961713Sgirish macp->m_driver = nxgep; 632944961713Sgirish macp->m_dip = nxgep->dip; 633044961713Sgirish macp->m_src_addr = nxgep->ouraddr.ether_addr_octet; 633144961713Sgirish macp->m_callbacks = &nxge_m_callbacks; 633244961713Sgirish macp->m_min_sdu = 0; 63331bd6825cSml nxgep->mac.default_mtu = nxgep->mac.maxframesize - 63341bd6825cSml NXGE_EHEADER_VLAN_CRC; 63351bd6825cSml macp->m_max_sdu = nxgep->mac.default_mtu; 6336d62bc4baSyz macp->m_margin = VLAN_TAGSZ; 63374045d941Ssowmini macp->m_priv_props = nxge_priv_props; 63384045d941Ssowmini macp->m_priv_prop_count = NXGE_MAX_PRIV_PROPS; 6339*da14cebeSEric Cheng macp->m_v12n = MAC_VIRT_HIO | MAC_VIRT_LEVEL1 | MAC_VIRT_SERIALIZE; 634044961713Sgirish 63411bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 63421bd6825cSml "==> nxge_mac_register: instance %d " 63431bd6825cSml "max_sdu %d margin %d maxframe %d (header %d)", 63441bd6825cSml nxgep->instance, 63451bd6825cSml macp->m_max_sdu, macp->m_margin, 63461bd6825cSml nxgep->mac.maxframesize, 63471bd6825cSml NXGE_EHEADER_VLAN_CRC)); 63481bd6825cSml 634944961713Sgirish status = mac_register(macp, &nxgep->mach); 635044961713Sgirish mac_free(macp); 635144961713Sgirish 635244961713Sgirish if (status != 0) { 635344961713Sgirish cmn_err(CE_WARN, 63544045d941Ssowmini "!nxge_mac_register failed (status %d instance %d)", 63554045d941Ssowmini status, nxgep->instance); 635644961713Sgirish return (NXGE_ERROR); 635744961713Sgirish } 635844961713Sgirish 635944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_mac_register success " 63604045d941Ssowmini "(instance %d)", nxgep->instance)); 636144961713Sgirish 636244961713Sgirish return (NXGE_OK); 636344961713Sgirish } 636444961713Sgirish 636544961713Sgirish void 636644961713Sgirish nxge_err_inject(p_nxge_t nxgep, queue_t *wq, mblk_t *mp) 636744961713Sgirish { 636844961713Sgirish ssize_t size; 636944961713Sgirish mblk_t *nmp; 637044961713Sgirish uint8_t blk_id; 637144961713Sgirish uint8_t chan; 637244961713Sgirish uint32_t err_id; 637344961713Sgirish err_inject_t *eip; 637444961713Sgirish 637544961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_err_inject")); 637644961713Sgirish 637744961713Sgirish size = 1024; 637844961713Sgirish nmp = mp->b_cont; 637944961713Sgirish eip = (err_inject_t *)nmp->b_rptr; 638044961713Sgirish blk_id = eip->blk_id; 638144961713Sgirish err_id = eip->err_id; 638244961713Sgirish chan = eip->chan; 638344961713Sgirish cmn_err(CE_NOTE, "!blk_id = 0x%x\n", blk_id); 638444961713Sgirish cmn_err(CE_NOTE, "!err_id = 0x%x\n", err_id); 638544961713Sgirish cmn_err(CE_NOTE, "!chan = 0x%x\n", chan); 638644961713Sgirish switch (blk_id) { 638744961713Sgirish case MAC_BLK_ID: 638844961713Sgirish break; 638944961713Sgirish case TXMAC_BLK_ID: 639044961713Sgirish break; 639144961713Sgirish case RXMAC_BLK_ID: 639244961713Sgirish break; 639344961713Sgirish case MIF_BLK_ID: 639444961713Sgirish break; 639544961713Sgirish case IPP_BLK_ID: 639644961713Sgirish nxge_ipp_inject_err(nxgep, err_id); 639744961713Sgirish break; 639844961713Sgirish case TXC_BLK_ID: 639944961713Sgirish nxge_txc_inject_err(nxgep, err_id); 640044961713Sgirish break; 640144961713Sgirish case TXDMA_BLK_ID: 640244961713Sgirish nxge_txdma_inject_err(nxgep, err_id, chan); 640344961713Sgirish break; 640444961713Sgirish case RXDMA_BLK_ID: 640544961713Sgirish nxge_rxdma_inject_err(nxgep, err_id, chan); 640644961713Sgirish break; 640744961713Sgirish case ZCP_BLK_ID: 640844961713Sgirish nxge_zcp_inject_err(nxgep, err_id); 640944961713Sgirish break; 641044961713Sgirish case ESPC_BLK_ID: 641144961713Sgirish break; 641244961713Sgirish case FFLP_BLK_ID: 641344961713Sgirish break; 641444961713Sgirish case PHY_BLK_ID: 641544961713Sgirish break; 641644961713Sgirish case ETHER_SERDES_BLK_ID: 641744961713Sgirish break; 641844961713Sgirish case PCIE_SERDES_BLK_ID: 641944961713Sgirish break; 642044961713Sgirish case VIR_BLK_ID: 642144961713Sgirish break; 642244961713Sgirish } 642344961713Sgirish 642444961713Sgirish nmp->b_wptr = nmp->b_rptr + size; 642544961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_err_inject")); 642644961713Sgirish 642744961713Sgirish miocack(wq, mp, (int)size, 0); 642844961713Sgirish } 642944961713Sgirish 643044961713Sgirish static int 643144961713Sgirish nxge_init_common_dev(p_nxge_t nxgep) 643244961713Sgirish { 643344961713Sgirish p_nxge_hw_list_t hw_p; 643444961713Sgirish dev_info_t *p_dip; 643544961713Sgirish 643644961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_init_common_device")); 643744961713Sgirish 643844961713Sgirish p_dip = nxgep->p_dip; 643944961713Sgirish MUTEX_ENTER(&nxge_common_lock); 644044961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 64414045d941Ssowmini "==> nxge_init_common_dev:func # %d", 64424045d941Ssowmini nxgep->function_num)); 644344961713Sgirish /* 644444961713Sgirish * Loop through existing per neptune hardware list. 644544961713Sgirish */ 644644961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 644744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 64484045d941Ssowmini "==> nxge_init_common_device:func # %d " 64494045d941Ssowmini "hw_p $%p parent dip $%p", 64504045d941Ssowmini nxgep->function_num, 64514045d941Ssowmini hw_p, 64524045d941Ssowmini p_dip)); 645344961713Sgirish if (hw_p->parent_devp == p_dip) { 645444961713Sgirish nxgep->nxge_hw_p = hw_p; 645544961713Sgirish hw_p->ndevs++; 645644961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 645744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 64584045d941Ssowmini "==> nxge_init_common_device:func # %d " 64594045d941Ssowmini "hw_p $%p parent dip $%p " 64604045d941Ssowmini "ndevs %d (found)", 64614045d941Ssowmini nxgep->function_num, 64624045d941Ssowmini hw_p, 64634045d941Ssowmini p_dip, 64644045d941Ssowmini hw_p->ndevs)); 646544961713Sgirish break; 646644961713Sgirish } 646744961713Sgirish } 646844961713Sgirish 646944961713Sgirish if (hw_p == NULL) { 647023b952a3SSantwona Behera 647123b952a3SSantwona Behera char **prop_val; 647223b952a3SSantwona Behera uint_t prop_len; 647323b952a3SSantwona Behera int i; 647423b952a3SSantwona Behera 647544961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 64764045d941Ssowmini "==> nxge_init_common_device:func # %d " 64774045d941Ssowmini "parent dip $%p (new)", 64784045d941Ssowmini nxgep->function_num, 64794045d941Ssowmini p_dip)); 648044961713Sgirish hw_p = kmem_zalloc(sizeof (nxge_hw_list_t), KM_SLEEP); 648144961713Sgirish hw_p->parent_devp = p_dip; 648244961713Sgirish hw_p->magic = NXGE_NEPTUNE_MAGIC; 648344961713Sgirish nxgep->nxge_hw_p = hw_p; 648444961713Sgirish hw_p->ndevs++; 648544961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 648644961713Sgirish hw_p->next = nxge_hw_list; 648759ac0c16Sdavemq if (nxgep->niu_type == N2_NIU) { 648859ac0c16Sdavemq hw_p->niu_type = N2_NIU; 648959ac0c16Sdavemq hw_p->platform_type = P_NEPTUNE_NIU; 649059ac0c16Sdavemq } else { 649159ac0c16Sdavemq hw_p->niu_type = NIU_TYPE_NONE; 64922e59129aSraghus hw_p->platform_type = P_NEPTUNE_NONE; 649359ac0c16Sdavemq } 649444961713Sgirish 649544961713Sgirish MUTEX_INIT(&hw_p->nxge_cfg_lock, NULL, MUTEX_DRIVER, NULL); 649644961713Sgirish MUTEX_INIT(&hw_p->nxge_tcam_lock, NULL, MUTEX_DRIVER, NULL); 649744961713Sgirish MUTEX_INIT(&hw_p->nxge_vlan_lock, NULL, MUTEX_DRIVER, NULL); 649844961713Sgirish MUTEX_INIT(&hw_p->nxge_mdio_lock, NULL, MUTEX_DRIVER, NULL); 649944961713Sgirish 650044961713Sgirish nxge_hw_list = hw_p; 650159ac0c16Sdavemq 650223b952a3SSantwona Behera if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, nxgep->dip, 0, 650323b952a3SSantwona Behera "compatible", &prop_val, &prop_len) == DDI_PROP_SUCCESS) { 650423b952a3SSantwona Behera for (i = 0; i < prop_len; i++) { 650523b952a3SSantwona Behera if ((strcmp((caddr_t)prop_val[i], 650623b952a3SSantwona Behera NXGE_ROCK_COMPATIBLE) == 0)) { 650723b952a3SSantwona Behera hw_p->platform_type = P_NEPTUNE_ROCK; 650823b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MOD_CTL, 650923b952a3SSantwona Behera "ROCK hw_p->platform_type %d", 651023b952a3SSantwona Behera hw_p->platform_type)); 651123b952a3SSantwona Behera break; 651223b952a3SSantwona Behera } 651323b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MOD_CTL, 651423b952a3SSantwona Behera "nxge_init_common_dev: read compatible" 651523b952a3SSantwona Behera " property[%d] val[%s]", 651623b952a3SSantwona Behera i, (caddr_t)prop_val[i])); 651723b952a3SSantwona Behera } 651823b952a3SSantwona Behera } 651923b952a3SSantwona Behera 652023b952a3SSantwona Behera ddi_prop_free(prop_val); 652123b952a3SSantwona Behera 652259ac0c16Sdavemq (void) nxge_scan_ports_phy(nxgep, nxge_hw_list); 652344961713Sgirish } 652444961713Sgirish 652544961713Sgirish MUTEX_EXIT(&nxge_common_lock); 652659ac0c16Sdavemq 65272e59129aSraghus nxgep->platform_type = hw_p->platform_type; 652823b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MOD_CTL, "nxgep->platform_type %d", 652923b952a3SSantwona Behera nxgep->platform_type)); 653059ac0c16Sdavemq if (nxgep->niu_type != N2_NIU) { 653159ac0c16Sdavemq nxgep->niu_type = hw_p->niu_type; 653259ac0c16Sdavemq } 653359ac0c16Sdavemq 653444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65354045d941Ssowmini "==> nxge_init_common_device (nxge_hw_list) $%p", 65364045d941Ssowmini nxge_hw_list)); 653744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<== nxge_init_common_device")); 653844961713Sgirish 653944961713Sgirish return (NXGE_OK); 654044961713Sgirish } 654144961713Sgirish 654244961713Sgirish static void 654344961713Sgirish nxge_uninit_common_dev(p_nxge_t nxgep) 654444961713Sgirish { 654544961713Sgirish p_nxge_hw_list_t hw_p, h_hw_p; 65460b0beae0Sspeer p_nxge_dma_pt_cfg_t p_dma_cfgp; 65470b0beae0Sspeer p_nxge_hw_pt_cfg_t p_cfgp; 654844961713Sgirish dev_info_t *p_dip; 654944961713Sgirish 655044961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_uninit_common_device")); 655144961713Sgirish if (nxgep->nxge_hw_p == NULL) { 655244961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65534045d941Ssowmini "<== nxge_uninit_common_device (no common)")); 655444961713Sgirish return; 655544961713Sgirish } 655644961713Sgirish 655744961713Sgirish MUTEX_ENTER(&nxge_common_lock); 655844961713Sgirish h_hw_p = nxge_hw_list; 655944961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 656044961713Sgirish p_dip = hw_p->parent_devp; 656144961713Sgirish if (nxgep->nxge_hw_p == hw_p && 65624045d941Ssowmini p_dip == nxgep->p_dip && 65634045d941Ssowmini nxgep->nxge_hw_p->magic == NXGE_NEPTUNE_MAGIC && 65644045d941Ssowmini hw_p->magic == NXGE_NEPTUNE_MAGIC) { 656544961713Sgirish 656644961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65674045d941Ssowmini "==> nxge_uninit_common_device:func # %d " 65684045d941Ssowmini "hw_p $%p parent dip $%p " 65694045d941Ssowmini "ndevs %d (found)", 65704045d941Ssowmini nxgep->function_num, 65714045d941Ssowmini hw_p, 65724045d941Ssowmini p_dip, 65734045d941Ssowmini hw_p->ndevs)); 657444961713Sgirish 65750b0beae0Sspeer /* 65760b0beae0Sspeer * Release the RDC table, a shared resoruce 65770b0beae0Sspeer * of the nxge hardware. The RDC table was 65780b0beae0Sspeer * assigned to this instance of nxge in 65790b0beae0Sspeer * nxge_use_cfg_dma_config(). 65800b0beae0Sspeer */ 65819d5b8bc5SMichael Speer if (!isLDOMguest(nxgep)) { 65829d5b8bc5SMichael Speer p_dma_cfgp = 65839d5b8bc5SMichael Speer (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 65849d5b8bc5SMichael Speer p_cfgp = 65859d5b8bc5SMichael Speer (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; 65869d5b8bc5SMichael Speer (void) nxge_fzc_rdc_tbl_unbind(nxgep, 65879d5b8bc5SMichael Speer p_cfgp->def_mac_rxdma_grpid); 6588651ce697SMichael Speer 6589651ce697SMichael Speer /* Cleanup any outstanding groups. */ 6590651ce697SMichael Speer nxge_grp_cleanup(nxgep); 65919d5b8bc5SMichael Speer } 65920b0beae0Sspeer 659344961713Sgirish if (hw_p->ndevs) { 659444961713Sgirish hw_p->ndevs--; 659544961713Sgirish } 659644961713Sgirish hw_p->nxge_p[nxgep->function_num] = NULL; 659744961713Sgirish if (!hw_p->ndevs) { 659844961713Sgirish MUTEX_DESTROY(&hw_p->nxge_vlan_lock); 659944961713Sgirish MUTEX_DESTROY(&hw_p->nxge_tcam_lock); 660044961713Sgirish MUTEX_DESTROY(&hw_p->nxge_cfg_lock); 660144961713Sgirish MUTEX_DESTROY(&hw_p->nxge_mdio_lock); 660244961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66034045d941Ssowmini "==> nxge_uninit_common_device: " 66044045d941Ssowmini "func # %d " 66054045d941Ssowmini "hw_p $%p parent dip $%p " 66064045d941Ssowmini "ndevs %d (last)", 66074045d941Ssowmini nxgep->function_num, 66084045d941Ssowmini hw_p, 66094045d941Ssowmini p_dip, 66104045d941Ssowmini hw_p->ndevs)); 661144961713Sgirish 6612678453a8Sspeer nxge_hio_uninit(nxgep); 6613678453a8Sspeer 661444961713Sgirish if (hw_p == nxge_hw_list) { 661544961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66164045d941Ssowmini "==> nxge_uninit_common_device:" 66174045d941Ssowmini "remove head func # %d " 66184045d941Ssowmini "hw_p $%p parent dip $%p " 66194045d941Ssowmini "ndevs %d (head)", 66204045d941Ssowmini nxgep->function_num, 66214045d941Ssowmini hw_p, 66224045d941Ssowmini p_dip, 66234045d941Ssowmini hw_p->ndevs)); 662444961713Sgirish nxge_hw_list = hw_p->next; 662544961713Sgirish } else { 662644961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66274045d941Ssowmini "==> nxge_uninit_common_device:" 66284045d941Ssowmini "remove middle func # %d " 66294045d941Ssowmini "hw_p $%p parent dip $%p " 66304045d941Ssowmini "ndevs %d (middle)", 66314045d941Ssowmini nxgep->function_num, 66324045d941Ssowmini hw_p, 66334045d941Ssowmini p_dip, 66344045d941Ssowmini hw_p->ndevs)); 663544961713Sgirish h_hw_p->next = hw_p->next; 663644961713Sgirish } 663744961713Sgirish 6638678453a8Sspeer nxgep->nxge_hw_p = NULL; 663944961713Sgirish KMEM_FREE(hw_p, sizeof (nxge_hw_list_t)); 664044961713Sgirish } 664144961713Sgirish break; 664244961713Sgirish } else { 664344961713Sgirish h_hw_p = hw_p; 664444961713Sgirish } 664544961713Sgirish } 664644961713Sgirish 664744961713Sgirish MUTEX_EXIT(&nxge_common_lock); 664844961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66494045d941Ssowmini "==> nxge_uninit_common_device (nxge_hw_list) $%p", 66504045d941Ssowmini nxge_hw_list)); 665144961713Sgirish 665244961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<= nxge_uninit_common_device")); 665344961713Sgirish } 665459ac0c16Sdavemq 665559ac0c16Sdavemq /* 66562e59129aSraghus * Determines the number of ports from the niu_type or the platform type. 665759ac0c16Sdavemq * Returns the number of ports, or returns zero on failure. 665859ac0c16Sdavemq */ 665959ac0c16Sdavemq 666059ac0c16Sdavemq int 66612e59129aSraghus nxge_get_nports(p_nxge_t nxgep) 666259ac0c16Sdavemq { 666359ac0c16Sdavemq int nports = 0; 666459ac0c16Sdavemq 66652e59129aSraghus switch (nxgep->niu_type) { 666659ac0c16Sdavemq case N2_NIU: 666759ac0c16Sdavemq case NEPTUNE_2_10GF: 666859ac0c16Sdavemq nports = 2; 666959ac0c16Sdavemq break; 667059ac0c16Sdavemq case NEPTUNE_4_1GC: 667159ac0c16Sdavemq case NEPTUNE_2_10GF_2_1GC: 667259ac0c16Sdavemq case NEPTUNE_1_10GF_3_1GC: 667359ac0c16Sdavemq case NEPTUNE_1_1GC_1_10GF_2_1GC: 667459a835ddSjoycey case NEPTUNE_2_10GF_2_1GRF: 667559ac0c16Sdavemq nports = 4; 667659ac0c16Sdavemq break; 667759ac0c16Sdavemq default: 66782e59129aSraghus switch (nxgep->platform_type) { 66792e59129aSraghus case P_NEPTUNE_NIU: 66802e59129aSraghus case P_NEPTUNE_ATLAS_2PORT: 66812e59129aSraghus nports = 2; 66822e59129aSraghus break; 66832e59129aSraghus case P_NEPTUNE_ATLAS_4PORT: 66842e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 66852e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 668623b952a3SSantwona Behera case P_NEPTUNE_ROCK: 6687d81011f0Ssbehera case P_NEPTUNE_ALONSO: 66882e59129aSraghus nports = 4; 66892e59129aSraghus break; 66902e59129aSraghus default: 66912e59129aSraghus break; 66922e59129aSraghus } 669359ac0c16Sdavemq break; 669459ac0c16Sdavemq } 669559ac0c16Sdavemq 669659ac0c16Sdavemq return (nports); 669759ac0c16Sdavemq } 6698ec090658Sml 6699ec090658Sml /* 6700ec090658Sml * The following two functions are to support 6701ec090658Sml * PSARC/2007/453 MSI-X interrupt limit override. 6702ec090658Sml */ 6703ec090658Sml static int 6704ec090658Sml nxge_create_msi_property(p_nxge_t nxgep) 6705ec090658Sml { 6706ec090658Sml int nmsi; 6707ec090658Sml extern int ncpus; 6708ec090658Sml 6709ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==>nxge_create_msi_property")); 6710ec090658Sml 6711ec090658Sml switch (nxgep->mac.portmode) { 6712ec090658Sml case PORT_10G_COPPER: 6713ec090658Sml case PORT_10G_FIBER: 671400161856Syc case PORT_10G_TN1010: 6715ec090658Sml (void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip, 6716ec090658Sml DDI_PROP_CANSLEEP, "#msix-request", NULL, 0); 6717ec090658Sml /* 6718ec090658Sml * The maximum MSI-X requested will be 8. 6719ec090658Sml * If the # of CPUs is less than 8, we will reqeust 6720ec090658Sml * # MSI-X based on the # of CPUs. 6721ec090658Sml */ 6722ec090658Sml if (ncpus >= NXGE_MSIX_REQUEST_10G) { 6723ec090658Sml nmsi = NXGE_MSIX_REQUEST_10G; 6724ec090658Sml } else { 6725ec090658Sml nmsi = ncpus; 6726ec090658Sml } 6727ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6728ec090658Sml "==>nxge_create_msi_property(10G): exists 0x%x (nmsi %d)", 6729ec090658Sml ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 6730ec090658Sml DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 6731ec090658Sml break; 6732ec090658Sml 6733ec090658Sml default: 6734ec090658Sml nmsi = NXGE_MSIX_REQUEST_1G; 6735ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6736ec090658Sml "==>nxge_create_msi_property(1G): exists 0x%x (nmsi %d)", 6737ec090658Sml ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 6738ec090658Sml DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 6739ec090658Sml break; 6740ec090658Sml } 6741ec090658Sml 6742ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<==nxge_create_msi_property")); 6743ec090658Sml return (nmsi); 6744ec090658Sml } 67454045d941Ssowmini 67464045d941Ssowmini /* ARGSUSED */ 67474045d941Ssowmini static int 67484045d941Ssowmini nxge_get_def_val(nxge_t *nxgep, mac_prop_id_t pr_num, uint_t pr_valsize, 67494045d941Ssowmini void *pr_val) 67504045d941Ssowmini { 67514045d941Ssowmini int err = 0; 67524045d941Ssowmini link_flowctrl_t fl; 67534045d941Ssowmini 67544045d941Ssowmini switch (pr_num) { 67553fd94f8cSam case MAC_PROP_AUTONEG: 67564045d941Ssowmini *(uint8_t *)pr_val = 1; 67574045d941Ssowmini break; 67583fd94f8cSam case MAC_PROP_FLOWCTRL: 67594045d941Ssowmini if (pr_valsize < sizeof (link_flowctrl_t)) 67604045d941Ssowmini return (EINVAL); 67614045d941Ssowmini fl = LINK_FLOWCTRL_RX; 67624045d941Ssowmini bcopy(&fl, pr_val, sizeof (fl)); 67634045d941Ssowmini break; 67643fd94f8cSam case MAC_PROP_ADV_1000FDX_CAP: 67653fd94f8cSam case MAC_PROP_EN_1000FDX_CAP: 67664045d941Ssowmini *(uint8_t *)pr_val = 1; 67674045d941Ssowmini break; 67683fd94f8cSam case MAC_PROP_ADV_100FDX_CAP: 67693fd94f8cSam case MAC_PROP_EN_100FDX_CAP: 67704045d941Ssowmini *(uint8_t *)pr_val = 1; 67714045d941Ssowmini break; 67724045d941Ssowmini default: 67734045d941Ssowmini err = ENOTSUP; 67744045d941Ssowmini break; 67754045d941Ssowmini } 67764045d941Ssowmini return (err); 67774045d941Ssowmini } 67786f157acbSml 67796f157acbSml 67806f157acbSml /* 67816f157acbSml * The following is a software around for the Neptune hardware's 67826f157acbSml * interrupt bugs; The Neptune hardware may generate spurious interrupts when 67836f157acbSml * an interrupr handler is removed. 67846f157acbSml */ 67856f157acbSml #define NXGE_PCI_PORT_LOGIC_OFFSET 0x98 67866f157acbSml #define NXGE_PIM_RESET (1ULL << 29) 67876f157acbSml #define NXGE_GLU_RESET (1ULL << 30) 67886f157acbSml #define NXGE_NIU_RESET (1ULL << 31) 67896f157acbSml #define NXGE_PCI_RESET_ALL (NXGE_PIM_RESET | \ 67906f157acbSml NXGE_GLU_RESET | \ 67916f157acbSml NXGE_NIU_RESET) 67926f157acbSml 67936f157acbSml #define NXGE_WAIT_QUITE_TIME 200000 67946f157acbSml #define NXGE_WAIT_QUITE_RETRY 40 67956f157acbSml #define NXGE_PCI_RESET_WAIT 1000000 /* one second */ 67966f157acbSml 67976f157acbSml static void 67986f157acbSml nxge_niu_peu_reset(p_nxge_t nxgep) 67996f157acbSml { 68006f157acbSml uint32_t rvalue; 68016f157acbSml p_nxge_hw_list_t hw_p; 68026f157acbSml p_nxge_t fnxgep; 68036f157acbSml int i, j; 68046f157acbSml 68056f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_niu_peu_reset")); 68066f157acbSml if ((hw_p = nxgep->nxge_hw_p) == NULL) { 68076f157acbSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 68086f157acbSml "==> nxge_niu_peu_reset: NULL hardware pointer")); 68096f157acbSml return; 68106f157acbSml } 68116f157acbSml 68126f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 68136f157acbSml "==> nxge_niu_peu_reset: flags 0x%x link timer id %d timer id %d", 68146f157acbSml hw_p->flags, nxgep->nxge_link_poll_timerid, 68156f157acbSml nxgep->nxge_timerid)); 68166f157acbSml 68176f157acbSml MUTEX_ENTER(&hw_p->nxge_cfg_lock); 68186f157acbSml /* 68196f157acbSml * Make sure other instances from the same hardware 68206f157acbSml * stop sending PIO and in quiescent state. 68216f157acbSml */ 68226f157acbSml for (i = 0; i < NXGE_MAX_PORTS; i++) { 68236f157acbSml fnxgep = hw_p->nxge_p[i]; 68246f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 68256f157acbSml "==> nxge_niu_peu_reset: checking entry %d " 68266f157acbSml "nxgep $%p", i, fnxgep)); 68276f157acbSml #ifdef NXGE_DEBUG 68286f157acbSml if (fnxgep) { 68296f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 68306f157acbSml "==> nxge_niu_peu_reset: entry %d (function %d) " 68316f157acbSml "link timer id %d hw timer id %d", 68326f157acbSml i, fnxgep->function_num, 68336f157acbSml fnxgep->nxge_link_poll_timerid, 68346f157acbSml fnxgep->nxge_timerid)); 68356f157acbSml } 68366f157acbSml #endif 68376f157acbSml if (fnxgep && fnxgep != nxgep && 68386f157acbSml (fnxgep->nxge_timerid || fnxgep->nxge_link_poll_timerid)) { 68396f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 68406f157acbSml "==> nxge_niu_peu_reset: checking $%p " 68416f157acbSml "(function %d) timer ids", 68426f157acbSml fnxgep, fnxgep->function_num)); 68436f157acbSml for (j = 0; j < NXGE_WAIT_QUITE_RETRY; j++) { 68446f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 68456f157acbSml "==> nxge_niu_peu_reset: waiting")); 68466f157acbSml NXGE_DELAY(NXGE_WAIT_QUITE_TIME); 68476f157acbSml if (!fnxgep->nxge_timerid && 68486f157acbSml !fnxgep->nxge_link_poll_timerid) { 68496f157acbSml break; 68506f157acbSml } 68516f157acbSml } 68526f157acbSml NXGE_DELAY(NXGE_WAIT_QUITE_TIME); 68536f157acbSml if (fnxgep->nxge_timerid || 68546f157acbSml fnxgep->nxge_link_poll_timerid) { 68556f157acbSml MUTEX_EXIT(&hw_p->nxge_cfg_lock); 68566f157acbSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 68576f157acbSml "<== nxge_niu_peu_reset: cannot reset " 68586f157acbSml "hardware (devices are still in use)")); 68596f157acbSml return; 68606f157acbSml } 68616f157acbSml } 68626f157acbSml } 68636f157acbSml 68646f157acbSml if ((hw_p->flags & COMMON_RESET_NIU_PCI) != COMMON_RESET_NIU_PCI) { 68656f157acbSml hw_p->flags |= COMMON_RESET_NIU_PCI; 68666f157acbSml rvalue = pci_config_get32(nxgep->dev_regs->nxge_pciregh, 68676f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET); 68686f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 68696f157acbSml "nxge_niu_peu_reset: read offset 0x%x (%d) " 68706f157acbSml "(data 0x%x)", 68716f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, 68726f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, 68736f157acbSml rvalue)); 68746f157acbSml 68756f157acbSml rvalue |= NXGE_PCI_RESET_ALL; 68766f157acbSml pci_config_put32(nxgep->dev_regs->nxge_pciregh, 68776f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, rvalue); 68786f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 68796f157acbSml "nxge_niu_peu_reset: RESETTING NIU: write NIU reset 0x%x", 68806f157acbSml rvalue)); 68816f157acbSml 68826f157acbSml NXGE_DELAY(NXGE_PCI_RESET_WAIT); 68836f157acbSml } 68846f157acbSml 68856f157acbSml MUTEX_EXIT(&hw_p->nxge_cfg_lock); 68866f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_niu_peu_reset")); 68876f157acbSml } 6888d6d3405fSml 6889d6d3405fSml static void 6890d6d3405fSml nxge_set_pci_replay_timeout(p_nxge_t nxgep) 6891d6d3405fSml { 6892*da14cebeSEric Cheng p_dev_regs_t dev_regs; 6893d6d3405fSml uint32_t value; 6894d6d3405fSml 6895d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_set_pci_replay_timeout")); 6896d6d3405fSml 6897d6d3405fSml if (!nxge_set_replay_timer) { 6898d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 6899d6d3405fSml "==> nxge_set_pci_replay_timeout: will not change " 6900d6d3405fSml "the timeout")); 6901d6d3405fSml return; 6902d6d3405fSml } 6903d6d3405fSml 6904d6d3405fSml dev_regs = nxgep->dev_regs; 6905d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 6906d6d3405fSml "==> nxge_set_pci_replay_timeout: dev_regs 0x%p pcireg 0x%p", 6907d6d3405fSml dev_regs, dev_regs->nxge_pciregh)); 6908d6d3405fSml 6909d6d3405fSml if (dev_regs == NULL || (dev_regs->nxge_pciregh == NULL)) { 6910f720bc57Syc NXGE_DEBUG_MSG((nxgep, DDI_CTL, 6911d6d3405fSml "==> nxge_set_pci_replay_timeout: NULL dev_regs $%p or " 6912d6d3405fSml "no PCI handle", 6913d6d3405fSml dev_regs)); 6914d6d3405fSml return; 6915d6d3405fSml } 6916d6d3405fSml value = (pci_config_get32(dev_regs->nxge_pciregh, 6917d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET) | 6918d6d3405fSml (nxge_replay_timeout << PCI_REPLAY_TIMEOUT_SHIFT)); 6919d6d3405fSml 6920d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 6921d6d3405fSml "nxge_set_pci_replay_timeout: replay timeout value before set 0x%x " 6922d6d3405fSml "(timeout value to set 0x%x at offset 0x%x) value 0x%x", 6923d6d3405fSml pci_config_get32(dev_regs->nxge_pciregh, 6924d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET), nxge_replay_timeout, 6925d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET, value)); 6926d6d3405fSml 6927d6d3405fSml pci_config_put32(dev_regs->nxge_pciregh, PCI_REPLAY_TIMEOUT_CFG_OFFSET, 6928d6d3405fSml value); 6929d6d3405fSml 6930d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 6931d6d3405fSml "nxge_set_pci_replay_timeout: replay timeout value after set 0x%x", 6932d6d3405fSml pci_config_get32(dev_regs->nxge_pciregh, 6933d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET))); 6934d6d3405fSml 6935d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_set_pci_replay_timeout")); 6936d6d3405fSml } 693719397407SSherry Moore 693819397407SSherry Moore /* 693919397407SSherry Moore * quiesce(9E) entry point. 694019397407SSherry Moore * 694119397407SSherry Moore * This function is called when the system is single-threaded at high 694219397407SSherry Moore * PIL with preemption disabled. Therefore, this function must not be 694319397407SSherry Moore * blocked. 694419397407SSherry Moore * 694519397407SSherry Moore * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 694619397407SSherry Moore * DDI_FAILURE indicates an error condition and should almost never happen. 694719397407SSherry Moore */ 694819397407SSherry Moore static int 694919397407SSherry Moore nxge_quiesce(dev_info_t *dip) 695019397407SSherry Moore { 695119397407SSherry Moore int instance = ddi_get_instance(dip); 695219397407SSherry Moore p_nxge_t nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 695319397407SSherry Moore 695419397407SSherry Moore if (nxgep == NULL) 695519397407SSherry Moore return (DDI_FAILURE); 695619397407SSherry Moore 695719397407SSherry Moore /* Turn off debugging */ 695819397407SSherry Moore nxge_debug_level = NO_DEBUG; 695919397407SSherry Moore nxgep->nxge_debug_level = NO_DEBUG; 696019397407SSherry Moore npi_debug_level = NO_DEBUG; 696119397407SSherry Moore 696219397407SSherry Moore /* 696319397407SSherry Moore * Stop link monitor only when linkchkmod is interrupt based 696419397407SSherry Moore */ 696519397407SSherry Moore if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 696619397407SSherry Moore (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 696719397407SSherry Moore } 696819397407SSherry Moore 696919397407SSherry Moore (void) nxge_intr_hw_disable(nxgep); 697019397407SSherry Moore 697119397407SSherry Moore /* 697219397407SSherry Moore * Reset the receive MAC side. 697319397407SSherry Moore */ 697419397407SSherry Moore (void) nxge_rx_mac_disable(nxgep); 697519397407SSherry Moore 697619397407SSherry Moore /* Disable and soft reset the IPP */ 697719397407SSherry Moore if (!isLDOMguest(nxgep)) 697819397407SSherry Moore (void) nxge_ipp_disable(nxgep); 697919397407SSherry Moore 698019397407SSherry Moore /* 698119397407SSherry Moore * Reset the transmit/receive DMA side. 698219397407SSherry Moore */ 698319397407SSherry Moore (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 698419397407SSherry Moore (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 698519397407SSherry Moore 698619397407SSherry Moore /* 698719397407SSherry Moore * Reset the transmit MAC side. 698819397407SSherry Moore */ 698919397407SSherry Moore (void) nxge_tx_mac_disable(nxgep); 699019397407SSherry Moore 699119397407SSherry Moore return (DDI_SUCCESS); 699219397407SSherry Moore } 6993