144961713Sgirish /* 244961713Sgirish * CDDL HEADER START 344961713Sgirish * 444961713Sgirish * The contents of this file are subject to the terms of the 544961713Sgirish * Common Development and Distribution License (the "License"). 644961713Sgirish * You may not use this file except in compliance with the License. 744961713Sgirish * 844961713Sgirish * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 944961713Sgirish * or http://www.opensolaris.org/os/licensing. 1044961713Sgirish * See the License for the specific language governing permissions 1144961713Sgirish * and limitations under the License. 1244961713Sgirish * 1344961713Sgirish * When distributing Covered Code, include this CDDL HEADER in each 1444961713Sgirish * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1544961713Sgirish * If applicable, add the following below this CDDL HEADER, with the 1644961713Sgirish * fields enclosed by brackets "[]" replaced with your own identifying 1744961713Sgirish * information: Portions Copyright [yyyy] [name of copyright owner] 1844961713Sgirish * 1944961713Sgirish * CDDL HEADER END 2044961713Sgirish */ 2148056c53SMichael Speer 2244961713Sgirish /* 237b26d9ffSSantwona Behera * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2444961713Sgirish * Use is subject to license terms. 2544961713Sgirish */ 2644961713Sgirish 2744961713Sgirish /* 2844961713Sgirish * SunOs MT STREAMS NIU/Neptune 10Gb Ethernet Device Driver. 2944961713Sgirish */ 3044961713Sgirish #include <sys/nxge/nxge_impl.h> 31678453a8Sspeer #include <sys/nxge/nxge_hio.h> 32678453a8Sspeer #include <sys/nxge/nxge_rxdma.h> 3314ea4bb7Ssd #include <sys/pcie.h> 3444961713Sgirish 3544961713Sgirish uint32_t nxge_use_partition = 0; /* debug partition flag */ 3644961713Sgirish uint32_t nxge_dma_obp_props_only = 1; /* use obp published props */ 3744961713Sgirish uint32_t nxge_use_rdc_intr = 1; /* debug to assign rdc intr */ 3844961713Sgirish /* 39ec090658Sml * PSARC/2007/453 MSI-X interrupt limit override 4044961713Sgirish */ 41ec090658Sml uint32_t nxge_msi_enable = 2; 4244961713Sgirish 436f157acbSml /* 446f157acbSml * Software workaround for a Neptune (PCI-E) 456f157acbSml * hardware interrupt bug which the hardware 466f157acbSml * may generate spurious interrupts after the 476f157acbSml * device interrupt handler was removed. If this flag 486f157acbSml * is enabled, the driver will reset the 496f157acbSml * hardware when devices are being detached. 506f157acbSml */ 516f157acbSml uint32_t nxge_peu_reset_enable = 0; 526f157acbSml 53b4d05839Sml /* 54b4d05839Sml * Software workaround for the hardware 55b4d05839Sml * checksum bugs that affect packet transmission 56b4d05839Sml * and receive: 57b4d05839Sml * 58b4d05839Sml * Usage of nxge_cksum_offload: 59b4d05839Sml * 60b4d05839Sml * (1) nxge_cksum_offload = 0 (default): 61b4d05839Sml * - transmits packets: 62b4d05839Sml * TCP: uses the hardware checksum feature. 63b4d05839Sml * UDP: driver will compute the software checksum 64b4d05839Sml * based on the partial checksum computed 65b4d05839Sml * by the IP layer. 66b4d05839Sml * - receives packets 67b4d05839Sml * TCP: marks packets checksum flags based on hardware result. 68b4d05839Sml * UDP: will not mark checksum flags. 69b4d05839Sml * 70b4d05839Sml * (2) nxge_cksum_offload = 1: 71b4d05839Sml * - transmit packets: 72b4d05839Sml * TCP/UDP: uses the hardware checksum feature. 73b4d05839Sml * - receives packets 74b4d05839Sml * TCP/UDP: marks packet checksum flags based on hardware result. 75b4d05839Sml * 76b4d05839Sml * (3) nxge_cksum_offload = 2: 77b4d05839Sml * - The driver will not register its checksum capability. 78b4d05839Sml * Checksum for both TCP and UDP will be computed 79b4d05839Sml * by the stack. 80b4d05839Sml * - The software LSO is not allowed in this case. 81b4d05839Sml * 82b4d05839Sml * (4) nxge_cksum_offload > 2: 83b4d05839Sml * - Will be treated as it is set to 2 84b4d05839Sml * (stack will compute the checksum). 85b4d05839Sml * 86b4d05839Sml * (5) If the hardware bug is fixed, this workaround 87b4d05839Sml * needs to be updated accordingly to reflect 88b4d05839Sml * the new hardware revision. 89b4d05839Sml */ 90b4d05839Sml uint32_t nxge_cksum_offload = 0; 91678453a8Sspeer 9244961713Sgirish /* 9344961713Sgirish * Globals: tunable parameters (/etc/system or adb) 9444961713Sgirish * 9544961713Sgirish */ 9644961713Sgirish uint32_t nxge_rbr_size = NXGE_RBR_RBB_DEFAULT; 9744961713Sgirish uint32_t nxge_rbr_spare_size = 0; 9844961713Sgirish uint32_t nxge_rcr_size = NXGE_RCR_DEFAULT; 9944961713Sgirish uint32_t nxge_tx_ring_size = NXGE_TX_RING_DEFAULT; 100b3a0105bSspeer boolean_t nxge_no_msg = B_TRUE; /* control message display */ 10144961713Sgirish uint32_t nxge_no_link_notify = 0; /* control DL_NOTIFY */ 10244961713Sgirish uint32_t nxge_bcopy_thresh = TX_BCOPY_MAX; 10344961713Sgirish uint32_t nxge_dvma_thresh = TX_FASTDVMA_MIN; 10444961713Sgirish uint32_t nxge_dma_stream_thresh = TX_STREAM_MIN; 10544961713Sgirish uint32_t nxge_jumbo_mtu = TX_JUMBO_MTU; 1061f8914d5Sml nxge_tx_mode_t nxge_tx_scheme = NXGE_USE_SERIAL; 10744961713Sgirish 10830ac2e7bSml /* MAX LSO size */ 10930ac2e7bSml #define NXGE_LSO_MAXLEN 65535 11030ac2e7bSml uint32_t nxge_lso_max = NXGE_LSO_MAXLEN; 11130ac2e7bSml 11244961713Sgirish 11344961713Sgirish /* 11444961713Sgirish * Add tunable to reduce the amount of time spent in the 11544961713Sgirish * ISR doing Rx Processing. 11644961713Sgirish */ 11744961713Sgirish uint32_t nxge_max_rx_pkts = 1024; 11844961713Sgirish 11944961713Sgirish /* 12044961713Sgirish * Tunables to manage the receive buffer blocks. 12144961713Sgirish * 12244961713Sgirish * nxge_rx_threshold_hi: copy all buffers. 12344961713Sgirish * nxge_rx_bcopy_size_type: receive buffer block size type. 12444961713Sgirish * nxge_rx_threshold_lo: copy only up to tunable block size type. 12544961713Sgirish */ 12644961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_hi = NXGE_RX_COPY_6; 12744961713Sgirish nxge_rxbuf_type_t nxge_rx_buf_size_type = RCR_PKTBUFSZ_0; 12844961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_lo = NXGE_RX_COPY_3; 12944961713Sgirish 130678453a8Sspeer /* Use kmem_alloc() to allocate data buffers. */ 131b1000363Sml #if defined(_BIG_ENDIAN) 132d00f30bbSspeer uint32_t nxge_use_kmem_alloc = 1; 133678453a8Sspeer #else 134d00f30bbSspeer uint32_t nxge_use_kmem_alloc = 0; 135678453a8Sspeer #endif 136678453a8Sspeer 13744961713Sgirish rtrace_t npi_rtracebuf; 13844961713Sgirish 139d6d3405fSml /* 140d6d3405fSml * The hardware sometimes fails to allow enough time for the link partner 141d6d3405fSml * to send an acknowledgement for packets that the hardware sent to it. The 142d6d3405fSml * hardware resends the packets earlier than it should be in those instances. 143d6d3405fSml * This behavior caused some switches to acknowledge the wrong packets 144d6d3405fSml * and it triggered the fatal error. 145d6d3405fSml * This software workaround is to set the replay timer to a value 146d6d3405fSml * suggested by the hardware team. 147d6d3405fSml * 148d6d3405fSml * PCI config space replay timer register: 149d6d3405fSml * The following replay timeout value is 0xc 150d6d3405fSml * for bit 14:18. 151d6d3405fSml */ 152d6d3405fSml #define PCI_REPLAY_TIMEOUT_CFG_OFFSET 0xb8 153d6d3405fSml #define PCI_REPLAY_TIMEOUT_SHIFT 14 154d6d3405fSml 155d6d3405fSml uint32_t nxge_set_replay_timer = 1; 156d6d3405fSml uint32_t nxge_replay_timeout = 0xc; 157d6d3405fSml 158cf020df9Sml /* 159cf020df9Sml * The transmit serialization sometimes causes 160cf020df9Sml * longer sleep before calling the driver transmit 161cf020df9Sml * function as it sleeps longer than it should. 162cf020df9Sml * The performace group suggests that a time wait tunable 163cf020df9Sml * can be used to set the maximum wait time when needed 164cf020df9Sml * and the default is set to 1 tick. 165cf020df9Sml */ 166cf020df9Sml uint32_t nxge_tx_serial_maxsleep = 1; 167cf020df9Sml 16844961713Sgirish #if defined(sun4v) 16944961713Sgirish /* 17044961713Sgirish * Hypervisor N2/NIU services information. 17144961713Sgirish */ 17244961713Sgirish static hsvc_info_t niu_hsvc = { 17344961713Sgirish HSVC_REV_1, NULL, HSVC_GROUP_NIU, NIU_MAJOR_VER, 17444961713Sgirish NIU_MINOR_VER, "nxge" 17544961713Sgirish }; 176678453a8Sspeer 177678453a8Sspeer static int nxge_hsvc_register(p_nxge_t); 17844961713Sgirish #endif 17944961713Sgirish 18044961713Sgirish /* 18144961713Sgirish * Function Prototypes 18244961713Sgirish */ 18344961713Sgirish static int nxge_attach(dev_info_t *, ddi_attach_cmd_t); 18444961713Sgirish static int nxge_detach(dev_info_t *, ddi_detach_cmd_t); 18544961713Sgirish static void nxge_unattach(p_nxge_t); 18619397407SSherry Moore static int nxge_quiesce(dev_info_t *); 18744961713Sgirish 18844961713Sgirish #if NXGE_PROPERTY 18944961713Sgirish static void nxge_remove_hard_properties(p_nxge_t); 19044961713Sgirish #endif 19144961713Sgirish 192678453a8Sspeer /* 193678453a8Sspeer * These two functions are required by nxge_hio.c 194678453a8Sspeer */ 195da14cebeSEric Cheng extern int nxge_m_mmac_remove(void *arg, int slot); 196651ce697SMichael Speer extern void nxge_grp_cleanup(p_nxge_t nxge); 197678453a8Sspeer 19844961713Sgirish static nxge_status_t nxge_setup_system_dma_pages(p_nxge_t); 19944961713Sgirish 20044961713Sgirish static nxge_status_t nxge_setup_mutexes(p_nxge_t); 20144961713Sgirish static void nxge_destroy_mutexes(p_nxge_t); 20244961713Sgirish 20344961713Sgirish static nxge_status_t nxge_map_regs(p_nxge_t nxgep); 20444961713Sgirish static void nxge_unmap_regs(p_nxge_t nxgep); 20544961713Sgirish #ifdef NXGE_DEBUG 20644961713Sgirish static void nxge_test_map_regs(p_nxge_t nxgep); 20744961713Sgirish #endif 20844961713Sgirish 20944961713Sgirish static nxge_status_t nxge_add_intrs(p_nxge_t nxgep); 21044961713Sgirish static void nxge_remove_intrs(p_nxge_t nxgep); 21144961713Sgirish 21244961713Sgirish static nxge_status_t nxge_add_intrs_adv(p_nxge_t nxgep); 21344961713Sgirish static nxge_status_t nxge_add_intrs_adv_type(p_nxge_t, uint32_t); 21444961713Sgirish static nxge_status_t nxge_add_intrs_adv_type_fix(p_nxge_t, uint32_t); 21544961713Sgirish static void nxge_intrs_enable(p_nxge_t nxgep); 21644961713Sgirish static void nxge_intrs_disable(p_nxge_t nxgep); 21744961713Sgirish 21844961713Sgirish static void nxge_suspend(p_nxge_t); 21944961713Sgirish static nxge_status_t nxge_resume(p_nxge_t); 22044961713Sgirish 22144961713Sgirish static nxge_status_t nxge_setup_dev(p_nxge_t); 22244961713Sgirish static void nxge_destroy_dev(p_nxge_t); 22344961713Sgirish 22444961713Sgirish static nxge_status_t nxge_alloc_mem_pool(p_nxge_t); 22544961713Sgirish static void nxge_free_mem_pool(p_nxge_t); 22644961713Sgirish 227678453a8Sspeer nxge_status_t nxge_alloc_rx_mem_pool(p_nxge_t); 22844961713Sgirish static void nxge_free_rx_mem_pool(p_nxge_t); 22944961713Sgirish 230678453a8Sspeer nxge_status_t nxge_alloc_tx_mem_pool(p_nxge_t); 23144961713Sgirish static void nxge_free_tx_mem_pool(p_nxge_t); 23244961713Sgirish 23344961713Sgirish static nxge_status_t nxge_dma_mem_alloc(p_nxge_t, dma_method_t, 23444961713Sgirish struct ddi_dma_attr *, 23544961713Sgirish size_t, ddi_device_acc_attr_t *, uint_t, 23644961713Sgirish p_nxge_dma_common_t); 23744961713Sgirish 23844961713Sgirish static void nxge_dma_mem_free(p_nxge_dma_common_t); 239678453a8Sspeer static void nxge_dma_free_rx_data_buf(p_nxge_dma_common_t); 24044961713Sgirish 24144961713Sgirish static nxge_status_t nxge_alloc_rx_buf_dma(p_nxge_t, uint16_t, 24244961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 24344961713Sgirish static void nxge_free_rx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 24444961713Sgirish 24544961713Sgirish static nxge_status_t nxge_alloc_rx_cntl_dma(p_nxge_t, uint16_t, 24644961713Sgirish p_nxge_dma_common_t *, size_t); 24744961713Sgirish static void nxge_free_rx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 24844961713Sgirish 249678453a8Sspeer extern nxge_status_t nxge_alloc_tx_buf_dma(p_nxge_t, uint16_t, 25044961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 25144961713Sgirish static void nxge_free_tx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 25244961713Sgirish 253678453a8Sspeer extern nxge_status_t nxge_alloc_tx_cntl_dma(p_nxge_t, uint16_t, 25444961713Sgirish p_nxge_dma_common_t *, 25544961713Sgirish size_t); 25644961713Sgirish static void nxge_free_tx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 25744961713Sgirish 25844961713Sgirish static int nxge_init_common_dev(p_nxge_t); 25944961713Sgirish static void nxge_uninit_common_dev(p_nxge_t); 2604045d941Ssowmini extern int nxge_param_set_mac(p_nxge_t, queue_t *, mblk_t *, 2614045d941Ssowmini char *, caddr_t); 262e759c33aSMichael Speer #if defined(sun4v) 263e759c33aSMichael Speer extern nxge_status_t nxge_hio_rdc_enable(p_nxge_t nxgep); 264e759c33aSMichael Speer extern nxge_status_t nxge_hio_rdc_intr_arm(p_nxge_t nxge, boolean_t arm); 265e759c33aSMichael Speer #endif 26644961713Sgirish 26744961713Sgirish /* 26844961713Sgirish * The next declarations are for the GLDv3 interface. 26944961713Sgirish */ 27044961713Sgirish static int nxge_m_start(void *); 27144961713Sgirish static void nxge_m_stop(void *); 27244961713Sgirish static int nxge_m_multicst(void *, boolean_t, const uint8_t *); 27344961713Sgirish static int nxge_m_promisc(void *, boolean_t); 27444961713Sgirish static void nxge_m_ioctl(void *, queue_t *, mblk_t *); 275*63f531d1SSriharsha Basavapatna nxge_status_t nxge_mac_register(p_nxge_t); 276da14cebeSEric Cheng static int nxge_altmac_set(p_nxge_t nxgep, uint8_t *mac_addr, 277da14cebeSEric Cheng int slot, int rdctbl, boolean_t usetbl); 278da14cebeSEric Cheng void nxge_mmac_kstat_update(p_nxge_t nxgep, int slot, 27958324dfcSspeer boolean_t factory); 280da14cebeSEric Cheng 281da14cebeSEric Cheng static void nxge_m_getfactaddr(void *, uint_t, uint8_t *); 2821bd6825cSml static boolean_t nxge_m_getcapab(void *, mac_capab_t, void *); 2831bd6825cSml static int nxge_m_setprop(void *, const char *, mac_prop_id_t, 2841bd6825cSml uint_t, const void *); 2851bd6825cSml static int nxge_m_getprop(void *, const char *, mac_prop_id_t, 286afdda45fSVasumathi Sundaram - Sun Microsystems uint_t, uint_t, void *, uint_t *); 2871bd6825cSml static int nxge_set_priv_prop(nxge_t *, const char *, uint_t, 2881bd6825cSml const void *); 2894045d941Ssowmini static int nxge_get_priv_prop(nxge_t *, const char *, uint_t, uint_t, 290afdda45fSVasumathi Sundaram - Sun Microsystems void *, uint_t *); 2914045d941Ssowmini static int nxge_get_def_val(nxge_t *, mac_prop_id_t, uint_t, void *); 292da14cebeSEric Cheng static void nxge_fill_ring(void *, mac_ring_type_t, const int, const int, 293da14cebeSEric Cheng mac_ring_info_t *, mac_ring_handle_t); 294da14cebeSEric Cheng static void nxge_group_add_ring(mac_group_driver_t, mac_ring_driver_t, 295da14cebeSEric Cheng mac_ring_type_t); 296da14cebeSEric Cheng static void nxge_group_rem_ring(mac_group_driver_t, mac_ring_driver_t, 297da14cebeSEric Cheng mac_ring_type_t); 2984045d941Ssowmini 2996f157acbSml static void nxge_niu_peu_reset(p_nxge_t nxgep); 300d6d3405fSml static void nxge_set_pci_replay_timeout(nxge_t *); 3014045d941Ssowmini 3024045d941Ssowmini mac_priv_prop_t nxge_priv_props[] = { 3034045d941Ssowmini {"_adv_10gfdx_cap", MAC_PROP_PERM_RW}, 3044045d941Ssowmini {"_adv_pause_cap", MAC_PROP_PERM_RW}, 3054045d941Ssowmini {"_function_number", MAC_PROP_PERM_READ}, 3064045d941Ssowmini {"_fw_version", MAC_PROP_PERM_READ}, 3074045d941Ssowmini {"_port_mode", MAC_PROP_PERM_READ}, 3084045d941Ssowmini {"_hot_swap_phy", MAC_PROP_PERM_READ}, 3094045d941Ssowmini {"_rxdma_intr_time", MAC_PROP_PERM_RW}, 3104045d941Ssowmini {"_rxdma_intr_pkts", MAC_PROP_PERM_RW}, 3114045d941Ssowmini {"_class_opt_ipv4_tcp", MAC_PROP_PERM_RW}, 3124045d941Ssowmini {"_class_opt_ipv4_udp", MAC_PROP_PERM_RW}, 3134045d941Ssowmini {"_class_opt_ipv4_ah", MAC_PROP_PERM_RW}, 3144045d941Ssowmini {"_class_opt_ipv4_sctp", MAC_PROP_PERM_RW}, 3154045d941Ssowmini {"_class_opt_ipv6_tcp", MAC_PROP_PERM_RW}, 3164045d941Ssowmini {"_class_opt_ipv6_udp", MAC_PROP_PERM_RW}, 3174045d941Ssowmini {"_class_opt_ipv6_ah", MAC_PROP_PERM_RW}, 3184045d941Ssowmini {"_class_opt_ipv6_sctp", MAC_PROP_PERM_RW}, 3194045d941Ssowmini {"_soft_lso_enable", MAC_PROP_PERM_RW} 3204045d941Ssowmini }; 3214045d941Ssowmini 3224045d941Ssowmini #define NXGE_MAX_PRIV_PROPS \ 3234045d941Ssowmini (sizeof (nxge_priv_props)/sizeof (mac_priv_prop_t)) 3241bd6825cSml 32544961713Sgirish #define NXGE_NEPTUNE_MAGIC 0x4E584745UL 32644961713Sgirish #define MAX_DUMP_SZ 256 32744961713Sgirish 3281bd6825cSml #define NXGE_M_CALLBACK_FLAGS \ 329da14cebeSEric Cheng (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP) 33044961713Sgirish 331678453a8Sspeer mac_callbacks_t nxge_m_callbacks = { 33244961713Sgirish NXGE_M_CALLBACK_FLAGS, 33344961713Sgirish nxge_m_stat, 33444961713Sgirish nxge_m_start, 33544961713Sgirish nxge_m_stop, 33644961713Sgirish nxge_m_promisc, 33744961713Sgirish nxge_m_multicst, 338da14cebeSEric Cheng NULL, 339da14cebeSEric Cheng NULL, 34044961713Sgirish nxge_m_ioctl, 3411bd6825cSml nxge_m_getcapab, 3421bd6825cSml NULL, 3431bd6825cSml NULL, 3441bd6825cSml nxge_m_setprop, 3451bd6825cSml nxge_m_getprop 34644961713Sgirish }; 34744961713Sgirish 34844961713Sgirish void 34944961713Sgirish nxge_err_inject(p_nxge_t, queue_t *, mblk_t *); 35044961713Sgirish 351ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override. */ 352ec090658Sml #define NXGE_MSIX_REQUEST_10G 8 353ec090658Sml #define NXGE_MSIX_REQUEST_1G 2 354ec090658Sml static int nxge_create_msi_property(p_nxge_t); 355ef755e7aStc /* 356ef755e7aStc * For applications that care about the 357ef755e7aStc * latency, it was requested by PAE and the 358ef755e7aStc * customers that the driver has tunables that 359ef755e7aStc * allow the user to tune it to a higher number 360ef755e7aStc * interrupts to spread the interrupts among 361ef755e7aStc * multiple channels. The DDI framework limits 362ef755e7aStc * the maximum number of MSI-X resources to allocate 363ef755e7aStc * to 8 (ddi_msix_alloc_limit). If more than 8 364ef755e7aStc * is set, ddi_msix_alloc_limit must be set accordingly. 365ef755e7aStc * The default number of MSI interrupts are set to 366ef755e7aStc * 8 for 10G and 2 for 1G link. 367ef755e7aStc */ 368ef755e7aStc #define NXGE_MSIX_MAX_ALLOWED 32 369ef755e7aStc uint32_t nxge_msix_10g_intrs = NXGE_MSIX_REQUEST_10G; 370ef755e7aStc uint32_t nxge_msix_1g_intrs = NXGE_MSIX_REQUEST_1G; 371ec090658Sml 37244961713Sgirish /* 37344961713Sgirish * These global variables control the message 37444961713Sgirish * output. 37544961713Sgirish */ 37644961713Sgirish out_dbgmsg_t nxge_dbgmsg_out = DBG_CONSOLE | STR_LOG; 377678453a8Sspeer uint64_t nxge_debug_level; 37844961713Sgirish 37944961713Sgirish /* 38044961713Sgirish * This list contains the instance structures for the Neptune 38144961713Sgirish * devices present in the system. The lock exists to guarantee 38244961713Sgirish * mutually exclusive access to the list. 38344961713Sgirish */ 38444961713Sgirish void *nxge_list = NULL; 38544961713Sgirish void *nxge_hw_list = NULL; 38644961713Sgirish nxge_os_mutex_t nxge_common_lock; 3873b2d9860SMichael Speer nxge_os_mutex_t nxgedebuglock; 38844961713Sgirish 38944961713Sgirish extern uint64_t npi_debug_level; 39044961713Sgirish 39144961713Sgirish extern nxge_status_t nxge_ldgv_init(p_nxge_t, int *, int *); 39244961713Sgirish extern nxge_status_t nxge_ldgv_init_n2(p_nxge_t, int *, int *); 39344961713Sgirish extern nxge_status_t nxge_ldgv_uninit(p_nxge_t); 39444961713Sgirish extern nxge_status_t nxge_intr_ldgv_init(p_nxge_t); 39544961713Sgirish extern void nxge_fm_init(p_nxge_t, 39644961713Sgirish ddi_device_acc_attr_t *, 39744961713Sgirish ddi_device_acc_attr_t *, 39844961713Sgirish ddi_dma_attr_t *); 39944961713Sgirish extern void nxge_fm_fini(p_nxge_t); 40058324dfcSspeer extern npi_status_t npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t); 40144961713Sgirish 40244961713Sgirish /* 40344961713Sgirish * Count used to maintain the number of buffers being used 40444961713Sgirish * by Neptune instances and loaned up to the upper layers. 40544961713Sgirish */ 40644961713Sgirish uint32_t nxge_mblks_pending = 0; 40744961713Sgirish 40844961713Sgirish /* 40944961713Sgirish * Device register access attributes for PIO. 41044961713Sgirish */ 41144961713Sgirish static ddi_device_acc_attr_t nxge_dev_reg_acc_attr = { 41244961713Sgirish DDI_DEVICE_ATTR_V0, 41344961713Sgirish DDI_STRUCTURE_LE_ACC, 41444961713Sgirish DDI_STRICTORDER_ACC, 41544961713Sgirish }; 41644961713Sgirish 41744961713Sgirish /* 41844961713Sgirish * Device descriptor access attributes for DMA. 41944961713Sgirish */ 42044961713Sgirish static ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr = { 42144961713Sgirish DDI_DEVICE_ATTR_V0, 42244961713Sgirish DDI_STRUCTURE_LE_ACC, 42344961713Sgirish DDI_STRICTORDER_ACC 42444961713Sgirish }; 42544961713Sgirish 42644961713Sgirish /* 42744961713Sgirish * Device buffer access attributes for DMA. 42844961713Sgirish */ 42944961713Sgirish static ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr = { 43044961713Sgirish DDI_DEVICE_ATTR_V0, 43144961713Sgirish DDI_STRUCTURE_BE_ACC, 43244961713Sgirish DDI_STRICTORDER_ACC 43344961713Sgirish }; 43444961713Sgirish 43544961713Sgirish ddi_dma_attr_t nxge_desc_dma_attr = { 43644961713Sgirish DMA_ATTR_V0, /* version number. */ 43744961713Sgirish 0, /* low address */ 43844961713Sgirish 0xffffffffffffffff, /* high address */ 43944961713Sgirish 0xffffffffffffffff, /* address counter max */ 44044961713Sgirish #ifndef NIU_PA_WORKAROUND 44144961713Sgirish 0x100000, /* alignment */ 44244961713Sgirish #else 44344961713Sgirish 0x2000, 44444961713Sgirish #endif 44544961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 44644961713Sgirish 0x1, /* minimum transfer size */ 44744961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 44844961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 44944961713Sgirish 1, /* scatter/gather list length */ 45044961713Sgirish (unsigned int) 1, /* granularity */ 45144961713Sgirish 0 /* attribute flags */ 45244961713Sgirish }; 45344961713Sgirish 45444961713Sgirish ddi_dma_attr_t nxge_tx_dma_attr = { 45544961713Sgirish DMA_ATTR_V0, /* version number. */ 45644961713Sgirish 0, /* low address */ 45744961713Sgirish 0xffffffffffffffff, /* high address */ 45844961713Sgirish 0xffffffffffffffff, /* address counter max */ 45944961713Sgirish #if defined(_BIG_ENDIAN) 46044961713Sgirish 0x2000, /* alignment */ 46144961713Sgirish #else 46244961713Sgirish 0x1000, /* alignment */ 46344961713Sgirish #endif 46444961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 46544961713Sgirish 0x1, /* minimum transfer size */ 46644961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 46744961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 46844961713Sgirish 5, /* scatter/gather list length */ 46944961713Sgirish (unsigned int) 1, /* granularity */ 47044961713Sgirish 0 /* attribute flags */ 47144961713Sgirish }; 47244961713Sgirish 47344961713Sgirish ddi_dma_attr_t nxge_rx_dma_attr = { 47444961713Sgirish DMA_ATTR_V0, /* version number. */ 47544961713Sgirish 0, /* low address */ 47644961713Sgirish 0xffffffffffffffff, /* high address */ 47744961713Sgirish 0xffffffffffffffff, /* address counter max */ 47844961713Sgirish 0x2000, /* alignment */ 47944961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 48044961713Sgirish 0x1, /* minimum transfer size */ 48144961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 48244961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 48344961713Sgirish 1, /* scatter/gather list length */ 48444961713Sgirish (unsigned int) 1, /* granularity */ 4850e2bd521Ssbehera DDI_DMA_RELAXED_ORDERING /* attribute flags */ 48644961713Sgirish }; 48744961713Sgirish 48844961713Sgirish ddi_dma_lim_t nxge_dma_limits = { 48944961713Sgirish (uint_t)0, /* dlim_addr_lo */ 49044961713Sgirish (uint_t)0xffffffff, /* dlim_addr_hi */ 49144961713Sgirish (uint_t)0xffffffff, /* dlim_cntr_max */ 49244961713Sgirish (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */ 49344961713Sgirish 0x1, /* dlim_minxfer */ 49444961713Sgirish 1024 /* dlim_speed */ 49544961713Sgirish }; 49644961713Sgirish 49744961713Sgirish dma_method_t nxge_force_dma = DVMA; 49844961713Sgirish 49944961713Sgirish /* 50044961713Sgirish * dma chunk sizes. 50144961713Sgirish * 50244961713Sgirish * Try to allocate the largest possible size 50344961713Sgirish * so that fewer number of dma chunks would be managed 50444961713Sgirish */ 50544961713Sgirish #ifdef NIU_PA_WORKAROUND 50644961713Sgirish size_t alloc_sizes [] = {0x2000}; 50744961713Sgirish #else 50844961713Sgirish size_t alloc_sizes [] = {0x1000, 0x2000, 0x4000, 0x8000, 50944961713Sgirish 0x10000, 0x20000, 0x40000, 0x80000, 51030ac2e7bSml 0x100000, 0x200000, 0x400000, 0x800000, 51130ac2e7bSml 0x1000000, 0x2000000, 0x4000000}; 51244961713Sgirish #endif 51344961713Sgirish 51444961713Sgirish /* 51544961713Sgirish * Translate "dev_t" to a pointer to the associated "dev_info_t". 51644961713Sgirish */ 51744961713Sgirish 518678453a8Sspeer extern void nxge_get_environs(nxge_t *); 519678453a8Sspeer 52044961713Sgirish static int 52144961713Sgirish nxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 52244961713Sgirish { 52344961713Sgirish p_nxge_t nxgep = NULL; 52444961713Sgirish int instance; 52544961713Sgirish int status = DDI_SUCCESS; 52644961713Sgirish uint8_t portn; 52758324dfcSspeer nxge_mmac_t *mmac_info; 52844961713Sgirish 52944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_attach")); 53044961713Sgirish 53144961713Sgirish /* 53244961713Sgirish * Get the device instance since we'll need to setup 53344961713Sgirish * or retrieve a soft state for this instance. 53444961713Sgirish */ 53544961713Sgirish instance = ddi_get_instance(dip); 53644961713Sgirish 53744961713Sgirish switch (cmd) { 53844961713Sgirish case DDI_ATTACH: 53944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_ATTACH")); 54044961713Sgirish break; 54144961713Sgirish 54244961713Sgirish case DDI_RESUME: 54344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_RESUME")); 54444961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 54544961713Sgirish if (nxgep == NULL) { 54644961713Sgirish status = DDI_FAILURE; 54744961713Sgirish break; 54844961713Sgirish } 54944961713Sgirish if (nxgep->dip != dip) { 55044961713Sgirish status = DDI_FAILURE; 55144961713Sgirish break; 55244961713Sgirish } 55344961713Sgirish if (nxgep->suspended == DDI_PM_SUSPEND) { 55444961713Sgirish status = ddi_dev_is_needed(nxgep->dip, 0, 1); 55544961713Sgirish } else { 55656d930aeSspeer status = nxge_resume(nxgep); 55744961713Sgirish } 55844961713Sgirish goto nxge_attach_exit; 55944961713Sgirish 56044961713Sgirish case DDI_PM_RESUME: 56144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_RESUME")); 56244961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 56344961713Sgirish if (nxgep == NULL) { 56444961713Sgirish status = DDI_FAILURE; 56544961713Sgirish break; 56644961713Sgirish } 56744961713Sgirish if (nxgep->dip != dip) { 56844961713Sgirish status = DDI_FAILURE; 56944961713Sgirish break; 57044961713Sgirish } 57156d930aeSspeer status = nxge_resume(nxgep); 57244961713Sgirish goto nxge_attach_exit; 57344961713Sgirish 57444961713Sgirish default: 57544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing unknown")); 57644961713Sgirish status = DDI_FAILURE; 57744961713Sgirish goto nxge_attach_exit; 57844961713Sgirish } 57944961713Sgirish 58044961713Sgirish 58144961713Sgirish if (ddi_soft_state_zalloc(nxge_list, instance) == DDI_FAILURE) { 58244961713Sgirish status = DDI_FAILURE; 58344961713Sgirish goto nxge_attach_exit; 58444961713Sgirish } 58544961713Sgirish 58644961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance); 58744961713Sgirish if (nxgep == NULL) { 5882e59129aSraghus status = NXGE_ERROR; 5892e59129aSraghus goto nxge_attach_fail2; 59044961713Sgirish } 59144961713Sgirish 59298ecde52Stm nxgep->nxge_magic = NXGE_MAGIC; 59398ecde52Stm 59444961713Sgirish nxgep->drv_state = 0; 59544961713Sgirish nxgep->dip = dip; 59644961713Sgirish nxgep->instance = instance; 59744961713Sgirish nxgep->p_dip = ddi_get_parent(dip); 59844961713Sgirish nxgep->nxge_debug_level = nxge_debug_level; 59944961713Sgirish npi_debug_level = nxge_debug_level; 60044961713Sgirish 601678453a8Sspeer /* Are we a guest running in a Hybrid I/O environment? */ 602678453a8Sspeer nxge_get_environs(nxgep); 60344961713Sgirish 60444961713Sgirish status = nxge_map_regs(nxgep); 605678453a8Sspeer 60644961713Sgirish if (status != NXGE_OK) { 60744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_map_regs failed")); 6082e59129aSraghus goto nxge_attach_fail3; 60944961713Sgirish } 61044961713Sgirish 611678453a8Sspeer nxge_fm_init(nxgep, &nxge_dev_reg_acc_attr, 612678453a8Sspeer &nxge_dev_desc_dma_acc_attr, 613678453a8Sspeer &nxge_rx_dma_attr); 614678453a8Sspeer 615678453a8Sspeer /* Create & initialize the per-Neptune data structure */ 616678453a8Sspeer /* (even if we're a guest). */ 61744961713Sgirish status = nxge_init_common_dev(nxgep); 61844961713Sgirish if (status != NXGE_OK) { 61944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6204045d941Ssowmini "nxge_init_common_dev failed")); 6212e59129aSraghus goto nxge_attach_fail4; 62244961713Sgirish } 62344961713Sgirish 624d6d3405fSml /* 625d6d3405fSml * Software workaround: set the replay timer. 626d6d3405fSml */ 627d6d3405fSml if (nxgep->niu_type != N2_NIU) { 628d6d3405fSml nxge_set_pci_replay_timeout(nxgep); 629d6d3405fSml } 630d6d3405fSml 631678453a8Sspeer #if defined(sun4v) 632678453a8Sspeer /* This is required by nxge_hio_init(), which follows. */ 633678453a8Sspeer if ((status = nxge_hsvc_register(nxgep)) != DDI_SUCCESS) 6349d5b8bc5SMichael Speer goto nxge_attach_fail4; 635678453a8Sspeer #endif 636678453a8Sspeer 637678453a8Sspeer if ((status = nxge_hio_init(nxgep)) != NXGE_OK) { 638678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6394045d941Ssowmini "nxge_hio_init failed")); 640678453a8Sspeer goto nxge_attach_fail4; 641678453a8Sspeer } 642678453a8Sspeer 64359ac0c16Sdavemq if (nxgep->niu_type == NEPTUNE_2_10GF) { 64459ac0c16Sdavemq if (nxgep->function_num > 1) { 6454202ea4bSsbehera NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Unsupported" 64659ac0c16Sdavemq " function %d. Only functions 0 and 1 are " 64759ac0c16Sdavemq "supported for this card.", nxgep->function_num)); 64859ac0c16Sdavemq status = NXGE_ERROR; 6492e59129aSraghus goto nxge_attach_fail4; 65059ac0c16Sdavemq } 65159ac0c16Sdavemq } 65259ac0c16Sdavemq 653678453a8Sspeer if (isLDOMguest(nxgep)) { 654678453a8Sspeer /* 655678453a8Sspeer * Use the function number here. 656678453a8Sspeer */ 657678453a8Sspeer nxgep->mac.portnum = nxgep->function_num; 658678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_LOGICAL; 659678453a8Sspeer 660678453a8Sspeer /* XXX We'll set the MAC address counts to 1 for now. */ 661678453a8Sspeer mmac_info = &nxgep->nxge_mmac_info; 662678453a8Sspeer mmac_info->num_mmac = 1; 663678453a8Sspeer mmac_info->naddrfree = 1; 66458324dfcSspeer } else { 665678453a8Sspeer portn = NXGE_GET_PORT_NUM(nxgep->function_num); 666678453a8Sspeer nxgep->mac.portnum = portn; 667678453a8Sspeer if ((portn == 0) || (portn == 1)) 668678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_XMAC; 669678453a8Sspeer else 670678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_BMAC; 671678453a8Sspeer /* 672678453a8Sspeer * Neptune has 4 ports, the first 2 ports use XMAC (10G MAC) 673678453a8Sspeer * internally, the rest 2 ports use BMAC (1G "Big" MAC). 674678453a8Sspeer * The two types of MACs have different characterizations. 675678453a8Sspeer */ 676678453a8Sspeer mmac_info = &nxgep->nxge_mmac_info; 677678453a8Sspeer if (nxgep->function_num < 2) { 678678453a8Sspeer mmac_info->num_mmac = XMAC_MAX_ALT_ADDR_ENTRY; 679678453a8Sspeer mmac_info->naddrfree = XMAC_MAX_ALT_ADDR_ENTRY; 680678453a8Sspeer } else { 681678453a8Sspeer mmac_info->num_mmac = BMAC_MAX_ALT_ADDR_ENTRY; 682678453a8Sspeer mmac_info->naddrfree = BMAC_MAX_ALT_ADDR_ENTRY; 683678453a8Sspeer } 68458324dfcSspeer } 68544961713Sgirish /* 68644961713Sgirish * Setup the Ndd parameters for the this instance. 68744961713Sgirish */ 68844961713Sgirish nxge_init_param(nxgep); 68944961713Sgirish 69044961713Sgirish /* 69144961713Sgirish * Setup Register Tracing Buffer. 69244961713Sgirish */ 69344961713Sgirish npi_rtrace_buf_init((rtrace_t *)&npi_rtracebuf); 69444961713Sgirish 69544961713Sgirish /* init stats ptr */ 69644961713Sgirish nxge_init_statsp(nxgep); 69756d930aeSspeer 6982e59129aSraghus /* 699678453a8Sspeer * Copy the vpd info from eeprom to a local data 700678453a8Sspeer * structure, and then check its validity. 7012e59129aSraghus */ 702678453a8Sspeer if (!isLDOMguest(nxgep)) { 703678453a8Sspeer int *regp; 704678453a8Sspeer uint_t reglen; 705678453a8Sspeer int rv; 70656d930aeSspeer 707678453a8Sspeer nxge_vpd_info_get(nxgep); 70844961713Sgirish 709678453a8Sspeer /* Find the NIU config handle. */ 710678453a8Sspeer rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, 711678453a8Sspeer ddi_get_parent(nxgep->dip), DDI_PROP_DONTPASS, 712678453a8Sspeer "reg", ®p, ®len); 713678453a8Sspeer 714678453a8Sspeer if (rv != DDI_PROP_SUCCESS) { 715678453a8Sspeer goto nxge_attach_fail5; 716678453a8Sspeer } 717678453a8Sspeer /* 718678453a8Sspeer * The address_hi, that is the first int, in the reg 719678453a8Sspeer * property consists of config handle, but need to remove 720678453a8Sspeer * the bits 28-31 which are OBP specific info. 721678453a8Sspeer */ 722678453a8Sspeer nxgep->niu_cfg_hdl = (*regp) & 0xFFFFFFF; 723678453a8Sspeer ddi_prop_free(regp); 72444961713Sgirish } 72544961713Sgirish 72648056c53SMichael Speer /* 72748056c53SMichael Speer * Set the defaults for the MTU size. 72848056c53SMichael Speer */ 72948056c53SMichael Speer nxge_hw_id_init(nxgep); 73048056c53SMichael Speer 731678453a8Sspeer if (isLDOMguest(nxgep)) { 732678453a8Sspeer uchar_t *prop_val; 733678453a8Sspeer uint_t prop_len; 7347b1f684aSSriharsha Basavapatna uint32_t max_frame_size; 73544961713Sgirish 736678453a8Sspeer extern void nxge_get_logical_props(p_nxge_t); 737678453a8Sspeer 738678453a8Sspeer nxgep->statsp->mac_stats.xcvr_inuse = LOGICAL_XCVR; 739678453a8Sspeer nxgep->mac.portmode = PORT_LOGICAL; 740678453a8Sspeer (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 741678453a8Sspeer "phy-type", "virtual transceiver"); 742678453a8Sspeer 743678453a8Sspeer nxgep->nports = 1; 744678453a8Sspeer nxgep->board_ver = 0; /* XXX What? */ 745678453a8Sspeer 746678453a8Sspeer /* 747678453a8Sspeer * local-mac-address property gives us info on which 748678453a8Sspeer * specific MAC address the Hybrid resource is associated 749678453a8Sspeer * with. 750678453a8Sspeer */ 751678453a8Sspeer if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0, 752678453a8Sspeer "local-mac-address", &prop_val, 753678453a8Sspeer &prop_len) != DDI_PROP_SUCCESS) { 754678453a8Sspeer goto nxge_attach_fail5; 755678453a8Sspeer } 756678453a8Sspeer if (prop_len != ETHERADDRL) { 757678453a8Sspeer ddi_prop_free(prop_val); 758678453a8Sspeer goto nxge_attach_fail5; 759678453a8Sspeer } 760678453a8Sspeer ether_copy(prop_val, nxgep->hio_mac_addr); 761678453a8Sspeer ddi_prop_free(prop_val); 762678453a8Sspeer nxge_get_logical_props(nxgep); 763678453a8Sspeer 7647b1f684aSSriharsha Basavapatna /* 7657b1f684aSSriharsha Basavapatna * Enable Jumbo property based on the "max-frame-size" 7667b1f684aSSriharsha Basavapatna * property value. 7677b1f684aSSriharsha Basavapatna */ 7687b1f684aSSriharsha Basavapatna max_frame_size = ddi_prop_get_int(DDI_DEV_T_ANY, 7697b1f684aSSriharsha Basavapatna nxgep->dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 7707b1f684aSSriharsha Basavapatna "max-frame-size", NXGE_MTU_DEFAULT_MAX); 7717b1f684aSSriharsha Basavapatna if ((max_frame_size > NXGE_MTU_DEFAULT_MAX) && 7727b1f684aSSriharsha Basavapatna (max_frame_size <= TX_JUMBO_MTU)) { 7737b1f684aSSriharsha Basavapatna nxgep->mac.is_jumbo = B_TRUE; 7747b1f684aSSriharsha Basavapatna nxgep->mac.maxframesize = (uint16_t)max_frame_size; 7757b1f684aSSriharsha Basavapatna nxgep->mac.default_mtu = nxgep->mac.maxframesize - 7767b1f684aSSriharsha Basavapatna NXGE_EHEADER_VLAN_CRC; 7777b1f684aSSriharsha Basavapatna } 778678453a8Sspeer } else { 779678453a8Sspeer status = nxge_xcvr_find(nxgep); 780678453a8Sspeer 781678453a8Sspeer if (status != NXGE_OK) { 782678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_attach: " 7834045d941Ssowmini " Couldn't determine card type" 7844045d941Ssowmini " .... exit ")); 785678453a8Sspeer goto nxge_attach_fail5; 786678453a8Sspeer } 787678453a8Sspeer 788678453a8Sspeer status = nxge_get_config_properties(nxgep); 789678453a8Sspeer 790678453a8Sspeer if (status != NXGE_OK) { 791678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7924045d941Ssowmini "get_hw create failed")); 793678453a8Sspeer goto nxge_attach_fail; 794678453a8Sspeer } 79544961713Sgirish } 79644961713Sgirish 79744961713Sgirish /* 79844961713Sgirish * Setup the Kstats for the driver. 79944961713Sgirish */ 80044961713Sgirish nxge_setup_kstats(nxgep); 80144961713Sgirish 802678453a8Sspeer if (!isLDOMguest(nxgep)) 803678453a8Sspeer nxge_setup_param(nxgep); 80444961713Sgirish 80544961713Sgirish status = nxge_setup_system_dma_pages(nxgep); 80644961713Sgirish if (status != NXGE_OK) { 80744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "set dma page failed")); 80844961713Sgirish goto nxge_attach_fail; 80944961713Sgirish } 81044961713Sgirish 811678453a8Sspeer 812678453a8Sspeer if (!isLDOMguest(nxgep)) 813678453a8Sspeer nxge_hw_init_niu_common(nxgep); 81444961713Sgirish 81544961713Sgirish status = nxge_setup_mutexes(nxgep); 81644961713Sgirish if (status != NXGE_OK) { 81744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set mutex failed")); 81844961713Sgirish goto nxge_attach_fail; 81944961713Sgirish } 82044961713Sgirish 821678453a8Sspeer #if defined(sun4v) 822678453a8Sspeer if (isLDOMguest(nxgep)) { 823678453a8Sspeer /* Find our VR & channel sets. */ 824678453a8Sspeer status = nxge_hio_vr_add(nxgep); 825330cd344SMichael Speer if (status != NXGE_OK) { 826330cd344SMichael Speer NXGE_DEBUG_MSG((nxgep, DDI_CTL, 827330cd344SMichael Speer "nxge_hio_vr_add failed")); 828330cd344SMichael Speer (void) hsvc_unregister(&nxgep->niu_hsvc); 829330cd344SMichael Speer nxgep->niu_hsvc_available = B_FALSE; 830330cd344SMichael Speer } 831678453a8Sspeer goto nxge_attach_exit; 832678453a8Sspeer } 833678453a8Sspeer #endif 834678453a8Sspeer 83544961713Sgirish status = nxge_setup_dev(nxgep); 83644961713Sgirish if (status != DDI_SUCCESS) { 83744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set dev failed")); 83844961713Sgirish goto nxge_attach_fail; 83944961713Sgirish } 84044961713Sgirish 84144961713Sgirish status = nxge_add_intrs(nxgep); 84244961713Sgirish if (status != DDI_SUCCESS) { 84344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "add_intr failed")); 84444961713Sgirish goto nxge_attach_fail; 84544961713Sgirish } 846330cd344SMichael Speer 84700161856Syc /* If a guest, register with vio_net instead. */ 8482e59129aSraghus if ((status = nxge_mac_register(nxgep)) != NXGE_OK) { 84944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 850678453a8Sspeer "unable to register to mac layer (%d)", status)); 85144961713Sgirish goto nxge_attach_fail; 85244961713Sgirish } 85344961713Sgirish 85444961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_UNKNOWN); 85544961713Sgirish 856678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DDI_CTL, 857678453a8Sspeer "registered to mac (instance %d)", instance)); 85844961713Sgirish 85900161856Syc /* nxge_link_monitor calls xcvr.check_link recursively */ 86044961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 86144961713Sgirish 86244961713Sgirish goto nxge_attach_exit; 86344961713Sgirish 86444961713Sgirish nxge_attach_fail: 86544961713Sgirish nxge_unattach(nxgep); 8662e59129aSraghus goto nxge_attach_fail1; 8672e59129aSraghus 8682e59129aSraghus nxge_attach_fail5: 8692e59129aSraghus /* 8702e59129aSraghus * Tear down the ndd parameters setup. 8712e59129aSraghus */ 8722e59129aSraghus nxge_destroy_param(nxgep); 8732e59129aSraghus 8742e59129aSraghus /* 8752e59129aSraghus * Tear down the kstat setup. 8762e59129aSraghus */ 8772e59129aSraghus nxge_destroy_kstats(nxgep); 8782e59129aSraghus 8792e59129aSraghus nxge_attach_fail4: 8802e59129aSraghus if (nxgep->nxge_hw_p) { 8812e59129aSraghus nxge_uninit_common_dev(nxgep); 8822e59129aSraghus nxgep->nxge_hw_p = NULL; 8832e59129aSraghus } 8842e59129aSraghus 8852e59129aSraghus nxge_attach_fail3: 8862e59129aSraghus /* 8872e59129aSraghus * Unmap the register setup. 8882e59129aSraghus */ 8892e59129aSraghus nxge_unmap_regs(nxgep); 8902e59129aSraghus 8912e59129aSraghus nxge_fm_fini(nxgep); 8922e59129aSraghus 8932e59129aSraghus nxge_attach_fail2: 8942e59129aSraghus ddi_soft_state_free(nxge_list, nxgep->instance); 8952e59129aSraghus 8962e59129aSraghus nxge_attach_fail1: 89756d930aeSspeer if (status != NXGE_OK) 89856d930aeSspeer status = (NXGE_ERROR | NXGE_DDI_FAILED); 89944961713Sgirish nxgep = NULL; 90044961713Sgirish 90144961713Sgirish nxge_attach_exit: 90244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_attach status = 0x%08x", 9034045d941Ssowmini status)); 90444961713Sgirish 90544961713Sgirish return (status); 90644961713Sgirish } 90744961713Sgirish 90844961713Sgirish static int 90944961713Sgirish nxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 91044961713Sgirish { 91144961713Sgirish int status = DDI_SUCCESS; 91244961713Sgirish int instance; 91344961713Sgirish p_nxge_t nxgep = NULL; 91444961713Sgirish 91544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_detach")); 91644961713Sgirish instance = ddi_get_instance(dip); 91744961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance); 91844961713Sgirish if (nxgep == NULL) { 91944961713Sgirish status = DDI_FAILURE; 92044961713Sgirish goto nxge_detach_exit; 92144961713Sgirish } 92244961713Sgirish 92344961713Sgirish switch (cmd) { 92444961713Sgirish case DDI_DETACH: 92544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_DETACH")); 92644961713Sgirish break; 92744961713Sgirish 92844961713Sgirish case DDI_PM_SUSPEND: 92944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_SUSPEND")); 93044961713Sgirish nxgep->suspended = DDI_PM_SUSPEND; 93144961713Sgirish nxge_suspend(nxgep); 93244961713Sgirish break; 93344961713Sgirish 93444961713Sgirish case DDI_SUSPEND: 93544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_SUSPEND")); 93644961713Sgirish if (nxgep->suspended != DDI_PM_SUSPEND) { 93744961713Sgirish nxgep->suspended = DDI_SUSPEND; 93844961713Sgirish nxge_suspend(nxgep); 93944961713Sgirish } 94044961713Sgirish break; 94144961713Sgirish 94244961713Sgirish default: 94344961713Sgirish status = DDI_FAILURE; 94444961713Sgirish } 94544961713Sgirish 94644961713Sgirish if (cmd != DDI_DETACH) 94744961713Sgirish goto nxge_detach_exit; 94844961713Sgirish 94944961713Sgirish /* 95044961713Sgirish * Stop the xcvr polling. 95144961713Sgirish */ 95244961713Sgirish nxgep->suspended = cmd; 95344961713Sgirish 95444961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 95544961713Sgirish 956*63f531d1SSriharsha Basavapatna if (nxgep->mach && (status = mac_unregister(nxgep->mach)) != 0) { 95744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 9584045d941Ssowmini "<== nxge_detach status = 0x%08X", status)); 95944961713Sgirish return (DDI_FAILURE); 96044961713Sgirish } 96144961713Sgirish 96244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 9634045d941Ssowmini "<== nxge_detach (mac_unregister) status = 0x%08X", status)); 96444961713Sgirish 96544961713Sgirish nxge_unattach(nxgep); 96644961713Sgirish nxgep = NULL; 96744961713Sgirish 96844961713Sgirish nxge_detach_exit: 96944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_detach status = 0x%08X", 9704045d941Ssowmini status)); 97144961713Sgirish 97244961713Sgirish return (status); 97344961713Sgirish } 97444961713Sgirish 97544961713Sgirish static void 97644961713Sgirish nxge_unattach(p_nxge_t nxgep) 97744961713Sgirish { 97844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unattach")); 97944961713Sgirish 98044961713Sgirish if (nxgep == NULL || nxgep->dev_regs == NULL) { 98144961713Sgirish return; 98244961713Sgirish } 98344961713Sgirish 98498ecde52Stm nxgep->nxge_magic = 0; 98598ecde52Stm 98644961713Sgirish if (nxgep->nxge_timerid) { 98744961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 98844961713Sgirish nxgep->nxge_timerid = 0; 98944961713Sgirish } 99044961713Sgirish 9916f157acbSml /* 9926f157acbSml * If this flag is set, it will affect the Neptune 9936f157acbSml * only. 9946f157acbSml */ 9956f157acbSml if ((nxgep->niu_type != N2_NIU) && nxge_peu_reset_enable) { 9966f157acbSml nxge_niu_peu_reset(nxgep); 9976f157acbSml } 9986f157acbSml 999678453a8Sspeer #if defined(sun4v) 1000678453a8Sspeer if (isLDOMguest(nxgep)) { 1001d00f30bbSspeer (void) nxge_hio_vr_release(nxgep); 1002678453a8Sspeer } 1003678453a8Sspeer #endif 1004678453a8Sspeer 100553560810Ssbehera if (nxgep->nxge_hw_p) { 100653560810Ssbehera nxge_uninit_common_dev(nxgep); 100753560810Ssbehera nxgep->nxge_hw_p = NULL; 100853560810Ssbehera } 100953560810Ssbehera 101044961713Sgirish #if defined(sun4v) 101144961713Sgirish if (nxgep->niu_type == N2_NIU && nxgep->niu_hsvc_available == B_TRUE) { 101244961713Sgirish (void) hsvc_unregister(&nxgep->niu_hsvc); 101344961713Sgirish nxgep->niu_hsvc_available = B_FALSE; 101444961713Sgirish } 101544961713Sgirish #endif 101644961713Sgirish /* 101744961713Sgirish * Stop any further interrupts. 101844961713Sgirish */ 101944961713Sgirish nxge_remove_intrs(nxgep); 102044961713Sgirish 102144961713Sgirish /* 102244961713Sgirish * Stop the device and free resources. 102344961713Sgirish */ 1024678453a8Sspeer if (!isLDOMguest(nxgep)) { 1025678453a8Sspeer nxge_destroy_dev(nxgep); 1026678453a8Sspeer } 102744961713Sgirish 102844961713Sgirish /* 102944961713Sgirish * Tear down the ndd parameters setup. 103044961713Sgirish */ 103144961713Sgirish nxge_destroy_param(nxgep); 103244961713Sgirish 103344961713Sgirish /* 103444961713Sgirish * Tear down the kstat setup. 103544961713Sgirish */ 103644961713Sgirish nxge_destroy_kstats(nxgep); 103744961713Sgirish 103844961713Sgirish /* 103944961713Sgirish * Destroy all mutexes. 104044961713Sgirish */ 104144961713Sgirish nxge_destroy_mutexes(nxgep); 104244961713Sgirish 104344961713Sgirish /* 104444961713Sgirish * Remove the list of ndd parameters which 104544961713Sgirish * were setup during attach. 104644961713Sgirish */ 104744961713Sgirish if (nxgep->dip) { 104844961713Sgirish NXGE_DEBUG_MSG((nxgep, OBP_CTL, 10494045d941Ssowmini " nxge_unattach: remove all properties")); 105044961713Sgirish 105144961713Sgirish (void) ddi_prop_remove_all(nxgep->dip); 105244961713Sgirish } 105344961713Sgirish 105444961713Sgirish #if NXGE_PROPERTY 105544961713Sgirish nxge_remove_hard_properties(nxgep); 105644961713Sgirish #endif 105744961713Sgirish 105844961713Sgirish /* 105944961713Sgirish * Unmap the register setup. 106044961713Sgirish */ 106144961713Sgirish nxge_unmap_regs(nxgep); 106244961713Sgirish 106344961713Sgirish nxge_fm_fini(nxgep); 106444961713Sgirish 106544961713Sgirish ddi_soft_state_free(nxge_list, nxgep->instance); 106644961713Sgirish 106744961713Sgirish NXGE_DEBUG_MSG((NULL, DDI_CTL, "<== nxge_unattach")); 106844961713Sgirish } 106944961713Sgirish 1070678453a8Sspeer #if defined(sun4v) 1071678453a8Sspeer int 10729d5b8bc5SMichael Speer nxge_hsvc_register(nxge_t *nxgep) 1073678453a8Sspeer { 1074678453a8Sspeer nxge_status_t status; 1075678453a8Sspeer 1076678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 1077678453a8Sspeer nxgep->niu_hsvc_available = B_FALSE; 1078678453a8Sspeer bcopy(&niu_hsvc, &nxgep->niu_hsvc, sizeof (hsvc_info_t)); 1079678453a8Sspeer if ((status = hsvc_register(&nxgep->niu_hsvc, 1080678453a8Sspeer &nxgep->niu_min_ver)) != 0) { 1081678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1082678453a8Sspeer "nxge_attach: %s: cannot negotiate " 1083678453a8Sspeer "hypervisor services revision %d group: 0x%lx " 1084678453a8Sspeer "major: 0x%lx minor: 0x%lx errno: %d", 1085678453a8Sspeer niu_hsvc.hsvc_modname, niu_hsvc.hsvc_rev, 1086678453a8Sspeer niu_hsvc.hsvc_group, niu_hsvc.hsvc_major, 1087678453a8Sspeer niu_hsvc.hsvc_minor, status)); 1088678453a8Sspeer return (DDI_FAILURE); 1089678453a8Sspeer } 1090678453a8Sspeer nxgep->niu_hsvc_available = B_TRUE; 1091678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DDI_CTL, 10924045d941Ssowmini "NIU Hypervisor service enabled")); 1093678453a8Sspeer } 1094678453a8Sspeer 1095678453a8Sspeer return (DDI_SUCCESS); 1096678453a8Sspeer } 1097678453a8Sspeer #endif 1098678453a8Sspeer 109944961713Sgirish static char n2_siu_name[] = "niu"; 110044961713Sgirish 110144961713Sgirish static nxge_status_t 110244961713Sgirish nxge_map_regs(p_nxge_t nxgep) 110344961713Sgirish { 110444961713Sgirish int ddi_status = DDI_SUCCESS; 110544961713Sgirish p_dev_regs_t dev_regs; 110644961713Sgirish char buf[MAXPATHLEN + 1]; 110744961713Sgirish char *devname; 110844961713Sgirish #ifdef NXGE_DEBUG 110944961713Sgirish char *sysname; 111044961713Sgirish #endif 111144961713Sgirish off_t regsize; 111244961713Sgirish nxge_status_t status = NXGE_OK; 111314ea4bb7Ssd #if !defined(_BIG_ENDIAN) 111414ea4bb7Ssd off_t pci_offset; 111514ea4bb7Ssd uint16_t pcie_devctl; 111614ea4bb7Ssd #endif 111744961713Sgirish 1118678453a8Sspeer if (isLDOMguest(nxgep)) { 1119678453a8Sspeer return (nxge_guest_regs_map(nxgep)); 1120678453a8Sspeer } 1121678453a8Sspeer 112244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_map_regs")); 112344961713Sgirish nxgep->dev_regs = NULL; 112444961713Sgirish dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP); 112544961713Sgirish dev_regs->nxge_regh = NULL; 112644961713Sgirish dev_regs->nxge_pciregh = NULL; 112744961713Sgirish dev_regs->nxge_msix_regh = NULL; 112844961713Sgirish dev_regs->nxge_vir_regh = NULL; 112944961713Sgirish dev_regs->nxge_vir2_regh = NULL; 113059ac0c16Sdavemq nxgep->niu_type = NIU_TYPE_NONE; 113144961713Sgirish 113244961713Sgirish devname = ddi_pathname(nxgep->dip, buf); 113344961713Sgirish ASSERT(strlen(devname) > 0); 113444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11354045d941Ssowmini "nxge_map_regs: pathname devname %s", devname)); 113644961713Sgirish 113700161856Syc /* 113800161856Syc * The driver is running on a N2-NIU system if devname is something 113900161856Syc * like "/niu@80/network@0" 114000161856Syc */ 114144961713Sgirish if (strstr(devname, n2_siu_name)) { 114244961713Sgirish /* N2/NIU */ 114344961713Sgirish nxgep->niu_type = N2_NIU; 114444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11454045d941Ssowmini "nxge_map_regs: N2/NIU devname %s", devname)); 114644961713Sgirish /* get function number */ 114744961713Sgirish nxgep->function_num = 11484045d941Ssowmini (devname[strlen(devname) -1] == '1' ? 1 : 0); 114944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11504045d941Ssowmini "nxge_map_regs: N2/NIU function number %d", 11514045d941Ssowmini nxgep->function_num)); 115244961713Sgirish } else { 115344961713Sgirish int *prop_val; 115444961713Sgirish uint_t prop_len; 115544961713Sgirish uint8_t func_num; 115644961713Sgirish 115744961713Sgirish if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 11584045d941Ssowmini 0, "reg", 11594045d941Ssowmini &prop_val, &prop_len) != DDI_PROP_SUCCESS) { 116044961713Sgirish NXGE_DEBUG_MSG((nxgep, VPD_CTL, 11614045d941Ssowmini "Reg property not found")); 116244961713Sgirish ddi_status = DDI_FAILURE; 116344961713Sgirish goto nxge_map_regs_fail0; 116444961713Sgirish 116544961713Sgirish } else { 116644961713Sgirish func_num = (prop_val[0] >> 8) & 0x7; 116744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11684045d941Ssowmini "Reg property found: fun # %d", 11694045d941Ssowmini func_num)); 117044961713Sgirish nxgep->function_num = func_num; 1171678453a8Sspeer if (isLDOMguest(nxgep)) { 1172678453a8Sspeer nxgep->function_num /= 2; 1173678453a8Sspeer return (NXGE_OK); 1174678453a8Sspeer } 117544961713Sgirish ddi_prop_free(prop_val); 117644961713Sgirish } 117744961713Sgirish } 117844961713Sgirish 117944961713Sgirish switch (nxgep->niu_type) { 118044961713Sgirish default: 118144961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 0, ®size); 118244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11834045d941Ssowmini "nxge_map_regs: pci config size 0x%x", regsize)); 118444961713Sgirish 118544961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 0, 11864045d941Ssowmini (caddr_t *)&(dev_regs->nxge_pciregp), 0, 0, 11874045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_pciregh); 118844961713Sgirish if (ddi_status != DDI_SUCCESS) { 118944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 11904045d941Ssowmini "ddi_map_regs, nxge bus config regs failed")); 119144961713Sgirish goto nxge_map_regs_fail0; 119244961713Sgirish } 119344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11944045d941Ssowmini "nxge_map_reg: PCI config addr 0x%0llx " 11954045d941Ssowmini " handle 0x%0llx", dev_regs->nxge_pciregp, 11964045d941Ssowmini dev_regs->nxge_pciregh)); 119744961713Sgirish /* 119844961713Sgirish * IMP IMP 119944961713Sgirish * workaround for bit swapping bug in HW 120044961713Sgirish * which ends up in no-snoop = yes 120144961713Sgirish * resulting, in DMA not synched properly 120244961713Sgirish */ 120344961713Sgirish #if !defined(_BIG_ENDIAN) 120414ea4bb7Ssd /* workarounds for x86 systems */ 120514ea4bb7Ssd pci_offset = 0x80 + PCIE_DEVCTL; 120648056c53SMichael Speer pcie_devctl = pci_config_get16(dev_regs->nxge_pciregh, 120748056c53SMichael Speer pci_offset); 120848056c53SMichael Speer 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 162244961713Sgirish /* 1623e759c33aSMichael Speer * Enable the interrrupts for DDI. 162444961713Sgirish */ 1625e759c33aSMichael Speer nxge_intrs_enable(nxgep); 1626e759c33aSMichael Speer 162744961713Sgirish nxgep->drv_state |= STATE_HW_INITIALIZED; 162844961713Sgirish 162944961713Sgirish goto nxge_init_exit; 163044961713Sgirish 163144961713Sgirish nxge_init_fail5: 163244961713Sgirish nxge_uninit_rxdma_channels(nxgep); 163344961713Sgirish nxge_init_fail4: 163444961713Sgirish nxge_uninit_txdma_channels(nxgep); 163544961713Sgirish nxge_init_fail3: 1636678453a8Sspeer if (!isLDOMguest(nxgep)) { 1637678453a8Sspeer (void) nxge_txc_uninit(nxgep); 1638678453a8Sspeer } 163944961713Sgirish nxge_init_fail2: 164044961713Sgirish nxge_free_mem_pool(nxgep); 164144961713Sgirish nxge_init_fail1: 164244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16434045d941Ssowmini "<== nxge_init status (failed) = 0x%08x", status)); 164444961713Sgirish return (status); 164544961713Sgirish 164644961713Sgirish nxge_init_exit: 164744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_init status = 0x%08x", 16484045d941Ssowmini status)); 164944961713Sgirish return (status); 165044961713Sgirish } 165144961713Sgirish 165244961713Sgirish 165344961713Sgirish timeout_id_t 165444961713Sgirish nxge_start_timer(p_nxge_t nxgep, fptrv_t func, int msec) 165544961713Sgirish { 16564045d941Ssowmini if ((nxgep->suspended == 0) || (nxgep->suspended == DDI_RESUME)) { 165744961713Sgirish return (timeout(func, (caddr_t)nxgep, 16584045d941Ssowmini drv_usectohz(1000 * msec))); 165944961713Sgirish } 166044961713Sgirish return (NULL); 166144961713Sgirish } 166244961713Sgirish 166344961713Sgirish /*ARGSUSED*/ 166444961713Sgirish void 166544961713Sgirish nxge_stop_timer(p_nxge_t nxgep, timeout_id_t timerid) 166644961713Sgirish { 166744961713Sgirish if (timerid) { 166844961713Sgirish (void) untimeout(timerid); 166944961713Sgirish } 167044961713Sgirish } 167144961713Sgirish 167244961713Sgirish void 167344961713Sgirish nxge_uninit(p_nxge_t nxgep) 167444961713Sgirish { 167544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_uninit")); 167644961713Sgirish 167744961713Sgirish if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 167844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 16794045d941Ssowmini "==> nxge_uninit: not initialized")); 168044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 16814045d941Ssowmini "<== nxge_uninit")); 168244961713Sgirish return; 168344961713Sgirish } 168444961713Sgirish 1685e759c33aSMichael Speer if (!isLDOMguest(nxgep)) { 1686e759c33aSMichael Speer /* 1687e759c33aSMichael Speer * Reset the receive MAC side. 1688e759c33aSMichael Speer */ 1689e759c33aSMichael Speer (void) nxge_rx_mac_disable(nxgep); 1690e759c33aSMichael Speer 1691e759c33aSMichael Speer /* 1692e759c33aSMichael Speer * Drain the IPP. 1693e759c33aSMichael Speer */ 1694e759c33aSMichael Speer (void) nxge_ipp_drain(nxgep); 1695e759c33aSMichael Speer } 1696e759c33aSMichael Speer 169744961713Sgirish /* stop timer */ 169844961713Sgirish if (nxgep->nxge_timerid) { 169944961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 170044961713Sgirish nxgep->nxge_timerid = 0; 170144961713Sgirish } 170244961713Sgirish 170344961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 170444961713Sgirish (void) nxge_intr_hw_disable(nxgep); 170544961713Sgirish 170644961713Sgirish 170744961713Sgirish /* Disable and soft reset the IPP */ 1708678453a8Sspeer if (!isLDOMguest(nxgep)) 1709678453a8Sspeer (void) nxge_ipp_disable(nxgep); 171044961713Sgirish 1711a3c5bd6dSspeer /* Free classification resources */ 1712a3c5bd6dSspeer (void) nxge_classify_uninit(nxgep); 1713a3c5bd6dSspeer 171444961713Sgirish /* 171544961713Sgirish * Reset the transmit/receive DMA side. 171644961713Sgirish */ 171744961713Sgirish (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 171844961713Sgirish (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 171944961713Sgirish 172044961713Sgirish nxge_uninit_txdma_channels(nxgep); 172144961713Sgirish nxge_uninit_rxdma_channels(nxgep); 172244961713Sgirish 172344961713Sgirish /* 172444961713Sgirish * Reset the transmit MAC side. 172544961713Sgirish */ 172644961713Sgirish (void) nxge_tx_mac_disable(nxgep); 172744961713Sgirish 172844961713Sgirish nxge_free_mem_pool(nxgep); 172944961713Sgirish 17306f157acbSml /* 17316f157acbSml * Start the timer if the reset flag is not set. 17326f157acbSml * If this reset flag is set, the link monitor 17336f157acbSml * will not be started in order to stop furthur bus 17346f157acbSml * activities coming from this interface. 17356f157acbSml * The driver will start the monitor function 17366f157acbSml * if the interface was initialized again later. 17376f157acbSml */ 17386f157acbSml if (!nxge_peu_reset_enable) { 17396f157acbSml (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 17406f157acbSml } 174144961713Sgirish 174244961713Sgirish nxgep->drv_state &= ~STATE_HW_INITIALIZED; 174344961713Sgirish 174444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_uninit: " 17454045d941Ssowmini "nxge_mblks_pending %d", nxge_mblks_pending)); 174644961713Sgirish } 174744961713Sgirish 174844961713Sgirish void 174944961713Sgirish nxge_get64(p_nxge_t nxgep, p_mblk_t mp) 175044961713Sgirish { 175144961713Sgirish uint64_t reg; 175244961713Sgirish uint64_t regdata; 175344961713Sgirish int i, retry; 175444961713Sgirish 175544961713Sgirish bcopy((char *)mp->b_rptr, (char *)®, sizeof (uint64_t)); 175644961713Sgirish regdata = 0; 175744961713Sgirish retry = 1; 175844961713Sgirish 175944961713Sgirish for (i = 0; i < retry; i++) { 176044961713Sgirish NXGE_REG_RD64(nxgep->npi_handle, reg, ®data); 176144961713Sgirish } 176244961713Sgirish bcopy((char *)®data, (char *)mp->b_rptr, sizeof (uint64_t)); 176344961713Sgirish } 176444961713Sgirish 176544961713Sgirish void 176644961713Sgirish nxge_put64(p_nxge_t nxgep, p_mblk_t mp) 176744961713Sgirish { 176844961713Sgirish uint64_t reg; 176944961713Sgirish uint64_t buf[2]; 177044961713Sgirish 177144961713Sgirish bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t)); 177244961713Sgirish reg = buf[0]; 177344961713Sgirish 177444961713Sgirish NXGE_NPI_PIO_WRITE64(nxgep->npi_handle, reg, buf[1]); 177544961713Sgirish } 177644961713Sgirish 177744961713Sgirish /*ARGSUSED*/ 177844961713Sgirish /*VARARGS*/ 177944961713Sgirish void 178044961713Sgirish nxge_debug_msg(p_nxge_t nxgep, uint64_t level, char *fmt, ...) 178144961713Sgirish { 178244961713Sgirish char msg_buffer[1048]; 178344961713Sgirish char prefix_buffer[32]; 178444961713Sgirish int instance; 178544961713Sgirish uint64_t debug_level; 178644961713Sgirish int cmn_level = CE_CONT; 178744961713Sgirish va_list ap; 178844961713Sgirish 1789678453a8Sspeer if (nxgep && nxgep->nxge_debug_level != nxge_debug_level) { 1790678453a8Sspeer /* In case a developer has changed nxge_debug_level. */ 1791678453a8Sspeer if (nxgep->nxge_debug_level != nxge_debug_level) 1792678453a8Sspeer nxgep->nxge_debug_level = nxge_debug_level; 1793678453a8Sspeer } 1794678453a8Sspeer 179544961713Sgirish debug_level = (nxgep == NULL) ? nxge_debug_level : 17964045d941Ssowmini nxgep->nxge_debug_level; 179744961713Sgirish 179844961713Sgirish if ((level & debug_level) || 17994045d941Ssowmini (level == NXGE_NOTE) || 18004045d941Ssowmini (level == NXGE_ERR_CTL)) { 180144961713Sgirish /* do the msg processing */ 180244961713Sgirish MUTEX_ENTER(&nxgedebuglock); 180344961713Sgirish 180444961713Sgirish if ((level & NXGE_NOTE)) { 180544961713Sgirish cmn_level = CE_NOTE; 180644961713Sgirish } 180744961713Sgirish 180844961713Sgirish if (level & NXGE_ERR_CTL) { 180944961713Sgirish cmn_level = CE_WARN; 181044961713Sgirish } 181144961713Sgirish 181244961713Sgirish va_start(ap, fmt); 181344961713Sgirish (void) vsprintf(msg_buffer, fmt, ap); 181444961713Sgirish va_end(ap); 181544961713Sgirish if (nxgep == NULL) { 181644961713Sgirish instance = -1; 181744961713Sgirish (void) sprintf(prefix_buffer, "%s :", "nxge"); 181844961713Sgirish } else { 181944961713Sgirish instance = nxgep->instance; 182044961713Sgirish (void) sprintf(prefix_buffer, 18214045d941Ssowmini "%s%d :", "nxge", instance); 182244961713Sgirish } 182344961713Sgirish 182444961713Sgirish MUTEX_EXIT(&nxgedebuglock); 182544961713Sgirish cmn_err(cmn_level, "!%s %s\n", 18264045d941Ssowmini prefix_buffer, msg_buffer); 182744961713Sgirish 182844961713Sgirish } 182944961713Sgirish } 183044961713Sgirish 183144961713Sgirish char * 183244961713Sgirish nxge_dump_packet(char *addr, int size) 183344961713Sgirish { 183444961713Sgirish uchar_t *ap = (uchar_t *)addr; 183544961713Sgirish int i; 183644961713Sgirish static char etherbuf[1024]; 183744961713Sgirish char *cp = etherbuf; 183844961713Sgirish char digits[] = "0123456789abcdef"; 183944961713Sgirish 184044961713Sgirish if (!size) 184144961713Sgirish size = 60; 184244961713Sgirish 184344961713Sgirish if (size > MAX_DUMP_SZ) { 184444961713Sgirish /* Dump the leading bytes */ 184544961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 184644961713Sgirish if (*ap > 0x0f) 184744961713Sgirish *cp++ = digits[*ap >> 4]; 184844961713Sgirish *cp++ = digits[*ap++ & 0xf]; 184944961713Sgirish *cp++ = ':'; 185044961713Sgirish } 185144961713Sgirish for (i = 0; i < 20; i++) 185244961713Sgirish *cp++ = '.'; 185344961713Sgirish /* Dump the last MAX_DUMP_SZ/2 bytes */ 185444961713Sgirish ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ/2)); 185544961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 185644961713Sgirish if (*ap > 0x0f) 185744961713Sgirish *cp++ = digits[*ap >> 4]; 185844961713Sgirish *cp++ = digits[*ap++ & 0xf]; 185944961713Sgirish *cp++ = ':'; 186044961713Sgirish } 186144961713Sgirish } else { 186244961713Sgirish for (i = 0; i < size; i++) { 186344961713Sgirish if (*ap > 0x0f) 186444961713Sgirish *cp++ = digits[*ap >> 4]; 186544961713Sgirish *cp++ = digits[*ap++ & 0xf]; 186644961713Sgirish *cp++ = ':'; 186744961713Sgirish } 186844961713Sgirish } 186944961713Sgirish *--cp = 0; 187044961713Sgirish return (etherbuf); 187144961713Sgirish } 187244961713Sgirish 187344961713Sgirish #ifdef NXGE_DEBUG 187444961713Sgirish static void 187544961713Sgirish nxge_test_map_regs(p_nxge_t nxgep) 187644961713Sgirish { 187744961713Sgirish ddi_acc_handle_t cfg_handle; 187844961713Sgirish p_pci_cfg_t cfg_ptr; 187944961713Sgirish ddi_acc_handle_t dev_handle; 188044961713Sgirish char *dev_ptr; 188144961713Sgirish ddi_acc_handle_t pci_config_handle; 188244961713Sgirish uint32_t regval; 188344961713Sgirish int i; 188444961713Sgirish 188544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_test_map_regs")); 188644961713Sgirish 188744961713Sgirish dev_handle = nxgep->dev_regs->nxge_regh; 188844961713Sgirish dev_ptr = (char *)nxgep->dev_regs->nxge_regp; 188944961713Sgirish 18902e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 189144961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 189244961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 189344961713Sgirish 189444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 189559ac0c16Sdavemq "Neptune PCI regp cfg_ptr 0x%llx", (char *)cfg_ptr)); 189644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 189759ac0c16Sdavemq "Neptune PCI cfg_ptr vendor id ptr 0x%llx", 189859ac0c16Sdavemq &cfg_ptr->vendorid)); 189944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 190059ac0c16Sdavemq "\tvendorid 0x%x devid 0x%x", 190159ac0c16Sdavemq NXGE_PIO_READ16(cfg_handle, &cfg_ptr->vendorid, 0), 190259ac0c16Sdavemq NXGE_PIO_READ16(cfg_handle, &cfg_ptr->devid, 0))); 190344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 190459ac0c16Sdavemq "PCI BAR: base 0x%x base14 0x%x base 18 0x%x " 190559ac0c16Sdavemq "bar1c 0x%x", 190659ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base, 0), 190759ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base14, 0), 190859ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base18, 0), 190959ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base1c, 0))); 191044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 191159ac0c16Sdavemq "\nNeptune PCI BAR: base20 0x%x base24 0x%x " 191259ac0c16Sdavemq "base 28 0x%x bar2c 0x%x\n", 191359ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base20, 0), 191459ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base24, 0), 191559ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base28, 0), 191659ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base2c, 0))); 191744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 191859ac0c16Sdavemq "\nNeptune PCI BAR: base30 0x%x\n", 191959ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base30, 0))); 192044961713Sgirish 192144961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 192244961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 192344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 192459ac0c16Sdavemq "first 0x%llx second 0x%llx third 0x%llx " 192559ac0c16Sdavemq "last 0x%llx ", 192659ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 192759ac0c16Sdavemq (uint64_t *)(dev_ptr + 0), 0), 192859ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 192959ac0c16Sdavemq (uint64_t *)(dev_ptr + 8), 0), 193059ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 193159ac0c16Sdavemq (uint64_t *)(dev_ptr + 16), 0), 193259ac0c16Sdavemq NXGE_PIO_READ64(cfg_handle, 193359ac0c16Sdavemq (uint64_t *)(dev_ptr + 24), 0))); 193444961713Sgirish } 193544961713Sgirish } 193644961713Sgirish 193744961713Sgirish #endif 193844961713Sgirish 193944961713Sgirish static void 194044961713Sgirish nxge_suspend(p_nxge_t nxgep) 194144961713Sgirish { 194244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_suspend")); 194344961713Sgirish 194444961713Sgirish nxge_intrs_disable(nxgep); 194544961713Sgirish nxge_destroy_dev(nxgep); 194644961713Sgirish 194744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_suspend")); 194844961713Sgirish } 194944961713Sgirish 195044961713Sgirish static nxge_status_t 195144961713Sgirish nxge_resume(p_nxge_t nxgep) 195244961713Sgirish { 195344961713Sgirish nxge_status_t status = NXGE_OK; 195444961713Sgirish 195544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_resume")); 195644961713Sgirish 195791c98b31Sjoycey nxgep->suspended = DDI_RESUME; 195891c98b31Sjoycey (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 195991c98b31Sjoycey (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_START); 196091c98b31Sjoycey (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START); 196191c98b31Sjoycey (void) nxge_rx_mac_enable(nxgep); 196291c98b31Sjoycey (void) nxge_tx_mac_enable(nxgep); 196391c98b31Sjoycey nxge_intrs_enable(nxgep); 196444961713Sgirish nxgep->suspended = 0; 196544961713Sgirish 196644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 19674045d941Ssowmini "<== nxge_resume status = 0x%x", status)); 196844961713Sgirish return (status); 196944961713Sgirish } 197044961713Sgirish 197144961713Sgirish static nxge_status_t 197244961713Sgirish nxge_setup_dev(p_nxge_t nxgep) 197344961713Sgirish { 197444961713Sgirish nxge_status_t status = NXGE_OK; 197544961713Sgirish 197644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_dev port %d", 197759ac0c16Sdavemq nxgep->mac.portnum)); 197844961713Sgirish 197944961713Sgirish status = nxge_link_init(nxgep); 198014ea4bb7Ssd 198114ea4bb7Ssd if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) { 198214ea4bb7Ssd NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 19834045d941Ssowmini "port%d Bad register acc handle", nxgep->mac.portnum)); 198414ea4bb7Ssd status = NXGE_ERROR; 198514ea4bb7Ssd } 198614ea4bb7Ssd 198744961713Sgirish if (status != NXGE_OK) { 198844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 19894045d941Ssowmini " nxge_setup_dev status " 19904045d941Ssowmini "(xcvr init 0x%08x)", status)); 199144961713Sgirish goto nxge_setup_dev_exit; 199244961713Sgirish } 199344961713Sgirish 199444961713Sgirish nxge_setup_dev_exit: 199544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 19964045d941Ssowmini "<== nxge_setup_dev port %d status = 0x%08x", 19974045d941Ssowmini nxgep->mac.portnum, status)); 199844961713Sgirish 199944961713Sgirish return (status); 200044961713Sgirish } 200144961713Sgirish 200244961713Sgirish static void 200344961713Sgirish nxge_destroy_dev(p_nxge_t nxgep) 200444961713Sgirish { 200544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_dev")); 200644961713Sgirish 200744961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 200844961713Sgirish 200944961713Sgirish (void) nxge_hw_stop(nxgep); 201044961713Sgirish 201144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_dev")); 201244961713Sgirish } 201344961713Sgirish 201444961713Sgirish static nxge_status_t 201544961713Sgirish nxge_setup_system_dma_pages(p_nxge_t nxgep) 201644961713Sgirish { 201744961713Sgirish int ddi_status = DDI_SUCCESS; 201844961713Sgirish uint_t count; 201944961713Sgirish ddi_dma_cookie_t cookie; 202044961713Sgirish uint_t iommu_pagesize; 202144961713Sgirish nxge_status_t status = NXGE_OK; 202244961713Sgirish 2023678453a8Sspeer NXGE_ERROR_MSG((nxgep, DDI_CTL, "==> nxge_setup_system_dma_pages")); 202444961713Sgirish nxgep->sys_page_sz = ddi_ptob(nxgep->dip, (ulong_t)1); 202544961713Sgirish if (nxgep->niu_type != N2_NIU) { 202644961713Sgirish iommu_pagesize = dvma_pagesize(nxgep->dip); 202744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20284045d941Ssowmini " nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 20294045d941Ssowmini " default_block_size %d iommu_pagesize %d", 20304045d941Ssowmini nxgep->sys_page_sz, 20314045d941Ssowmini ddi_ptob(nxgep->dip, (ulong_t)1), 20324045d941Ssowmini nxgep->rx_default_block_size, 20334045d941Ssowmini iommu_pagesize)); 203444961713Sgirish 203544961713Sgirish if (iommu_pagesize != 0) { 203644961713Sgirish if (nxgep->sys_page_sz == iommu_pagesize) { 203744961713Sgirish if (iommu_pagesize > 0x4000) 203844961713Sgirish nxgep->sys_page_sz = 0x4000; 203944961713Sgirish } else { 204044961713Sgirish if (nxgep->sys_page_sz > iommu_pagesize) 204144961713Sgirish nxgep->sys_page_sz = iommu_pagesize; 204244961713Sgirish } 204344961713Sgirish } 204444961713Sgirish } 204544961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 204644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20474045d941Ssowmini "==> nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 20484045d941Ssowmini "default_block_size %d page mask %d", 20494045d941Ssowmini nxgep->sys_page_sz, 20504045d941Ssowmini ddi_ptob(nxgep->dip, (ulong_t)1), 20514045d941Ssowmini nxgep->rx_default_block_size, 20524045d941Ssowmini nxgep->sys_page_mask)); 205344961713Sgirish 205444961713Sgirish 205544961713Sgirish switch (nxgep->sys_page_sz) { 205644961713Sgirish default: 205744961713Sgirish nxgep->sys_page_sz = 0x1000; 205844961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 205944961713Sgirish nxgep->rx_default_block_size = 0x1000; 206044961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 206144961713Sgirish break; 206244961713Sgirish case 0x1000: 206344961713Sgirish nxgep->rx_default_block_size = 0x1000; 206444961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 206544961713Sgirish break; 206644961713Sgirish case 0x2000: 206744961713Sgirish nxgep->rx_default_block_size = 0x2000; 206844961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 206944961713Sgirish break; 207044961713Sgirish case 0x4000: 207144961713Sgirish nxgep->rx_default_block_size = 0x4000; 207244961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_16K; 207344961713Sgirish break; 207444961713Sgirish case 0x8000: 207544961713Sgirish nxgep->rx_default_block_size = 0x8000; 207644961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_32K; 207744961713Sgirish break; 207844961713Sgirish } 207944961713Sgirish 208044961713Sgirish #ifndef USE_RX_BIG_BUF 208144961713Sgirish nxge_rx_dma_attr.dma_attr_align = nxgep->sys_page_sz; 208244961713Sgirish #else 208344961713Sgirish nxgep->rx_default_block_size = 0x2000; 208444961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 208544961713Sgirish #endif 208644961713Sgirish /* 208744961713Sgirish * Get the system DMA burst size. 208844961713Sgirish */ 208944961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr, 20904045d941Ssowmini DDI_DMA_DONTWAIT, 0, 20914045d941Ssowmini &nxgep->dmasparehandle); 209244961713Sgirish if (ddi_status != DDI_SUCCESS) { 209344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20944045d941Ssowmini "ddi_dma_alloc_handle: failed " 20954045d941Ssowmini " status 0x%x", ddi_status)); 209644961713Sgirish goto nxge_get_soft_properties_exit; 209744961713Sgirish } 209844961713Sgirish 209944961713Sgirish ddi_status = ddi_dma_addr_bind_handle(nxgep->dmasparehandle, NULL, 21004045d941Ssowmini (caddr_t)nxgep->dmasparehandle, 21014045d941Ssowmini sizeof (nxgep->dmasparehandle), 21024045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 21034045d941Ssowmini DDI_DMA_DONTWAIT, 0, 21044045d941Ssowmini &cookie, &count); 210544961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 210644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 21074045d941Ssowmini "Binding spare handle to find system" 21084045d941Ssowmini " burstsize failed.")); 210944961713Sgirish ddi_status = DDI_FAILURE; 211044961713Sgirish goto nxge_get_soft_properties_fail1; 211144961713Sgirish } 211244961713Sgirish 211344961713Sgirish nxgep->sys_burst_sz = ddi_dma_burstsizes(nxgep->dmasparehandle); 211444961713Sgirish (void) ddi_dma_unbind_handle(nxgep->dmasparehandle); 211544961713Sgirish 211644961713Sgirish nxge_get_soft_properties_fail1: 211744961713Sgirish ddi_dma_free_handle(&nxgep->dmasparehandle); 211844961713Sgirish 211944961713Sgirish nxge_get_soft_properties_exit: 212044961713Sgirish 212144961713Sgirish if (ddi_status != DDI_SUCCESS) 212244961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 212344961713Sgirish 212444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 21254045d941Ssowmini "<== nxge_setup_system_dma_pages status = 0x%08x", status)); 212644961713Sgirish return (status); 212744961713Sgirish } 212844961713Sgirish 212944961713Sgirish static nxge_status_t 213044961713Sgirish nxge_alloc_mem_pool(p_nxge_t nxgep) 213144961713Sgirish { 213244961713Sgirish nxge_status_t status = NXGE_OK; 213344961713Sgirish 213444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_alloc_mem_pool")); 213544961713Sgirish 213644961713Sgirish status = nxge_alloc_rx_mem_pool(nxgep); 213744961713Sgirish if (status != NXGE_OK) { 213844961713Sgirish return (NXGE_ERROR); 213944961713Sgirish } 214044961713Sgirish 214144961713Sgirish status = nxge_alloc_tx_mem_pool(nxgep); 214244961713Sgirish if (status != NXGE_OK) { 214344961713Sgirish nxge_free_rx_mem_pool(nxgep); 214444961713Sgirish return (NXGE_ERROR); 214544961713Sgirish } 214644961713Sgirish 214744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_alloc_mem_pool")); 214844961713Sgirish return (NXGE_OK); 214944961713Sgirish } 215044961713Sgirish 215144961713Sgirish static void 215244961713Sgirish nxge_free_mem_pool(p_nxge_t nxgep) 215344961713Sgirish { 215444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_mem_pool")); 215544961713Sgirish 215644961713Sgirish nxge_free_rx_mem_pool(nxgep); 215744961713Sgirish nxge_free_tx_mem_pool(nxgep); 215844961713Sgirish 215944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_mem_pool")); 216044961713Sgirish } 216144961713Sgirish 2162678453a8Sspeer nxge_status_t 216344961713Sgirish nxge_alloc_rx_mem_pool(p_nxge_t nxgep) 216444961713Sgirish { 2165678453a8Sspeer uint32_t rdc_max; 216644961713Sgirish p_nxge_dma_pt_cfg_t p_all_cfgp; 216744961713Sgirish p_nxge_hw_pt_cfg_t p_cfgp; 216844961713Sgirish p_nxge_dma_pool_t dma_poolp; 216944961713Sgirish p_nxge_dma_common_t *dma_buf_p; 217044961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 217144961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 217244961713Sgirish uint32_t *num_chunks; /* per dma */ 217344961713Sgirish nxge_status_t status = NXGE_OK; 217444961713Sgirish 217544961713Sgirish uint32_t nxge_port_rbr_size; 217644961713Sgirish uint32_t nxge_port_rbr_spare_size; 217744961713Sgirish uint32_t nxge_port_rcr_size; 2178678453a8Sspeer uint32_t rx_cntl_alloc_size; 217944961713Sgirish 218044961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_mem_pool")); 218144961713Sgirish 218244961713Sgirish p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 218344961713Sgirish p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 2184678453a8Sspeer rdc_max = NXGE_MAX_RDCS; 218544961713Sgirish 218644961713Sgirish /* 2187678453a8Sspeer * Allocate memory for the common DMA data structures. 218844961713Sgirish */ 218944961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 21904045d941Ssowmini KM_SLEEP); 219144961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 21924045d941Ssowmini sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP); 219344961713Sgirish 219444961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 21954045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 219644961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 21974045d941Ssowmini sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP); 219844961713Sgirish 219944961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 22004045d941Ssowmini sizeof (uint32_t) * rdc_max, KM_SLEEP); 220144961713Sgirish 220244961713Sgirish /* 2203678453a8Sspeer * Assume that each DMA channel will be configured with 2204678453a8Sspeer * the default block size. 2205678453a8Sspeer * rbr block counts are modulo the batch count (16). 220644961713Sgirish */ 220744961713Sgirish nxge_port_rbr_size = p_all_cfgp->rbr_size; 220844961713Sgirish nxge_port_rcr_size = p_all_cfgp->rcr_size; 220944961713Sgirish 221044961713Sgirish if (!nxge_port_rbr_size) { 221144961713Sgirish nxge_port_rbr_size = NXGE_RBR_RBB_DEFAULT; 221244961713Sgirish } 221344961713Sgirish if (nxge_port_rbr_size % NXGE_RXDMA_POST_BATCH) { 221444961713Sgirish nxge_port_rbr_size = (NXGE_RXDMA_POST_BATCH * 22154045d941Ssowmini (nxge_port_rbr_size / NXGE_RXDMA_POST_BATCH + 1)); 221644961713Sgirish } 221744961713Sgirish 221844961713Sgirish p_all_cfgp->rbr_size = nxge_port_rbr_size; 221944961713Sgirish nxge_port_rbr_spare_size = nxge_rbr_spare_size; 222044961713Sgirish 222144961713Sgirish if (nxge_port_rbr_spare_size % NXGE_RXDMA_POST_BATCH) { 222244961713Sgirish nxge_port_rbr_spare_size = (NXGE_RXDMA_POST_BATCH * 22234045d941Ssowmini (nxge_port_rbr_spare_size / NXGE_RXDMA_POST_BATCH + 1)); 222444961713Sgirish } 222530ac2e7bSml if (nxge_port_rbr_size > RBR_DEFAULT_MAX_BLKS) { 222630ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 222730ac2e7bSml "nxge_alloc_rx_mem_pool: RBR size too high %d, " 222830ac2e7bSml "set to default %d", 222930ac2e7bSml nxge_port_rbr_size, RBR_DEFAULT_MAX_BLKS)); 223030ac2e7bSml nxge_port_rbr_size = RBR_DEFAULT_MAX_BLKS; 223130ac2e7bSml } 223230ac2e7bSml if (nxge_port_rcr_size > RCR_DEFAULT_MAX) { 223330ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 223430ac2e7bSml "nxge_alloc_rx_mem_pool: RCR too high %d, " 223530ac2e7bSml "set to default %d", 223630ac2e7bSml nxge_port_rcr_size, RCR_DEFAULT_MAX)); 223730ac2e7bSml nxge_port_rcr_size = RCR_DEFAULT_MAX; 223830ac2e7bSml } 223944961713Sgirish 224044961713Sgirish /* 224144961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 224244961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 224344961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 224444961713Sgirish * function). 224544961713Sgirish */ 224644961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 224744961713Sgirish if (nxgep->niu_type == N2_NIU) { 224844961713Sgirish nxge_port_rbr_spare_size = 0; 224944961713Sgirish if ((nxge_port_rbr_size > NXGE_NIU_CONTIG_RBR_MAX) || 22504045d941Ssowmini (!ISP2(nxge_port_rbr_size))) { 225144961713Sgirish nxge_port_rbr_size = NXGE_NIU_CONTIG_RBR_MAX; 225244961713Sgirish } 225344961713Sgirish if ((nxge_port_rcr_size > NXGE_NIU_CONTIG_RCR_MAX) || 22544045d941Ssowmini (!ISP2(nxge_port_rcr_size))) { 225544961713Sgirish nxge_port_rcr_size = NXGE_NIU_CONTIG_RCR_MAX; 225644961713Sgirish } 225744961713Sgirish } 225844961713Sgirish #endif 225944961713Sgirish 226044961713Sgirish /* 226144961713Sgirish * Addresses of receive block ring, receive completion ring and the 226244961713Sgirish * mailbox must be all cache-aligned (64 bytes). 226344961713Sgirish */ 226444961713Sgirish rx_cntl_alloc_size = nxge_port_rbr_size + nxge_port_rbr_spare_size; 226544961713Sgirish rx_cntl_alloc_size *= (sizeof (rx_desc_t)); 226644961713Sgirish rx_cntl_alloc_size += (sizeof (rcr_entry_t) * nxge_port_rcr_size); 226744961713Sgirish rx_cntl_alloc_size += sizeof (rxdma_mailbox_t); 226844961713Sgirish 226944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_alloc_rx_mem_pool: " 22704045d941Ssowmini "nxge_port_rbr_size = %d nxge_port_rbr_spare_size = %d " 22714045d941Ssowmini "nxge_port_rcr_size = %d " 22724045d941Ssowmini "rx_cntl_alloc_size = %d", 22734045d941Ssowmini nxge_port_rbr_size, nxge_port_rbr_spare_size, 22744045d941Ssowmini nxge_port_rcr_size, 22754045d941Ssowmini rx_cntl_alloc_size)); 227644961713Sgirish 227744961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 227844961713Sgirish if (nxgep->niu_type == N2_NIU) { 2279678453a8Sspeer uint32_t rx_buf_alloc_size = (nxgep->rx_default_block_size * 2280678453a8Sspeer (nxge_port_rbr_size + nxge_port_rbr_spare_size)); 2281678453a8Sspeer 228244961713Sgirish if (!ISP2(rx_buf_alloc_size)) { 228344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 22844045d941Ssowmini "==> nxge_alloc_rx_mem_pool: " 22854045d941Ssowmini " must be power of 2")); 228644961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 228744961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 228844961713Sgirish } 228944961713Sgirish 229044961713Sgirish if (rx_buf_alloc_size > (1 << 22)) { 229144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 22924045d941Ssowmini "==> nxge_alloc_rx_mem_pool: " 22934045d941Ssowmini " limit size to 4M")); 229444961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 229544961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 229644961713Sgirish } 229744961713Sgirish 229844961713Sgirish if (rx_cntl_alloc_size < 0x2000) { 229944961713Sgirish rx_cntl_alloc_size = 0x2000; 230044961713Sgirish } 230144961713Sgirish } 230244961713Sgirish #endif 230344961713Sgirish nxgep->nxge_port_rbr_size = nxge_port_rbr_size; 230444961713Sgirish nxgep->nxge_port_rcr_size = nxge_port_rcr_size; 2305678453a8Sspeer nxgep->nxge_port_rbr_spare_size = nxge_port_rbr_spare_size; 2306678453a8Sspeer nxgep->nxge_port_rx_cntl_alloc_size = rx_cntl_alloc_size; 230744961713Sgirish 2308678453a8Sspeer dma_poolp->ndmas = p_cfgp->max_rdcs; 230944961713Sgirish dma_poolp->num_chunks = num_chunks; 231044961713Sgirish dma_poolp->buf_allocated = B_TRUE; 231144961713Sgirish nxgep->rx_buf_pool_p = dma_poolp; 231244961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 231344961713Sgirish 2314678453a8Sspeer dma_cntl_poolp->ndmas = p_cfgp->max_rdcs; 231544961713Sgirish dma_cntl_poolp->buf_allocated = B_TRUE; 231644961713Sgirish nxgep->rx_cntl_pool_p = dma_cntl_poolp; 231744961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 231844961713Sgirish 2319678453a8Sspeer /* Allocate the receive rings, too. */ 2320678453a8Sspeer nxgep->rx_rbr_rings = 23214045d941Ssowmini KMEM_ZALLOC(sizeof (rx_rbr_rings_t), KM_SLEEP); 2322678453a8Sspeer nxgep->rx_rbr_rings->rbr_rings = 23234045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_rbr_ring_t) * rdc_max, KM_SLEEP); 2324678453a8Sspeer nxgep->rx_rcr_rings = 23254045d941Ssowmini KMEM_ZALLOC(sizeof (rx_rcr_rings_t), KM_SLEEP); 2326678453a8Sspeer nxgep->rx_rcr_rings->rcr_rings = 23274045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_rcr_ring_t) * rdc_max, KM_SLEEP); 2328678453a8Sspeer nxgep->rx_mbox_areas_p = 23294045d941Ssowmini KMEM_ZALLOC(sizeof (rx_mbox_areas_t), KM_SLEEP); 2330678453a8Sspeer nxgep->rx_mbox_areas_p->rxmbox_areas = 23314045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_mbox_t) * rdc_max, KM_SLEEP); 2332678453a8Sspeer 2333678453a8Sspeer nxgep->rx_rbr_rings->ndmas = nxgep->rx_rcr_rings->ndmas = 2334678453a8Sspeer p_cfgp->max_rdcs; 233544961713Sgirish 233644961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 23374045d941Ssowmini "<== nxge_alloc_rx_mem_pool:status 0x%08x", status)); 233844961713Sgirish 2339678453a8Sspeer nxge_alloc_rx_mem_pool_exit: 2340678453a8Sspeer return (status); 2341678453a8Sspeer } 2342678453a8Sspeer 2343678453a8Sspeer /* 2344678453a8Sspeer * nxge_alloc_rxb 2345678453a8Sspeer * 2346678453a8Sspeer * Allocate buffers for an RDC. 2347678453a8Sspeer * 2348678453a8Sspeer * Arguments: 2349678453a8Sspeer * nxgep 2350678453a8Sspeer * channel The channel to map into our kernel space. 2351678453a8Sspeer * 2352678453a8Sspeer * Notes: 2353678453a8Sspeer * 2354678453a8Sspeer * NPI function calls: 2355678453a8Sspeer * 2356678453a8Sspeer * NXGE function calls: 2357678453a8Sspeer * 2358678453a8Sspeer * Registers accessed: 2359678453a8Sspeer * 2360678453a8Sspeer * Context: 2361678453a8Sspeer * 2362678453a8Sspeer * Taking apart: 2363678453a8Sspeer * 2364678453a8Sspeer * Open questions: 2365678453a8Sspeer * 2366678453a8Sspeer */ 2367678453a8Sspeer nxge_status_t 2368678453a8Sspeer nxge_alloc_rxb( 2369678453a8Sspeer p_nxge_t nxgep, 2370678453a8Sspeer int channel) 2371678453a8Sspeer { 2372678453a8Sspeer size_t rx_buf_alloc_size; 2373678453a8Sspeer nxge_status_t status = NXGE_OK; 2374678453a8Sspeer 2375678453a8Sspeer nxge_dma_common_t **data; 2376678453a8Sspeer nxge_dma_common_t **control; 2377678453a8Sspeer uint32_t *num_chunks; 2378678453a8Sspeer 2379678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb")); 2380678453a8Sspeer 2381678453a8Sspeer /* 2382678453a8Sspeer * Allocate memory for the receive buffers and descriptor rings. 2383678453a8Sspeer * Replace these allocation functions with the interface functions 2384678453a8Sspeer * provided by the partition manager if/when they are available. 2385678453a8Sspeer */ 2386678453a8Sspeer 2387678453a8Sspeer /* 2388678453a8Sspeer * Allocate memory for the receive buffer blocks. 2389678453a8Sspeer */ 2390678453a8Sspeer rx_buf_alloc_size = (nxgep->rx_default_block_size * 23914045d941Ssowmini (nxgep->nxge_port_rbr_size + nxgep->nxge_port_rbr_spare_size)); 2392678453a8Sspeer 2393678453a8Sspeer data = &nxgep->rx_buf_pool_p->dma_buf_pool_p[channel]; 2394678453a8Sspeer num_chunks = &nxgep->rx_buf_pool_p->num_chunks[channel]; 2395678453a8Sspeer 2396678453a8Sspeer if ((status = nxge_alloc_rx_buf_dma( 2397678453a8Sspeer nxgep, channel, data, rx_buf_alloc_size, 2398678453a8Sspeer nxgep->rx_default_block_size, num_chunks)) != NXGE_OK) { 2399678453a8Sspeer return (status); 240044961713Sgirish } 240144961713Sgirish 2402678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_alloc_rxb(): " 2403678453a8Sspeer "dma %d dma_buf_p %llx &dma_buf_p %llx", channel, *data, data)); 2404678453a8Sspeer 2405678453a8Sspeer /* 2406678453a8Sspeer * Allocate memory for descriptor rings and mailbox. 2407678453a8Sspeer */ 2408678453a8Sspeer control = &nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel]; 2409678453a8Sspeer 2410678453a8Sspeer if ((status = nxge_alloc_rx_cntl_dma( 2411678453a8Sspeer nxgep, channel, control, nxgep->nxge_port_rx_cntl_alloc_size)) 2412678453a8Sspeer != NXGE_OK) { 2413678453a8Sspeer nxge_free_rx_cntl_dma(nxgep, *control); 2414678453a8Sspeer (*data)->buf_alloc_state |= BUF_ALLOCATED_WAIT_FREE; 2415678453a8Sspeer nxge_free_rx_buf_dma(nxgep, *data, *num_chunks); 2416678453a8Sspeer return (status); 2417678453a8Sspeer } 241844961713Sgirish 241944961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 2420678453a8Sspeer "<== nxge_alloc_rx_mem_pool:status 0x%08x", status)); 242144961713Sgirish 242244961713Sgirish return (status); 242344961713Sgirish } 242444961713Sgirish 2425678453a8Sspeer void 2426678453a8Sspeer nxge_free_rxb( 2427678453a8Sspeer p_nxge_t nxgep, 2428678453a8Sspeer int channel) 2429678453a8Sspeer { 2430678453a8Sspeer nxge_dma_common_t *data; 2431678453a8Sspeer nxge_dma_common_t *control; 2432678453a8Sspeer uint32_t num_chunks; 2433678453a8Sspeer 2434678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb")); 2435678453a8Sspeer 2436678453a8Sspeer data = nxgep->rx_buf_pool_p->dma_buf_pool_p[channel]; 2437678453a8Sspeer num_chunks = nxgep->rx_buf_pool_p->num_chunks[channel]; 2438678453a8Sspeer nxge_free_rx_buf_dma(nxgep, data, num_chunks); 2439678453a8Sspeer 2440678453a8Sspeer nxgep->rx_buf_pool_p->dma_buf_pool_p[channel] = 0; 2441678453a8Sspeer nxgep->rx_buf_pool_p->num_chunks[channel] = 0; 2442678453a8Sspeer 2443678453a8Sspeer control = nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel]; 2444678453a8Sspeer nxge_free_rx_cntl_dma(nxgep, control); 2445678453a8Sspeer 2446678453a8Sspeer nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel] = 0; 2447678453a8Sspeer 2448678453a8Sspeer KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 2449678453a8Sspeer KMEM_FREE(control, sizeof (nxge_dma_common_t)); 2450678453a8Sspeer 2451678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_alloc_rbb")); 2452678453a8Sspeer } 2453678453a8Sspeer 245444961713Sgirish static void 245544961713Sgirish nxge_free_rx_mem_pool(p_nxge_t nxgep) 245644961713Sgirish { 2457678453a8Sspeer int rdc_max = NXGE_MAX_RDCS; 245844961713Sgirish 245944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_mem_pool")); 246044961713Sgirish 2461678453a8Sspeer if (!nxgep->rx_buf_pool_p || !nxgep->rx_buf_pool_p->buf_allocated) { 246244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 24634045d941Ssowmini "<== nxge_free_rx_mem_pool " 24644045d941Ssowmini "(null rx buf pool or buf not allocated")); 246544961713Sgirish return; 246644961713Sgirish } 2467678453a8Sspeer if (!nxgep->rx_cntl_pool_p || !nxgep->rx_cntl_pool_p->buf_allocated) { 246844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 24694045d941Ssowmini "<== nxge_free_rx_mem_pool " 24704045d941Ssowmini "(null rx cntl buf pool or cntl buf not allocated")); 247144961713Sgirish return; 247244961713Sgirish } 247344961713Sgirish 2474678453a8Sspeer KMEM_FREE(nxgep->rx_cntl_pool_p->dma_buf_pool_p, 2475678453a8Sspeer sizeof (p_nxge_dma_common_t) * rdc_max); 2476678453a8Sspeer KMEM_FREE(nxgep->rx_cntl_pool_p, sizeof (nxge_dma_pool_t)); 247744961713Sgirish 2478678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p->num_chunks, 2479678453a8Sspeer sizeof (uint32_t) * rdc_max); 2480678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p->dma_buf_pool_p, 2481678453a8Sspeer sizeof (p_nxge_dma_common_t) * rdc_max); 2482678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p, sizeof (nxge_dma_pool_t)); 248344961713Sgirish 2484678453a8Sspeer nxgep->rx_buf_pool_p = 0; 2485678453a8Sspeer nxgep->rx_cntl_pool_p = 0; 248644961713Sgirish 2487678453a8Sspeer KMEM_FREE(nxgep->rx_rbr_rings->rbr_rings, 2488678453a8Sspeer sizeof (p_rx_rbr_ring_t) * rdc_max); 2489678453a8Sspeer KMEM_FREE(nxgep->rx_rbr_rings, sizeof (rx_rbr_rings_t)); 2490678453a8Sspeer KMEM_FREE(nxgep->rx_rcr_rings->rcr_rings, 2491678453a8Sspeer sizeof (p_rx_rcr_ring_t) * rdc_max); 2492678453a8Sspeer KMEM_FREE(nxgep->rx_rcr_rings, sizeof (rx_rcr_rings_t)); 2493678453a8Sspeer KMEM_FREE(nxgep->rx_mbox_areas_p->rxmbox_areas, 2494678453a8Sspeer sizeof (p_rx_mbox_t) * rdc_max); 2495678453a8Sspeer KMEM_FREE(nxgep->rx_mbox_areas_p, sizeof (rx_mbox_areas_t)); 249644961713Sgirish 2497678453a8Sspeer nxgep->rx_rbr_rings = 0; 2498678453a8Sspeer nxgep->rx_rcr_rings = 0; 2499678453a8Sspeer nxgep->rx_mbox_areas_p = 0; 250044961713Sgirish 250144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_rx_mem_pool")); 250244961713Sgirish } 250344961713Sgirish 250444961713Sgirish 250544961713Sgirish static nxge_status_t 250644961713Sgirish nxge_alloc_rx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 250744961713Sgirish p_nxge_dma_common_t *dmap, 250844961713Sgirish size_t alloc_size, size_t block_size, uint32_t *num_chunks) 250944961713Sgirish { 251044961713Sgirish p_nxge_dma_common_t rx_dmap; 251144961713Sgirish nxge_status_t status = NXGE_OK; 251244961713Sgirish size_t total_alloc_size; 251344961713Sgirish size_t allocated = 0; 251444961713Sgirish int i, size_index, array_size; 2515678453a8Sspeer boolean_t use_kmem_alloc = B_FALSE; 251644961713Sgirish 251744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_buf_dma")); 251844961713Sgirish 251944961713Sgirish rx_dmap = (p_nxge_dma_common_t) 25204045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 25214045d941Ssowmini KM_SLEEP); 252244961713Sgirish 252344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 25244045d941Ssowmini " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ", 25254045d941Ssowmini dma_channel, alloc_size, block_size, dmap)); 252644961713Sgirish 252744961713Sgirish total_alloc_size = alloc_size; 252844961713Sgirish 252944961713Sgirish #if defined(RX_USE_RECLAIM_POST) 253044961713Sgirish total_alloc_size = alloc_size + alloc_size/4; 253144961713Sgirish #endif 253244961713Sgirish 253344961713Sgirish i = 0; 253444961713Sgirish size_index = 0; 253544961713Sgirish array_size = sizeof (alloc_sizes)/sizeof (size_t); 25367b26d9ffSSantwona Behera while ((size_index < array_size) && 25377b26d9ffSSantwona Behera (alloc_sizes[size_index] < alloc_size)) 25384045d941Ssowmini size_index++; 253944961713Sgirish if (size_index >= array_size) { 254044961713Sgirish size_index = array_size - 1; 254144961713Sgirish } 254244961713Sgirish 2543678453a8Sspeer /* For Neptune, use kmem_alloc if the kmem flag is set. */ 2544678453a8Sspeer if (nxgep->niu_type != N2_NIU && nxge_use_kmem_alloc) { 2545678453a8Sspeer use_kmem_alloc = B_TRUE; 2546678453a8Sspeer #if defined(__i386) || defined(__amd64) 2547678453a8Sspeer size_index = 0; 2548678453a8Sspeer #endif 2549678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2550678453a8Sspeer "==> nxge_alloc_rx_buf_dma: " 2551678453a8Sspeer "Neptune use kmem_alloc() - size_index %d", 2552678453a8Sspeer size_index)); 2553678453a8Sspeer } 2554678453a8Sspeer 255544961713Sgirish while ((allocated < total_alloc_size) && 25564045d941Ssowmini (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 255744961713Sgirish rx_dmap[i].dma_chunk_index = i; 255844961713Sgirish rx_dmap[i].block_size = block_size; 255944961713Sgirish rx_dmap[i].alength = alloc_sizes[size_index]; 256044961713Sgirish rx_dmap[i].orig_alength = rx_dmap[i].alength; 256144961713Sgirish rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 256244961713Sgirish rx_dmap[i].dma_channel = dma_channel; 256344961713Sgirish rx_dmap[i].contig_alloc_type = B_FALSE; 2564678453a8Sspeer rx_dmap[i].kmem_alloc_type = B_FALSE; 2565678453a8Sspeer rx_dmap[i].buf_alloc_type = DDI_MEM_ALLOC; 256644961713Sgirish 256744961713Sgirish /* 256844961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 256944961713Sgirish * needs to call Hypervisor api to set up 257044961713Sgirish * logical pages. 257144961713Sgirish */ 257244961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 257344961713Sgirish rx_dmap[i].contig_alloc_type = B_TRUE; 2574678453a8Sspeer rx_dmap[i].buf_alloc_type = CONTIG_MEM_ALLOC; 2575678453a8Sspeer } else if (use_kmem_alloc) { 2576678453a8Sspeer /* For Neptune, use kmem_alloc */ 2577678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2578678453a8Sspeer "==> nxge_alloc_rx_buf_dma: " 2579678453a8Sspeer "Neptune use kmem_alloc()")); 2580678453a8Sspeer rx_dmap[i].kmem_alloc_type = B_TRUE; 2581678453a8Sspeer rx_dmap[i].buf_alloc_type = KMEM_ALLOC; 258244961713Sgirish } 258344961713Sgirish 258444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 25854045d941Ssowmini "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x " 25864045d941Ssowmini "i %d nblocks %d alength %d", 25874045d941Ssowmini dma_channel, i, &rx_dmap[i], block_size, 25884045d941Ssowmini i, rx_dmap[i].nblocks, 25894045d941Ssowmini rx_dmap[i].alength)); 259044961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 25914045d941Ssowmini &nxge_rx_dma_attr, 25924045d941Ssowmini rx_dmap[i].alength, 25934045d941Ssowmini &nxge_dev_buf_dma_acc_attr, 25944045d941Ssowmini DDI_DMA_READ | DDI_DMA_STREAMING, 25954045d941Ssowmini (p_nxge_dma_common_t)(&rx_dmap[i])); 259644961713Sgirish if (status != NXGE_OK) { 259744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2598678453a8Sspeer "nxge_alloc_rx_buf_dma: Alloc Failed: " 2599678453a8Sspeer "dma %d size_index %d size requested %d", 2600678453a8Sspeer dma_channel, 2601678453a8Sspeer size_index, 2602678453a8Sspeer rx_dmap[i].alength)); 260344961713Sgirish size_index--; 260444961713Sgirish } else { 2605678453a8Sspeer rx_dmap[i].buf_alloc_state = BUF_ALLOCATED; 2606678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2607678453a8Sspeer " nxge_alloc_rx_buf_dma DONE alloc mem: " 2608678453a8Sspeer "dma %d dma_buf_p $%p kaddrp $%p alength %d " 2609678453a8Sspeer "buf_alloc_state %d alloc_type %d", 2610678453a8Sspeer dma_channel, 2611678453a8Sspeer &rx_dmap[i], 2612678453a8Sspeer rx_dmap[i].kaddrp, 2613678453a8Sspeer rx_dmap[i].alength, 2614678453a8Sspeer rx_dmap[i].buf_alloc_state, 2615678453a8Sspeer rx_dmap[i].buf_alloc_type)); 2616678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2617678453a8Sspeer " alloc_rx_buf_dma allocated rdc %d " 2618678453a8Sspeer "chunk %d size %x dvma %x bufp %llx kaddrp $%p", 2619678453a8Sspeer dma_channel, i, rx_dmap[i].alength, 2620678453a8Sspeer rx_dmap[i].ioaddr_pp, &rx_dmap[i], 2621678453a8Sspeer rx_dmap[i].kaddrp)); 262244961713Sgirish i++; 262344961713Sgirish allocated += alloc_sizes[size_index]; 262444961713Sgirish } 262544961713Sgirish } 262644961713Sgirish 262744961713Sgirish if (allocated < total_alloc_size) { 262830ac2e7bSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2629678453a8Sspeer "==> nxge_alloc_rx_buf_dma: not enough for channel %d " 263030ac2e7bSml "allocated 0x%x requested 0x%x", 263130ac2e7bSml dma_channel, 263230ac2e7bSml allocated, total_alloc_size)); 263330ac2e7bSml status = NXGE_ERROR; 263444961713Sgirish goto nxge_alloc_rx_mem_fail1; 263544961713Sgirish } 263644961713Sgirish 263730ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2638678453a8Sspeer "==> nxge_alloc_rx_buf_dma: Allocated for channel %d " 263930ac2e7bSml "allocated 0x%x requested 0x%x", 264030ac2e7bSml dma_channel, 264130ac2e7bSml allocated, total_alloc_size)); 264230ac2e7bSml 264344961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 26444045d941Ssowmini " alloc_rx_buf_dma rdc %d allocated %d chunks", 26454045d941Ssowmini dma_channel, i)); 264644961713Sgirish *num_chunks = i; 264744961713Sgirish *dmap = rx_dmap; 264844961713Sgirish 264944961713Sgirish goto nxge_alloc_rx_mem_exit; 265044961713Sgirish 265144961713Sgirish nxge_alloc_rx_mem_fail1: 265244961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 265344961713Sgirish 265444961713Sgirish nxge_alloc_rx_mem_exit: 265544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 26564045d941Ssowmini "<== nxge_alloc_rx_buf_dma status 0x%08x", status)); 265744961713Sgirish 265844961713Sgirish return (status); 265944961713Sgirish } 266044961713Sgirish 266144961713Sgirish /*ARGSUSED*/ 266244961713Sgirish static void 266344961713Sgirish nxge_free_rx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 266444961713Sgirish uint32_t num_chunks) 266544961713Sgirish { 266644961713Sgirish int i; 266744961713Sgirish 266844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 26694045d941Ssowmini "==> nxge_free_rx_buf_dma: # of chunks %d", num_chunks)); 267044961713Sgirish 2671678453a8Sspeer if (dmap == 0) 2672678453a8Sspeer return; 2673678453a8Sspeer 267444961713Sgirish for (i = 0; i < num_chunks; i++) { 267544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 26764045d941Ssowmini "==> nxge_free_rx_buf_dma: chunk %d dmap 0x%llx", 26774045d941Ssowmini i, dmap)); 2678678453a8Sspeer nxge_dma_free_rx_data_buf(dmap++); 267944961713Sgirish } 268044961713Sgirish 268144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_buf_dma")); 268244961713Sgirish } 268344961713Sgirish 268444961713Sgirish /*ARGSUSED*/ 268544961713Sgirish static nxge_status_t 268644961713Sgirish nxge_alloc_rx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 268744961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 268844961713Sgirish { 268944961713Sgirish p_nxge_dma_common_t rx_dmap; 269044961713Sgirish nxge_status_t status = NXGE_OK; 269144961713Sgirish 269244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_cntl_dma")); 269344961713Sgirish 269444961713Sgirish rx_dmap = (p_nxge_dma_common_t) 26954045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 269644961713Sgirish 269744961713Sgirish rx_dmap->contig_alloc_type = B_FALSE; 2698678453a8Sspeer rx_dmap->kmem_alloc_type = B_FALSE; 269944961713Sgirish 270044961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 27014045d941Ssowmini &nxge_desc_dma_attr, 27024045d941Ssowmini size, 27034045d941Ssowmini &nxge_dev_desc_dma_acc_attr, 27044045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 27054045d941Ssowmini rx_dmap); 270644961713Sgirish if (status != NXGE_OK) { 270744961713Sgirish goto nxge_alloc_rx_cntl_dma_fail1; 270844961713Sgirish } 270944961713Sgirish 271044961713Sgirish *dmap = rx_dmap; 271144961713Sgirish goto nxge_alloc_rx_cntl_dma_exit; 271244961713Sgirish 271344961713Sgirish nxge_alloc_rx_cntl_dma_fail1: 271444961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t)); 271544961713Sgirish 271644961713Sgirish nxge_alloc_rx_cntl_dma_exit: 271744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 27184045d941Ssowmini "<== nxge_alloc_rx_cntl_dma status 0x%08x", status)); 271944961713Sgirish 2720678453a8Sspeer return (status); 2721678453a8Sspeer } 2722678453a8Sspeer 2723678453a8Sspeer /*ARGSUSED*/ 2724678453a8Sspeer static void 2725678453a8Sspeer nxge_free_rx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 2726678453a8Sspeer { 2727678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_rx_cntl_dma")); 2728678453a8Sspeer 2729678453a8Sspeer if (dmap == 0) 2730678453a8Sspeer return; 2731678453a8Sspeer 2732678453a8Sspeer nxge_dma_mem_free(dmap); 2733678453a8Sspeer 2734678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_rx_cntl_dma")); 2735678453a8Sspeer } 2736678453a8Sspeer 2737678453a8Sspeer typedef struct { 2738678453a8Sspeer size_t tx_size; 2739678453a8Sspeer size_t cr_size; 2740678453a8Sspeer size_t threshhold; 2741678453a8Sspeer } nxge_tdc_sizes_t; 2742678453a8Sspeer 2743678453a8Sspeer static 2744678453a8Sspeer nxge_status_t 2745678453a8Sspeer nxge_tdc_sizes( 2746678453a8Sspeer nxge_t *nxgep, 2747678453a8Sspeer nxge_tdc_sizes_t *sizes) 2748678453a8Sspeer { 2749678453a8Sspeer uint32_t threshhold; /* The bcopy() threshhold */ 2750678453a8Sspeer size_t tx_size; /* Transmit buffer size */ 2751678453a8Sspeer size_t cr_size; /* Completion ring size */ 2752678453a8Sspeer 2753678453a8Sspeer /* 2754678453a8Sspeer * Assume that each DMA channel will be configured with the 2755678453a8Sspeer * default transmit buffer size for copying transmit data. 2756678453a8Sspeer * (If a packet is bigger than this, it will not be copied.) 2757678453a8Sspeer */ 2758678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 2759678453a8Sspeer threshhold = TX_BCOPY_SIZE; 2760678453a8Sspeer } else { 2761678453a8Sspeer threshhold = nxge_bcopy_thresh; 2762678453a8Sspeer } 2763678453a8Sspeer tx_size = nxge_tx_ring_size * threshhold; 2764678453a8Sspeer 2765678453a8Sspeer cr_size = nxge_tx_ring_size * sizeof (tx_desc_t); 2766678453a8Sspeer cr_size += sizeof (txdma_mailbox_t); 2767678453a8Sspeer 2768678453a8Sspeer #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 2769678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 2770678453a8Sspeer if (!ISP2(tx_size)) { 2771678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27724045d941Ssowmini "==> nxge_tdc_sizes: Tx size" 27734045d941Ssowmini " must be power of 2")); 2774678453a8Sspeer return (NXGE_ERROR); 2775678453a8Sspeer } 2776678453a8Sspeer 2777678453a8Sspeer if (tx_size > (1 << 22)) { 2778678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27794045d941Ssowmini "==> nxge_tdc_sizes: Tx size" 27804045d941Ssowmini " limited to 4M")); 2781678453a8Sspeer return (NXGE_ERROR); 2782678453a8Sspeer } 2783678453a8Sspeer 2784678453a8Sspeer if (cr_size < 0x2000) 2785678453a8Sspeer cr_size = 0x2000; 2786678453a8Sspeer } 2787678453a8Sspeer #endif 2788678453a8Sspeer 2789678453a8Sspeer sizes->threshhold = threshhold; 2790678453a8Sspeer sizes->tx_size = tx_size; 2791678453a8Sspeer sizes->cr_size = cr_size; 2792678453a8Sspeer 2793678453a8Sspeer return (NXGE_OK); 2794678453a8Sspeer } 2795678453a8Sspeer /* 2796678453a8Sspeer * nxge_alloc_txb 2797678453a8Sspeer * 2798678453a8Sspeer * Allocate buffers for an TDC. 2799678453a8Sspeer * 2800678453a8Sspeer * Arguments: 2801678453a8Sspeer * nxgep 2802678453a8Sspeer * channel The channel to map into our kernel space. 2803678453a8Sspeer * 2804678453a8Sspeer * Notes: 2805678453a8Sspeer * 2806678453a8Sspeer * NPI function calls: 2807678453a8Sspeer * 2808678453a8Sspeer * NXGE function calls: 2809678453a8Sspeer * 2810678453a8Sspeer * Registers accessed: 2811678453a8Sspeer * 2812678453a8Sspeer * Context: 2813678453a8Sspeer * 2814678453a8Sspeer * Taking apart: 2815678453a8Sspeer * 2816678453a8Sspeer * Open questions: 2817678453a8Sspeer * 2818678453a8Sspeer */ 2819678453a8Sspeer nxge_status_t 2820678453a8Sspeer nxge_alloc_txb( 2821678453a8Sspeer p_nxge_t nxgep, 2822678453a8Sspeer int channel) 2823678453a8Sspeer { 2824678453a8Sspeer nxge_dma_common_t **dma_buf_p; 2825678453a8Sspeer nxge_dma_common_t **dma_cntl_p; 2826678453a8Sspeer uint32_t *num_chunks; 2827678453a8Sspeer nxge_status_t status = NXGE_OK; 2828678453a8Sspeer 2829678453a8Sspeer nxge_tdc_sizes_t sizes; 2830678453a8Sspeer 2831678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tbb")); 2832678453a8Sspeer 2833678453a8Sspeer if (nxge_tdc_sizes(nxgep, &sizes) != NXGE_OK) 2834678453a8Sspeer return (NXGE_ERROR); 2835678453a8Sspeer 2836678453a8Sspeer /* 2837678453a8Sspeer * Allocate memory for transmit buffers and descriptor rings. 2838678453a8Sspeer * Replace these allocation functions with the interface functions 2839678453a8Sspeer * provided by the partition manager Real Soon Now. 2840678453a8Sspeer */ 2841678453a8Sspeer dma_buf_p = &nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2842678453a8Sspeer num_chunks = &nxgep->tx_buf_pool_p->num_chunks[channel]; 2843678453a8Sspeer 2844678453a8Sspeer dma_cntl_p = &nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2845678453a8Sspeer 2846678453a8Sspeer /* 2847678453a8Sspeer * Allocate memory for transmit buffers and descriptor rings. 2848678453a8Sspeer * Replace allocation functions with interface functions provided 2849678453a8Sspeer * by the partition manager when it is available. 2850678453a8Sspeer * 2851678453a8Sspeer * Allocate memory for the transmit buffer pool. 2852678453a8Sspeer */ 2853678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 28544045d941Ssowmini "sizes: tx: %ld, cr:%ld, th:%ld", 28554045d941Ssowmini sizes.tx_size, sizes.cr_size, sizes.threshhold)); 2856678453a8Sspeer 2857678453a8Sspeer *num_chunks = 0; 2858678453a8Sspeer status = nxge_alloc_tx_buf_dma(nxgep, channel, dma_buf_p, 2859678453a8Sspeer sizes.tx_size, sizes.threshhold, num_chunks); 2860678453a8Sspeer if (status != NXGE_OK) { 2861678453a8Sspeer cmn_err(CE_NOTE, "nxge_alloc_tx_buf_dma failed!"); 2862678453a8Sspeer return (status); 2863678453a8Sspeer } 2864678453a8Sspeer 2865678453a8Sspeer /* 2866678453a8Sspeer * Allocate memory for descriptor rings and mailbox. 2867678453a8Sspeer */ 2868678453a8Sspeer status = nxge_alloc_tx_cntl_dma(nxgep, channel, dma_cntl_p, 2869678453a8Sspeer sizes.cr_size); 2870678453a8Sspeer if (status != NXGE_OK) { 2871678453a8Sspeer nxge_free_tx_buf_dma(nxgep, *dma_buf_p, *num_chunks); 2872678453a8Sspeer cmn_err(CE_NOTE, "nxge_alloc_tx_cntl_dma failed!"); 2873678453a8Sspeer return (status); 2874678453a8Sspeer } 2875678453a8Sspeer 2876678453a8Sspeer return (NXGE_OK); 2877678453a8Sspeer } 2878678453a8Sspeer 2879678453a8Sspeer void 2880678453a8Sspeer nxge_free_txb( 2881678453a8Sspeer p_nxge_t nxgep, 2882678453a8Sspeer int channel) 2883678453a8Sspeer { 2884678453a8Sspeer nxge_dma_common_t *data; 2885678453a8Sspeer nxge_dma_common_t *control; 2886678453a8Sspeer uint32_t num_chunks; 2887678453a8Sspeer 2888678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_txb")); 2889678453a8Sspeer 2890678453a8Sspeer data = nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2891678453a8Sspeer num_chunks = nxgep->tx_buf_pool_p->num_chunks[channel]; 2892678453a8Sspeer nxge_free_tx_buf_dma(nxgep, data, num_chunks); 2893678453a8Sspeer 2894678453a8Sspeer nxgep->tx_buf_pool_p->dma_buf_pool_p[channel] = 0; 2895678453a8Sspeer nxgep->tx_buf_pool_p->num_chunks[channel] = 0; 2896678453a8Sspeer 2897678453a8Sspeer control = nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2898678453a8Sspeer nxge_free_tx_cntl_dma(nxgep, control); 289944961713Sgirish 2900678453a8Sspeer nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel] = 0; 290144961713Sgirish 2902678453a8Sspeer KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 2903678453a8Sspeer KMEM_FREE(control, sizeof (nxge_dma_common_t)); 290444961713Sgirish 2905678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_txb")); 290644961713Sgirish } 290744961713Sgirish 2908678453a8Sspeer /* 2909678453a8Sspeer * nxge_alloc_tx_mem_pool 2910678453a8Sspeer * 2911678453a8Sspeer * This function allocates all of the per-port TDC control data structures. 2912678453a8Sspeer * The per-channel (TDC) data structures are allocated when needed. 2913678453a8Sspeer * 2914678453a8Sspeer * Arguments: 2915678453a8Sspeer * nxgep 2916678453a8Sspeer * 2917678453a8Sspeer * Notes: 2918678453a8Sspeer * 2919678453a8Sspeer * Context: 2920678453a8Sspeer * Any domain 2921678453a8Sspeer */ 2922678453a8Sspeer nxge_status_t 292344961713Sgirish nxge_alloc_tx_mem_pool(p_nxge_t nxgep) 292444961713Sgirish { 2925678453a8Sspeer nxge_hw_pt_cfg_t *p_cfgp; 2926678453a8Sspeer nxge_dma_pool_t *dma_poolp; 2927678453a8Sspeer nxge_dma_common_t **dma_buf_p; 2928678453a8Sspeer nxge_dma_pool_t *dma_cntl_poolp; 2929678453a8Sspeer nxge_dma_common_t **dma_cntl_p; 293044961713Sgirish uint32_t *num_chunks; /* per dma */ 2931678453a8Sspeer int tdc_max; 293244961713Sgirish 293344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool")); 293444961713Sgirish 2935678453a8Sspeer p_cfgp = &nxgep->pt_config.hw_config; 2936678453a8Sspeer tdc_max = NXGE_MAX_TDCS; 293744961713Sgirish 293844961713Sgirish /* 293944961713Sgirish * Allocate memory for each transmit DMA channel. 294044961713Sgirish */ 294144961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 29424045d941Ssowmini KM_SLEEP); 294344961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 29444045d941Ssowmini sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP); 294544961713Sgirish 294644961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 29474045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 294844961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 29494045d941Ssowmini sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP); 295044961713Sgirish 295130ac2e7bSml if (nxge_tx_ring_size > TDC_DEFAULT_MAX) { 295230ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 295330ac2e7bSml "nxge_alloc_tx_mem_pool: TDC too high %d, " 295430ac2e7bSml "set to default %d", 295530ac2e7bSml nxge_tx_ring_size, TDC_DEFAULT_MAX)); 295630ac2e7bSml nxge_tx_ring_size = TDC_DEFAULT_MAX; 295730ac2e7bSml } 295830ac2e7bSml 295944961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 296044961713Sgirish /* 296144961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 296244961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 296344961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 296444961713Sgirish * function). The transmit ring is limited to 8K (includes the 296544961713Sgirish * mailbox). 296644961713Sgirish */ 296744961713Sgirish if (nxgep->niu_type == N2_NIU) { 296844961713Sgirish if ((nxge_tx_ring_size > NXGE_NIU_CONTIG_TX_MAX) || 29694045d941Ssowmini (!ISP2(nxge_tx_ring_size))) { 297044961713Sgirish nxge_tx_ring_size = NXGE_NIU_CONTIG_TX_MAX; 297144961713Sgirish } 297244961713Sgirish } 297344961713Sgirish #endif 297444961713Sgirish 297544961713Sgirish nxgep->nxge_port_tx_ring_size = nxge_tx_ring_size; 297644961713Sgirish 297744961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 29784045d941Ssowmini sizeof (uint32_t) * tdc_max, KM_SLEEP); 297944961713Sgirish 2980678453a8Sspeer dma_poolp->ndmas = p_cfgp->tdc.owned; 298144961713Sgirish dma_poolp->num_chunks = num_chunks; 298244961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 298344961713Sgirish nxgep->tx_buf_pool_p = dma_poolp; 298444961713Sgirish 2985678453a8Sspeer dma_poolp->buf_allocated = B_TRUE; 2986678453a8Sspeer 2987678453a8Sspeer dma_cntl_poolp->ndmas = p_cfgp->tdc.owned; 298844961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 298944961713Sgirish nxgep->tx_cntl_pool_p = dma_cntl_poolp; 299044961713Sgirish 2991678453a8Sspeer dma_cntl_poolp->buf_allocated = B_TRUE; 299244961713Sgirish 2993678453a8Sspeer nxgep->tx_rings = 2994678453a8Sspeer KMEM_ZALLOC(sizeof (tx_rings_t), KM_SLEEP); 2995678453a8Sspeer nxgep->tx_rings->rings = 2996678453a8Sspeer KMEM_ZALLOC(sizeof (p_tx_ring_t) * tdc_max, KM_SLEEP); 2997678453a8Sspeer nxgep->tx_mbox_areas_p = 2998678453a8Sspeer KMEM_ZALLOC(sizeof (tx_mbox_areas_t), KM_SLEEP); 2999678453a8Sspeer nxgep->tx_mbox_areas_p->txmbox_areas_p = 3000678453a8Sspeer KMEM_ZALLOC(sizeof (p_tx_mbox_t) * tdc_max, KM_SLEEP); 300144961713Sgirish 3002678453a8Sspeer nxgep->tx_rings->ndmas = p_cfgp->tdc.owned; 300344961713Sgirish 300444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, 30054045d941Ssowmini "==> nxge_alloc_tx_mem_pool: ndmas %d poolp->ndmas %d", 30064045d941Ssowmini tdc_max, dma_poolp->ndmas)); 300744961713Sgirish 3008678453a8Sspeer return (NXGE_OK); 300944961713Sgirish } 301044961713Sgirish 3011678453a8Sspeer nxge_status_t 301244961713Sgirish nxge_alloc_tx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 301344961713Sgirish p_nxge_dma_common_t *dmap, size_t alloc_size, 301444961713Sgirish size_t block_size, uint32_t *num_chunks) 301544961713Sgirish { 301644961713Sgirish p_nxge_dma_common_t tx_dmap; 301744961713Sgirish nxge_status_t status = NXGE_OK; 301844961713Sgirish size_t total_alloc_size; 301944961713Sgirish size_t allocated = 0; 302044961713Sgirish int i, size_index, array_size; 302144961713Sgirish 302244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_buf_dma")); 302344961713Sgirish 302444961713Sgirish tx_dmap = (p_nxge_dma_common_t) 30254045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 30264045d941Ssowmini KM_SLEEP); 302744961713Sgirish 302844961713Sgirish total_alloc_size = alloc_size; 302944961713Sgirish i = 0; 303044961713Sgirish size_index = 0; 303144961713Sgirish array_size = sizeof (alloc_sizes) / sizeof (size_t); 30327b26d9ffSSantwona Behera while ((size_index < array_size) && 30337b26d9ffSSantwona Behera (alloc_sizes[size_index] < alloc_size)) 303444961713Sgirish size_index++; 303544961713Sgirish if (size_index >= array_size) { 303644961713Sgirish size_index = array_size - 1; 303744961713Sgirish } 303844961713Sgirish 303944961713Sgirish while ((allocated < total_alloc_size) && 30404045d941Ssowmini (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 304144961713Sgirish 304244961713Sgirish tx_dmap[i].dma_chunk_index = i; 304344961713Sgirish tx_dmap[i].block_size = block_size; 304444961713Sgirish tx_dmap[i].alength = alloc_sizes[size_index]; 304544961713Sgirish tx_dmap[i].orig_alength = tx_dmap[i].alength; 304644961713Sgirish tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 304744961713Sgirish tx_dmap[i].dma_channel = dma_channel; 304844961713Sgirish tx_dmap[i].contig_alloc_type = B_FALSE; 3049678453a8Sspeer tx_dmap[i].kmem_alloc_type = B_FALSE; 305044961713Sgirish 305144961713Sgirish /* 305244961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 305344961713Sgirish * needs to call Hypervisor api to set up 305444961713Sgirish * logical pages. 305544961713Sgirish */ 305644961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 305744961713Sgirish tx_dmap[i].contig_alloc_type = B_TRUE; 305844961713Sgirish } 305944961713Sgirish 306044961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 30614045d941Ssowmini &nxge_tx_dma_attr, 30624045d941Ssowmini tx_dmap[i].alength, 30634045d941Ssowmini &nxge_dev_buf_dma_acc_attr, 30644045d941Ssowmini DDI_DMA_WRITE | DDI_DMA_STREAMING, 30654045d941Ssowmini (p_nxge_dma_common_t)(&tx_dmap[i])); 306644961713Sgirish if (status != NXGE_OK) { 306744961713Sgirish size_index--; 306844961713Sgirish } else { 306944961713Sgirish i++; 307044961713Sgirish allocated += alloc_sizes[size_index]; 307144961713Sgirish } 307244961713Sgirish } 307344961713Sgirish 307444961713Sgirish if (allocated < total_alloc_size) { 307530ac2e7bSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 307630ac2e7bSml "==> nxge_alloc_tx_buf_dma: not enough channel %d: " 307730ac2e7bSml "allocated 0x%x requested 0x%x", 307830ac2e7bSml dma_channel, 307930ac2e7bSml allocated, total_alloc_size)); 308030ac2e7bSml status = NXGE_ERROR; 308144961713Sgirish goto nxge_alloc_tx_mem_fail1; 308244961713Sgirish } 308344961713Sgirish 308430ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 308530ac2e7bSml "==> nxge_alloc_tx_buf_dma: Allocated for channel %d: " 308630ac2e7bSml "allocated 0x%x requested 0x%x", 308730ac2e7bSml dma_channel, 308830ac2e7bSml allocated, total_alloc_size)); 308930ac2e7bSml 309044961713Sgirish *num_chunks = i; 309144961713Sgirish *dmap = tx_dmap; 309244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 30934045d941Ssowmini "==> nxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d", 30944045d941Ssowmini *dmap, i)); 309544961713Sgirish goto nxge_alloc_tx_mem_exit; 309644961713Sgirish 309744961713Sgirish nxge_alloc_tx_mem_fail1: 309844961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 309944961713Sgirish 310044961713Sgirish nxge_alloc_tx_mem_exit: 310144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 31024045d941Ssowmini "<== nxge_alloc_tx_buf_dma status 0x%08x", status)); 310344961713Sgirish 310444961713Sgirish return (status); 310544961713Sgirish } 310644961713Sgirish 310744961713Sgirish /*ARGSUSED*/ 310844961713Sgirish static void 310944961713Sgirish nxge_free_tx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 311044961713Sgirish uint32_t num_chunks) 311144961713Sgirish { 311244961713Sgirish int i; 311344961713Sgirish 311444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_tx_buf_dma")); 311544961713Sgirish 3116678453a8Sspeer if (dmap == 0) 3117678453a8Sspeer return; 3118678453a8Sspeer 311944961713Sgirish for (i = 0; i < num_chunks; i++) { 312044961713Sgirish nxge_dma_mem_free(dmap++); 312144961713Sgirish } 312244961713Sgirish 312344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_tx_buf_dma")); 312444961713Sgirish } 312544961713Sgirish 312644961713Sgirish /*ARGSUSED*/ 3127678453a8Sspeer nxge_status_t 312844961713Sgirish nxge_alloc_tx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 312944961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 313044961713Sgirish { 313144961713Sgirish p_nxge_dma_common_t tx_dmap; 313244961713Sgirish nxge_status_t status = NXGE_OK; 313344961713Sgirish 313444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_cntl_dma")); 313544961713Sgirish tx_dmap = (p_nxge_dma_common_t) 31364045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 313744961713Sgirish 313844961713Sgirish tx_dmap->contig_alloc_type = B_FALSE; 3139678453a8Sspeer tx_dmap->kmem_alloc_type = B_FALSE; 314044961713Sgirish 314144961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 31424045d941Ssowmini &nxge_desc_dma_attr, 31434045d941Ssowmini size, 31444045d941Ssowmini &nxge_dev_desc_dma_acc_attr, 31454045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 31464045d941Ssowmini tx_dmap); 314744961713Sgirish if (status != NXGE_OK) { 314844961713Sgirish goto nxge_alloc_tx_cntl_dma_fail1; 314944961713Sgirish } 315044961713Sgirish 315144961713Sgirish *dmap = tx_dmap; 315244961713Sgirish goto nxge_alloc_tx_cntl_dma_exit; 315344961713Sgirish 315444961713Sgirish nxge_alloc_tx_cntl_dma_fail1: 315544961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t)); 315644961713Sgirish 315744961713Sgirish nxge_alloc_tx_cntl_dma_exit: 315844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 31594045d941Ssowmini "<== nxge_alloc_tx_cntl_dma status 0x%08x", status)); 316044961713Sgirish 316144961713Sgirish return (status); 316244961713Sgirish } 316344961713Sgirish 316444961713Sgirish /*ARGSUSED*/ 316544961713Sgirish static void 316644961713Sgirish nxge_free_tx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 316744961713Sgirish { 316844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_tx_cntl_dma")); 316944961713Sgirish 3170678453a8Sspeer if (dmap == 0) 3171678453a8Sspeer return; 3172678453a8Sspeer 317344961713Sgirish nxge_dma_mem_free(dmap); 317444961713Sgirish 317544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_tx_cntl_dma")); 317644961713Sgirish } 317744961713Sgirish 3178678453a8Sspeer /* 3179678453a8Sspeer * nxge_free_tx_mem_pool 3180678453a8Sspeer * 3181678453a8Sspeer * This function frees all of the per-port TDC control data structures. 3182678453a8Sspeer * The per-channel (TDC) data structures are freed when the channel 3183678453a8Sspeer * is stopped. 3184678453a8Sspeer * 3185678453a8Sspeer * Arguments: 3186678453a8Sspeer * nxgep 3187678453a8Sspeer * 3188678453a8Sspeer * Notes: 3189678453a8Sspeer * 3190678453a8Sspeer * Context: 3191678453a8Sspeer * Any domain 3192678453a8Sspeer */ 319344961713Sgirish static void 319444961713Sgirish nxge_free_tx_mem_pool(p_nxge_t nxgep) 319544961713Sgirish { 3196678453a8Sspeer int tdc_max = NXGE_MAX_TDCS; 319744961713Sgirish 3198678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_tx_mem_pool")); 319944961713Sgirish 3200678453a8Sspeer if (!nxgep->tx_buf_pool_p || !nxgep->tx_buf_pool_p->buf_allocated) { 3201678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 32024045d941Ssowmini "<== nxge_free_tx_mem_pool " 32034045d941Ssowmini "(null tx buf pool or buf not allocated")); 320444961713Sgirish return; 320544961713Sgirish } 3206678453a8Sspeer if (!nxgep->tx_cntl_pool_p || !nxgep->tx_cntl_pool_p->buf_allocated) { 3207678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 32084045d941Ssowmini "<== nxge_free_tx_mem_pool " 32094045d941Ssowmini "(null tx cntl buf pool or cntl buf not allocated")); 321044961713Sgirish return; 321144961713Sgirish } 321244961713Sgirish 3213678453a8Sspeer /* 1. Free the mailboxes. */ 3214678453a8Sspeer KMEM_FREE(nxgep->tx_mbox_areas_p->txmbox_areas_p, 3215678453a8Sspeer sizeof (p_tx_mbox_t) * tdc_max); 3216678453a8Sspeer KMEM_FREE(nxgep->tx_mbox_areas_p, sizeof (tx_mbox_areas_t)); 321744961713Sgirish 3218678453a8Sspeer nxgep->tx_mbox_areas_p = 0; 321944961713Sgirish 3220678453a8Sspeer /* 2. Free the transmit ring arrays. */ 3221678453a8Sspeer KMEM_FREE(nxgep->tx_rings->rings, 3222678453a8Sspeer sizeof (p_tx_ring_t) * tdc_max); 3223678453a8Sspeer KMEM_FREE(nxgep->tx_rings, sizeof (tx_rings_t)); 322444961713Sgirish 3225678453a8Sspeer nxgep->tx_rings = 0; 322644961713Sgirish 3227678453a8Sspeer /* 3. Free the completion ring data structures. */ 3228678453a8Sspeer KMEM_FREE(nxgep->tx_cntl_pool_p->dma_buf_pool_p, 3229678453a8Sspeer sizeof (p_nxge_dma_common_t) * tdc_max); 3230678453a8Sspeer KMEM_FREE(nxgep->tx_cntl_pool_p, sizeof (nxge_dma_pool_t)); 323144961713Sgirish 3232678453a8Sspeer nxgep->tx_cntl_pool_p = 0; 323344961713Sgirish 3234678453a8Sspeer /* 4. Free the data ring data structures. */ 3235678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p->num_chunks, 3236678453a8Sspeer sizeof (uint32_t) * tdc_max); 3237678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p->dma_buf_pool_p, 3238678453a8Sspeer sizeof (p_nxge_dma_common_t) * tdc_max); 3239678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p, sizeof (nxge_dma_pool_t)); 324044961713Sgirish 3241678453a8Sspeer nxgep->tx_buf_pool_p = 0; 3242678453a8Sspeer 3243678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_tx_mem_pool")); 324444961713Sgirish } 324544961713Sgirish 324644961713Sgirish /*ARGSUSED*/ 324744961713Sgirish static nxge_status_t 324844961713Sgirish nxge_dma_mem_alloc(p_nxge_t nxgep, dma_method_t method, 324944961713Sgirish struct ddi_dma_attr *dma_attrp, 325044961713Sgirish size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags, 325144961713Sgirish p_nxge_dma_common_t dma_p) 325244961713Sgirish { 325344961713Sgirish caddr_t kaddrp; 325444961713Sgirish int ddi_status = DDI_SUCCESS; 325544961713Sgirish boolean_t contig_alloc_type; 3256678453a8Sspeer boolean_t kmem_alloc_type; 325744961713Sgirish 325844961713Sgirish contig_alloc_type = dma_p->contig_alloc_type; 325944961713Sgirish 326044961713Sgirish if (contig_alloc_type && (nxgep->niu_type != N2_NIU)) { 326144961713Sgirish /* 326244961713Sgirish * contig_alloc_type for contiguous memory only allowed 326344961713Sgirish * for N2/NIU. 326444961713Sgirish */ 326544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 32664045d941Ssowmini "nxge_dma_mem_alloc: alloc type not allowed (%d)", 32674045d941Ssowmini dma_p->contig_alloc_type)); 326844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 326944961713Sgirish } 327044961713Sgirish 327144961713Sgirish dma_p->dma_handle = NULL; 327244961713Sgirish dma_p->acc_handle = NULL; 327344961713Sgirish dma_p->kaddrp = dma_p->last_kaddrp = NULL; 327444961713Sgirish dma_p->first_ioaddr_pp = dma_p->last_ioaddr_pp = NULL; 327544961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, dma_attrp, 32764045d941Ssowmini DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle); 327744961713Sgirish if (ddi_status != DDI_SUCCESS) { 327844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 32794045d941Ssowmini "nxge_dma_mem_alloc:ddi_dma_alloc_handle failed.")); 328044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 328144961713Sgirish } 328244961713Sgirish 3283678453a8Sspeer kmem_alloc_type = dma_p->kmem_alloc_type; 3284678453a8Sspeer 328544961713Sgirish switch (contig_alloc_type) { 328644961713Sgirish case B_FALSE: 3287678453a8Sspeer switch (kmem_alloc_type) { 3288678453a8Sspeer case B_FALSE: 3289678453a8Sspeer ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, 32904045d941Ssowmini length, 32914045d941Ssowmini acc_attr_p, 32924045d941Ssowmini xfer_flags, 32934045d941Ssowmini DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength, 32944045d941Ssowmini &dma_p->acc_handle); 3295678453a8Sspeer if (ddi_status != DDI_SUCCESS) { 3296678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3297678453a8Sspeer "nxge_dma_mem_alloc: " 3298678453a8Sspeer "ddi_dma_mem_alloc failed")); 3299678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3300678453a8Sspeer dma_p->dma_handle = NULL; 3301678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3302678453a8Sspeer } 3303678453a8Sspeer if (dma_p->alength < length) { 3304678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3305678453a8Sspeer "nxge_dma_mem_alloc:di_dma_mem_alloc " 3306678453a8Sspeer "< length.")); 330744961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 3308678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 330944961713Sgirish dma_p->acc_handle = NULL; 3310678453a8Sspeer dma_p->dma_handle = NULL; 3311678453a8Sspeer return (NXGE_ERROR); 331244961713Sgirish } 331344961713Sgirish 3314678453a8Sspeer ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, 3315678453a8Sspeer NULL, 3316678453a8Sspeer kaddrp, dma_p->alength, xfer_flags, 3317678453a8Sspeer DDI_DMA_DONTWAIT, 3318678453a8Sspeer 0, &dma_p->dma_cookie, &dma_p->ncookies); 3319678453a8Sspeer if (ddi_status != DDI_DMA_MAPPED) { 3320678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3321678453a8Sspeer "nxge_dma_mem_alloc: ddi_dma_addr_bind " 3322678453a8Sspeer "failed " 3323678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 3324678453a8Sspeer dma_p->ncookies)); 3325678453a8Sspeer if (dma_p->acc_handle) { 3326678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3327678453a8Sspeer dma_p->acc_handle = NULL; 3328678453a8Sspeer } 3329678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3330678453a8Sspeer dma_p->dma_handle = NULL; 3331678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3332678453a8Sspeer } 3333678453a8Sspeer 3334678453a8Sspeer if (dma_p->ncookies != 1) { 3335678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 3336678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind " 3337678453a8Sspeer "> 1 cookie" 3338678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 3339678453a8Sspeer dma_p->ncookies)); 3340330cd344SMichael Speer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3341678453a8Sspeer if (dma_p->acc_handle) { 3342678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3343678453a8Sspeer dma_p->acc_handle = NULL; 3344678453a8Sspeer } 3345678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3346678453a8Sspeer dma_p->dma_handle = NULL; 3347330cd344SMichael Speer dma_p->acc_handle = NULL; 3348678453a8Sspeer return (NXGE_ERROR); 3349678453a8Sspeer } 3350678453a8Sspeer break; 3351678453a8Sspeer 3352678453a8Sspeer case B_TRUE: 3353678453a8Sspeer kaddrp = KMEM_ALLOC(length, KM_NOSLEEP); 3354678453a8Sspeer if (kaddrp == NULL) { 3355678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3356678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_mem_alloc " 3357678453a8Sspeer "kmem alloc failed")); 3358678453a8Sspeer return (NXGE_ERROR); 3359678453a8Sspeer } 3360678453a8Sspeer 3361678453a8Sspeer dma_p->alength = length; 3362678453a8Sspeer ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, 3363678453a8Sspeer NULL, kaddrp, dma_p->alength, xfer_flags, 3364678453a8Sspeer DDI_DMA_DONTWAIT, 0, 3365678453a8Sspeer &dma_p->dma_cookie, &dma_p->ncookies); 3366678453a8Sspeer if (ddi_status != DDI_DMA_MAPPED) { 3367678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3368678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind: " 3369678453a8Sspeer "(kmem_alloc) failed kaddrp $%p length %d " 3370678453a8Sspeer "(staus 0x%x (%d) ncookies %d.)", 3371678453a8Sspeer kaddrp, length, 3372678453a8Sspeer ddi_status, ddi_status, dma_p->ncookies)); 3373678453a8Sspeer KMEM_FREE(kaddrp, length); 3374678453a8Sspeer dma_p->acc_handle = NULL; 3375678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3376678453a8Sspeer dma_p->dma_handle = NULL; 3377678453a8Sspeer dma_p->kaddrp = NULL; 3378678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3379678453a8Sspeer } 3380678453a8Sspeer 3381678453a8Sspeer if (dma_p->ncookies != 1) { 3382678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 3383678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind " 3384678453a8Sspeer "(kmem_alloc) > 1 cookie" 3385678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 33864045d941Ssowmini dma_p->ncookies)); 3387678453a8Sspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3388330cd344SMichael Speer KMEM_FREE(kaddrp, length); 3389678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3390678453a8Sspeer dma_p->dma_handle = NULL; 3391330cd344SMichael Speer dma_p->acc_handle = NULL; 3392678453a8Sspeer dma_p->kaddrp = NULL; 3393678453a8Sspeer return (NXGE_ERROR); 339444961713Sgirish } 3395678453a8Sspeer 3396678453a8Sspeer dma_p->kaddrp = kaddrp; 3397678453a8Sspeer 3398678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 33994045d941Ssowmini "nxge_dma_mem_alloc: kmem_alloc dmap $%p " 34004045d941Ssowmini "kaddr $%p alength %d", 34014045d941Ssowmini dma_p, 34024045d941Ssowmini kaddrp, 34034045d941Ssowmini dma_p->alength)); 3404678453a8Sspeer break; 340544961713Sgirish } 340644961713Sgirish break; 340744961713Sgirish 340844961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 340944961713Sgirish case B_TRUE: 341044961713Sgirish kaddrp = (caddr_t)contig_mem_alloc(length); 341144961713Sgirish if (kaddrp == NULL) { 341244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34134045d941Ssowmini "nxge_dma_mem_alloc:contig_mem_alloc failed.")); 341444961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 341544961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 341644961713Sgirish } 341744961713Sgirish 341844961713Sgirish dma_p->alength = length; 341944961713Sgirish ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL, 34204045d941Ssowmini kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0, 34214045d941Ssowmini &dma_p->dma_cookie, &dma_p->ncookies); 342244961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 342344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34244045d941Ssowmini "nxge_dma_mem_alloc:di_dma_addr_bind failed " 34254045d941Ssowmini "(status 0x%x ncookies %d.)", ddi_status, 34264045d941Ssowmini dma_p->ncookies)); 342744961713Sgirish 342844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 34294045d941Ssowmini "==> nxge_dma_mem_alloc: (not mapped)" 34304045d941Ssowmini "length %lu (0x%x) " 34314045d941Ssowmini "free contig kaddrp $%p " 34324045d941Ssowmini "va_to_pa $%p", 34334045d941Ssowmini length, length, 34344045d941Ssowmini kaddrp, 34354045d941Ssowmini va_to_pa(kaddrp))); 343644961713Sgirish 343744961713Sgirish 343844961713Sgirish contig_mem_free((void *)kaddrp, length); 343944961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 344044961713Sgirish 344144961713Sgirish dma_p->dma_handle = NULL; 344244961713Sgirish dma_p->acc_handle = NULL; 344344961713Sgirish dma_p->alength = NULL; 344444961713Sgirish dma_p->kaddrp = NULL; 344544961713Sgirish 344644961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 344744961713Sgirish } 344844961713Sgirish 344944961713Sgirish if (dma_p->ncookies != 1 || 34504045d941Ssowmini (dma_p->dma_cookie.dmac_laddress == NULL)) { 345144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34524045d941Ssowmini "nxge_dma_mem_alloc:di_dma_addr_bind > 1 " 34534045d941Ssowmini "cookie or " 34544045d941Ssowmini "dmac_laddress is NULL $%p size %d " 34554045d941Ssowmini " (status 0x%x ncookies %d.)", 34564045d941Ssowmini ddi_status, 34574045d941Ssowmini dma_p->dma_cookie.dmac_laddress, 34584045d941Ssowmini dma_p->dma_cookie.dmac_size, 34594045d941Ssowmini dma_p->ncookies)); 346044961713Sgirish 346144961713Sgirish contig_mem_free((void *)kaddrp, length); 346256d930aeSspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 346344961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 346444961713Sgirish 346544961713Sgirish dma_p->alength = 0; 346644961713Sgirish dma_p->dma_handle = NULL; 346744961713Sgirish dma_p->acc_handle = NULL; 346844961713Sgirish dma_p->kaddrp = NULL; 346944961713Sgirish 347044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 347144961713Sgirish } 347244961713Sgirish break; 347344961713Sgirish 347444961713Sgirish #else 347544961713Sgirish case B_TRUE: 347644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34774045d941Ssowmini "nxge_dma_mem_alloc: invalid alloc type for !sun4v")); 347844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 347944961713Sgirish #endif 348044961713Sgirish } 348144961713Sgirish 348244961713Sgirish dma_p->kaddrp = kaddrp; 348344961713Sgirish dma_p->last_kaddrp = (unsigned char *)kaddrp + 34844045d941Ssowmini dma_p->alength - RXBUF_64B_ALIGNED; 3485adfcba55Sjoycey #if defined(__i386) 3486adfcba55Sjoycey dma_p->ioaddr_pp = 34874045d941Ssowmini (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress; 3488adfcba55Sjoycey #else 348944961713Sgirish dma_p->ioaddr_pp = (unsigned char *)dma_p->dma_cookie.dmac_laddress; 3490adfcba55Sjoycey #endif 349144961713Sgirish dma_p->last_ioaddr_pp = 3492adfcba55Sjoycey #if defined(__i386) 34934045d941Ssowmini (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress + 3494adfcba55Sjoycey #else 34954045d941Ssowmini (unsigned char *)dma_p->dma_cookie.dmac_laddress + 3496adfcba55Sjoycey #endif 34974045d941Ssowmini dma_p->alength - RXBUF_64B_ALIGNED; 349844961713Sgirish 349944961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle); 350044961713Sgirish 350144961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 350244961713Sgirish dma_p->orig_ioaddr_pp = 35034045d941Ssowmini (unsigned char *)dma_p->dma_cookie.dmac_laddress; 350444961713Sgirish dma_p->orig_alength = length; 350544961713Sgirish dma_p->orig_kaddrp = kaddrp; 350644961713Sgirish dma_p->orig_vatopa = (uint64_t)va_to_pa(kaddrp); 350744961713Sgirish #endif 350844961713Sgirish 350944961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_dma_mem_alloc: " 35104045d941Ssowmini "dma buffer allocated: dma_p $%p " 35114045d941Ssowmini "return dmac_ladress from cookie $%p cookie dmac_size %d " 35124045d941Ssowmini "dma_p->ioaddr_p $%p " 35134045d941Ssowmini "dma_p->orig_ioaddr_p $%p " 35144045d941Ssowmini "orig_vatopa $%p " 35154045d941Ssowmini "alength %d (0x%x) " 35164045d941Ssowmini "kaddrp $%p " 35174045d941Ssowmini "length %d (0x%x)", 35184045d941Ssowmini dma_p, 35194045d941Ssowmini dma_p->dma_cookie.dmac_laddress, dma_p->dma_cookie.dmac_size, 35204045d941Ssowmini dma_p->ioaddr_pp, 35214045d941Ssowmini dma_p->orig_ioaddr_pp, 35224045d941Ssowmini dma_p->orig_vatopa, 35234045d941Ssowmini dma_p->alength, dma_p->alength, 35244045d941Ssowmini kaddrp, 35254045d941Ssowmini length, length)); 352644961713Sgirish 352744961713Sgirish return (NXGE_OK); 352844961713Sgirish } 352944961713Sgirish 353044961713Sgirish static void 353144961713Sgirish nxge_dma_mem_free(p_nxge_dma_common_t dma_p) 353244961713Sgirish { 353344961713Sgirish if (dma_p->dma_handle != NULL) { 353444961713Sgirish if (dma_p->ncookies) { 353544961713Sgirish (void) ddi_dma_unbind_handle(dma_p->dma_handle); 353644961713Sgirish dma_p->ncookies = 0; 353744961713Sgirish } 353844961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 353944961713Sgirish dma_p->dma_handle = NULL; 354044961713Sgirish } 354144961713Sgirish 354244961713Sgirish if (dma_p->acc_handle != NULL) { 354344961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 354444961713Sgirish dma_p->acc_handle = NULL; 354544961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 354644961713Sgirish } 354744961713Sgirish 354844961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 354944961713Sgirish if (dma_p->contig_alloc_type && 35504045d941Ssowmini dma_p->orig_kaddrp && dma_p->orig_alength) { 355144961713Sgirish NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_mem_free: " 35524045d941Ssowmini "kaddrp $%p (orig_kaddrp $%p)" 35534045d941Ssowmini "mem type %d ", 35544045d941Ssowmini "orig_alength %d " 35554045d941Ssowmini "alength 0x%x (%d)", 35564045d941Ssowmini dma_p->kaddrp, 35574045d941Ssowmini dma_p->orig_kaddrp, 35584045d941Ssowmini dma_p->contig_alloc_type, 35594045d941Ssowmini dma_p->orig_alength, 35604045d941Ssowmini dma_p->alength, dma_p->alength)); 356144961713Sgirish 356244961713Sgirish contig_mem_free(dma_p->orig_kaddrp, dma_p->orig_alength); 356344961713Sgirish dma_p->orig_alength = NULL; 356444961713Sgirish dma_p->orig_kaddrp = NULL; 356544961713Sgirish dma_p->contig_alloc_type = B_FALSE; 356644961713Sgirish } 356744961713Sgirish #endif 356844961713Sgirish dma_p->kaddrp = NULL; 356944961713Sgirish dma_p->alength = NULL; 357044961713Sgirish } 357144961713Sgirish 3572678453a8Sspeer static void 3573678453a8Sspeer nxge_dma_free_rx_data_buf(p_nxge_dma_common_t dma_p) 3574678453a8Sspeer { 3575678453a8Sspeer uint64_t kaddr; 3576678453a8Sspeer uint32_t buf_size; 3577678453a8Sspeer 3578678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "==> nxge_dma_free_rx_data_buf")); 3579678453a8Sspeer 3580678453a8Sspeer if (dma_p->dma_handle != NULL) { 3581678453a8Sspeer if (dma_p->ncookies) { 3582678453a8Sspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3583678453a8Sspeer dma_p->ncookies = 0; 3584678453a8Sspeer } 3585678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3586678453a8Sspeer dma_p->dma_handle = NULL; 3587678453a8Sspeer } 3588678453a8Sspeer 3589678453a8Sspeer if (dma_p->acc_handle != NULL) { 3590678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3591678453a8Sspeer dma_p->acc_handle = NULL; 3592678453a8Sspeer NPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 3593678453a8Sspeer } 3594678453a8Sspeer 3595678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3596678453a8Sspeer "==> nxge_dma_free_rx_data_buf: dmap $%p buf_alloc_state %d", 3597678453a8Sspeer dma_p, 3598678453a8Sspeer dma_p->buf_alloc_state)); 3599678453a8Sspeer 3600678453a8Sspeer if (!(dma_p->buf_alloc_state & BUF_ALLOCATED_WAIT_FREE)) { 3601678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3602678453a8Sspeer "<== nxge_dma_free_rx_data_buf: " 3603678453a8Sspeer "outstanding data buffers")); 3604678453a8Sspeer return; 3605678453a8Sspeer } 3606678453a8Sspeer 3607678453a8Sspeer #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 3608678453a8Sspeer if (dma_p->contig_alloc_type && 36094045d941Ssowmini dma_p->orig_kaddrp && dma_p->orig_alength) { 3610678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_free_rx_data_buf: " 3611678453a8Sspeer "kaddrp $%p (orig_kaddrp $%p)" 3612678453a8Sspeer "mem type %d ", 3613678453a8Sspeer "orig_alength %d " 3614678453a8Sspeer "alength 0x%x (%d)", 3615678453a8Sspeer dma_p->kaddrp, 3616678453a8Sspeer dma_p->orig_kaddrp, 3617678453a8Sspeer dma_p->contig_alloc_type, 3618678453a8Sspeer dma_p->orig_alength, 3619678453a8Sspeer dma_p->alength, dma_p->alength)); 3620678453a8Sspeer 3621678453a8Sspeer kaddr = (uint64_t)dma_p->orig_kaddrp; 3622678453a8Sspeer buf_size = dma_p->orig_alength; 3623678453a8Sspeer nxge_free_buf(CONTIG_MEM_ALLOC, kaddr, buf_size); 3624678453a8Sspeer dma_p->orig_alength = NULL; 3625678453a8Sspeer dma_p->orig_kaddrp = NULL; 3626678453a8Sspeer dma_p->contig_alloc_type = B_FALSE; 3627678453a8Sspeer dma_p->kaddrp = NULL; 3628678453a8Sspeer dma_p->alength = NULL; 3629678453a8Sspeer return; 3630678453a8Sspeer } 3631678453a8Sspeer #endif 3632678453a8Sspeer 3633678453a8Sspeer if (dma_p->kmem_alloc_type) { 3634678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3635678453a8Sspeer "nxge_dma_free_rx_data_buf: free kmem " 36364045d941Ssowmini "kaddrp $%p (orig_kaddrp $%p)" 36374045d941Ssowmini "alloc type %d " 36384045d941Ssowmini "orig_alength %d " 36394045d941Ssowmini "alength 0x%x (%d)", 36404045d941Ssowmini dma_p->kaddrp, 36414045d941Ssowmini dma_p->orig_kaddrp, 36424045d941Ssowmini dma_p->kmem_alloc_type, 36434045d941Ssowmini dma_p->orig_alength, 36444045d941Ssowmini dma_p->alength, dma_p->alength)); 3645678453a8Sspeer #if defined(__i386) 3646678453a8Sspeer kaddr = (uint64_t)(uint32_t)dma_p->kaddrp; 3647678453a8Sspeer #else 3648678453a8Sspeer kaddr = (uint64_t)dma_p->kaddrp; 3649678453a8Sspeer #endif 3650678453a8Sspeer buf_size = dma_p->orig_alength; 3651678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3652678453a8Sspeer "nxge_dma_free_rx_data_buf: free dmap $%p " 3653678453a8Sspeer "kaddr $%p buf_size %d", 3654678453a8Sspeer dma_p, 3655678453a8Sspeer kaddr, buf_size)); 3656678453a8Sspeer nxge_free_buf(KMEM_ALLOC, kaddr, buf_size); 3657678453a8Sspeer dma_p->alength = 0; 3658678453a8Sspeer dma_p->orig_alength = 0; 3659678453a8Sspeer dma_p->kaddrp = NULL; 3660678453a8Sspeer dma_p->kmem_alloc_type = B_FALSE; 3661678453a8Sspeer } 3662678453a8Sspeer 3663678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_dma_free_rx_data_buf")); 3664678453a8Sspeer } 3665678453a8Sspeer 366644961713Sgirish /* 366744961713Sgirish * nxge_m_start() -- start transmitting and receiving. 366844961713Sgirish * 366944961713Sgirish * This function is called by the MAC layer when the first 367044961713Sgirish * stream is open to prepare the hardware ready for sending 367144961713Sgirish * and transmitting packets. 367244961713Sgirish */ 367344961713Sgirish static int 367444961713Sgirish nxge_m_start(void *arg) 367544961713Sgirish { 367644961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 367744961713Sgirish 367844961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_start")); 367944961713Sgirish 3680e759c33aSMichael Speer /* 3681e759c33aSMichael Speer * Are we already started? 3682e759c33aSMichael Speer */ 3683e759c33aSMichael Speer if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 3684e759c33aSMichael Speer return (0); 3685e759c33aSMichael Speer } 3686e759c33aSMichael Speer 36876f157acbSml if (nxge_peu_reset_enable && !nxgep->nxge_link_poll_timerid) { 36886f157acbSml (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 36896f157acbSml } 36906f157acbSml 3691e759c33aSMichael Speer /* 3692e759c33aSMichael Speer * Make sure RX MAC is disabled while we initialize. 3693e759c33aSMichael Speer */ 3694e759c33aSMichael Speer if (!isLDOMguest(nxgep)) { 3695e759c33aSMichael Speer (void) nxge_rx_mac_disable(nxgep); 3696e759c33aSMichael Speer } 3697e759c33aSMichael Speer 3698e759c33aSMichael Speer /* 3699e759c33aSMichael Speer * Grab the global lock. 3700e759c33aSMichael Speer */ 370144961713Sgirish MUTEX_ENTER(nxgep->genlock); 3702e759c33aSMichael Speer 3703e759c33aSMichael Speer /* 3704e759c33aSMichael Speer * Initialize the driver and hardware. 3705e759c33aSMichael Speer */ 370614ea4bb7Ssd if (nxge_init(nxgep) != NXGE_OK) { 370744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 37084045d941Ssowmini "<== nxge_m_start: initialization failed")); 370944961713Sgirish MUTEX_EXIT(nxgep->genlock); 371044961713Sgirish return (EIO); 371144961713Sgirish } 371244961713Sgirish 371344961713Sgirish /* 371444961713Sgirish * Start timer to check the system error and tx hangs 371544961713Sgirish */ 3716678453a8Sspeer if (!isLDOMguest(nxgep)) 3717678453a8Sspeer nxgep->nxge_timerid = nxge_start_timer(nxgep, 3718678453a8Sspeer nxge_check_hw_state, NXGE_CHECK_TIMER); 3719e759c33aSMichael Speer #if defined(sun4v) 3720678453a8Sspeer else 3721678453a8Sspeer nxge_hio_start_timer(nxgep); 3722678453a8Sspeer #endif 372344961713Sgirish 3724a3c5bd6dSspeer nxgep->link_notify = B_TRUE; 372544961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STARTED; 372644961713Sgirish 3727e759c33aSMichael Speer /* 3728e759c33aSMichael Speer * Let the global lock go, since we are intialized. 3729e759c33aSMichael Speer */ 373044961713Sgirish MUTEX_EXIT(nxgep->genlock); 3731e759c33aSMichael Speer 3732e759c33aSMichael Speer /* 3733e759c33aSMichael Speer * Let the MAC start receiving packets, now that 3734e759c33aSMichael Speer * we are initialized. 3735e759c33aSMichael Speer */ 3736e759c33aSMichael Speer if (!isLDOMguest(nxgep)) { 3737e759c33aSMichael Speer if (nxge_rx_mac_enable(nxgep) != NXGE_OK) { 3738e759c33aSMichael Speer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3739e759c33aSMichael Speer "<== nxge_m_start: enable of RX mac failed")); 3740e759c33aSMichael Speer return (EIO); 3741e759c33aSMichael Speer } 3742e759c33aSMichael Speer 3743e759c33aSMichael Speer /* 3744e759c33aSMichael Speer * Enable hardware interrupts. 3745e759c33aSMichael Speer */ 3746e759c33aSMichael Speer nxge_intr_hw_enable(nxgep); 3747e759c33aSMichael Speer } 3748e759c33aSMichael Speer #if defined(sun4v) 3749e759c33aSMichael Speer else { 3750e759c33aSMichael Speer /* 3751e759c33aSMichael Speer * In guest domain we enable RDCs and their interrupts as 3752e759c33aSMichael Speer * the last step. 3753e759c33aSMichael Speer */ 3754e759c33aSMichael Speer if (nxge_hio_rdc_enable(nxgep) != NXGE_OK) { 3755e759c33aSMichael Speer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3756e759c33aSMichael Speer "<== nxge_m_start: enable of RDCs failed")); 3757e759c33aSMichael Speer return (EIO); 3758e759c33aSMichael Speer } 3759e759c33aSMichael Speer 3760e759c33aSMichael Speer if (nxge_hio_rdc_intr_arm(nxgep, B_TRUE) != NXGE_OK) { 3761e759c33aSMichael Speer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3762e759c33aSMichael Speer "<== nxge_m_start: intrs enable for RDCs failed")); 3763e759c33aSMichael Speer return (EIO); 3764e759c33aSMichael Speer } 3765e759c33aSMichael Speer } 3766e759c33aSMichael Speer #endif 376744961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_start")); 376844961713Sgirish return (0); 376944961713Sgirish } 377044961713Sgirish 3771da14cebeSEric Cheng static boolean_t 3772da14cebeSEric Cheng nxge_check_groups_stopped(p_nxge_t nxgep) 3773da14cebeSEric Cheng { 3774da14cebeSEric Cheng int i; 3775da14cebeSEric Cheng 3776da14cebeSEric Cheng for (i = 0; i < NXGE_MAX_RDC_GROUPS; i++) { 3777da14cebeSEric Cheng if (nxgep->rx_hio_groups[i].started) 3778da14cebeSEric Cheng return (B_FALSE); 3779da14cebeSEric Cheng } 3780da14cebeSEric Cheng 3781da14cebeSEric Cheng return (B_TRUE); 3782da14cebeSEric Cheng } 3783da14cebeSEric Cheng 378444961713Sgirish /* 378544961713Sgirish * nxge_m_stop(): stop transmitting and receiving. 378644961713Sgirish */ 378744961713Sgirish static void 378844961713Sgirish nxge_m_stop(void *arg) 378944961713Sgirish { 379044961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 3791da14cebeSEric Cheng boolean_t groups_stopped; 379244961713Sgirish 379344961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_stop")); 379444961713Sgirish 3795e759c33aSMichael Speer /* 3796e759c33aSMichael Speer * Are the groups stopped? 3797e759c33aSMichael Speer */ 3798da14cebeSEric Cheng groups_stopped = nxge_check_groups_stopped(nxgep); 3799e759c33aSMichael Speer ASSERT(groups_stopped == B_TRUE); 3800da14cebeSEric Cheng if (!groups_stopped) { 3801da14cebeSEric Cheng cmn_err(CE_WARN, "nxge(%d): groups are not stopped!\n", 3802da14cebeSEric Cheng nxgep->instance); 3803da14cebeSEric Cheng return; 3804da14cebeSEric Cheng } 3805da14cebeSEric Cheng 3806e759c33aSMichael Speer if (!isLDOMguest(nxgep)) { 3807e759c33aSMichael Speer /* 3808e759c33aSMichael Speer * Disable the RX mac. 3809e759c33aSMichael Speer */ 3810e759c33aSMichael Speer (void) nxge_rx_mac_disable(nxgep); 3811e759c33aSMichael Speer 3812e759c33aSMichael Speer /* 3813e759c33aSMichael Speer * Wait for the IPP to drain. 3814e759c33aSMichael Speer */ 3815e759c33aSMichael Speer (void) nxge_ipp_drain(nxgep); 3816e759c33aSMichael Speer 3817e759c33aSMichael Speer /* 3818e759c33aSMichael Speer * Disable hardware interrupts. 3819e759c33aSMichael Speer */ 3820e759c33aSMichael Speer nxge_intr_hw_disable(nxgep); 3821e759c33aSMichael Speer } 3822e759c33aSMichael Speer #if defined(sun4v) 3823e759c33aSMichael Speer else { 3824e759c33aSMichael Speer (void) nxge_hio_rdc_intr_arm(nxgep, B_FALSE); 3825e759c33aSMichael Speer } 3826e759c33aSMichael Speer #endif 3827e759c33aSMichael Speer 3828e759c33aSMichael Speer /* 3829e759c33aSMichael Speer * Grab the global lock. 3830e759c33aSMichael Speer */ 3831d7cf53fcSmisaki Miyashita MUTEX_ENTER(nxgep->genlock); 3832d7cf53fcSmisaki Miyashita 3833e759c33aSMichael Speer nxgep->nxge_mac_state = NXGE_MAC_STOPPING; 383444961713Sgirish if (nxgep->nxge_timerid) { 383544961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 383644961713Sgirish nxgep->nxge_timerid = 0; 383744961713Sgirish } 3838a3c5bd6dSspeer 3839e759c33aSMichael Speer /* 3840e759c33aSMichael Speer * Clean up. 3841e759c33aSMichael Speer */ 384244961713Sgirish nxge_uninit(nxgep); 384344961713Sgirish 384444961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STOPPED; 384544961713Sgirish 3846e759c33aSMichael Speer /* 3847e759c33aSMichael Speer * Let go of the global lock. 3848e759c33aSMichael Speer */ 384944961713Sgirish MUTEX_EXIT(nxgep->genlock); 385044961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_stop")); 385144961713Sgirish } 385244961713Sgirish 385344961713Sgirish static int 385444961713Sgirish nxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 385544961713Sgirish { 385644961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 385744961713Sgirish struct ether_addr addrp; 385844961713Sgirish 385944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38604045d941Ssowmini "==> nxge_m_multicst: add %d", add)); 386144961713Sgirish 386244961713Sgirish bcopy(mca, (uint8_t *)&addrp, ETHERADDRL); 386344961713Sgirish if (add) { 386444961713Sgirish if (nxge_add_mcast_addr(nxgep, &addrp)) { 386544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 38664045d941Ssowmini "<== nxge_m_multicst: add multicast failed")); 386744961713Sgirish return (EINVAL); 386844961713Sgirish } 386944961713Sgirish } else { 387044961713Sgirish if (nxge_del_mcast_addr(nxgep, &addrp)) { 387144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 38724045d941Ssowmini "<== nxge_m_multicst: del multicast failed")); 387344961713Sgirish return (EINVAL); 387444961713Sgirish } 387544961713Sgirish } 387644961713Sgirish 387744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_multicst")); 387844961713Sgirish 387944961713Sgirish return (0); 388044961713Sgirish } 388144961713Sgirish 388244961713Sgirish static int 388344961713Sgirish nxge_m_promisc(void *arg, boolean_t on) 388444961713Sgirish { 388544961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 388644961713Sgirish 388744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38884045d941Ssowmini "==> nxge_m_promisc: on %d", on)); 388944961713Sgirish 389044961713Sgirish if (nxge_set_promisc(nxgep, on)) { 389144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 38924045d941Ssowmini "<== nxge_m_promisc: set promisc failed")); 389344961713Sgirish return (EINVAL); 389444961713Sgirish } 389544961713Sgirish 389644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38974045d941Ssowmini "<== nxge_m_promisc: on %d", on)); 389844961713Sgirish 389944961713Sgirish return (0); 390044961713Sgirish } 390144961713Sgirish 390244961713Sgirish static void 390344961713Sgirish nxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 390444961713Sgirish { 390544961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 390656d930aeSspeer struct iocblk *iocp; 390744961713Sgirish boolean_t need_privilege; 390844961713Sgirish int err; 390944961713Sgirish int cmd; 391044961713Sgirish 391144961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl")); 391244961713Sgirish 391344961713Sgirish iocp = (struct iocblk *)mp->b_rptr; 391444961713Sgirish iocp->ioc_error = 0; 391544961713Sgirish need_privilege = B_TRUE; 391644961713Sgirish cmd = iocp->ioc_cmd; 391744961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl: cmd 0x%08x", cmd)); 391844961713Sgirish switch (cmd) { 391944961713Sgirish default: 392044961713Sgirish miocnak(wq, mp, 0, EINVAL); 392144961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl: invalid")); 392244961713Sgirish return; 392344961713Sgirish 392444961713Sgirish case LB_GET_INFO_SIZE: 392544961713Sgirish case LB_GET_INFO: 392644961713Sgirish case LB_GET_MODE: 392744961713Sgirish need_privilege = B_FALSE; 392844961713Sgirish break; 392944961713Sgirish case LB_SET_MODE: 393044961713Sgirish break; 393144961713Sgirish 393244961713Sgirish 393344961713Sgirish case NXGE_GET_MII: 393444961713Sgirish case NXGE_PUT_MII: 393544961713Sgirish case NXGE_GET64: 393644961713Sgirish case NXGE_PUT64: 393744961713Sgirish case NXGE_GET_TX_RING_SZ: 393844961713Sgirish case NXGE_GET_TX_DESC: 393944961713Sgirish case NXGE_TX_SIDE_RESET: 394044961713Sgirish case NXGE_RX_SIDE_RESET: 394144961713Sgirish case NXGE_GLOBAL_RESET: 394244961713Sgirish case NXGE_RESET_MAC: 394344961713Sgirish case NXGE_TX_REGS_DUMP: 394444961713Sgirish case NXGE_RX_REGS_DUMP: 394544961713Sgirish case NXGE_INT_REGS_DUMP: 394644961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 394744961713Sgirish case NXGE_PUT_TCAM: 394844961713Sgirish case NXGE_GET_TCAM: 394944961713Sgirish case NXGE_RTRACE: 395044961713Sgirish case NXGE_RDUMP: 395144961713Sgirish 395244961713Sgirish need_privilege = B_FALSE; 395344961713Sgirish break; 395444961713Sgirish case NXGE_INJECT_ERR: 395544961713Sgirish cmn_err(CE_NOTE, "!nxge_m_ioctl: Inject error\n"); 395644961713Sgirish nxge_err_inject(nxgep, wq, mp); 395744961713Sgirish break; 395844961713Sgirish } 395944961713Sgirish 396044961713Sgirish if (need_privilege) { 396156d930aeSspeer err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 396244961713Sgirish if (err != 0) { 396344961713Sgirish miocnak(wq, mp, 0, err); 396444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 39654045d941Ssowmini "<== nxge_m_ioctl: no priv")); 396644961713Sgirish return; 396744961713Sgirish } 396844961713Sgirish } 396944961713Sgirish 397044961713Sgirish switch (cmd) { 397144961713Sgirish 397244961713Sgirish case LB_GET_MODE: 397344961713Sgirish case LB_SET_MODE: 397444961713Sgirish case LB_GET_INFO_SIZE: 397544961713Sgirish case LB_GET_INFO: 397644961713Sgirish nxge_loopback_ioctl(nxgep, wq, mp, iocp); 397744961713Sgirish break; 397844961713Sgirish 397944961713Sgirish case NXGE_GET_MII: 398044961713Sgirish case NXGE_PUT_MII: 398144961713Sgirish case NXGE_PUT_TCAM: 398244961713Sgirish case NXGE_GET_TCAM: 398344961713Sgirish case NXGE_GET64: 398444961713Sgirish case NXGE_PUT64: 398544961713Sgirish case NXGE_GET_TX_RING_SZ: 398644961713Sgirish case NXGE_GET_TX_DESC: 398744961713Sgirish case NXGE_TX_SIDE_RESET: 398844961713Sgirish case NXGE_RX_SIDE_RESET: 398944961713Sgirish case NXGE_GLOBAL_RESET: 399044961713Sgirish case NXGE_RESET_MAC: 399144961713Sgirish case NXGE_TX_REGS_DUMP: 399244961713Sgirish case NXGE_RX_REGS_DUMP: 399344961713Sgirish case NXGE_INT_REGS_DUMP: 399444961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 399544961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 39964045d941Ssowmini "==> nxge_m_ioctl: cmd 0x%x", cmd)); 399744961713Sgirish nxge_hw_ioctl(nxgep, wq, mp, iocp); 399844961713Sgirish break; 399944961713Sgirish } 400044961713Sgirish 400144961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl")); 400244961713Sgirish } 400344961713Sgirish 400444961713Sgirish extern void nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count); 400544961713Sgirish 4006678453a8Sspeer void 4007da14cebeSEric Cheng nxge_mmac_kstat_update(p_nxge_t nxgep, int slot, boolean_t factory) 400858324dfcSspeer { 400958324dfcSspeer p_nxge_mmac_stats_t mmac_stats; 401058324dfcSspeer int i; 401158324dfcSspeer nxge_mmac_t *mmac_info; 401258324dfcSspeer 401358324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 401458324dfcSspeer 401558324dfcSspeer mmac_stats = &nxgep->statsp->mmac_stats; 401658324dfcSspeer mmac_stats->mmac_max_cnt = mmac_info->num_mmac; 401758324dfcSspeer mmac_stats->mmac_avail_cnt = mmac_info->naddrfree; 401858324dfcSspeer 401958324dfcSspeer for (i = 0; i < ETHERADDRL; i++) { 402058324dfcSspeer if (factory) { 402158324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 40224045d941Ssowmini = mmac_info->factory_mac_pool[slot][ 40234045d941Ssowmini (ETHERADDRL-1) - i]; 402458324dfcSspeer } else { 402558324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 40264045d941Ssowmini = mmac_info->mac_pool[slot].addr[ 40274045d941Ssowmini (ETHERADDRL - 1) - i]; 402858324dfcSspeer } 402958324dfcSspeer } 403058324dfcSspeer } 403158324dfcSspeer 403258324dfcSspeer /* 403358324dfcSspeer * nxge_altmac_set() -- Set an alternate MAC address 403458324dfcSspeer */ 4035da14cebeSEric Cheng static int 4036da14cebeSEric Cheng nxge_altmac_set(p_nxge_t nxgep, uint8_t *maddr, int slot, 4037da14cebeSEric Cheng int rdctbl, boolean_t usetbl) 403858324dfcSspeer { 403958324dfcSspeer uint8_t addrn; 404058324dfcSspeer uint8_t portn; 404158324dfcSspeer npi_mac_addr_t altmac; 40427b9fa28bSspeer hostinfo_t mac_rdc; 40437b9fa28bSspeer p_nxge_class_pt_cfg_t clscfgp; 404458324dfcSspeer 4045da14cebeSEric Cheng 404658324dfcSspeer altmac.w2 = ((uint16_t)maddr[0] << 8) | ((uint16_t)maddr[1] & 0x0ff); 404758324dfcSspeer altmac.w1 = ((uint16_t)maddr[2] << 8) | ((uint16_t)maddr[3] & 0x0ff); 404858324dfcSspeer altmac.w0 = ((uint16_t)maddr[4] << 8) | ((uint16_t)maddr[5] & 0x0ff); 404958324dfcSspeer 405058324dfcSspeer portn = nxgep->mac.portnum; 405158324dfcSspeer addrn = (uint8_t)slot - 1; 405258324dfcSspeer 4053da14cebeSEric Cheng if (npi_mac_altaddr_entry(nxgep->npi_handle, OP_SET, 4054da14cebeSEric Cheng nxgep->function_num, addrn, &altmac) != NPI_SUCCESS) 405558324dfcSspeer return (EIO); 40567b9fa28bSspeer 40577b9fa28bSspeer /* 40587b9fa28bSspeer * Set the rdc table number for the host info entry 40597b9fa28bSspeer * for this mac address slot. 40607b9fa28bSspeer */ 40617b9fa28bSspeer clscfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config; 40627b9fa28bSspeer mac_rdc.value = 0; 4063da14cebeSEric Cheng if (usetbl) 4064da14cebeSEric Cheng mac_rdc.bits.w0.rdc_tbl_num = rdctbl; 4065da14cebeSEric Cheng else 4066da14cebeSEric Cheng mac_rdc.bits.w0.rdc_tbl_num = 4067da14cebeSEric Cheng clscfgp->mac_host_info[addrn].rdctbl; 40687b9fa28bSspeer mac_rdc.bits.w0.mac_pref = clscfgp->mac_host_info[addrn].mpr_npr; 40697b9fa28bSspeer 40707b9fa28bSspeer if (npi_mac_hostinfo_entry(nxgep->npi_handle, OP_SET, 40717b9fa28bSspeer nxgep->function_num, addrn, &mac_rdc) != NPI_SUCCESS) { 40727b9fa28bSspeer return (EIO); 40737b9fa28bSspeer } 40747b9fa28bSspeer 407558324dfcSspeer /* 407658324dfcSspeer * Enable comparison with the alternate MAC address. 407758324dfcSspeer * While the first alternate addr is enabled by bit 1 of register 407858324dfcSspeer * BMAC_ALTAD_CMPEN, it is enabled by bit 0 of register 407958324dfcSspeer * XMAC_ADDR_CMPEN, so slot needs to be converted to addrn 408058324dfcSspeer * accordingly before calling npi_mac_altaddr_entry. 408158324dfcSspeer */ 408258324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 408358324dfcSspeer addrn = (uint8_t)slot - 1; 408458324dfcSspeer else 408558324dfcSspeer addrn = (uint8_t)slot; 408658324dfcSspeer 4087da14cebeSEric Cheng if (npi_mac_altaddr_enable(nxgep->npi_handle, 4088da14cebeSEric Cheng nxgep->function_num, addrn) != NPI_SUCCESS) { 408958324dfcSspeer return (EIO); 4090da14cebeSEric Cheng } 4091da14cebeSEric Cheng 409258324dfcSspeer return (0); 409358324dfcSspeer } 409458324dfcSspeer 409558324dfcSspeer /* 4096da14cebeSEric Cheng * nxeg_m_mmac_add_g() - find an unused address slot, set the address 409758324dfcSspeer * value to the one specified, enable the port to start filtering on 409858324dfcSspeer * the new MAC address. Returns 0 on success. 409958324dfcSspeer */ 4100678453a8Sspeer int 4101da14cebeSEric Cheng nxge_m_mmac_add_g(void *arg, const uint8_t *maddr, int rdctbl, 4102da14cebeSEric Cheng boolean_t usetbl) 410358324dfcSspeer { 410458324dfcSspeer p_nxge_t nxgep = arg; 4105da14cebeSEric Cheng int slot; 410658324dfcSspeer nxge_mmac_t *mmac_info; 410758324dfcSspeer int err; 410858324dfcSspeer nxge_status_t status; 410958324dfcSspeer 411058324dfcSspeer mutex_enter(nxgep->genlock); 411158324dfcSspeer 411258324dfcSspeer /* 411358324dfcSspeer * Make sure that nxge is initialized, if _start() has 411458324dfcSspeer * not been called. 411558324dfcSspeer */ 411658324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 411758324dfcSspeer status = nxge_init(nxgep); 411858324dfcSspeer if (status != NXGE_OK) { 411958324dfcSspeer mutex_exit(nxgep->genlock); 412058324dfcSspeer return (ENXIO); 412158324dfcSspeer } 412258324dfcSspeer } 412358324dfcSspeer 412458324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 412558324dfcSspeer if (mmac_info->naddrfree == 0) { 412658324dfcSspeer mutex_exit(nxgep->genlock); 412758324dfcSspeer return (ENOSPC); 412858324dfcSspeer } 4129da14cebeSEric Cheng 413058324dfcSspeer /* 413158324dfcSspeer * Search for the first available slot. Because naddrfree 413258324dfcSspeer * is not zero, we are guaranteed to find one. 413358324dfcSspeer * Each of the first two ports of Neptune has 16 alternate 4134678453a8Sspeer * MAC slots but only the first 7 (of 15) slots have assigned factory 413558324dfcSspeer * MAC addresses. We first search among the slots without bundled 413658324dfcSspeer * factory MACs. If we fail to find one in that range, then we 413758324dfcSspeer * search the slots with bundled factory MACs. A factory MAC 413858324dfcSspeer * will be wasted while the slot is used with a user MAC address. 413958324dfcSspeer * But the slot could be used by factory MAC again after calling 414058324dfcSspeer * nxge_m_mmac_remove and nxge_m_mmac_reserve. 414158324dfcSspeer */ 4142da14cebeSEric Cheng for (slot = 0; slot <= mmac_info->num_mmac; slot++) { 4143da14cebeSEric Cheng if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 4144da14cebeSEric Cheng break; 414558324dfcSspeer } 4146da14cebeSEric Cheng 414758324dfcSspeer ASSERT(slot <= mmac_info->num_mmac); 4148e857d0f3SMichael Speer 4149da14cebeSEric Cheng if ((err = nxge_altmac_set(nxgep, (uint8_t *)maddr, slot, rdctbl, 4150da14cebeSEric Cheng usetbl)) != 0) { 415158324dfcSspeer mutex_exit(nxgep->genlock); 415258324dfcSspeer return (err); 415358324dfcSspeer } 4154e857d0f3SMichael Speer 4155da14cebeSEric Cheng bcopy(maddr, mmac_info->mac_pool[slot].addr, ETHERADDRL); 415658324dfcSspeer mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED; 415758324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR; 415858324dfcSspeer mmac_info->naddrfree--; 415958324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 416058324dfcSspeer 416158324dfcSspeer mutex_exit(nxgep->genlock); 416258324dfcSspeer return (0); 416358324dfcSspeer } 416458324dfcSspeer 416558324dfcSspeer /* 416658324dfcSspeer * Remove the specified mac address and update the HW not to filter 416758324dfcSspeer * the mac address anymore. 416858324dfcSspeer */ 4169678453a8Sspeer int 4170da14cebeSEric Cheng nxge_m_mmac_remove(void *arg, int slot) 417158324dfcSspeer { 417258324dfcSspeer p_nxge_t nxgep = arg; 417358324dfcSspeer nxge_mmac_t *mmac_info; 417458324dfcSspeer uint8_t addrn; 417558324dfcSspeer uint8_t portn; 417658324dfcSspeer int err = 0; 417758324dfcSspeer nxge_status_t status; 417858324dfcSspeer 417958324dfcSspeer mutex_enter(nxgep->genlock); 418058324dfcSspeer 418158324dfcSspeer /* 418258324dfcSspeer * Make sure that nxge is initialized, if _start() has 418358324dfcSspeer * not been called. 418458324dfcSspeer */ 418558324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 418658324dfcSspeer status = nxge_init(nxgep); 418758324dfcSspeer if (status != NXGE_OK) { 418858324dfcSspeer mutex_exit(nxgep->genlock); 418958324dfcSspeer return (ENXIO); 419058324dfcSspeer } 419158324dfcSspeer } 419258324dfcSspeer 419358324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 419458324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 419558324dfcSspeer mutex_exit(nxgep->genlock); 419658324dfcSspeer return (EINVAL); 419758324dfcSspeer } 419858324dfcSspeer 419958324dfcSspeer portn = nxgep->mac.portnum; 420058324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 420158324dfcSspeer addrn = (uint8_t)slot - 1; 420258324dfcSspeer else 420358324dfcSspeer addrn = (uint8_t)slot; 420458324dfcSspeer 420558324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 420658324dfcSspeer if (npi_mac_altaddr_disable(nxgep->npi_handle, portn, addrn) 42074045d941Ssowmini == NPI_SUCCESS) { 420858324dfcSspeer mmac_info->naddrfree++; 420958324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_SLOT_USED; 421058324dfcSspeer /* 421158324dfcSspeer * Regardless if the MAC we just stopped filtering 421258324dfcSspeer * is a user addr or a facory addr, we must set 421358324dfcSspeer * the MMAC_VENDOR_ADDR flag if this slot has an 421458324dfcSspeer * associated factory MAC to indicate that a factory 421558324dfcSspeer * MAC is available. 421658324dfcSspeer */ 421758324dfcSspeer if (slot <= mmac_info->num_factory_mmac) { 421858324dfcSspeer mmac_info->mac_pool[slot].flags 42194045d941Ssowmini |= MMAC_VENDOR_ADDR; 422058324dfcSspeer } 422158324dfcSspeer /* 422258324dfcSspeer * Clear mac_pool[slot].addr so that kstat shows 0 422358324dfcSspeer * alternate MAC address if the slot is not used. 422458324dfcSspeer * (But nxge_m_mmac_get returns the factory MAC even 422558324dfcSspeer * when the slot is not used!) 422658324dfcSspeer */ 422758324dfcSspeer bzero(mmac_info->mac_pool[slot].addr, ETHERADDRL); 422858324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 422958324dfcSspeer } else { 423058324dfcSspeer err = EIO; 423158324dfcSspeer } 423258324dfcSspeer } else { 423358324dfcSspeer err = EINVAL; 423458324dfcSspeer } 423558324dfcSspeer 423658324dfcSspeer mutex_exit(nxgep->genlock); 423758324dfcSspeer return (err); 423858324dfcSspeer } 423958324dfcSspeer 424058324dfcSspeer /* 4241da14cebeSEric Cheng * The callback to query all the factory addresses. naddr must be the same as 4242da14cebeSEric Cheng * the number of factory addresses (returned by MAC_CAPAB_MULTIFACTADDR), and 4243da14cebeSEric Cheng * mcm_addr is the space allocated for keep all the addresses, whose size is 4244da14cebeSEric Cheng * naddr * MAXMACADDRLEN. 424558324dfcSspeer */ 4246da14cebeSEric Cheng static void 4247da14cebeSEric Cheng nxge_m_getfactaddr(void *arg, uint_t naddr, uint8_t *addr) 424858324dfcSspeer { 4249da14cebeSEric Cheng nxge_t *nxgep = arg; 4250da14cebeSEric Cheng nxge_mmac_t *mmac_info; 4251da14cebeSEric Cheng int i; 425258324dfcSspeer 425358324dfcSspeer mutex_enter(nxgep->genlock); 425458324dfcSspeer 425558324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 4256da14cebeSEric Cheng ASSERT(naddr == mmac_info->num_factory_mmac); 425758324dfcSspeer 4258da14cebeSEric Cheng for (i = 0; i < naddr; i++) { 4259da14cebeSEric Cheng bcopy(mmac_info->factory_mac_pool[i + 1], 4260da14cebeSEric Cheng addr + i * MAXMACADDRLEN, ETHERADDRL); 426158324dfcSspeer } 426258324dfcSspeer 426358324dfcSspeer mutex_exit(nxgep->genlock); 426458324dfcSspeer } 426558324dfcSspeer 4266da14cebeSEric Cheng 426744961713Sgirish static boolean_t 426844961713Sgirish nxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 426944961713Sgirish { 427058324dfcSspeer nxge_t *nxgep = arg; 427158324dfcSspeer uint32_t *txflags = cap_data; 427244961713Sgirish 427358324dfcSspeer switch (cap) { 427458324dfcSspeer case MAC_CAPAB_HCKSUM: 4275678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4276b4d05839Sml "==> nxge_m_getcapab: checksum %d", nxge_cksum_offload)); 4277b4d05839Sml if (nxge_cksum_offload <= 1) { 4278678453a8Sspeer *txflags = HCKSUM_INET_PARTIAL; 4279678453a8Sspeer } 428044961713Sgirish break; 4281678453a8Sspeer 4282da14cebeSEric Cheng case MAC_CAPAB_MULTIFACTADDR: { 4283da14cebeSEric Cheng mac_capab_multifactaddr_t *mfacp = cap_data; 428444961713Sgirish 4285*63f531d1SSriharsha Basavapatna if (!isLDOMguest(nxgep)) { 4286*63f531d1SSriharsha Basavapatna mutex_enter(nxgep->genlock); 4287*63f531d1SSriharsha Basavapatna mfacp->mcm_naddr = 4288*63f531d1SSriharsha Basavapatna nxgep->nxge_mmac_info.num_factory_mmac; 4289*63f531d1SSriharsha Basavapatna mfacp->mcm_getaddr = nxge_m_getfactaddr; 4290*63f531d1SSriharsha Basavapatna mutex_exit(nxgep->genlock); 4291*63f531d1SSriharsha Basavapatna } 429258324dfcSspeer break; 4293da14cebeSEric Cheng } 4294678453a8Sspeer 429530ac2e7bSml case MAC_CAPAB_LSO: { 429630ac2e7bSml mac_capab_lso_t *cap_lso = cap_data; 429730ac2e7bSml 42983d16f8e7Sml if (nxgep->soft_lso_enable) { 4299b4d05839Sml if (nxge_cksum_offload <= 1) { 4300b4d05839Sml cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 4301b4d05839Sml if (nxge_lso_max > NXGE_LSO_MAXLEN) { 4302b4d05839Sml nxge_lso_max = NXGE_LSO_MAXLEN; 4303b4d05839Sml } 4304b4d05839Sml cap_lso->lso_basic_tcp_ipv4.lso_max = 4305b4d05839Sml nxge_lso_max; 430630ac2e7bSml } 430730ac2e7bSml break; 430830ac2e7bSml } else { 430930ac2e7bSml return (B_FALSE); 431030ac2e7bSml } 431130ac2e7bSml } 431230ac2e7bSml 4313678453a8Sspeer case MAC_CAPAB_RINGS: { 4314da14cebeSEric Cheng mac_capab_rings_t *cap_rings = cap_data; 4315da14cebeSEric Cheng p_nxge_hw_pt_cfg_t p_cfgp = &nxgep->pt_config.hw_config; 4316678453a8Sspeer 4317da14cebeSEric Cheng mutex_enter(nxgep->genlock); 4318da14cebeSEric Cheng if (cap_rings->mr_type == MAC_RING_TYPE_RX) { 4319*63f531d1SSriharsha Basavapatna if (isLDOMguest(nxgep)) { 4320*63f531d1SSriharsha Basavapatna cap_rings->mr_group_type = 4321*63f531d1SSriharsha Basavapatna MAC_GROUP_TYPE_STATIC; 4322*63f531d1SSriharsha Basavapatna cap_rings->mr_rnum = 4323*63f531d1SSriharsha Basavapatna NXGE_HIO_SHARE_MAX_CHANNELS; 4324*63f531d1SSriharsha Basavapatna cap_rings->mr_rget = nxge_fill_ring; 4325*63f531d1SSriharsha Basavapatna cap_rings->mr_gnum = 1; 4326*63f531d1SSriharsha Basavapatna cap_rings->mr_gget = nxge_hio_group_get; 4327*63f531d1SSriharsha Basavapatna cap_rings->mr_gaddring = NULL; 4328*63f531d1SSriharsha Basavapatna cap_rings->mr_gremring = NULL; 4329*63f531d1SSriharsha Basavapatna } else { 4330*63f531d1SSriharsha Basavapatna /* 4331*63f531d1SSriharsha Basavapatna * Service Domain. 4332*63f531d1SSriharsha Basavapatna */ 4333*63f531d1SSriharsha Basavapatna cap_rings->mr_group_type = 4334*63f531d1SSriharsha Basavapatna MAC_GROUP_TYPE_DYNAMIC; 4335*63f531d1SSriharsha Basavapatna cap_rings->mr_rnum = p_cfgp->max_rdcs; 4336*63f531d1SSriharsha Basavapatna cap_rings->mr_rget = nxge_fill_ring; 4337*63f531d1SSriharsha Basavapatna cap_rings->mr_gnum = p_cfgp->max_rdc_grpids; 4338*63f531d1SSriharsha Basavapatna cap_rings->mr_gget = nxge_hio_group_get; 4339*63f531d1SSriharsha Basavapatna cap_rings->mr_gaddring = nxge_group_add_ring; 4340*63f531d1SSriharsha Basavapatna cap_rings->mr_gremring = nxge_group_rem_ring; 4341*63f531d1SSriharsha Basavapatna } 4342da14cebeSEric Cheng 4343da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, RX_CTL, 4344da14cebeSEric Cheng "==> nxge_m_getcapab: rx nrings[%d] ngroups[%d]", 4345da14cebeSEric Cheng p_cfgp->max_rdcs, p_cfgp->max_rdc_grpids)); 4346da14cebeSEric Cheng } else { 4347*63f531d1SSriharsha Basavapatna /* 4348*63f531d1SSriharsha Basavapatna * TX Rings. 4349*63f531d1SSriharsha Basavapatna */ 4350*63f531d1SSriharsha Basavapatna if (isLDOMguest(nxgep)) { 4351*63f531d1SSriharsha Basavapatna cap_rings->mr_group_type = 4352*63f531d1SSriharsha Basavapatna MAC_GROUP_TYPE_STATIC; 4353*63f531d1SSriharsha Basavapatna cap_rings->mr_rnum = 4354*63f531d1SSriharsha Basavapatna NXGE_HIO_SHARE_MAX_CHANNELS; 4355*63f531d1SSriharsha Basavapatna cap_rings->mr_rget = nxge_fill_ring; 4356*63f531d1SSriharsha Basavapatna cap_rings->mr_gnum = 0; 4357*63f531d1SSriharsha Basavapatna cap_rings->mr_gget = NULL; 4358*63f531d1SSriharsha Basavapatna cap_rings->mr_gaddring = NULL; 4359*63f531d1SSriharsha Basavapatna cap_rings->mr_gremring = NULL; 4360*63f531d1SSriharsha Basavapatna } else { 4361*63f531d1SSriharsha Basavapatna /* 4362*63f531d1SSriharsha Basavapatna * Service Domain. 4363*63f531d1SSriharsha Basavapatna */ 4364*63f531d1SSriharsha Basavapatna cap_rings->mr_group_type = 4365*63f531d1SSriharsha Basavapatna MAC_GROUP_TYPE_DYNAMIC; 4366*63f531d1SSriharsha Basavapatna cap_rings->mr_rnum = p_cfgp->tdc.count; 4367*63f531d1SSriharsha Basavapatna cap_rings->mr_rget = nxge_fill_ring; 4368*63f531d1SSriharsha Basavapatna 4369*63f531d1SSriharsha Basavapatna /* 4370*63f531d1SSriharsha Basavapatna * Share capable. 4371*63f531d1SSriharsha Basavapatna * 4372*63f531d1SSriharsha Basavapatna * Do not report the default group: hence -1 4373*63f531d1SSriharsha Basavapatna */ 4374da14cebeSEric Cheng cap_rings->mr_gnum = 4375da14cebeSEric Cheng NXGE_MAX_TDC_GROUPS / nxgep->nports - 1; 4376*63f531d1SSriharsha Basavapatna cap_rings->mr_gget = nxge_hio_group_get; 4377*63f531d1SSriharsha Basavapatna cap_rings->mr_gaddring = nxge_group_add_ring; 4378*63f531d1SSriharsha Basavapatna cap_rings->mr_gremring = nxge_group_rem_ring; 4379678453a8Sspeer } 4380da14cebeSEric Cheng 4381da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, TX_CTL, 4382da14cebeSEric Cheng "==> nxge_m_getcapab: tx rings # of rings %d", 4383da14cebeSEric Cheng p_cfgp->tdc.count)); 4384da14cebeSEric Cheng } 4385da14cebeSEric Cheng mutex_exit(nxgep->genlock); 4386678453a8Sspeer break; 4387678453a8Sspeer } 4388678453a8Sspeer 4389da14cebeSEric Cheng #if defined(sun4v) 4390678453a8Sspeer case MAC_CAPAB_SHARES: { 4391678453a8Sspeer mac_capab_share_t *mshares = (mac_capab_share_t *)cap_data; 4392678453a8Sspeer 4393678453a8Sspeer /* 4394678453a8Sspeer * Only the service domain driver responds to 4395678453a8Sspeer * this capability request. 4396678453a8Sspeer */ 4397da14cebeSEric Cheng mutex_enter(nxgep->genlock); 4398678453a8Sspeer if (isLDOMservice(nxgep)) { 4399678453a8Sspeer mshares->ms_snum = 3; 4400678453a8Sspeer mshares->ms_handle = (void *)nxgep; 4401678453a8Sspeer mshares->ms_salloc = nxge_hio_share_alloc; 4402678453a8Sspeer mshares->ms_sfree = nxge_hio_share_free; 4403da14cebeSEric Cheng mshares->ms_sadd = nxge_hio_share_add_group; 4404da14cebeSEric Cheng mshares->ms_sremove = nxge_hio_share_rem_group; 4405678453a8Sspeer mshares->ms_squery = nxge_hio_share_query; 4406da14cebeSEric Cheng mshares->ms_sbind = nxge_hio_share_bind; 4407da14cebeSEric Cheng mshares->ms_sunbind = nxge_hio_share_unbind; 4408da14cebeSEric Cheng mutex_exit(nxgep->genlock); 4409da14cebeSEric Cheng } else { 4410da14cebeSEric Cheng mutex_exit(nxgep->genlock); 4411678453a8Sspeer return (B_FALSE); 4412da14cebeSEric Cheng } 4413678453a8Sspeer break; 4414678453a8Sspeer } 4415678453a8Sspeer #endif 441644961713Sgirish default: 441744961713Sgirish return (B_FALSE); 441844961713Sgirish } 441944961713Sgirish return (B_TRUE); 442044961713Sgirish } 442144961713Sgirish 44221bd6825cSml static boolean_t 44231bd6825cSml nxge_param_locked(mac_prop_id_t pr_num) 44241bd6825cSml { 44251bd6825cSml /* 44261bd6825cSml * All adv_* parameters are locked (read-only) while 44271bd6825cSml * the device is in any sort of loopback mode ... 44281bd6825cSml */ 44291bd6825cSml switch (pr_num) { 44303fd94f8cSam case MAC_PROP_ADV_1000FDX_CAP: 44313fd94f8cSam case MAC_PROP_EN_1000FDX_CAP: 44323fd94f8cSam case MAC_PROP_ADV_1000HDX_CAP: 44333fd94f8cSam case MAC_PROP_EN_1000HDX_CAP: 44343fd94f8cSam case MAC_PROP_ADV_100FDX_CAP: 44353fd94f8cSam case MAC_PROP_EN_100FDX_CAP: 44363fd94f8cSam case MAC_PROP_ADV_100HDX_CAP: 44373fd94f8cSam case MAC_PROP_EN_100HDX_CAP: 44383fd94f8cSam case MAC_PROP_ADV_10FDX_CAP: 44393fd94f8cSam case MAC_PROP_EN_10FDX_CAP: 44403fd94f8cSam case MAC_PROP_ADV_10HDX_CAP: 44413fd94f8cSam case MAC_PROP_EN_10HDX_CAP: 44423fd94f8cSam case MAC_PROP_AUTONEG: 44433fd94f8cSam case MAC_PROP_FLOWCTRL: 44441bd6825cSml return (B_TRUE); 44451bd6825cSml } 44461bd6825cSml return (B_FALSE); 44471bd6825cSml } 44481bd6825cSml 44491bd6825cSml /* 44501bd6825cSml * callback functions for set/get of properties 44511bd6825cSml */ 44521bd6825cSml static int 44531bd6825cSml nxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 44541bd6825cSml uint_t pr_valsize, const void *pr_val) 44551bd6825cSml { 44561bd6825cSml nxge_t *nxgep = barg; 44571bd6825cSml p_nxge_param_t param_arr; 44581bd6825cSml p_nxge_stats_t statsp; 44591bd6825cSml int err = 0; 44601bd6825cSml uint8_t val; 44611bd6825cSml uint32_t cur_mtu, new_mtu, old_framesize; 44621bd6825cSml link_flowctrl_t fl; 44631bd6825cSml 44641bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_setprop")); 44651bd6825cSml param_arr = nxgep->param_arr; 44661bd6825cSml statsp = nxgep->statsp; 44671bd6825cSml mutex_enter(nxgep->genlock); 44681bd6825cSml if (statsp->port_stats.lb_mode != nxge_lb_normal && 44691bd6825cSml nxge_param_locked(pr_num)) { 44701bd6825cSml /* 44711bd6825cSml * All adv_* parameters are locked (read-only) 44721bd6825cSml * while the device is in any sort of loopback mode. 44731bd6825cSml */ 44741bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 44751bd6825cSml "==> nxge_m_setprop: loopback mode: read only")); 44761bd6825cSml mutex_exit(nxgep->genlock); 44771bd6825cSml return (EBUSY); 44781bd6825cSml } 44791bd6825cSml 44801bd6825cSml val = *(uint8_t *)pr_val; 44811bd6825cSml switch (pr_num) { 44823fd94f8cSam case MAC_PROP_EN_1000FDX_CAP: 44831bd6825cSml nxgep->param_en_1000fdx = val; 44841bd6825cSml param_arr[param_anar_1000fdx].value = val; 44851bd6825cSml 44861bd6825cSml goto reprogram; 44871bd6825cSml 44883fd94f8cSam case MAC_PROP_EN_100FDX_CAP: 44891bd6825cSml nxgep->param_en_100fdx = val; 44901bd6825cSml param_arr[param_anar_100fdx].value = val; 44911bd6825cSml 44921bd6825cSml goto reprogram; 44931bd6825cSml 44943fd94f8cSam case MAC_PROP_EN_10FDX_CAP: 44951bd6825cSml nxgep->param_en_10fdx = val; 44961bd6825cSml param_arr[param_anar_10fdx].value = val; 44971bd6825cSml 44981bd6825cSml goto reprogram; 44991bd6825cSml 45003fd94f8cSam case MAC_PROP_EN_1000HDX_CAP: 45013fd94f8cSam case MAC_PROP_EN_100HDX_CAP: 45023fd94f8cSam case MAC_PROP_EN_10HDX_CAP: 45033fd94f8cSam case MAC_PROP_ADV_1000FDX_CAP: 45043fd94f8cSam case MAC_PROP_ADV_1000HDX_CAP: 45053fd94f8cSam case MAC_PROP_ADV_100FDX_CAP: 45063fd94f8cSam case MAC_PROP_ADV_100HDX_CAP: 45073fd94f8cSam case MAC_PROP_ADV_10FDX_CAP: 45083fd94f8cSam case MAC_PROP_ADV_10HDX_CAP: 45093fd94f8cSam case MAC_PROP_STATUS: 45103fd94f8cSam case MAC_PROP_SPEED: 45113fd94f8cSam case MAC_PROP_DUPLEX: 45121bd6825cSml err = EINVAL; /* cannot set read-only properties */ 45131bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 45141bd6825cSml "==> nxge_m_setprop: read only property %d", 45151bd6825cSml pr_num)); 45161bd6825cSml break; 45171bd6825cSml 45183fd94f8cSam case MAC_PROP_AUTONEG: 45191bd6825cSml param_arr[param_autoneg].value = val; 45201bd6825cSml 45211bd6825cSml goto reprogram; 45221bd6825cSml 45233fd94f8cSam case MAC_PROP_MTU: 45241bd6825cSml cur_mtu = nxgep->mac.default_mtu; 45251bd6825cSml bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 45261bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 45271bd6825cSml "==> nxge_m_setprop: set MTU: %d is_jumbo %d", 45281bd6825cSml new_mtu, nxgep->mac.is_jumbo)); 45291bd6825cSml 45301bd6825cSml if (new_mtu == cur_mtu) { 45311bd6825cSml err = 0; 45321bd6825cSml break; 45331bd6825cSml } 453448056c53SMichael Speer 4535afdda45fSVasumathi Sundaram - Sun Microsystems if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 4536afdda45fSVasumathi Sundaram - Sun Microsystems err = EBUSY; 4537afdda45fSVasumathi Sundaram - Sun Microsystems break; 4538afdda45fSVasumathi Sundaram - Sun Microsystems } 45391bd6825cSml 454048056c53SMichael Speer if ((new_mtu < NXGE_DEFAULT_MTU) || 454148056c53SMichael Speer (new_mtu > NXGE_MAXIMUM_MTU)) { 45421bd6825cSml err = EINVAL; 45431bd6825cSml break; 45441bd6825cSml } 45451bd6825cSml 45461bd6825cSml old_framesize = (uint32_t)nxgep->mac.maxframesize; 45471bd6825cSml nxgep->mac.maxframesize = (uint16_t) 45481bd6825cSml (new_mtu + NXGE_EHEADER_VLAN_CRC); 45491bd6825cSml if (nxge_mac_set_framesize(nxgep)) { 4550c2d37b8bSml nxgep->mac.maxframesize = 4551c2d37b8bSml (uint16_t)old_framesize; 45521bd6825cSml err = EINVAL; 45531bd6825cSml break; 45541bd6825cSml } 45551bd6825cSml 45561bd6825cSml err = mac_maxsdu_update(nxgep->mach, new_mtu); 45571bd6825cSml if (err) { 4558c2d37b8bSml nxgep->mac.maxframesize = 4559c2d37b8bSml (uint16_t)old_framesize; 45601bd6825cSml err = EINVAL; 45611bd6825cSml break; 45621bd6825cSml } 45631bd6825cSml 45641bd6825cSml nxgep->mac.default_mtu = new_mtu; 456548056c53SMichael Speer if (new_mtu > NXGE_DEFAULT_MTU) 456648056c53SMichael Speer nxgep->mac.is_jumbo = B_TRUE; 456748056c53SMichael Speer else 456848056c53SMichael Speer nxgep->mac.is_jumbo = B_FALSE; 456948056c53SMichael Speer 45701bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 45711bd6825cSml "==> nxge_m_setprop: set MTU: %d maxframe %d", 45721bd6825cSml new_mtu, nxgep->mac.maxframesize)); 45731bd6825cSml break; 45741bd6825cSml 45753fd94f8cSam case MAC_PROP_FLOWCTRL: 45761bd6825cSml bcopy(pr_val, &fl, sizeof (fl)); 45771bd6825cSml switch (fl) { 45781bd6825cSml default: 45791bd6825cSml err = EINVAL; 45801bd6825cSml break; 45811bd6825cSml 45821bd6825cSml case LINK_FLOWCTRL_NONE: 45831bd6825cSml param_arr[param_anar_pause].value = 0; 45841bd6825cSml break; 45851bd6825cSml 45861bd6825cSml case LINK_FLOWCTRL_RX: 45871bd6825cSml param_arr[param_anar_pause].value = 1; 45881bd6825cSml break; 45891bd6825cSml 45901bd6825cSml case LINK_FLOWCTRL_TX: 45911bd6825cSml case LINK_FLOWCTRL_BI: 45921bd6825cSml err = EINVAL; 45931bd6825cSml break; 45941bd6825cSml } 45951bd6825cSml 45961bd6825cSml reprogram: 45971bd6825cSml if (err == 0) { 45981bd6825cSml if (!nxge_param_link_update(nxgep)) { 45991bd6825cSml err = EINVAL; 46001bd6825cSml } 46011bd6825cSml } 46021bd6825cSml break; 46033fd94f8cSam case MAC_PROP_PRIVATE: 46041bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46051bd6825cSml "==> nxge_m_setprop: private property")); 46061bd6825cSml err = nxge_set_priv_prop(nxgep, pr_name, pr_valsize, 46071bd6825cSml pr_val); 46081bd6825cSml break; 46094045d941Ssowmini 46104045d941Ssowmini default: 46114045d941Ssowmini err = ENOTSUP; 46124045d941Ssowmini break; 46131bd6825cSml } 46141bd6825cSml 46151bd6825cSml mutex_exit(nxgep->genlock); 46161bd6825cSml 46171bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46181bd6825cSml "<== nxge_m_setprop (return %d)", err)); 46191bd6825cSml return (err); 46201bd6825cSml } 46211bd6825cSml 46221bd6825cSml static int 46231bd6825cSml nxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 4624afdda45fSVasumathi Sundaram - Sun Microsystems uint_t pr_flags, uint_t pr_valsize, void *pr_val, uint_t *perm) 46251bd6825cSml { 46261bd6825cSml nxge_t *nxgep = barg; 46271bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 46281bd6825cSml p_nxge_stats_t statsp = nxgep->statsp; 46291bd6825cSml int err = 0; 46301bd6825cSml link_flowctrl_t fl; 46311bd6825cSml uint64_t tmp = 0; 46324045d941Ssowmini link_state_t ls; 46333fd94f8cSam boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT); 46341bd6825cSml 46351bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46361bd6825cSml "==> nxge_m_getprop: pr_num %d", pr_num)); 46374045d941Ssowmini 46384045d941Ssowmini if (pr_valsize == 0) 46394045d941Ssowmini return (EINVAL); 46404045d941Ssowmini 4641afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_RW; 4642afdda45fSVasumathi Sundaram - Sun Microsystems 46433fd94f8cSam if ((is_default) && (pr_num != MAC_PROP_PRIVATE)) { 46444045d941Ssowmini err = nxge_get_def_val(nxgep, pr_num, pr_valsize, pr_val); 46454045d941Ssowmini return (err); 46464045d941Ssowmini } 46474045d941Ssowmini 46481bd6825cSml bzero(pr_val, pr_valsize); 46491bd6825cSml switch (pr_num) { 46503fd94f8cSam case MAC_PROP_DUPLEX: 4651afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 46521bd6825cSml *(uint8_t *)pr_val = statsp->mac_stats.link_duplex; 46531bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46541bd6825cSml "==> nxge_m_getprop: duplex mode %d", 46551bd6825cSml *(uint8_t *)pr_val)); 46561bd6825cSml break; 46571bd6825cSml 46583fd94f8cSam case MAC_PROP_SPEED: 46591bd6825cSml if (pr_valsize < sizeof (uint64_t)) 46601bd6825cSml return (EINVAL); 4661afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 46621bd6825cSml tmp = statsp->mac_stats.link_speed * 1000000ull; 46631bd6825cSml bcopy(&tmp, pr_val, sizeof (tmp)); 46641bd6825cSml break; 46651bd6825cSml 46663fd94f8cSam case MAC_PROP_STATUS: 46674045d941Ssowmini if (pr_valsize < sizeof (link_state_t)) 46681bd6825cSml return (EINVAL); 4669afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 46704045d941Ssowmini if (!statsp->mac_stats.link_up) 46714045d941Ssowmini ls = LINK_STATE_DOWN; 46724045d941Ssowmini else 46734045d941Ssowmini ls = LINK_STATE_UP; 46744045d941Ssowmini bcopy(&ls, pr_val, sizeof (ls)); 46751bd6825cSml break; 46761bd6825cSml 46773fd94f8cSam case MAC_PROP_AUTONEG: 46781bd6825cSml *(uint8_t *)pr_val = 46791bd6825cSml param_arr[param_autoneg].value; 46801bd6825cSml break; 46811bd6825cSml 46823fd94f8cSam case MAC_PROP_FLOWCTRL: 46831bd6825cSml if (pr_valsize < sizeof (link_flowctrl_t)) 46841bd6825cSml return (EINVAL); 46851bd6825cSml 46861bd6825cSml fl = LINK_FLOWCTRL_NONE; 46871bd6825cSml if (param_arr[param_anar_pause].value) { 46881bd6825cSml fl = LINK_FLOWCTRL_RX; 46891bd6825cSml } 46901bd6825cSml bcopy(&fl, pr_val, sizeof (fl)); 46911bd6825cSml break; 46921bd6825cSml 46933fd94f8cSam case MAC_PROP_ADV_1000FDX_CAP: 4694afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 46951bd6825cSml *(uint8_t *)pr_val = 46961bd6825cSml param_arr[param_anar_1000fdx].value; 46971bd6825cSml break; 46981bd6825cSml 46993fd94f8cSam case MAC_PROP_EN_1000FDX_CAP: 47001bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_1000fdx; 47011bd6825cSml break; 47021bd6825cSml 47033fd94f8cSam case MAC_PROP_ADV_100FDX_CAP: 4704afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 47051bd6825cSml *(uint8_t *)pr_val = 47061bd6825cSml param_arr[param_anar_100fdx].value; 47071bd6825cSml break; 47081bd6825cSml 47093fd94f8cSam case MAC_PROP_EN_100FDX_CAP: 47101bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_100fdx; 47111bd6825cSml break; 47121bd6825cSml 47133fd94f8cSam case MAC_PROP_ADV_10FDX_CAP: 4714afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 47151bd6825cSml *(uint8_t *)pr_val = 47161bd6825cSml param_arr[param_anar_10fdx].value; 47171bd6825cSml break; 47181bd6825cSml 47193fd94f8cSam case MAC_PROP_EN_10FDX_CAP: 47201bd6825cSml *(uint8_t *)pr_val = nxgep->param_en_10fdx; 47211bd6825cSml break; 47221bd6825cSml 47233fd94f8cSam case MAC_PROP_EN_1000HDX_CAP: 47243fd94f8cSam case MAC_PROP_EN_100HDX_CAP: 47253fd94f8cSam case MAC_PROP_EN_10HDX_CAP: 47263fd94f8cSam case MAC_PROP_ADV_1000HDX_CAP: 47273fd94f8cSam case MAC_PROP_ADV_100HDX_CAP: 47283fd94f8cSam case MAC_PROP_ADV_10HDX_CAP: 47294045d941Ssowmini err = ENOTSUP; 47301bd6825cSml break; 47311bd6825cSml 47323fd94f8cSam case MAC_PROP_PRIVATE: 47334045d941Ssowmini err = nxge_get_priv_prop(nxgep, pr_name, pr_flags, 4734afdda45fSVasumathi Sundaram - Sun Microsystems pr_valsize, pr_val, perm); 47354045d941Ssowmini break; 4736f0f2c3a5SGirish Moodalbail 4737f0f2c3a5SGirish Moodalbail case MAC_PROP_MTU: { 4738f0f2c3a5SGirish Moodalbail mac_propval_range_t range; 4739f0f2c3a5SGirish Moodalbail 4740f0f2c3a5SGirish Moodalbail if (!(pr_flags & MAC_PROP_POSSIBLE)) 4741f0f2c3a5SGirish Moodalbail return (ENOTSUP); 4742f0f2c3a5SGirish Moodalbail if (pr_valsize < sizeof (mac_propval_range_t)) 4743f0f2c3a5SGirish Moodalbail return (EINVAL); 4744f0f2c3a5SGirish Moodalbail range.mpr_count = 1; 4745f0f2c3a5SGirish Moodalbail range.mpr_type = MAC_PROPVAL_UINT32; 4746f0f2c3a5SGirish Moodalbail range.range_uint32[0].mpur_min = 4747f0f2c3a5SGirish Moodalbail range.range_uint32[0].mpur_max = NXGE_DEFAULT_MTU; 4748f0f2c3a5SGirish Moodalbail if (nxgep->mac.is_jumbo) 4749f0f2c3a5SGirish Moodalbail range.range_uint32[0].mpur_max = 4750f0f2c3a5SGirish Moodalbail NXGE_MAXIMUM_MTU; 4751f0f2c3a5SGirish Moodalbail bcopy(&range, pr_val, sizeof (range)); 4752f0f2c3a5SGirish Moodalbail break; 4753f0f2c3a5SGirish Moodalbail } 47541bd6825cSml default: 47554045d941Ssowmini err = EINVAL; 47564045d941Ssowmini break; 47571bd6825cSml } 47581bd6825cSml 47591bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_getprop")); 47601bd6825cSml 47611bd6825cSml return (err); 47621bd6825cSml } 47631bd6825cSml 47641bd6825cSml /* ARGSUSED */ 47651bd6825cSml static int 47661bd6825cSml nxge_set_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_valsize, 47671bd6825cSml const void *pr_val) 47681bd6825cSml { 47691bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 47701bd6825cSml int err = 0; 47711bd6825cSml long result; 47721bd6825cSml 47731bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47741bd6825cSml "==> nxge_set_priv_prop: name %s", pr_name)); 47751bd6825cSml 47761bd6825cSml /* Blanking */ 47771bd6825cSml if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 47781bd6825cSml err = nxge_param_rx_intr_time(nxgep, NULL, NULL, 47791bd6825cSml (char *)pr_val, 47801bd6825cSml (caddr_t)¶m_arr[param_rxdma_intr_time]); 47811bd6825cSml if (err) { 47821bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47831bd6825cSml "<== nxge_set_priv_prop: " 47841bd6825cSml "unable to set (%s)", pr_name)); 47851bd6825cSml err = EINVAL; 47861bd6825cSml } else { 47871bd6825cSml err = 0; 47881bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47891bd6825cSml "<== nxge_set_priv_prop: " 47901bd6825cSml "set (%s)", pr_name)); 47911bd6825cSml } 47921bd6825cSml 47931bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47941bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 47951bd6825cSml pr_name, result)); 47961bd6825cSml 47971bd6825cSml return (err); 47981bd6825cSml } 47991bd6825cSml 48001bd6825cSml if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 48011bd6825cSml err = nxge_param_rx_intr_pkts(nxgep, NULL, NULL, 48021bd6825cSml (char *)pr_val, 48031bd6825cSml (caddr_t)¶m_arr[param_rxdma_intr_pkts]); 48041bd6825cSml if (err) { 48051bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48061bd6825cSml "<== nxge_set_priv_prop: " 48071bd6825cSml "unable to set (%s)", pr_name)); 48081bd6825cSml err = EINVAL; 48091bd6825cSml } else { 48101bd6825cSml err = 0; 48111bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48121bd6825cSml "<== nxge_set_priv_prop: " 48131bd6825cSml "set (%s)", pr_name)); 48141bd6825cSml } 48151bd6825cSml 48161bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48171bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 48181bd6825cSml pr_name, result)); 48191bd6825cSml 48201bd6825cSml return (err); 48211bd6825cSml } 48221bd6825cSml 48231bd6825cSml /* Classification */ 48241bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 48251bd6825cSml if (pr_val == NULL) { 48261bd6825cSml err = EINVAL; 48271bd6825cSml return (err); 48281bd6825cSml } 48291bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 48301bd6825cSml 48311bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 48321bd6825cSml NULL, (char *)pr_val, 48331bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 48341bd6825cSml 48351bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48361bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 48371bd6825cSml pr_name, result)); 48381bd6825cSml 48391bd6825cSml return (err); 48401bd6825cSml } 48411bd6825cSml 48421bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 48431bd6825cSml if (pr_val == NULL) { 48441bd6825cSml err = EINVAL; 48451bd6825cSml return (err); 48461bd6825cSml } 48471bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 48481bd6825cSml 48491bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 48501bd6825cSml NULL, (char *)pr_val, 48511bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 48521bd6825cSml 48531bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48541bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 48551bd6825cSml pr_name, result)); 48561bd6825cSml 48571bd6825cSml return (err); 48581bd6825cSml } 48591bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 48601bd6825cSml if (pr_val == NULL) { 48611bd6825cSml err = EINVAL; 48621bd6825cSml return (err); 48631bd6825cSml } 48641bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 48651bd6825cSml 48661bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 48671bd6825cSml NULL, (char *)pr_val, 48681bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 48691bd6825cSml 48701bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48711bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 48721bd6825cSml pr_name, result)); 48731bd6825cSml 48741bd6825cSml return (err); 48751bd6825cSml } 48761bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 48771bd6825cSml if (pr_val == NULL) { 48781bd6825cSml err = EINVAL; 48791bd6825cSml return (err); 48801bd6825cSml } 48811bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 48821bd6825cSml 48831bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 48841bd6825cSml NULL, (char *)pr_val, 48851bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 48861bd6825cSml 48871bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48881bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 48891bd6825cSml pr_name, result)); 48901bd6825cSml 48911bd6825cSml return (err); 48921bd6825cSml } 48931bd6825cSml 48941bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 48951bd6825cSml if (pr_val == NULL) { 48961bd6825cSml err = EINVAL; 48971bd6825cSml return (err); 48981bd6825cSml } 48991bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49001bd6825cSml 49011bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 49021bd6825cSml NULL, (char *)pr_val, 49031bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 49041bd6825cSml 49051bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49061bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 49071bd6825cSml pr_name, result)); 49081bd6825cSml 49091bd6825cSml return (err); 49101bd6825cSml } 49111bd6825cSml 49121bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 49131bd6825cSml if (pr_val == NULL) { 49141bd6825cSml err = EINVAL; 49151bd6825cSml return (err); 49161bd6825cSml } 49171bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49181bd6825cSml 49191bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 49201bd6825cSml NULL, (char *)pr_val, 49211bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 49221bd6825cSml 49231bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49241bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 49251bd6825cSml pr_name, result)); 49261bd6825cSml 49271bd6825cSml return (err); 49281bd6825cSml } 49291bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 49301bd6825cSml if (pr_val == NULL) { 49311bd6825cSml err = EINVAL; 49321bd6825cSml return (err); 49331bd6825cSml } 49341bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49351bd6825cSml 49361bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 49371bd6825cSml NULL, (char *)pr_val, 49381bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 49391bd6825cSml 49401bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49411bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 49421bd6825cSml pr_name, result)); 49431bd6825cSml 49441bd6825cSml return (err); 49451bd6825cSml } 49461bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 49471bd6825cSml if (pr_val == NULL) { 49481bd6825cSml err = EINVAL; 49491bd6825cSml return (err); 49501bd6825cSml } 49511bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49521bd6825cSml 49531bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 49541bd6825cSml NULL, (char *)pr_val, 49551bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 49561bd6825cSml 49571bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49581bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 49591bd6825cSml pr_name, result)); 49601bd6825cSml 49611bd6825cSml return (err); 49621bd6825cSml } 49631bd6825cSml 49641bd6825cSml if (strcmp(pr_name, "_soft_lso_enable") == 0) { 49651bd6825cSml if (pr_val == NULL) { 49661bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49671bd6825cSml "==> nxge_set_priv_prop: name %s (null)", pr_name)); 49681bd6825cSml err = EINVAL; 49691bd6825cSml return (err); 49701bd6825cSml } 49711bd6825cSml 49721bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49731bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49741bd6825cSml "<== nxge_set_priv_prop: name %s " 49751bd6825cSml "(lso %d pr_val %s value %d)", 49761bd6825cSml pr_name, nxgep->soft_lso_enable, pr_val, result)); 49771bd6825cSml 49781bd6825cSml if (result > 1 || result < 0) { 49791bd6825cSml err = EINVAL; 49801bd6825cSml } else { 49811bd6825cSml if (nxgep->soft_lso_enable == (uint32_t)result) { 49821bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49831bd6825cSml "no change (%d %d)", 49841bd6825cSml nxgep->soft_lso_enable, result)); 49851bd6825cSml return (0); 49861bd6825cSml } 49871bd6825cSml } 49881bd6825cSml 49891bd6825cSml nxgep->soft_lso_enable = (int)result; 49901bd6825cSml 49911bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49921bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 49931bd6825cSml pr_name, result)); 49941bd6825cSml 49951bd6825cSml return (err); 49961bd6825cSml } 499700161856Syc /* 499800161856Syc * Commands like "ndd -set /dev/nxge0 adv_10gfdx_cap 1" cause the 499900161856Syc * following code to be executed. 500000161856Syc */ 50014045d941Ssowmini if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) { 50024045d941Ssowmini err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val, 50034045d941Ssowmini (caddr_t)¶m_arr[param_anar_10gfdx]); 50044045d941Ssowmini return (err); 50054045d941Ssowmini } 50064045d941Ssowmini if (strcmp(pr_name, "_adv_pause_cap") == 0) { 50074045d941Ssowmini err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val, 50084045d941Ssowmini (caddr_t)¶m_arr[param_anar_pause]); 50094045d941Ssowmini return (err); 50104045d941Ssowmini } 50111bd6825cSml 50121bd6825cSml return (EINVAL); 50131bd6825cSml } 50141bd6825cSml 50151bd6825cSml static int 50164045d941Ssowmini nxge_get_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_flags, 5017afdda45fSVasumathi Sundaram - Sun Microsystems uint_t pr_valsize, void *pr_val, uint_t *perm) 50181bd6825cSml { 50191bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 50201bd6825cSml char valstr[MAXNAMELEN]; 50211bd6825cSml int err = EINVAL; 50221bd6825cSml uint_t strsize; 50233fd94f8cSam boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT); 50241bd6825cSml 50251bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50261bd6825cSml "==> nxge_get_priv_prop: property %s", pr_name)); 50271bd6825cSml 50281bd6825cSml /* function number */ 50291bd6825cSml if (strcmp(pr_name, "_function_number") == 0) { 50304045d941Ssowmini if (is_default) 50314045d941Ssowmini return (ENOTSUP); 5032afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 50334045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 50344045d941Ssowmini nxgep->function_num); 50351bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50361bd6825cSml "==> nxge_get_priv_prop: name %s " 50371bd6825cSml "(value %d valstr %s)", 50381bd6825cSml pr_name, nxgep->function_num, valstr)); 50391bd6825cSml 50401bd6825cSml err = 0; 50411bd6825cSml goto done; 50421bd6825cSml } 50431bd6825cSml 50441bd6825cSml /* Neptune firmware version */ 50451bd6825cSml if (strcmp(pr_name, "_fw_version") == 0) { 50464045d941Ssowmini if (is_default) 50474045d941Ssowmini return (ENOTSUP); 5048afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 50494045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%s", 50504045d941Ssowmini nxgep->vpd_info.ver); 50511bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50521bd6825cSml "==> nxge_get_priv_prop: name %s " 50531bd6825cSml "(value %d valstr %s)", 50541bd6825cSml pr_name, nxgep->vpd_info.ver, valstr)); 50551bd6825cSml 50561bd6825cSml err = 0; 50571bd6825cSml goto done; 50581bd6825cSml } 50591bd6825cSml 50601bd6825cSml /* port PHY mode */ 50611bd6825cSml if (strcmp(pr_name, "_port_mode") == 0) { 50624045d941Ssowmini if (is_default) 50634045d941Ssowmini return (ENOTSUP); 5064afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 50651bd6825cSml switch (nxgep->mac.portmode) { 50661bd6825cSml case PORT_1G_COPPER: 50674045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G copper %s", 50681bd6825cSml nxgep->hot_swappable_phy ? 50691bd6825cSml "[Hot Swappable]" : ""); 50701bd6825cSml break; 50711bd6825cSml case PORT_1G_FIBER: 50724045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G fiber %s", 50731bd6825cSml nxgep->hot_swappable_phy ? 50741bd6825cSml "[hot swappable]" : ""); 50751bd6825cSml break; 50761bd6825cSml case PORT_10G_COPPER: 50774045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 50784045d941Ssowmini "10G copper %s", 50791bd6825cSml nxgep->hot_swappable_phy ? 50801bd6825cSml "[hot swappable]" : ""); 50811bd6825cSml break; 50821bd6825cSml case PORT_10G_FIBER: 50834045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "10G fiber %s", 50841bd6825cSml nxgep->hot_swappable_phy ? 50851bd6825cSml "[hot swappable]" : ""); 50861bd6825cSml break; 50871bd6825cSml case PORT_10G_SERDES: 50884045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 50894045d941Ssowmini "10G serdes %s", nxgep->hot_swappable_phy ? 50901bd6825cSml "[hot swappable]" : ""); 50911bd6825cSml break; 50921bd6825cSml case PORT_1G_SERDES: 50934045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G serdes %s", 50941bd6825cSml nxgep->hot_swappable_phy ? 50951bd6825cSml "[hot swappable]" : ""); 50961bd6825cSml break; 509700161856Syc case PORT_1G_TN1010: 509800161856Syc (void) snprintf(valstr, sizeof (valstr), 509900161856Syc "1G TN1010 copper %s", nxgep->hot_swappable_phy ? 510000161856Syc "[hot swappable]" : ""); 510100161856Syc break; 510200161856Syc case PORT_10G_TN1010: 510300161856Syc (void) snprintf(valstr, sizeof (valstr), 510400161856Syc "10G TN1010 copper %s", nxgep->hot_swappable_phy ? 510500161856Syc "[hot swappable]" : ""); 510600161856Syc break; 51071bd6825cSml case PORT_1G_RGMII_FIBER: 51084045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 51094045d941Ssowmini "1G rgmii fiber %s", nxgep->hot_swappable_phy ? 51101bd6825cSml "[hot swappable]" : ""); 51111bd6825cSml break; 51121bd6825cSml case PORT_HSP_MODE: 51134045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 5114c2d37b8bSml "phy not present[hot swappable]"); 51151bd6825cSml break; 51161bd6825cSml default: 51174045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "unknown %s", 51181bd6825cSml nxgep->hot_swappable_phy ? 51191bd6825cSml "[hot swappable]" : ""); 51201bd6825cSml break; 51211bd6825cSml } 51221bd6825cSml 51231bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51241bd6825cSml "==> nxge_get_priv_prop: name %s (value %s)", 51251bd6825cSml pr_name, valstr)); 51261bd6825cSml 51271bd6825cSml err = 0; 51281bd6825cSml goto done; 51291bd6825cSml } 51301bd6825cSml 51311bd6825cSml /* Hot swappable PHY */ 51321bd6825cSml if (strcmp(pr_name, "_hot_swap_phy") == 0) { 51334045d941Ssowmini if (is_default) 51344045d941Ssowmini return (ENOTSUP); 5135afdda45fSVasumathi Sundaram - Sun Microsystems *perm = MAC_PROP_PERM_READ; 51364045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%s", 51371bd6825cSml nxgep->hot_swappable_phy ? 51381bd6825cSml "yes" : "no"); 51391bd6825cSml 51401bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51411bd6825cSml "==> nxge_get_priv_prop: name %s " 51421bd6825cSml "(value %d valstr %s)", 51431bd6825cSml pr_name, nxgep->hot_swappable_phy, valstr)); 51441bd6825cSml 51451bd6825cSml err = 0; 51461bd6825cSml goto done; 51471bd6825cSml } 51481bd6825cSml 51491bd6825cSml 51501bd6825cSml /* Receive Interrupt Blanking Parameters */ 51511bd6825cSml if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 51524045d941Ssowmini err = 0; 51534045d941Ssowmini if (is_default) { 51544045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 51554045d941Ssowmini "%d", RXDMA_RCR_TO_DEFAULT); 51564045d941Ssowmini goto done; 51574045d941Ssowmini } 51584045d941Ssowmini 51594045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 51604045d941Ssowmini nxgep->intr_timeout); 51611bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51621bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 51631bd6825cSml pr_name, 51641bd6825cSml (uint32_t)nxgep->intr_timeout)); 51651bd6825cSml goto done; 51661bd6825cSml } 51671bd6825cSml 51681bd6825cSml if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 51694045d941Ssowmini err = 0; 51704045d941Ssowmini if (is_default) { 51714045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 51724045d941Ssowmini "%d", RXDMA_RCR_PTHRES_DEFAULT); 51734045d941Ssowmini goto done; 51744045d941Ssowmini } 51754045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 51764045d941Ssowmini nxgep->intr_threshold); 51771bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51781bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 51791bd6825cSml pr_name, (uint32_t)nxgep->intr_threshold)); 51801bd6825cSml 51811bd6825cSml goto done; 51821bd6825cSml } 51831bd6825cSml 51841bd6825cSml /* Classification and Load Distribution Configuration */ 51851bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 51864045d941Ssowmini if (is_default) { 51874045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 51884045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 51894045d941Ssowmini err = 0; 51904045d941Ssowmini goto done; 51914045d941Ssowmini } 51921bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 51931bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 51941bd6825cSml 51954045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 51961bd6825cSml (int)param_arr[param_class_opt_ipv4_tcp].value); 51971bd6825cSml 51981bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51991bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 52001bd6825cSml goto done; 52011bd6825cSml } 52021bd6825cSml 52031bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 52044045d941Ssowmini if (is_default) { 52054045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52064045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 52074045d941Ssowmini err = 0; 52084045d941Ssowmini goto done; 52094045d941Ssowmini } 52101bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 52111bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 52121bd6825cSml 52134045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52141bd6825cSml (int)param_arr[param_class_opt_ipv4_udp].value); 52151bd6825cSml 52161bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52171bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 52181bd6825cSml goto done; 52191bd6825cSml } 52201bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 52214045d941Ssowmini if (is_default) { 52224045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52234045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 52244045d941Ssowmini err = 0; 52254045d941Ssowmini goto done; 52264045d941Ssowmini } 52271bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 52281bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 52291bd6825cSml 52304045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52311bd6825cSml (int)param_arr[param_class_opt_ipv4_ah].value); 52321bd6825cSml 52331bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52341bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 52351bd6825cSml goto done; 52361bd6825cSml } 52371bd6825cSml 52381bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 52394045d941Ssowmini if (is_default) { 52404045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52414045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 52424045d941Ssowmini err = 0; 52434045d941Ssowmini goto done; 52444045d941Ssowmini } 52451bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 52461bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 52471bd6825cSml 52484045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52491bd6825cSml (int)param_arr[param_class_opt_ipv4_sctp].value); 52501bd6825cSml 52511bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52521bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 52531bd6825cSml goto done; 52541bd6825cSml } 52551bd6825cSml 52561bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 52574045d941Ssowmini if (is_default) { 52584045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52594045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 52604045d941Ssowmini err = 0; 52614045d941Ssowmini goto done; 52624045d941Ssowmini } 52631bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 52641bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 52651bd6825cSml 52664045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52671bd6825cSml (int)param_arr[param_class_opt_ipv6_tcp].value); 52681bd6825cSml 52691bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52701bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 52711bd6825cSml goto done; 52721bd6825cSml } 52731bd6825cSml 52741bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 52754045d941Ssowmini if (is_default) { 52764045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52774045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 52784045d941Ssowmini err = 0; 52794045d941Ssowmini goto done; 52804045d941Ssowmini } 52811bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 52821bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 52831bd6825cSml 52844045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52851bd6825cSml (int)param_arr[param_class_opt_ipv6_udp].value); 52861bd6825cSml 52871bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52881bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 52891bd6825cSml goto done; 52901bd6825cSml } 52911bd6825cSml 52921bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 52934045d941Ssowmini if (is_default) { 52944045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52954045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 52964045d941Ssowmini err = 0; 52974045d941Ssowmini goto done; 52984045d941Ssowmini } 52991bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 53001bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 53011bd6825cSml 53024045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53031bd6825cSml (int)param_arr[param_class_opt_ipv6_ah].value); 53041bd6825cSml 53051bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53061bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 53071bd6825cSml goto done; 53081bd6825cSml } 53091bd6825cSml 53101bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 53114045d941Ssowmini if (is_default) { 53124045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53134045d941Ssowmini NXGE_CLASS_FLOW_GEN_SERVER); 53144045d941Ssowmini err = 0; 53154045d941Ssowmini goto done; 53164045d941Ssowmini } 53171bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 53181bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 53191bd6825cSml 53204045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53211bd6825cSml (int)param_arr[param_class_opt_ipv6_sctp].value); 53221bd6825cSml 53231bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53241bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 53251bd6825cSml goto done; 53261bd6825cSml } 53271bd6825cSml 53281bd6825cSml /* Software LSO */ 53291bd6825cSml if (strcmp(pr_name, "_soft_lso_enable") == 0) { 53304045d941Ssowmini if (is_default) { 53314045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 53324045d941Ssowmini err = 0; 53334045d941Ssowmini goto done; 53344045d941Ssowmini } 53354045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 53364045d941Ssowmini "%d", nxgep->soft_lso_enable); 53371bd6825cSml err = 0; 53381bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53391bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 53401bd6825cSml pr_name, nxgep->soft_lso_enable)); 53411bd6825cSml 53421bd6825cSml goto done; 53431bd6825cSml } 53444045d941Ssowmini if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) { 53454045d941Ssowmini err = 0; 53464045d941Ssowmini if (is_default || 53474045d941Ssowmini nxgep->param_arr[param_anar_10gfdx].value != 0) { 53484045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 1); 53494045d941Ssowmini goto done; 53504045d941Ssowmini } else { 53514045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 53524045d941Ssowmini goto done; 53534045d941Ssowmini } 53544045d941Ssowmini } 53554045d941Ssowmini if (strcmp(pr_name, "_adv_pause_cap") == 0) { 53564045d941Ssowmini err = 0; 53574045d941Ssowmini if (is_default || 53584045d941Ssowmini nxgep->param_arr[param_anar_pause].value != 0) { 53594045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 1); 53604045d941Ssowmini goto done; 53614045d941Ssowmini } else { 53624045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 53634045d941Ssowmini goto done; 53644045d941Ssowmini } 53654045d941Ssowmini } 53661bd6825cSml 53671bd6825cSml done: 53681bd6825cSml if (err == 0) { 53691bd6825cSml strsize = (uint_t)strlen(valstr); 53701bd6825cSml if (pr_valsize < strsize) { 53711bd6825cSml err = ENOBUFS; 53721bd6825cSml } else { 53731bd6825cSml (void) strlcpy(pr_val, valstr, pr_valsize); 53741bd6825cSml } 53751bd6825cSml } 53761bd6825cSml 53771bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53781bd6825cSml "<== nxge_get_priv_prop: return %d", err)); 53791bd6825cSml return (err); 53801bd6825cSml } 53811bd6825cSml 538244961713Sgirish /* 538344961713Sgirish * Module loading and removing entry points. 538444961713Sgirish */ 538544961713Sgirish 53866f157acbSml DDI_DEFINE_STREAM_OPS(nxge_dev_ops, nulldev, nulldev, nxge_attach, nxge_detach, 538719397407SSherry Moore nodev, NULL, D_MP, NULL, nxge_quiesce); 538844961713Sgirish 53892e59129aSraghus #define NXGE_DESC_VER "Sun NIU 10Gb Ethernet" 539044961713Sgirish 539144961713Sgirish /* 539244961713Sgirish * Module linkage information for the kernel. 539344961713Sgirish */ 539444961713Sgirish static struct modldrv nxge_modldrv = { 539544961713Sgirish &mod_driverops, 539644961713Sgirish NXGE_DESC_VER, 539744961713Sgirish &nxge_dev_ops 539844961713Sgirish }; 539944961713Sgirish 540044961713Sgirish static struct modlinkage modlinkage = { 540144961713Sgirish MODREV_1, (void *) &nxge_modldrv, NULL 540244961713Sgirish }; 540344961713Sgirish 540444961713Sgirish int 540544961713Sgirish _init(void) 540644961713Sgirish { 540744961713Sgirish int status; 540844961713Sgirish 54093b2d9860SMichael Speer MUTEX_INIT(&nxgedebuglock, NULL, MUTEX_DRIVER, NULL); 54103b2d9860SMichael Speer 541144961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init")); 54123b2d9860SMichael Speer 541344961713Sgirish mac_init_ops(&nxge_dev_ops, "nxge"); 54143b2d9860SMichael Speer 541544961713Sgirish status = ddi_soft_state_init(&nxge_list, sizeof (nxge_t), 0); 541644961713Sgirish if (status != 0) { 541744961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, 54184045d941Ssowmini "failed to init device soft state")); 541944961713Sgirish goto _init_exit; 542044961713Sgirish } 54213b2d9860SMichael Speer 542244961713Sgirish status = mod_install(&modlinkage); 542344961713Sgirish if (status != 0) { 542444961713Sgirish ddi_soft_state_fini(&nxge_list); 542544961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, "Mod install failed")); 542644961713Sgirish goto _init_exit; 542744961713Sgirish } 542844961713Sgirish 542944961713Sgirish MUTEX_INIT(&nxge_common_lock, NULL, MUTEX_DRIVER, NULL); 543044961713Sgirish 54313b2d9860SMichael Speer NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _init status = 0x%X", status)); 54323b2d9860SMichael Speer return (status); 543344961713Sgirish 54343b2d9860SMichael Speer _init_exit: 54353b2d9860SMichael Speer NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _init status = 0x%X", status)); 54363b2d9860SMichael Speer MUTEX_DESTROY(&nxgedebuglock); 543744961713Sgirish return (status); 543844961713Sgirish } 543944961713Sgirish 544044961713Sgirish int 544144961713Sgirish _fini(void) 544244961713Sgirish { 544344961713Sgirish int status; 544444961713Sgirish 544544961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini")); 544644961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove")); 5447a3c5bd6dSspeer 5448a3c5bd6dSspeer if (nxge_mblks_pending) 5449a3c5bd6dSspeer return (EBUSY); 5450a3c5bd6dSspeer 545144961713Sgirish status = mod_remove(&modlinkage); 545244961713Sgirish if (status != DDI_SUCCESS) { 545344961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, 54544045d941Ssowmini "Module removal failed 0x%08x", 54554045d941Ssowmini status)); 545644961713Sgirish goto _fini_exit; 545744961713Sgirish } 545844961713Sgirish 545944961713Sgirish mac_fini_ops(&nxge_dev_ops); 546044961713Sgirish 546144961713Sgirish ddi_soft_state_fini(&nxge_list); 546244961713Sgirish 54633b2d9860SMichael Speer NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _fini status = 0x%08x", status)); 54643b2d9860SMichael Speer 546544961713Sgirish MUTEX_DESTROY(&nxge_common_lock); 54663b2d9860SMichael Speer MUTEX_DESTROY(&nxgedebuglock); 54673b2d9860SMichael Speer return (status); 546844961713Sgirish 54693b2d9860SMichael Speer _fini_exit: 54703b2d9860SMichael Speer NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _fini status = 0x%08x", status)); 547144961713Sgirish return (status); 547244961713Sgirish } 547344961713Sgirish 547444961713Sgirish int 547544961713Sgirish _info(struct modinfo *modinfop) 547644961713Sgirish { 547744961713Sgirish int status; 547844961713Sgirish 547944961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info")); 548044961713Sgirish status = mod_info(&modlinkage, modinfop); 548144961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status)); 548244961713Sgirish 548344961713Sgirish return (status); 548444961713Sgirish } 548544961713Sgirish 5486da14cebeSEric Cheng /*ARGSUSED*/ 5487da14cebeSEric Cheng static int 5488da14cebeSEric Cheng nxge_tx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num) 5489da14cebeSEric Cheng { 5490da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5491da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5492da14cebeSEric Cheng uint32_t channel; 5493da14cebeSEric Cheng p_tx_ring_t ring; 5494da14cebeSEric Cheng 5495da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.tdc.start + rhp->index; 5496da14cebeSEric Cheng ring = nxgep->tx_rings->rings[channel]; 5497da14cebeSEric Cheng 5498da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 5499da14cebeSEric Cheng ring->tx_ring_handle = rhp->ring_handle; 5500da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5501da14cebeSEric Cheng 5502da14cebeSEric Cheng return (0); 5503da14cebeSEric Cheng } 5504da14cebeSEric Cheng 5505da14cebeSEric Cheng static void 5506da14cebeSEric Cheng nxge_tx_ring_stop(mac_ring_driver_t rdriver) 5507da14cebeSEric Cheng { 5508da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5509da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5510da14cebeSEric Cheng uint32_t channel; 5511da14cebeSEric Cheng p_tx_ring_t ring; 5512da14cebeSEric Cheng 5513da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.tdc.start + rhp->index; 5514da14cebeSEric Cheng ring = nxgep->tx_rings->rings[channel]; 5515da14cebeSEric Cheng 5516da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 5517da14cebeSEric Cheng ring->tx_ring_handle = (mac_ring_handle_t)NULL; 5518da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5519da14cebeSEric Cheng } 5520da14cebeSEric Cheng 5521da14cebeSEric Cheng static int 5522da14cebeSEric Cheng nxge_rx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num) 5523da14cebeSEric Cheng { 5524da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5525da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5526da14cebeSEric Cheng uint32_t channel; 5527da14cebeSEric Cheng p_rx_rcr_ring_t ring; 5528da14cebeSEric Cheng int i; 5529da14cebeSEric Cheng 5530da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.start_rdc + rhp->index; 5531da14cebeSEric Cheng ring = nxgep->rx_rcr_rings->rcr_rings[channel]; 5532da14cebeSEric Cheng 5533da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 5534da14cebeSEric Cheng 5535da14cebeSEric Cheng if (nxgep->rx_channel_started[channel] == B_TRUE) { 5536da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5537da14cebeSEric Cheng return (0); 5538da14cebeSEric Cheng } 5539da14cebeSEric Cheng 5540da14cebeSEric Cheng /* set rcr_ring */ 5541da14cebeSEric Cheng for (i = 0; i < nxgep->ldgvp->maxldvs; i++) { 5542da14cebeSEric Cheng if ((nxgep->ldgvp->ldvp[i].is_rxdma == 1) && 5543da14cebeSEric Cheng (nxgep->ldgvp->ldvp[i].channel == channel)) { 5544da14cebeSEric Cheng ring->ldvp = &nxgep->ldgvp->ldvp[i]; 5545da14cebeSEric Cheng ring->ldgp = nxgep->ldgvp->ldvp[i].ldgp; 5546da14cebeSEric Cheng } 5547da14cebeSEric Cheng } 5548da14cebeSEric Cheng 5549da14cebeSEric Cheng nxgep->rx_channel_started[channel] = B_TRUE; 5550da14cebeSEric Cheng ring->rcr_mac_handle = rhp->ring_handle; 5551da14cebeSEric Cheng ring->rcr_gen_num = mr_gen_num; 5552da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5553da14cebeSEric Cheng 5554da14cebeSEric Cheng return (0); 5555da14cebeSEric Cheng } 5556da14cebeSEric Cheng 5557da14cebeSEric Cheng static void 5558da14cebeSEric Cheng nxge_rx_ring_stop(mac_ring_driver_t rdriver) 5559da14cebeSEric Cheng { 5560da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5561da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5562da14cebeSEric Cheng uint32_t channel; 5563da14cebeSEric Cheng p_rx_rcr_ring_t ring; 5564da14cebeSEric Cheng 5565da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.start_rdc + rhp->index; 5566da14cebeSEric Cheng ring = nxgep->rx_rcr_rings->rcr_rings[channel]; 5567da14cebeSEric Cheng 5568da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 5569da14cebeSEric Cheng nxgep->rx_channel_started[channel] = B_FALSE; 5570da14cebeSEric Cheng ring->rcr_mac_handle = NULL; 5571da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5572da14cebeSEric Cheng } 5573da14cebeSEric Cheng 5574da14cebeSEric Cheng /* 5575da14cebeSEric Cheng * Callback funtion for MAC layer to register all rings. 5576da14cebeSEric Cheng */ 5577da14cebeSEric Cheng static void 5578da14cebeSEric Cheng nxge_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index, 5579da14cebeSEric Cheng const int index, mac_ring_info_t *infop, mac_ring_handle_t rh) 5580da14cebeSEric Cheng { 5581da14cebeSEric Cheng p_nxge_t nxgep = (p_nxge_t)arg; 5582da14cebeSEric Cheng p_nxge_hw_pt_cfg_t p_cfgp = &nxgep->pt_config.hw_config; 5583da14cebeSEric Cheng 5584da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, TX_CTL, 5585da14cebeSEric Cheng "==> nxge_fill_ring 0x%x index %d", rtype, index)); 5586da14cebeSEric Cheng 5587da14cebeSEric Cheng switch (rtype) { 5588da14cebeSEric Cheng case MAC_RING_TYPE_TX: { 5589da14cebeSEric Cheng p_nxge_ring_handle_t rhandlep; 5590da14cebeSEric Cheng 5591da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, TX_CTL, 5592da14cebeSEric Cheng "==> nxge_fill_ring (TX) 0x%x index %d ntdcs %d", 5593da14cebeSEric Cheng rtype, index, p_cfgp->tdc.count)); 5594da14cebeSEric Cheng 5595da14cebeSEric Cheng ASSERT((index >= 0) && (index < p_cfgp->tdc.count)); 5596da14cebeSEric Cheng rhandlep = &nxgep->tx_ring_handles[index]; 5597da14cebeSEric Cheng rhandlep->nxgep = nxgep; 5598da14cebeSEric Cheng rhandlep->index = index; 5599da14cebeSEric Cheng rhandlep->ring_handle = rh; 5600da14cebeSEric Cheng 5601da14cebeSEric Cheng infop->mri_driver = (mac_ring_driver_t)rhandlep; 5602da14cebeSEric Cheng infop->mri_start = nxge_tx_ring_start; 5603da14cebeSEric Cheng infop->mri_stop = nxge_tx_ring_stop; 5604da14cebeSEric Cheng infop->mri_tx = nxge_tx_ring_send; 5605da14cebeSEric Cheng 5606da14cebeSEric Cheng break; 5607da14cebeSEric Cheng } 5608da14cebeSEric Cheng case MAC_RING_TYPE_RX: { 5609da14cebeSEric Cheng p_nxge_ring_handle_t rhandlep; 5610da14cebeSEric Cheng int nxge_rindex; 5611da14cebeSEric Cheng mac_intr_t nxge_mac_intr; 5612da14cebeSEric Cheng 5613da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, RX_CTL, 5614da14cebeSEric Cheng "==> nxge_fill_ring (RX) 0x%x index %d nrdcs %d", 5615da14cebeSEric Cheng rtype, index, p_cfgp->max_rdcs)); 5616da14cebeSEric Cheng 5617da14cebeSEric Cheng /* 5618da14cebeSEric Cheng * 'index' is the ring index within the group. 5619da14cebeSEric Cheng * Find the ring index in the nxge instance. 5620da14cebeSEric Cheng */ 5621da14cebeSEric Cheng nxge_rindex = nxge_get_rxring_index(nxgep, rg_index, index); 5622da14cebeSEric Cheng 5623da14cebeSEric Cheng ASSERT((nxge_rindex >= 0) && (nxge_rindex < p_cfgp->max_rdcs)); 5624da14cebeSEric Cheng rhandlep = &nxgep->rx_ring_handles[nxge_rindex]; 5625da14cebeSEric Cheng rhandlep->nxgep = nxgep; 5626da14cebeSEric Cheng rhandlep->index = nxge_rindex; 5627da14cebeSEric Cheng rhandlep->ring_handle = rh; 5628da14cebeSEric Cheng 5629da14cebeSEric Cheng /* 5630da14cebeSEric Cheng * Entrypoint to enable interrupt (disable poll) and 5631da14cebeSEric Cheng * disable interrupt (enable poll). 5632da14cebeSEric Cheng */ 5633da14cebeSEric Cheng nxge_mac_intr.mi_handle = (mac_intr_handle_t)rhandlep; 5634da14cebeSEric Cheng nxge_mac_intr.mi_enable = (mac_intr_enable_t)nxge_disable_poll; 5635da14cebeSEric Cheng nxge_mac_intr.mi_disable = (mac_intr_disable_t)nxge_enable_poll; 5636da14cebeSEric Cheng infop->mri_driver = (mac_ring_driver_t)rhandlep; 5637da14cebeSEric Cheng infop->mri_start = nxge_rx_ring_start; 5638da14cebeSEric Cheng infop->mri_stop = nxge_rx_ring_stop; 5639da14cebeSEric Cheng infop->mri_intr = nxge_mac_intr; /* ??? */ 5640da14cebeSEric Cheng infop->mri_poll = nxge_rx_poll; 5641da14cebeSEric Cheng 5642da14cebeSEric Cheng break; 5643da14cebeSEric Cheng } 5644da14cebeSEric Cheng default: 5645da14cebeSEric Cheng break; 5646da14cebeSEric Cheng } 5647da14cebeSEric Cheng 5648da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_fill_ring 0x%x", 5649da14cebeSEric Cheng rtype)); 5650da14cebeSEric Cheng } 5651da14cebeSEric Cheng 5652da14cebeSEric Cheng static void 5653da14cebeSEric Cheng nxge_group_add_ring(mac_group_driver_t gh, mac_ring_driver_t rh, 5654da14cebeSEric Cheng mac_ring_type_t type) 5655da14cebeSEric Cheng { 5656da14cebeSEric Cheng nxge_ring_group_t *rgroup = (nxge_ring_group_t *)gh; 5657da14cebeSEric Cheng nxge_ring_handle_t *rhandle = (nxge_ring_handle_t *)rh; 5658da14cebeSEric Cheng nxge_t *nxge; 5659da14cebeSEric Cheng nxge_grp_t *grp; 5660da14cebeSEric Cheng nxge_rdc_grp_t *rdc_grp; 5661da14cebeSEric Cheng uint16_t channel; /* device-wise ring id */ 5662da14cebeSEric Cheng int dev_gindex; 5663da14cebeSEric Cheng int rv; 5664da14cebeSEric Cheng 5665da14cebeSEric Cheng nxge = rgroup->nxgep; 5666da14cebeSEric Cheng 5667da14cebeSEric Cheng switch (type) { 5668da14cebeSEric Cheng case MAC_RING_TYPE_TX: 5669da14cebeSEric Cheng /* 5670da14cebeSEric Cheng * nxge_grp_dc_add takes a channel number which is a 5671da14cebeSEric Cheng * "devise" ring ID. 5672da14cebeSEric Cheng */ 5673da14cebeSEric Cheng channel = nxge->pt_config.hw_config.tdc.start + rhandle->index; 5674da14cebeSEric Cheng 5675da14cebeSEric Cheng /* 5676da14cebeSEric Cheng * Remove the ring from the default group 5677da14cebeSEric Cheng */ 5678da14cebeSEric Cheng if (rgroup->gindex != 0) { 5679da14cebeSEric Cheng (void) nxge_grp_dc_remove(nxge, VP_BOUND_TX, channel); 5680da14cebeSEric Cheng } 5681da14cebeSEric Cheng 5682da14cebeSEric Cheng /* 5683da14cebeSEric Cheng * nxge->tx_set.group[] is an array of groups indexed by 5684da14cebeSEric Cheng * a "port" group ID. 5685da14cebeSEric Cheng */ 5686da14cebeSEric Cheng grp = nxge->tx_set.group[rgroup->gindex]; 5687da14cebeSEric Cheng rv = nxge_grp_dc_add(nxge, grp, VP_BOUND_TX, channel); 5688da14cebeSEric Cheng if (rv != 0) { 5689da14cebeSEric Cheng NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 5690da14cebeSEric Cheng "nxge_group_add_ring: nxge_grp_dc_add failed")); 5691da14cebeSEric Cheng } 5692da14cebeSEric Cheng break; 5693da14cebeSEric Cheng 5694da14cebeSEric Cheng case MAC_RING_TYPE_RX: 5695da14cebeSEric Cheng /* 5696da14cebeSEric Cheng * nxge->rx_set.group[] is an array of groups indexed by 5697da14cebeSEric Cheng * a "port" group ID. 5698da14cebeSEric Cheng */ 5699da14cebeSEric Cheng grp = nxge->rx_set.group[rgroup->gindex]; 5700da14cebeSEric Cheng 5701da14cebeSEric Cheng dev_gindex = nxge->pt_config.hw_config.def_mac_rxdma_grpid + 5702da14cebeSEric Cheng rgroup->gindex; 5703da14cebeSEric Cheng rdc_grp = &nxge->pt_config.rdc_grps[dev_gindex]; 5704da14cebeSEric Cheng 5705da14cebeSEric Cheng /* 5706da14cebeSEric Cheng * nxge_grp_dc_add takes a channel number which is a 5707da14cebeSEric Cheng * "devise" ring ID. 5708da14cebeSEric Cheng */ 5709da14cebeSEric Cheng channel = nxge->pt_config.hw_config.start_rdc + rhandle->index; 5710da14cebeSEric Cheng rv = nxge_grp_dc_add(nxge, grp, VP_BOUND_RX, channel); 5711da14cebeSEric Cheng if (rv != 0) { 5712da14cebeSEric Cheng NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 5713da14cebeSEric Cheng "nxge_group_add_ring: nxge_grp_dc_add failed")); 5714da14cebeSEric Cheng } 5715da14cebeSEric Cheng 5716da14cebeSEric Cheng rdc_grp->map |= (1 << channel); 5717da14cebeSEric Cheng rdc_grp->max_rdcs++; 5718da14cebeSEric Cheng 57194ba491f5SMichael Speer (void) nxge_init_fzc_rdc_tbl(nxge, rdc_grp, rgroup->rdctbl); 5720da14cebeSEric Cheng break; 5721da14cebeSEric Cheng } 5722da14cebeSEric Cheng } 5723da14cebeSEric Cheng 5724da14cebeSEric Cheng static void 5725da14cebeSEric Cheng nxge_group_rem_ring(mac_group_driver_t gh, mac_ring_driver_t rh, 5726da14cebeSEric Cheng mac_ring_type_t type) 5727da14cebeSEric Cheng { 5728da14cebeSEric Cheng nxge_ring_group_t *rgroup = (nxge_ring_group_t *)gh; 5729da14cebeSEric Cheng nxge_ring_handle_t *rhandle = (nxge_ring_handle_t *)rh; 5730da14cebeSEric Cheng nxge_t *nxge; 5731da14cebeSEric Cheng uint16_t channel; /* device-wise ring id */ 5732da14cebeSEric Cheng nxge_rdc_grp_t *rdc_grp; 5733da14cebeSEric Cheng int dev_gindex; 5734da14cebeSEric Cheng 5735da14cebeSEric Cheng nxge = rgroup->nxgep; 5736da14cebeSEric Cheng 5737da14cebeSEric Cheng switch (type) { 5738da14cebeSEric Cheng case MAC_RING_TYPE_TX: 5739da14cebeSEric Cheng dev_gindex = nxge->pt_config.hw_config.def_mac_txdma_grpid + 5740da14cebeSEric Cheng rgroup->gindex; 5741da14cebeSEric Cheng channel = nxge->pt_config.hw_config.tdc.start + rhandle->index; 5742da14cebeSEric Cheng nxge_grp_dc_remove(nxge, VP_BOUND_TX, channel); 5743da14cebeSEric Cheng 5744da14cebeSEric Cheng /* 5745da14cebeSEric Cheng * Add the ring back to the default group 5746da14cebeSEric Cheng */ 5747da14cebeSEric Cheng if (rgroup->gindex != 0) { 5748da14cebeSEric Cheng nxge_grp_t *grp; 5749da14cebeSEric Cheng grp = nxge->tx_set.group[0]; 5750da14cebeSEric Cheng (void) nxge_grp_dc_add(nxge, grp, VP_BOUND_TX, channel); 5751da14cebeSEric Cheng } 5752da14cebeSEric Cheng break; 5753da14cebeSEric Cheng 5754da14cebeSEric Cheng case MAC_RING_TYPE_RX: 5755da14cebeSEric Cheng dev_gindex = nxge->pt_config.hw_config.def_mac_rxdma_grpid + 5756da14cebeSEric Cheng rgroup->gindex; 5757da14cebeSEric Cheng rdc_grp = &nxge->pt_config.rdc_grps[dev_gindex]; 5758da14cebeSEric Cheng channel = rdc_grp->start_rdc + rhandle->index; 5759da14cebeSEric Cheng nxge_grp_dc_remove(nxge, VP_BOUND_RX, channel); 5760da14cebeSEric Cheng 5761da14cebeSEric Cheng rdc_grp->map &= ~(1 << channel); 5762da14cebeSEric Cheng rdc_grp->max_rdcs--; 5763da14cebeSEric Cheng 57644ba491f5SMichael Speer (void) nxge_init_fzc_rdc_tbl(nxge, rdc_grp, rgroup->rdctbl); 5765da14cebeSEric Cheng break; 5766da14cebeSEric Cheng } 5767da14cebeSEric Cheng } 5768da14cebeSEric Cheng 5769da14cebeSEric Cheng 577044961713Sgirish /*ARGSUSED*/ 577144961713Sgirish static nxge_status_t 577244961713Sgirish nxge_add_intrs(p_nxge_t nxgep) 577344961713Sgirish { 577444961713Sgirish 577544961713Sgirish int intr_types; 577644961713Sgirish int type = 0; 577744961713Sgirish int ddi_status = DDI_SUCCESS; 577844961713Sgirish nxge_status_t status = NXGE_OK; 577944961713Sgirish 578044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs")); 578144961713Sgirish 578244961713Sgirish nxgep->nxge_intr_type.intr_registered = B_FALSE; 578344961713Sgirish nxgep->nxge_intr_type.intr_enabled = B_FALSE; 578444961713Sgirish nxgep->nxge_intr_type.msi_intx_cnt = 0; 578544961713Sgirish nxgep->nxge_intr_type.intr_added = 0; 578644961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_FALSE; 578744961713Sgirish nxgep->nxge_intr_type.intr_type = 0; 578844961713Sgirish 578944961713Sgirish if (nxgep->niu_type == N2_NIU) { 579044961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 579144961713Sgirish } else if (nxge_msi_enable) { 579244961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 579344961713Sgirish } 579444961713Sgirish 579544961713Sgirish /* Get the supported interrupt types */ 579644961713Sgirish if ((ddi_status = ddi_intr_get_supported_types(nxgep->dip, &intr_types)) 57974045d941Ssowmini != DDI_SUCCESS) { 579844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_intrs: " 57994045d941Ssowmini "ddi_intr_get_supported_types failed: status 0x%08x", 58004045d941Ssowmini ddi_status)); 580144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 580244961713Sgirish } 580344961713Sgirish nxgep->nxge_intr_type.intr_types = intr_types; 580444961713Sgirish 580544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 58064045d941Ssowmini "ddi_intr_get_supported_types: 0x%08x", intr_types)); 580744961713Sgirish 580844961713Sgirish /* 580944961713Sgirish * Solaris MSIX is not supported yet. use MSI for now. 581044961713Sgirish * nxge_msi_enable (1): 581144961713Sgirish * 1 - MSI 2 - MSI-X others - FIXED 581244961713Sgirish */ 581344961713Sgirish switch (nxge_msi_enable) { 581444961713Sgirish default: 581544961713Sgirish type = DDI_INTR_TYPE_FIXED; 581644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 58174045d941Ssowmini "use fixed (intx emulation) type %08x", 58184045d941Ssowmini type)); 581944961713Sgirish break; 582044961713Sgirish 582144961713Sgirish case 2: 582244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 58234045d941Ssowmini "ddi_intr_get_supported_types: 0x%08x", intr_types)); 582444961713Sgirish if (intr_types & DDI_INTR_TYPE_MSIX) { 582544961713Sgirish type = DDI_INTR_TYPE_MSIX; 582644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 58274045d941Ssowmini "ddi_intr_get_supported_types: MSIX 0x%08x", 58284045d941Ssowmini type)); 582944961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSI) { 583044961713Sgirish type = DDI_INTR_TYPE_MSI; 583144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 58324045d941Ssowmini "ddi_intr_get_supported_types: MSI 0x%08x", 58334045d941Ssowmini type)); 583444961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 583544961713Sgirish type = DDI_INTR_TYPE_FIXED; 583644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 58374045d941Ssowmini "ddi_intr_get_supported_types: MSXED0x%08x", 58384045d941Ssowmini type)); 583944961713Sgirish } 584044961713Sgirish break; 584144961713Sgirish 584244961713Sgirish case 1: 584344961713Sgirish if (intr_types & DDI_INTR_TYPE_MSI) { 584444961713Sgirish type = DDI_INTR_TYPE_MSI; 584544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 58464045d941Ssowmini "ddi_intr_get_supported_types: MSI 0x%08x", 58474045d941Ssowmini type)); 584844961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSIX) { 584944961713Sgirish type = DDI_INTR_TYPE_MSIX; 585044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 58514045d941Ssowmini "ddi_intr_get_supported_types: MSIX 0x%08x", 58524045d941Ssowmini type)); 585344961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 585444961713Sgirish type = DDI_INTR_TYPE_FIXED; 585544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 58564045d941Ssowmini "ddi_intr_get_supported_types: MSXED0x%08x", 58574045d941Ssowmini type)); 585844961713Sgirish } 585944961713Sgirish } 586044961713Sgirish 586144961713Sgirish nxgep->nxge_intr_type.intr_type = type; 586244961713Sgirish if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI || 58634045d941Ssowmini type == DDI_INTR_TYPE_FIXED) && 58644045d941Ssowmini nxgep->nxge_intr_type.niu_msi_enable) { 586544961713Sgirish if ((status = nxge_add_intrs_adv(nxgep)) != DDI_SUCCESS) { 586644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58674045d941Ssowmini " nxge_add_intrs: " 58684045d941Ssowmini " nxge_add_intrs_adv failed: status 0x%08x", 58694045d941Ssowmini status)); 587044961713Sgirish return (status); 587144961713Sgirish } else { 587244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 58734045d941Ssowmini "interrupts registered : type %d", type)); 587444961713Sgirish nxgep->nxge_intr_type.intr_registered = B_TRUE; 587544961713Sgirish 587644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 58774045d941Ssowmini "\nAdded advanced nxge add_intr_adv " 58784045d941Ssowmini "intr type 0x%x\n", type)); 587944961713Sgirish 588044961713Sgirish return (status); 588144961713Sgirish } 588244961713Sgirish } 588344961713Sgirish 588444961713Sgirish if (!nxgep->nxge_intr_type.intr_registered) { 588544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_add_intrs: " 58864045d941Ssowmini "failed to register interrupts")); 588744961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 588844961713Sgirish } 588944961713Sgirish 589044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_add_intrs")); 589144961713Sgirish return (status); 589244961713Sgirish } 589344961713Sgirish 589444961713Sgirish static nxge_status_t 589544961713Sgirish nxge_add_intrs_adv(p_nxge_t nxgep) 589644961713Sgirish { 589744961713Sgirish int intr_type; 589844961713Sgirish p_nxge_intr_t intrp; 589944961713Sgirish 590044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv")); 590144961713Sgirish 590244961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 590344961713Sgirish intr_type = intrp->intr_type; 590444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv: type 0x%x", 59054045d941Ssowmini intr_type)); 590644961713Sgirish 590744961713Sgirish switch (intr_type) { 590844961713Sgirish case DDI_INTR_TYPE_MSI: /* 0x2 */ 590944961713Sgirish case DDI_INTR_TYPE_MSIX: /* 0x4 */ 591044961713Sgirish return (nxge_add_intrs_adv_type(nxgep, intr_type)); 591144961713Sgirish 591244961713Sgirish case DDI_INTR_TYPE_FIXED: /* 0x1 */ 591344961713Sgirish return (nxge_add_intrs_adv_type_fix(nxgep, intr_type)); 591444961713Sgirish 591544961713Sgirish default: 591644961713Sgirish return (NXGE_ERROR); 591744961713Sgirish } 591844961713Sgirish } 591944961713Sgirish 592044961713Sgirish 592144961713Sgirish /*ARGSUSED*/ 592244961713Sgirish static nxge_status_t 592344961713Sgirish nxge_add_intrs_adv_type(p_nxge_t nxgep, uint32_t int_type) 592444961713Sgirish { 592544961713Sgirish dev_info_t *dip = nxgep->dip; 592644961713Sgirish p_nxge_ldg_t ldgp; 592744961713Sgirish p_nxge_intr_t intrp; 592844961713Sgirish uint_t *inthandler; 592944961713Sgirish void *arg1, *arg2; 593044961713Sgirish int behavior; 5931ec090658Sml int nintrs, navail, nrequest; 593244961713Sgirish int nactual, nrequired; 593344961713Sgirish int inum = 0; 593444961713Sgirish int x, y; 593544961713Sgirish int ddi_status = DDI_SUCCESS; 593644961713Sgirish nxge_status_t status = NXGE_OK; 593744961713Sgirish 593844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type")); 593944961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 594044961713Sgirish intrp->start_inum = 0; 594144961713Sgirish 594244961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 594344961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 594444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59454045d941Ssowmini "ddi_intr_get_nintrs() failed, status: 0x%x%, " 59464045d941Ssowmini "nintrs: %d", ddi_status, nintrs)); 594744961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 594844961713Sgirish } 594944961713Sgirish 595044961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 595144961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 595244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59534045d941Ssowmini "ddi_intr_get_navail() failed, status: 0x%x%, " 59544045d941Ssowmini "nintrs: %d", ddi_status, navail)); 595544961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 595644961713Sgirish } 595744961713Sgirish 595844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 59594045d941Ssowmini "ddi_intr_get_navail() returned: nintrs %d, navail %d", 59604045d941Ssowmini nintrs, navail)); 596144961713Sgirish 5962ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override */ 5963ec090658Sml if (int_type == DDI_INTR_TYPE_MSIX) { 5964ec090658Sml nrequest = nxge_create_msi_property(nxgep); 5965ec090658Sml if (nrequest < navail) { 5966ec090658Sml navail = nrequest; 5967ec090658Sml NXGE_DEBUG_MSG((nxgep, INT_CTL, 5968ec090658Sml "nxge_add_intrs_adv_type: nintrs %d " 5969ec090658Sml "navail %d (nrequest %d)", 5970ec090658Sml nintrs, navail, nrequest)); 5971ec090658Sml } 5972ec090658Sml } 5973ec090658Sml 597444961713Sgirish if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) { 597544961713Sgirish /* MSI must be power of 2 */ 597644961713Sgirish if ((navail & 16) == 16) { 597744961713Sgirish navail = 16; 597844961713Sgirish } else if ((navail & 8) == 8) { 597944961713Sgirish navail = 8; 598044961713Sgirish } else if ((navail & 4) == 4) { 598144961713Sgirish navail = 4; 598244961713Sgirish } else if ((navail & 2) == 2) { 598344961713Sgirish navail = 2; 598444961713Sgirish } else { 598544961713Sgirish navail = 1; 598644961713Sgirish } 598744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 59884045d941Ssowmini "ddi_intr_get_navail(): (msi power of 2) nintrs %d, " 59894045d941Ssowmini "navail %d", nintrs, navail)); 599044961713Sgirish } 599144961713Sgirish 599244961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 59934045d941Ssowmini DDI_INTR_ALLOC_NORMAL); 599444961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 599544961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 599644961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 59974045d941Ssowmini navail, &nactual, behavior); 599844961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 599944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60004045d941Ssowmini " ddi_intr_alloc() failed: %d", 60014045d941Ssowmini ddi_status)); 600244961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 600344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 600444961713Sgirish } 600544961713Sgirish 600644961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 60074045d941Ssowmini (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 600844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60094045d941Ssowmini " ddi_intr_get_pri() failed: %d", 60104045d941Ssowmini ddi_status)); 601144961713Sgirish /* Free already allocated interrupts */ 601244961713Sgirish for (y = 0; y < nactual; y++) { 601344961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 601444961713Sgirish } 601544961713Sgirish 601644961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 601744961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 601844961713Sgirish } 601944961713Sgirish 602044961713Sgirish nrequired = 0; 602144961713Sgirish switch (nxgep->niu_type) { 602244961713Sgirish default: 602344961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 602444961713Sgirish break; 602544961713Sgirish 602644961713Sgirish case N2_NIU: 602744961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 602844961713Sgirish break; 602944961713Sgirish } 603044961713Sgirish 603144961713Sgirish if (status != NXGE_OK) { 603244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60334045d941Ssowmini "nxge_add_intrs_adv_typ:nxge_ldgv_init " 60344045d941Ssowmini "failed: 0x%x", status)); 603544961713Sgirish /* Free already allocated interrupts */ 603644961713Sgirish for (y = 0; y < nactual; y++) { 603744961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 603844961713Sgirish } 603944961713Sgirish 604044961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 604144961713Sgirish return (status); 604244961713Sgirish } 604344961713Sgirish 604444961713Sgirish ldgp = nxgep->ldgvp->ldgp; 604544961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 604644961713Sgirish ldgp->vector = (uint8_t)x; 604744961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 604844961713Sgirish arg1 = ldgp->ldvp; 604944961713Sgirish arg2 = nxgep; 605044961713Sgirish if (ldgp->nldvs == 1) { 605144961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 605244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 60534045d941Ssowmini "nxge_add_intrs_adv_type: " 60544045d941Ssowmini "arg1 0x%x arg2 0x%x: " 60554045d941Ssowmini "1-1 int handler (entry %d intdata 0x%x)\n", 60564045d941Ssowmini arg1, arg2, 60574045d941Ssowmini x, ldgp->intdata)); 605844961713Sgirish } else if (ldgp->nldvs > 1) { 605944961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 606044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 60614045d941Ssowmini "nxge_add_intrs_adv_type: " 60624045d941Ssowmini "arg1 0x%x arg2 0x%x: " 60634045d941Ssowmini "nldevs %d int handler " 60644045d941Ssowmini "(entry %d intdata 0x%x)\n", 60654045d941Ssowmini arg1, arg2, 60664045d941Ssowmini ldgp->nldvs, x, ldgp->intdata)); 606744961713Sgirish } 606844961713Sgirish 606944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 60704045d941Ssowmini "==> nxge_add_intrs_adv_type: ddi_add_intr(inum) #%d " 60714045d941Ssowmini "htable 0x%llx", x, intrp->htable[x])); 607244961713Sgirish 607344961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 60744045d941Ssowmini (ddi_intr_handler_t *)inthandler, arg1, arg2)) 60754045d941Ssowmini != DDI_SUCCESS) { 607644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60774045d941Ssowmini "==> nxge_add_intrs_adv_type: failed #%d " 60784045d941Ssowmini "status 0x%x", x, ddi_status)); 607944961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 608044961713Sgirish (void) ddi_intr_remove_handler( 60814045d941Ssowmini intrp->htable[y]); 608244961713Sgirish } 608344961713Sgirish /* Free already allocated intr */ 608444961713Sgirish for (y = 0; y < nactual; y++) { 608544961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 608644961713Sgirish } 608744961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 608844961713Sgirish 608944961713Sgirish (void) nxge_ldgv_uninit(nxgep); 609044961713Sgirish 609144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 609244961713Sgirish } 609344961713Sgirish intrp->intr_added++; 609444961713Sgirish } 609544961713Sgirish 609644961713Sgirish intrp->msi_intx_cnt = nactual; 609744961713Sgirish 609844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 60994045d941Ssowmini "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d", 61004045d941Ssowmini navail, nactual, 61014045d941Ssowmini intrp->msi_intx_cnt, 61024045d941Ssowmini intrp->intr_added)); 610344961713Sgirish 610444961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 610544961713Sgirish 610644961713Sgirish (void) nxge_intr_ldgv_init(nxgep); 610744961713Sgirish 610844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type")); 610944961713Sgirish 611044961713Sgirish return (status); 611144961713Sgirish } 611244961713Sgirish 611344961713Sgirish /*ARGSUSED*/ 611444961713Sgirish static nxge_status_t 611544961713Sgirish nxge_add_intrs_adv_type_fix(p_nxge_t nxgep, uint32_t int_type) 611644961713Sgirish { 611744961713Sgirish dev_info_t *dip = nxgep->dip; 611844961713Sgirish p_nxge_ldg_t ldgp; 611944961713Sgirish p_nxge_intr_t intrp; 612044961713Sgirish uint_t *inthandler; 612144961713Sgirish void *arg1, *arg2; 612244961713Sgirish int behavior; 612344961713Sgirish int nintrs, navail; 612444961713Sgirish int nactual, nrequired; 612544961713Sgirish int inum = 0; 612644961713Sgirish int x, y; 612744961713Sgirish int ddi_status = DDI_SUCCESS; 612844961713Sgirish nxge_status_t status = NXGE_OK; 612944961713Sgirish 613044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type_fix")); 613144961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 613244961713Sgirish intrp->start_inum = 0; 613344961713Sgirish 613444961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 613544961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 613644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 61374045d941Ssowmini "ddi_intr_get_nintrs() failed, status: 0x%x%, " 61384045d941Ssowmini "nintrs: %d", status, nintrs)); 613944961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 614044961713Sgirish } 614144961713Sgirish 614244961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 614344961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 614444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61454045d941Ssowmini "ddi_intr_get_navail() failed, status: 0x%x%, " 61464045d941Ssowmini "nintrs: %d", ddi_status, navail)); 614744961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 614844961713Sgirish } 614944961713Sgirish 615044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 61514045d941Ssowmini "ddi_intr_get_navail() returned: nintrs %d, naavail %d", 61524045d941Ssowmini nintrs, navail)); 615344961713Sgirish 615444961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 61554045d941Ssowmini DDI_INTR_ALLOC_NORMAL); 615644961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 615744961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 615844961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 61594045d941Ssowmini navail, &nactual, behavior); 616044961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 616144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61624045d941Ssowmini " ddi_intr_alloc() failed: %d", 61634045d941Ssowmini ddi_status)); 616444961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 616544961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 616644961713Sgirish } 616744961713Sgirish 616844961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 61694045d941Ssowmini (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 617044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61714045d941Ssowmini " ddi_intr_get_pri() failed: %d", 61724045d941Ssowmini ddi_status)); 617344961713Sgirish /* Free already allocated interrupts */ 617444961713Sgirish for (y = 0; y < nactual; y++) { 617544961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 617644961713Sgirish } 617744961713Sgirish 617844961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 617944961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 618044961713Sgirish } 618144961713Sgirish 618244961713Sgirish nrequired = 0; 618344961713Sgirish switch (nxgep->niu_type) { 618444961713Sgirish default: 618544961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 618644961713Sgirish break; 618744961713Sgirish 618844961713Sgirish case N2_NIU: 618944961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 619044961713Sgirish break; 619144961713Sgirish } 619244961713Sgirish 619344961713Sgirish if (status != NXGE_OK) { 619444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61954045d941Ssowmini "nxge_add_intrs_adv_type_fix:nxge_ldgv_init " 61964045d941Ssowmini "failed: 0x%x", status)); 619744961713Sgirish /* Free already allocated interrupts */ 619844961713Sgirish for (y = 0; y < nactual; y++) { 619944961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 620044961713Sgirish } 620144961713Sgirish 620244961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 620344961713Sgirish return (status); 620444961713Sgirish } 620544961713Sgirish 620644961713Sgirish ldgp = nxgep->ldgvp->ldgp; 620744961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 620844961713Sgirish ldgp->vector = (uint8_t)x; 620944961713Sgirish if (nxgep->niu_type != N2_NIU) { 621044961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 621144961713Sgirish } 621244961713Sgirish 621344961713Sgirish arg1 = ldgp->ldvp; 621444961713Sgirish arg2 = nxgep; 621544961713Sgirish if (ldgp->nldvs == 1) { 621644961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 621744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 62184045d941Ssowmini "nxge_add_intrs_adv_type_fix: " 62194045d941Ssowmini "1-1 int handler(%d) ldg %d ldv %d " 62204045d941Ssowmini "arg1 $%p arg2 $%p\n", 62214045d941Ssowmini x, ldgp->ldg, ldgp->ldvp->ldv, 62224045d941Ssowmini arg1, arg2)); 622344961713Sgirish } else if (ldgp->nldvs > 1) { 622444961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 622544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 62264045d941Ssowmini "nxge_add_intrs_adv_type_fix: " 62274045d941Ssowmini "shared ldv %d int handler(%d) ldv %d ldg %d" 62284045d941Ssowmini "arg1 0x%016llx arg2 0x%016llx\n", 62294045d941Ssowmini x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv, 62304045d941Ssowmini arg1, arg2)); 623144961713Sgirish } 623244961713Sgirish 623344961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 62344045d941Ssowmini (ddi_intr_handler_t *)inthandler, arg1, arg2)) 62354045d941Ssowmini != DDI_SUCCESS) { 623644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 62374045d941Ssowmini "==> nxge_add_intrs_adv_type_fix: failed #%d " 62384045d941Ssowmini "status 0x%x", x, ddi_status)); 623944961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 624044961713Sgirish (void) ddi_intr_remove_handler( 62414045d941Ssowmini intrp->htable[y]); 624244961713Sgirish } 624344961713Sgirish for (y = 0; y < nactual; y++) { 624444961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 624544961713Sgirish } 624644961713Sgirish /* Free already allocated intr */ 624744961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 624844961713Sgirish 624944961713Sgirish (void) nxge_ldgv_uninit(nxgep); 625044961713Sgirish 625144961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 625244961713Sgirish } 625344961713Sgirish intrp->intr_added++; 625444961713Sgirish } 625544961713Sgirish 625644961713Sgirish intrp->msi_intx_cnt = nactual; 625744961713Sgirish 625844961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 625944961713Sgirish 626044961713Sgirish status = nxge_intr_ldgv_init(nxgep); 626144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type_fix")); 626244961713Sgirish 626344961713Sgirish return (status); 626444961713Sgirish } 626544961713Sgirish 626644961713Sgirish static void 626744961713Sgirish nxge_remove_intrs(p_nxge_t nxgep) 626844961713Sgirish { 626944961713Sgirish int i, inum; 627044961713Sgirish p_nxge_intr_t intrp; 627144961713Sgirish 627244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs")); 627344961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 627444961713Sgirish if (!intrp->intr_registered) { 627544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 62764045d941Ssowmini "<== nxge_remove_intrs: interrupts not registered")); 627744961713Sgirish return; 627844961713Sgirish } 627944961713Sgirish 628044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs:advanced")); 628144961713Sgirish 628244961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 628344961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 62844045d941Ssowmini intrp->intr_added); 628544961713Sgirish } else { 628644961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 628744961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 628844961713Sgirish } 628944961713Sgirish } 629044961713Sgirish 629144961713Sgirish for (inum = 0; inum < intrp->intr_added; inum++) { 629244961713Sgirish if (intrp->htable[inum]) { 629344961713Sgirish (void) ddi_intr_remove_handler(intrp->htable[inum]); 629444961713Sgirish } 629544961713Sgirish } 629644961713Sgirish 629744961713Sgirish for (inum = 0; inum < intrp->msi_intx_cnt; inum++) { 629844961713Sgirish if (intrp->htable[inum]) { 629944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 63004045d941Ssowmini "nxge_remove_intrs: ddi_intr_free inum %d " 63014045d941Ssowmini "msi_intx_cnt %d intr_added %d", 63024045d941Ssowmini inum, 63034045d941Ssowmini intrp->msi_intx_cnt, 63044045d941Ssowmini intrp->intr_added)); 630544961713Sgirish 630644961713Sgirish (void) ddi_intr_free(intrp->htable[inum]); 630744961713Sgirish } 630844961713Sgirish } 630944961713Sgirish 631044961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 631144961713Sgirish intrp->intr_registered = B_FALSE; 631244961713Sgirish intrp->intr_enabled = B_FALSE; 631344961713Sgirish intrp->msi_intx_cnt = 0; 631444961713Sgirish intrp->intr_added = 0; 631544961713Sgirish 6316a3c5bd6dSspeer (void) nxge_ldgv_uninit(nxgep); 6317a3c5bd6dSspeer 6318ec090658Sml (void) ddi_prop_remove(DDI_DEV_T_NONE, nxgep->dip, 6319ec090658Sml "#msix-request"); 6320ec090658Sml 632144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_intrs")); 632244961713Sgirish } 632344961713Sgirish 632444961713Sgirish /*ARGSUSED*/ 632544961713Sgirish static void 632644961713Sgirish nxge_intrs_enable(p_nxge_t nxgep) 632744961713Sgirish { 632844961713Sgirish p_nxge_intr_t intrp; 632944961713Sgirish int i; 633044961713Sgirish int status; 633144961713Sgirish 633244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable")); 633344961713Sgirish 633444961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 633544961713Sgirish 633644961713Sgirish if (!intrp->intr_registered) { 633744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_intrs_enable: " 63384045d941Ssowmini "interrupts are not registered")); 633944961713Sgirish return; 634044961713Sgirish } 634144961713Sgirish 634244961713Sgirish if (intrp->intr_enabled) { 634344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 63444045d941Ssowmini "<== nxge_intrs_enable: already enabled")); 634544961713Sgirish return; 634644961713Sgirish } 634744961713Sgirish 634844961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 634944961713Sgirish status = ddi_intr_block_enable(intrp->htable, 63504045d941Ssowmini intrp->intr_added); 635144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 63524045d941Ssowmini "block enable - status 0x%x total inums #%d\n", 63534045d941Ssowmini status, intrp->intr_added)); 635444961713Sgirish } else { 635544961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 635644961713Sgirish status = ddi_intr_enable(intrp->htable[i]); 635744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 63584045d941Ssowmini "ddi_intr_enable:enable - status 0x%x " 63594045d941Ssowmini "total inums %d enable inum #%d\n", 63604045d941Ssowmini status, intrp->intr_added, i)); 636144961713Sgirish if (status == DDI_SUCCESS) { 636244961713Sgirish intrp->intr_enabled = B_TRUE; 636344961713Sgirish } 636444961713Sgirish } 636544961713Sgirish } 636644961713Sgirish 636744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_enable")); 636844961713Sgirish } 636944961713Sgirish 637044961713Sgirish /*ARGSUSED*/ 637144961713Sgirish static void 637244961713Sgirish nxge_intrs_disable(p_nxge_t nxgep) 637344961713Sgirish { 637444961713Sgirish p_nxge_intr_t intrp; 637544961713Sgirish int i; 637644961713Sgirish 637744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_disable")); 637844961713Sgirish 637944961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 638044961713Sgirish 638144961713Sgirish if (!intrp->intr_registered) { 638244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable: " 63834045d941Ssowmini "interrupts are not registered")); 638444961713Sgirish return; 638544961713Sgirish } 638644961713Sgirish 638744961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 638844961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 63894045d941Ssowmini intrp->intr_added); 639044961713Sgirish } else { 639144961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 639244961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 639344961713Sgirish } 639444961713Sgirish } 639544961713Sgirish 639644961713Sgirish intrp->intr_enabled = B_FALSE; 639744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable")); 639844961713Sgirish } 639944961713Sgirish 6400*63f531d1SSriharsha Basavapatna nxge_status_t 640144961713Sgirish nxge_mac_register(p_nxge_t nxgep) 640244961713Sgirish { 640344961713Sgirish mac_register_t *macp; 640444961713Sgirish int status; 640544961713Sgirish 640644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_mac_register")); 640744961713Sgirish 640844961713Sgirish if ((macp = mac_alloc(MAC_VERSION)) == NULL) 640944961713Sgirish return (NXGE_ERROR); 641044961713Sgirish 641144961713Sgirish macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 641244961713Sgirish macp->m_driver = nxgep; 641344961713Sgirish macp->m_dip = nxgep->dip; 6414*63f531d1SSriharsha Basavapatna if (!isLDOMguest(nxgep)) { 6415*63f531d1SSriharsha Basavapatna macp->m_src_addr = nxgep->ouraddr.ether_addr_octet; 6416*63f531d1SSriharsha Basavapatna } else { 6417*63f531d1SSriharsha Basavapatna macp->m_src_addr = KMEM_ZALLOC(MAXMACADDRLEN, KM_SLEEP); 6418*63f531d1SSriharsha Basavapatna macp->m_dst_addr = KMEM_ZALLOC(MAXMACADDRLEN, KM_SLEEP); 6419*63f531d1SSriharsha Basavapatna (void) memset(macp->m_src_addr, 0xff, sizeof (MAXMACADDRLEN)); 6420*63f531d1SSriharsha Basavapatna } 642144961713Sgirish macp->m_callbacks = &nxge_m_callbacks; 642244961713Sgirish macp->m_min_sdu = 0; 64231bd6825cSml nxgep->mac.default_mtu = nxgep->mac.maxframesize - 64241bd6825cSml NXGE_EHEADER_VLAN_CRC; 64251bd6825cSml macp->m_max_sdu = nxgep->mac.default_mtu; 6426d62bc4baSyz macp->m_margin = VLAN_TAGSZ; 64274045d941Ssowmini macp->m_priv_props = nxge_priv_props; 64284045d941Ssowmini macp->m_priv_prop_count = NXGE_MAX_PRIV_PROPS; 6429*63f531d1SSriharsha Basavapatna if (isLDOMguest(nxgep)) { 6430*63f531d1SSriharsha Basavapatna macp->m_v12n = MAC_VIRT_LEVEL1 | MAC_VIRT_SERIALIZE; 6431*63f531d1SSriharsha Basavapatna } else { 6432*63f531d1SSriharsha Basavapatna macp->m_v12n = MAC_VIRT_HIO | MAC_VIRT_LEVEL1 | \ 6433*63f531d1SSriharsha Basavapatna MAC_VIRT_SERIALIZE; 6434*63f531d1SSriharsha Basavapatna } 643544961713Sgirish 64361bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 64371bd6825cSml "==> nxge_mac_register: instance %d " 64381bd6825cSml "max_sdu %d margin %d maxframe %d (header %d)", 64391bd6825cSml nxgep->instance, 64401bd6825cSml macp->m_max_sdu, macp->m_margin, 64411bd6825cSml nxgep->mac.maxframesize, 64421bd6825cSml NXGE_EHEADER_VLAN_CRC)); 64431bd6825cSml 644444961713Sgirish status = mac_register(macp, &nxgep->mach); 6445*63f531d1SSriharsha Basavapatna if (isLDOMguest(nxgep)) { 6446*63f531d1SSriharsha Basavapatna KMEM_FREE(macp->m_src_addr, MAXMACADDRLEN); 6447*63f531d1SSriharsha Basavapatna KMEM_FREE(macp->m_dst_addr, MAXMACADDRLEN); 6448*63f531d1SSriharsha Basavapatna } 644944961713Sgirish mac_free(macp); 645044961713Sgirish 645144961713Sgirish if (status != 0) { 645244961713Sgirish cmn_err(CE_WARN, 64534045d941Ssowmini "!nxge_mac_register failed (status %d instance %d)", 64544045d941Ssowmini status, nxgep->instance); 645544961713Sgirish return (NXGE_ERROR); 645644961713Sgirish } 645744961713Sgirish 645844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_mac_register success " 64594045d941Ssowmini "(instance %d)", nxgep->instance)); 646044961713Sgirish 646144961713Sgirish return (NXGE_OK); 646244961713Sgirish } 646344961713Sgirish 646444961713Sgirish void 646544961713Sgirish nxge_err_inject(p_nxge_t nxgep, queue_t *wq, mblk_t *mp) 646644961713Sgirish { 646744961713Sgirish ssize_t size; 646844961713Sgirish mblk_t *nmp; 646944961713Sgirish uint8_t blk_id; 647044961713Sgirish uint8_t chan; 647144961713Sgirish uint32_t err_id; 647244961713Sgirish err_inject_t *eip; 647344961713Sgirish 647444961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_err_inject")); 647544961713Sgirish 647644961713Sgirish size = 1024; 647744961713Sgirish nmp = mp->b_cont; 647844961713Sgirish eip = (err_inject_t *)nmp->b_rptr; 647944961713Sgirish blk_id = eip->blk_id; 648044961713Sgirish err_id = eip->err_id; 648144961713Sgirish chan = eip->chan; 648244961713Sgirish cmn_err(CE_NOTE, "!blk_id = 0x%x\n", blk_id); 648344961713Sgirish cmn_err(CE_NOTE, "!err_id = 0x%x\n", err_id); 648444961713Sgirish cmn_err(CE_NOTE, "!chan = 0x%x\n", chan); 648544961713Sgirish switch (blk_id) { 648644961713Sgirish case MAC_BLK_ID: 648744961713Sgirish break; 648844961713Sgirish case TXMAC_BLK_ID: 648944961713Sgirish break; 649044961713Sgirish case RXMAC_BLK_ID: 649144961713Sgirish break; 649244961713Sgirish case MIF_BLK_ID: 649344961713Sgirish break; 649444961713Sgirish case IPP_BLK_ID: 649544961713Sgirish nxge_ipp_inject_err(nxgep, err_id); 649644961713Sgirish break; 649744961713Sgirish case TXC_BLK_ID: 649844961713Sgirish nxge_txc_inject_err(nxgep, err_id); 649944961713Sgirish break; 650044961713Sgirish case TXDMA_BLK_ID: 650144961713Sgirish nxge_txdma_inject_err(nxgep, err_id, chan); 650244961713Sgirish break; 650344961713Sgirish case RXDMA_BLK_ID: 650444961713Sgirish nxge_rxdma_inject_err(nxgep, err_id, chan); 650544961713Sgirish break; 650644961713Sgirish case ZCP_BLK_ID: 650744961713Sgirish nxge_zcp_inject_err(nxgep, err_id); 650844961713Sgirish break; 650944961713Sgirish case ESPC_BLK_ID: 651044961713Sgirish break; 651144961713Sgirish case FFLP_BLK_ID: 651244961713Sgirish break; 651344961713Sgirish case PHY_BLK_ID: 651444961713Sgirish break; 651544961713Sgirish case ETHER_SERDES_BLK_ID: 651644961713Sgirish break; 651744961713Sgirish case PCIE_SERDES_BLK_ID: 651844961713Sgirish break; 651944961713Sgirish case VIR_BLK_ID: 652044961713Sgirish break; 652144961713Sgirish } 652244961713Sgirish 652344961713Sgirish nmp->b_wptr = nmp->b_rptr + size; 652444961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_err_inject")); 652544961713Sgirish 652644961713Sgirish miocack(wq, mp, (int)size, 0); 652744961713Sgirish } 652844961713Sgirish 652944961713Sgirish static int 653044961713Sgirish nxge_init_common_dev(p_nxge_t nxgep) 653144961713Sgirish { 653244961713Sgirish p_nxge_hw_list_t hw_p; 653344961713Sgirish dev_info_t *p_dip; 653444961713Sgirish 653544961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_init_common_device")); 653644961713Sgirish 653744961713Sgirish p_dip = nxgep->p_dip; 653844961713Sgirish MUTEX_ENTER(&nxge_common_lock); 653944961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65404045d941Ssowmini "==> nxge_init_common_dev:func # %d", 65414045d941Ssowmini nxgep->function_num)); 654244961713Sgirish /* 654344961713Sgirish * Loop through existing per neptune hardware list. 654444961713Sgirish */ 654544961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 654644961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65474045d941Ssowmini "==> nxge_init_common_device:func # %d " 65484045d941Ssowmini "hw_p $%p parent dip $%p", 65494045d941Ssowmini nxgep->function_num, 65504045d941Ssowmini hw_p, 65514045d941Ssowmini p_dip)); 655244961713Sgirish if (hw_p->parent_devp == p_dip) { 655344961713Sgirish nxgep->nxge_hw_p = hw_p; 655444961713Sgirish hw_p->ndevs++; 655544961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 655644961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65574045d941Ssowmini "==> nxge_init_common_device:func # %d " 65584045d941Ssowmini "hw_p $%p parent dip $%p " 65594045d941Ssowmini "ndevs %d (found)", 65604045d941Ssowmini nxgep->function_num, 65614045d941Ssowmini hw_p, 65624045d941Ssowmini p_dip, 65634045d941Ssowmini hw_p->ndevs)); 656444961713Sgirish break; 656544961713Sgirish } 656644961713Sgirish } 656744961713Sgirish 656844961713Sgirish if (hw_p == NULL) { 656923b952a3SSantwona Behera 657023b952a3SSantwona Behera char **prop_val; 657123b952a3SSantwona Behera uint_t prop_len; 657223b952a3SSantwona Behera int i; 657323b952a3SSantwona Behera 657444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 65754045d941Ssowmini "==> nxge_init_common_device:func # %d " 65764045d941Ssowmini "parent dip $%p (new)", 65774045d941Ssowmini nxgep->function_num, 65784045d941Ssowmini p_dip)); 657944961713Sgirish hw_p = kmem_zalloc(sizeof (nxge_hw_list_t), KM_SLEEP); 658044961713Sgirish hw_p->parent_devp = p_dip; 658144961713Sgirish hw_p->magic = NXGE_NEPTUNE_MAGIC; 658244961713Sgirish nxgep->nxge_hw_p = hw_p; 658344961713Sgirish hw_p->ndevs++; 658444961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 658544961713Sgirish hw_p->next = nxge_hw_list; 658659ac0c16Sdavemq if (nxgep->niu_type == N2_NIU) { 658759ac0c16Sdavemq hw_p->niu_type = N2_NIU; 658859ac0c16Sdavemq hw_p->platform_type = P_NEPTUNE_NIU; 658959ac0c16Sdavemq } else { 659059ac0c16Sdavemq hw_p->niu_type = NIU_TYPE_NONE; 65912e59129aSraghus hw_p->platform_type = P_NEPTUNE_NONE; 659259ac0c16Sdavemq } 659344961713Sgirish 659444961713Sgirish MUTEX_INIT(&hw_p->nxge_cfg_lock, NULL, MUTEX_DRIVER, NULL); 659544961713Sgirish MUTEX_INIT(&hw_p->nxge_tcam_lock, NULL, MUTEX_DRIVER, NULL); 659644961713Sgirish MUTEX_INIT(&hw_p->nxge_vlan_lock, NULL, MUTEX_DRIVER, NULL); 659744961713Sgirish MUTEX_INIT(&hw_p->nxge_mdio_lock, NULL, MUTEX_DRIVER, NULL); 659844961713Sgirish 659944961713Sgirish nxge_hw_list = hw_p; 660059ac0c16Sdavemq 660123b952a3SSantwona Behera if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, nxgep->dip, 0, 660223b952a3SSantwona Behera "compatible", &prop_val, &prop_len) == DDI_PROP_SUCCESS) { 660323b952a3SSantwona Behera for (i = 0; i < prop_len; i++) { 660423b952a3SSantwona Behera if ((strcmp((caddr_t)prop_val[i], 660523b952a3SSantwona Behera NXGE_ROCK_COMPATIBLE) == 0)) { 660623b952a3SSantwona Behera hw_p->platform_type = P_NEPTUNE_ROCK; 660723b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MOD_CTL, 660823b952a3SSantwona Behera "ROCK hw_p->platform_type %d", 660923b952a3SSantwona Behera hw_p->platform_type)); 661023b952a3SSantwona Behera break; 661123b952a3SSantwona Behera } 661223b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MOD_CTL, 661323b952a3SSantwona Behera "nxge_init_common_dev: read compatible" 661423b952a3SSantwona Behera " property[%d] val[%s]", 661523b952a3SSantwona Behera i, (caddr_t)prop_val[i])); 661623b952a3SSantwona Behera } 661723b952a3SSantwona Behera } 661823b952a3SSantwona Behera 661923b952a3SSantwona Behera ddi_prop_free(prop_val); 662023b952a3SSantwona Behera 662159ac0c16Sdavemq (void) nxge_scan_ports_phy(nxgep, nxge_hw_list); 662244961713Sgirish } 662344961713Sgirish 662444961713Sgirish MUTEX_EXIT(&nxge_common_lock); 662559ac0c16Sdavemq 66262e59129aSraghus nxgep->platform_type = hw_p->platform_type; 662723b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MOD_CTL, "nxgep->platform_type %d", 662823b952a3SSantwona Behera nxgep->platform_type)); 662959ac0c16Sdavemq if (nxgep->niu_type != N2_NIU) { 663059ac0c16Sdavemq nxgep->niu_type = hw_p->niu_type; 663159ac0c16Sdavemq } 663259ac0c16Sdavemq 663344961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66344045d941Ssowmini "==> nxge_init_common_device (nxge_hw_list) $%p", 66354045d941Ssowmini nxge_hw_list)); 663644961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<== nxge_init_common_device")); 663744961713Sgirish 663844961713Sgirish return (NXGE_OK); 663944961713Sgirish } 664044961713Sgirish 664144961713Sgirish static void 664244961713Sgirish nxge_uninit_common_dev(p_nxge_t nxgep) 664344961713Sgirish { 664444961713Sgirish p_nxge_hw_list_t hw_p, h_hw_p; 66450b0beae0Sspeer p_nxge_dma_pt_cfg_t p_dma_cfgp; 66460b0beae0Sspeer p_nxge_hw_pt_cfg_t p_cfgp; 664744961713Sgirish dev_info_t *p_dip; 664844961713Sgirish 664944961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_uninit_common_device")); 665044961713Sgirish if (nxgep->nxge_hw_p == NULL) { 665144961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66524045d941Ssowmini "<== nxge_uninit_common_device (no common)")); 665344961713Sgirish return; 665444961713Sgirish } 665544961713Sgirish 665644961713Sgirish MUTEX_ENTER(&nxge_common_lock); 665744961713Sgirish h_hw_p = nxge_hw_list; 665844961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 665944961713Sgirish p_dip = hw_p->parent_devp; 666044961713Sgirish if (nxgep->nxge_hw_p == hw_p && 66614045d941Ssowmini p_dip == nxgep->p_dip && 66624045d941Ssowmini nxgep->nxge_hw_p->magic == NXGE_NEPTUNE_MAGIC && 66634045d941Ssowmini hw_p->magic == NXGE_NEPTUNE_MAGIC) { 666444961713Sgirish 666544961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66664045d941Ssowmini "==> nxge_uninit_common_device:func # %d " 66674045d941Ssowmini "hw_p $%p parent dip $%p " 66684045d941Ssowmini "ndevs %d (found)", 66694045d941Ssowmini nxgep->function_num, 66704045d941Ssowmini hw_p, 66714045d941Ssowmini p_dip, 66724045d941Ssowmini hw_p->ndevs)); 667344961713Sgirish 66740b0beae0Sspeer /* 66750b0beae0Sspeer * Release the RDC table, a shared resoruce 66760b0beae0Sspeer * of the nxge hardware. The RDC table was 66770b0beae0Sspeer * assigned to this instance of nxge in 66780b0beae0Sspeer * nxge_use_cfg_dma_config(). 66790b0beae0Sspeer */ 66809d5b8bc5SMichael Speer if (!isLDOMguest(nxgep)) { 66819d5b8bc5SMichael Speer p_dma_cfgp = 66829d5b8bc5SMichael Speer (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 66839d5b8bc5SMichael Speer p_cfgp = 66849d5b8bc5SMichael Speer (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; 66859d5b8bc5SMichael Speer (void) nxge_fzc_rdc_tbl_unbind(nxgep, 66869d5b8bc5SMichael Speer p_cfgp->def_mac_rxdma_grpid); 6687651ce697SMichael Speer 6688651ce697SMichael Speer /* Cleanup any outstanding groups. */ 6689651ce697SMichael Speer nxge_grp_cleanup(nxgep); 66909d5b8bc5SMichael Speer } 66910b0beae0Sspeer 669244961713Sgirish if (hw_p->ndevs) { 669344961713Sgirish hw_p->ndevs--; 669444961713Sgirish } 669544961713Sgirish hw_p->nxge_p[nxgep->function_num] = NULL; 669644961713Sgirish if (!hw_p->ndevs) { 669744961713Sgirish MUTEX_DESTROY(&hw_p->nxge_vlan_lock); 669844961713Sgirish MUTEX_DESTROY(&hw_p->nxge_tcam_lock); 669944961713Sgirish MUTEX_DESTROY(&hw_p->nxge_cfg_lock); 670044961713Sgirish MUTEX_DESTROY(&hw_p->nxge_mdio_lock); 670144961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 67024045d941Ssowmini "==> nxge_uninit_common_device: " 67034045d941Ssowmini "func # %d " 67044045d941Ssowmini "hw_p $%p parent dip $%p " 67054045d941Ssowmini "ndevs %d (last)", 67064045d941Ssowmini nxgep->function_num, 67074045d941Ssowmini hw_p, 67084045d941Ssowmini p_dip, 67094045d941Ssowmini hw_p->ndevs)); 671044961713Sgirish 6711678453a8Sspeer nxge_hio_uninit(nxgep); 6712678453a8Sspeer 671344961713Sgirish if (hw_p == nxge_hw_list) { 671444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 67154045d941Ssowmini "==> nxge_uninit_common_device:" 67164045d941Ssowmini "remove head func # %d " 67174045d941Ssowmini "hw_p $%p parent dip $%p " 67184045d941Ssowmini "ndevs %d (head)", 67194045d941Ssowmini nxgep->function_num, 67204045d941Ssowmini hw_p, 67214045d941Ssowmini p_dip, 67224045d941Ssowmini hw_p->ndevs)); 672344961713Sgirish nxge_hw_list = hw_p->next; 672444961713Sgirish } else { 672544961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 67264045d941Ssowmini "==> nxge_uninit_common_device:" 67274045d941Ssowmini "remove middle func # %d " 67284045d941Ssowmini "hw_p $%p parent dip $%p " 67294045d941Ssowmini "ndevs %d (middle)", 67304045d941Ssowmini nxgep->function_num, 67314045d941Ssowmini hw_p, 67324045d941Ssowmini p_dip, 67334045d941Ssowmini hw_p->ndevs)); 673444961713Sgirish h_hw_p->next = hw_p->next; 673544961713Sgirish } 673644961713Sgirish 6737678453a8Sspeer nxgep->nxge_hw_p = NULL; 673844961713Sgirish KMEM_FREE(hw_p, sizeof (nxge_hw_list_t)); 673944961713Sgirish } 674044961713Sgirish break; 674144961713Sgirish } else { 674244961713Sgirish h_hw_p = hw_p; 674344961713Sgirish } 674444961713Sgirish } 674544961713Sgirish 674644961713Sgirish MUTEX_EXIT(&nxge_common_lock); 674744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 67484045d941Ssowmini "==> nxge_uninit_common_device (nxge_hw_list) $%p", 67494045d941Ssowmini nxge_hw_list)); 675044961713Sgirish 675144961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<= nxge_uninit_common_device")); 675244961713Sgirish } 675359ac0c16Sdavemq 675459ac0c16Sdavemq /* 67552e59129aSraghus * Determines the number of ports from the niu_type or the platform type. 675659ac0c16Sdavemq * Returns the number of ports, or returns zero on failure. 675759ac0c16Sdavemq */ 675859ac0c16Sdavemq 675959ac0c16Sdavemq int 67602e59129aSraghus nxge_get_nports(p_nxge_t nxgep) 676159ac0c16Sdavemq { 676259ac0c16Sdavemq int nports = 0; 676359ac0c16Sdavemq 67642e59129aSraghus switch (nxgep->niu_type) { 676559ac0c16Sdavemq case N2_NIU: 676659ac0c16Sdavemq case NEPTUNE_2_10GF: 676759ac0c16Sdavemq nports = 2; 676859ac0c16Sdavemq break; 676959ac0c16Sdavemq case NEPTUNE_4_1GC: 677059ac0c16Sdavemq case NEPTUNE_2_10GF_2_1GC: 677159ac0c16Sdavemq case NEPTUNE_1_10GF_3_1GC: 677259ac0c16Sdavemq case NEPTUNE_1_1GC_1_10GF_2_1GC: 677359a835ddSjoycey case NEPTUNE_2_10GF_2_1GRF: 677459ac0c16Sdavemq nports = 4; 677559ac0c16Sdavemq break; 677659ac0c16Sdavemq default: 67772e59129aSraghus switch (nxgep->platform_type) { 67782e59129aSraghus case P_NEPTUNE_NIU: 67792e59129aSraghus case P_NEPTUNE_ATLAS_2PORT: 67802e59129aSraghus nports = 2; 67812e59129aSraghus break; 67822e59129aSraghus case P_NEPTUNE_ATLAS_4PORT: 67832e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 67842e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 678523b952a3SSantwona Behera case P_NEPTUNE_ROCK: 6786d81011f0Ssbehera case P_NEPTUNE_ALONSO: 67872e59129aSraghus nports = 4; 67882e59129aSraghus break; 67892e59129aSraghus default: 67902e59129aSraghus break; 67912e59129aSraghus } 679259ac0c16Sdavemq break; 679359ac0c16Sdavemq } 679459ac0c16Sdavemq 679559ac0c16Sdavemq return (nports); 679659ac0c16Sdavemq } 6797ec090658Sml 6798ec090658Sml /* 6799ec090658Sml * The following two functions are to support 6800ec090658Sml * PSARC/2007/453 MSI-X interrupt limit override. 6801ec090658Sml */ 6802ec090658Sml static int 6803ec090658Sml nxge_create_msi_property(p_nxge_t nxgep) 6804ec090658Sml { 6805ec090658Sml int nmsi; 6806ec090658Sml extern int ncpus; 6807ec090658Sml 6808ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==>nxge_create_msi_property")); 6809ec090658Sml 6810ec090658Sml switch (nxgep->mac.portmode) { 6811ec090658Sml case PORT_10G_COPPER: 6812ec090658Sml case PORT_10G_FIBER: 681300161856Syc case PORT_10G_TN1010: 6814ec090658Sml (void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip, 6815ec090658Sml DDI_PROP_CANSLEEP, "#msix-request", NULL, 0); 6816ec090658Sml /* 6817ec090658Sml * The maximum MSI-X requested will be 8. 6818ef755e7aStc * If the # of CPUs is less than 8, we will request 6819ef755e7aStc * # MSI-X based on the # of CPUs (default). 6820ec090658Sml */ 6821ef755e7aStc NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6822ef755e7aStc "==>nxge_create_msi_property (10G): nxge_msix_10g_intrs %d", 6823ef755e7aStc nxge_msix_10g_intrs)); 6824ef755e7aStc if ((nxge_msix_10g_intrs == 0) || 6825ef755e7aStc (nxge_msix_10g_intrs > NXGE_MSIX_MAX_ALLOWED)) { 6826ec090658Sml nmsi = NXGE_MSIX_REQUEST_10G; 6827ef755e7aStc NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6828ef755e7aStc "==>nxge_create_msi_property (10G): reset to 8")); 6829ec090658Sml } else { 6830ef755e7aStc nmsi = nxge_msix_10g_intrs; 6831ef755e7aStc } 6832ef755e7aStc 6833ef755e7aStc /* 6834ef755e7aStc * If # of interrupts requested is 8 (default), 6835ef755e7aStc * the checking of the number of cpus will be 6836ef755e7aStc * be maintained. 6837ef755e7aStc */ 6838ef755e7aStc if ((nmsi == NXGE_MSIX_REQUEST_10G) && 6839ef755e7aStc (ncpus < nmsi)) { 6840ef755e7aStc NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6841ef755e7aStc "==>nxge_create_msi_property (10G): reset to 8")); 6842ec090658Sml nmsi = ncpus; 6843ec090658Sml } 6844ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6845ec090658Sml "==>nxge_create_msi_property(10G): exists 0x%x (nmsi %d)", 6846ec090658Sml ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 6847ec090658Sml DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 6848ec090658Sml break; 6849ec090658Sml 6850ec090658Sml default: 6851ef755e7aStc (void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip, 6852ef755e7aStc DDI_PROP_CANSLEEP, "#msix-request", NULL, 0); 6853ef755e7aStc NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6854ef755e7aStc "==>nxge_create_msi_property (1G): nxge_msix_1g_intrs %d", 6855ef755e7aStc nxge_msix_1g_intrs)); 6856ef755e7aStc if ((nxge_msix_1g_intrs == 0) || 6857ef755e7aStc (nxge_msix_1g_intrs > NXGE_MSIX_MAX_ALLOWED)) { 6858ef755e7aStc nmsi = NXGE_MSIX_REQUEST_1G; 6859ef755e7aStc NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6860ef755e7aStc "==>nxge_create_msi_property (1G): reset to 2")); 6861ef755e7aStc } else { 6862ef755e7aStc nmsi = nxge_msix_1g_intrs; 6863ef755e7aStc } 6864ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6865ec090658Sml "==>nxge_create_msi_property(1G): exists 0x%x (nmsi %d)", 6866ec090658Sml ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 6867ec090658Sml DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 6868ec090658Sml break; 6869ec090658Sml } 6870ec090658Sml 6871ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<==nxge_create_msi_property")); 6872ec090658Sml return (nmsi); 6873ec090658Sml } 68744045d941Ssowmini 68754045d941Ssowmini /* ARGSUSED */ 68764045d941Ssowmini static int 68774045d941Ssowmini nxge_get_def_val(nxge_t *nxgep, mac_prop_id_t pr_num, uint_t pr_valsize, 68784045d941Ssowmini void *pr_val) 68794045d941Ssowmini { 68804045d941Ssowmini int err = 0; 68814045d941Ssowmini link_flowctrl_t fl; 68824045d941Ssowmini 68834045d941Ssowmini switch (pr_num) { 68843fd94f8cSam case MAC_PROP_AUTONEG: 68854045d941Ssowmini *(uint8_t *)pr_val = 1; 68864045d941Ssowmini break; 68873fd94f8cSam case MAC_PROP_FLOWCTRL: 68884045d941Ssowmini if (pr_valsize < sizeof (link_flowctrl_t)) 68894045d941Ssowmini return (EINVAL); 68904045d941Ssowmini fl = LINK_FLOWCTRL_RX; 68914045d941Ssowmini bcopy(&fl, pr_val, sizeof (fl)); 68924045d941Ssowmini break; 68933fd94f8cSam case MAC_PROP_ADV_1000FDX_CAP: 68943fd94f8cSam case MAC_PROP_EN_1000FDX_CAP: 68954045d941Ssowmini *(uint8_t *)pr_val = 1; 68964045d941Ssowmini break; 68973fd94f8cSam case MAC_PROP_ADV_100FDX_CAP: 68983fd94f8cSam case MAC_PROP_EN_100FDX_CAP: 68994045d941Ssowmini *(uint8_t *)pr_val = 1; 69004045d941Ssowmini break; 69014045d941Ssowmini default: 69024045d941Ssowmini err = ENOTSUP; 69034045d941Ssowmini break; 69044045d941Ssowmini } 69054045d941Ssowmini return (err); 69064045d941Ssowmini } 69076f157acbSml 69086f157acbSml 69096f157acbSml /* 69106f157acbSml * The following is a software around for the Neptune hardware's 69116f157acbSml * interrupt bugs; The Neptune hardware may generate spurious interrupts when 69126f157acbSml * an interrupr handler is removed. 69136f157acbSml */ 69146f157acbSml #define NXGE_PCI_PORT_LOGIC_OFFSET 0x98 69156f157acbSml #define NXGE_PIM_RESET (1ULL << 29) 69166f157acbSml #define NXGE_GLU_RESET (1ULL << 30) 69176f157acbSml #define NXGE_NIU_RESET (1ULL << 31) 69186f157acbSml #define NXGE_PCI_RESET_ALL (NXGE_PIM_RESET | \ 69196f157acbSml NXGE_GLU_RESET | \ 69206f157acbSml NXGE_NIU_RESET) 69216f157acbSml 69226f157acbSml #define NXGE_WAIT_QUITE_TIME 200000 69236f157acbSml #define NXGE_WAIT_QUITE_RETRY 40 69246f157acbSml #define NXGE_PCI_RESET_WAIT 1000000 /* one second */ 69256f157acbSml 69266f157acbSml static void 69276f157acbSml nxge_niu_peu_reset(p_nxge_t nxgep) 69286f157acbSml { 69296f157acbSml uint32_t rvalue; 69306f157acbSml p_nxge_hw_list_t hw_p; 69316f157acbSml p_nxge_t fnxgep; 69326f157acbSml int i, j; 69336f157acbSml 69346f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_niu_peu_reset")); 69356f157acbSml if ((hw_p = nxgep->nxge_hw_p) == NULL) { 69366f157acbSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 69376f157acbSml "==> nxge_niu_peu_reset: NULL hardware pointer")); 69386f157acbSml return; 69396f157acbSml } 69406f157acbSml 69416f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 69426f157acbSml "==> nxge_niu_peu_reset: flags 0x%x link timer id %d timer id %d", 69436f157acbSml hw_p->flags, nxgep->nxge_link_poll_timerid, 69446f157acbSml nxgep->nxge_timerid)); 69456f157acbSml 69466f157acbSml MUTEX_ENTER(&hw_p->nxge_cfg_lock); 69476f157acbSml /* 69486f157acbSml * Make sure other instances from the same hardware 69496f157acbSml * stop sending PIO and in quiescent state. 69506f157acbSml */ 69516f157acbSml for (i = 0; i < NXGE_MAX_PORTS; i++) { 69526f157acbSml fnxgep = hw_p->nxge_p[i]; 69536f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 69546f157acbSml "==> nxge_niu_peu_reset: checking entry %d " 69556f157acbSml "nxgep $%p", i, fnxgep)); 69566f157acbSml #ifdef NXGE_DEBUG 69576f157acbSml if (fnxgep) { 69586f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 69596f157acbSml "==> nxge_niu_peu_reset: entry %d (function %d) " 69606f157acbSml "link timer id %d hw timer id %d", 69616f157acbSml i, fnxgep->function_num, 69626f157acbSml fnxgep->nxge_link_poll_timerid, 69636f157acbSml fnxgep->nxge_timerid)); 69646f157acbSml } 69656f157acbSml #endif 69666f157acbSml if (fnxgep && fnxgep != nxgep && 69676f157acbSml (fnxgep->nxge_timerid || fnxgep->nxge_link_poll_timerid)) { 69686f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 69696f157acbSml "==> nxge_niu_peu_reset: checking $%p " 69706f157acbSml "(function %d) timer ids", 69716f157acbSml fnxgep, fnxgep->function_num)); 69726f157acbSml for (j = 0; j < NXGE_WAIT_QUITE_RETRY; j++) { 69736f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 69746f157acbSml "==> nxge_niu_peu_reset: waiting")); 69756f157acbSml NXGE_DELAY(NXGE_WAIT_QUITE_TIME); 69766f157acbSml if (!fnxgep->nxge_timerid && 69776f157acbSml !fnxgep->nxge_link_poll_timerid) { 69786f157acbSml break; 69796f157acbSml } 69806f157acbSml } 69816f157acbSml NXGE_DELAY(NXGE_WAIT_QUITE_TIME); 69826f157acbSml if (fnxgep->nxge_timerid || 69836f157acbSml fnxgep->nxge_link_poll_timerid) { 69846f157acbSml MUTEX_EXIT(&hw_p->nxge_cfg_lock); 69856f157acbSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 69866f157acbSml "<== nxge_niu_peu_reset: cannot reset " 69876f157acbSml "hardware (devices are still in use)")); 69886f157acbSml return; 69896f157acbSml } 69906f157acbSml } 69916f157acbSml } 69926f157acbSml 69936f157acbSml if ((hw_p->flags & COMMON_RESET_NIU_PCI) != COMMON_RESET_NIU_PCI) { 69946f157acbSml hw_p->flags |= COMMON_RESET_NIU_PCI; 69956f157acbSml rvalue = pci_config_get32(nxgep->dev_regs->nxge_pciregh, 69966f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET); 69976f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 69986f157acbSml "nxge_niu_peu_reset: read offset 0x%x (%d) " 69996f157acbSml "(data 0x%x)", 70006f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, 70016f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, 70026f157acbSml rvalue)); 70036f157acbSml 70046f157acbSml rvalue |= NXGE_PCI_RESET_ALL; 70056f157acbSml pci_config_put32(nxgep->dev_regs->nxge_pciregh, 70066f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, rvalue); 70076f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 70086f157acbSml "nxge_niu_peu_reset: RESETTING NIU: write NIU reset 0x%x", 70096f157acbSml rvalue)); 70106f157acbSml 70116f157acbSml NXGE_DELAY(NXGE_PCI_RESET_WAIT); 70126f157acbSml } 70136f157acbSml 70146f157acbSml MUTEX_EXIT(&hw_p->nxge_cfg_lock); 70156f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_niu_peu_reset")); 70166f157acbSml } 7017d6d3405fSml 7018d6d3405fSml static void 7019d6d3405fSml nxge_set_pci_replay_timeout(p_nxge_t nxgep) 7020d6d3405fSml { 7021da14cebeSEric Cheng p_dev_regs_t dev_regs; 7022d6d3405fSml uint32_t value; 7023d6d3405fSml 7024d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_set_pci_replay_timeout")); 7025d6d3405fSml 7026d6d3405fSml if (!nxge_set_replay_timer) { 7027d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7028d6d3405fSml "==> nxge_set_pci_replay_timeout: will not change " 7029d6d3405fSml "the timeout")); 7030d6d3405fSml return; 7031d6d3405fSml } 7032d6d3405fSml 7033d6d3405fSml dev_regs = nxgep->dev_regs; 7034d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7035d6d3405fSml "==> nxge_set_pci_replay_timeout: dev_regs 0x%p pcireg 0x%p", 7036d6d3405fSml dev_regs, dev_regs->nxge_pciregh)); 7037d6d3405fSml 7038d6d3405fSml if (dev_regs == NULL || (dev_regs->nxge_pciregh == NULL)) { 7039f720bc57Syc NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7040d6d3405fSml "==> nxge_set_pci_replay_timeout: NULL dev_regs $%p or " 7041d6d3405fSml "no PCI handle", 7042d6d3405fSml dev_regs)); 7043d6d3405fSml return; 7044d6d3405fSml } 7045d6d3405fSml value = (pci_config_get32(dev_regs->nxge_pciregh, 7046d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET) | 7047d6d3405fSml (nxge_replay_timeout << PCI_REPLAY_TIMEOUT_SHIFT)); 7048d6d3405fSml 7049d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7050d6d3405fSml "nxge_set_pci_replay_timeout: replay timeout value before set 0x%x " 7051d6d3405fSml "(timeout value to set 0x%x at offset 0x%x) value 0x%x", 7052d6d3405fSml pci_config_get32(dev_regs->nxge_pciregh, 7053d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET), nxge_replay_timeout, 7054d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET, value)); 7055d6d3405fSml 7056d6d3405fSml pci_config_put32(dev_regs->nxge_pciregh, PCI_REPLAY_TIMEOUT_CFG_OFFSET, 7057d6d3405fSml value); 7058d6d3405fSml 7059d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7060d6d3405fSml "nxge_set_pci_replay_timeout: replay timeout value after set 0x%x", 7061d6d3405fSml pci_config_get32(dev_regs->nxge_pciregh, 7062d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET))); 7063d6d3405fSml 7064d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_set_pci_replay_timeout")); 7065d6d3405fSml } 706619397407SSherry Moore 706719397407SSherry Moore /* 706819397407SSherry Moore * quiesce(9E) entry point. 706919397407SSherry Moore * 707019397407SSherry Moore * This function is called when the system is single-threaded at high 707119397407SSherry Moore * PIL with preemption disabled. Therefore, this function must not be 707219397407SSherry Moore * blocked. 707319397407SSherry Moore * 707419397407SSherry Moore * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 707519397407SSherry Moore * DDI_FAILURE indicates an error condition and should almost never happen. 707619397407SSherry Moore */ 707719397407SSherry Moore static int 707819397407SSherry Moore nxge_quiesce(dev_info_t *dip) 707919397407SSherry Moore { 708019397407SSherry Moore int instance = ddi_get_instance(dip); 708119397407SSherry Moore p_nxge_t nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 708219397407SSherry Moore 708319397407SSherry Moore if (nxgep == NULL) 708419397407SSherry Moore return (DDI_FAILURE); 708519397407SSherry Moore 708619397407SSherry Moore /* Turn off debugging */ 708719397407SSherry Moore nxge_debug_level = NO_DEBUG; 708819397407SSherry Moore nxgep->nxge_debug_level = NO_DEBUG; 708919397407SSherry Moore npi_debug_level = NO_DEBUG; 709019397407SSherry Moore 709119397407SSherry Moore /* 709219397407SSherry Moore * Stop link monitor only when linkchkmod is interrupt based 709319397407SSherry Moore */ 709419397407SSherry Moore if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 709519397407SSherry Moore (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 709619397407SSherry Moore } 709719397407SSherry Moore 709819397407SSherry Moore (void) nxge_intr_hw_disable(nxgep); 709919397407SSherry Moore 710019397407SSherry Moore /* 710119397407SSherry Moore * Reset the receive MAC side. 710219397407SSherry Moore */ 710319397407SSherry Moore (void) nxge_rx_mac_disable(nxgep); 710419397407SSherry Moore 710519397407SSherry Moore /* Disable and soft reset the IPP */ 710619397407SSherry Moore if (!isLDOMguest(nxgep)) 710719397407SSherry Moore (void) nxge_ipp_disable(nxgep); 710819397407SSherry Moore 710919397407SSherry Moore /* 711019397407SSherry Moore * Reset the transmit/receive DMA side. 711119397407SSherry Moore */ 711219397407SSherry Moore (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 711319397407SSherry Moore (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 711419397407SSherry Moore 711519397407SSherry Moore /* 711619397407SSherry Moore * Reset the transmit MAC side. 711719397407SSherry Moore */ 711819397407SSherry Moore (void) nxge_tx_mac_disable(nxgep); 711919397407SSherry Moore 712019397407SSherry Moore return (DDI_SUCCESS); 712119397407SSherry Moore } 7122