16f45ec7bSml29623 /* 26f45ec7bSml29623 * CDDL HEADER START 36f45ec7bSml29623 * 46f45ec7bSml29623 * The contents of this file are subject to the terms of the 56f45ec7bSml29623 * Common Development and Distribution License (the "License"). 66f45ec7bSml29623 * You may not use this file except in compliance with the License. 76f45ec7bSml29623 * 86f45ec7bSml29623 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 96f45ec7bSml29623 * or http://www.opensolaris.org/os/licensing. 106f45ec7bSml29623 * See the License for the specific language governing permissions 116f45ec7bSml29623 * and limitations under the License. 126f45ec7bSml29623 * 136f45ec7bSml29623 * When distributing Covered Code, include this CDDL HEADER in each 146f45ec7bSml29623 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 156f45ec7bSml29623 * If applicable, add the following below this CDDL HEADER, with the 166f45ec7bSml29623 * fields enclosed by brackets "[]" replaced with your own identifying 176f45ec7bSml29623 * information: Portions Copyright [yyyy] [name of copyright owner] 186f45ec7bSml29623 * 196f45ec7bSml29623 * CDDL HEADER END 206f45ec7bSml29623 */ 216f45ec7bSml29623 /* 229d587972SSantwona Behera * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 23*238d8f47SDale Ghent * Copyright 2016 OmniTI Computer Consulting, Inc. All rights reserved. 246f45ec7bSml29623 */ 256f45ec7bSml29623 266f45ec7bSml29623 /* 276f45ec7bSml29623 * SunOs MT STREAMS NIU/Neptune 10Gb Ethernet Device Driver. 286f45ec7bSml29623 */ 296f45ec7bSml29623 #include <sys/nxge/nxge_impl.h> 30678453a8Sspeer #include <sys/nxge/nxge_hio.h> 31678453a8Sspeer #include <sys/nxge/nxge_rxdma.h> 326f45ec7bSml29623 #include <sys/pcie.h> 336f45ec7bSml29623 346f45ec7bSml29623 uint32_t nxge_use_partition = 0; /* debug partition flag */ 356f45ec7bSml29623 uint32_t nxge_dma_obp_props_only = 1; /* use obp published props */ 366f45ec7bSml29623 uint32_t nxge_use_rdc_intr = 1; /* debug to assign rdc intr */ 376f45ec7bSml29623 /* 38ec090658Sml29623 * PSARC/2007/453 MSI-X interrupt limit override 396f45ec7bSml29623 */ 40ec090658Sml29623 uint32_t nxge_msi_enable = 2; 416f45ec7bSml29623 42b4d05839Sml29623 /* 436f157acbSml29623 * Software workaround for a Neptune (PCI-E) 446f157acbSml29623 * hardware interrupt bug which the hardware 456f157acbSml29623 * may generate spurious interrupts after the 466f157acbSml29623 * device interrupt handler was removed. If this flag 476f157acbSml29623 * is enabled, the driver will reset the 486f157acbSml29623 * hardware when devices are being detached. 496f157acbSml29623 */ 506f157acbSml29623 uint32_t nxge_peu_reset_enable = 0; 516f157acbSml29623 526f157acbSml29623 /* 53b4d05839Sml29623 * Software workaround for the hardware 54b4d05839Sml29623 * checksum bugs that affect packet transmission 55b4d05839Sml29623 * and receive: 56b4d05839Sml29623 * 57b4d05839Sml29623 * Usage of nxge_cksum_offload: 58b4d05839Sml29623 * 59b4d05839Sml29623 * (1) nxge_cksum_offload = 0 (default): 60b4d05839Sml29623 * - transmits packets: 61b4d05839Sml29623 * TCP: uses the hardware checksum feature. 62b4d05839Sml29623 * UDP: driver will compute the software checksum 63b4d05839Sml29623 * based on the partial checksum computed 64b4d05839Sml29623 * by the IP layer. 65b4d05839Sml29623 * - receives packets 66b4d05839Sml29623 * TCP: marks packets checksum flags based on hardware result. 67b4d05839Sml29623 * UDP: will not mark checksum flags. 68b4d05839Sml29623 * 69b4d05839Sml29623 * (2) nxge_cksum_offload = 1: 70b4d05839Sml29623 * - transmit packets: 71b4d05839Sml29623 * TCP/UDP: uses the hardware checksum feature. 72b4d05839Sml29623 * - receives packets 73b4d05839Sml29623 * TCP/UDP: marks packet checksum flags based on hardware result. 74b4d05839Sml29623 * 75b4d05839Sml29623 * (3) nxge_cksum_offload = 2: 76b4d05839Sml29623 * - The driver will not register its checksum capability. 77b4d05839Sml29623 * Checksum for both TCP and UDP will be computed 78b4d05839Sml29623 * by the stack. 79b4d05839Sml29623 * - The software LSO is not allowed in this case. 80b4d05839Sml29623 * 81b4d05839Sml29623 * (4) nxge_cksum_offload > 2: 82b4d05839Sml29623 * - Will be treated as it is set to 2 83b4d05839Sml29623 * (stack will compute the checksum). 84b4d05839Sml29623 * 85b4d05839Sml29623 * (5) If the hardware bug is fixed, this workaround 86b4d05839Sml29623 * needs to be updated accordingly to reflect 87b4d05839Sml29623 * the new hardware revision. 88b4d05839Sml29623 */ 89b4d05839Sml29623 uint32_t nxge_cksum_offload = 0; 90678453a8Sspeer 916f45ec7bSml29623 /* 926f45ec7bSml29623 * Globals: tunable parameters (/etc/system or adb) 936f45ec7bSml29623 * 946f45ec7bSml29623 */ 956f45ec7bSml29623 uint32_t nxge_rbr_size = NXGE_RBR_RBB_DEFAULT; 966f45ec7bSml29623 uint32_t nxge_rbr_spare_size = 0; 976f45ec7bSml29623 uint32_t nxge_rcr_size = NXGE_RCR_DEFAULT; 984df55fdeSJanie Lu uint16_t nxge_rdc_buf_offset = SW_OFFSET_NO_OFFSET; 996f45ec7bSml29623 uint32_t nxge_tx_ring_size = NXGE_TX_RING_DEFAULT; 100b3a0105bSspeer boolean_t nxge_no_msg = B_TRUE; /* control message display */ 1016f45ec7bSml29623 uint32_t nxge_no_link_notify = 0; /* control DL_NOTIFY */ 1026f45ec7bSml29623 uint32_t nxge_bcopy_thresh = TX_BCOPY_MAX; 1036f45ec7bSml29623 uint32_t nxge_dvma_thresh = TX_FASTDVMA_MIN; 1046f45ec7bSml29623 uint32_t nxge_dma_stream_thresh = TX_STREAM_MIN; 1056f45ec7bSml29623 uint32_t nxge_jumbo_mtu = TX_JUMBO_MTU; 1061f8914d5Sml29623 nxge_tx_mode_t nxge_tx_scheme = NXGE_USE_SERIAL; 1076f45ec7bSml29623 10830ac2e7bSml29623 /* MAX LSO size */ 10930ac2e7bSml29623 #define NXGE_LSO_MAXLEN 65535 11030ac2e7bSml29623 uint32_t nxge_lso_max = NXGE_LSO_MAXLEN; 11130ac2e7bSml29623 1126f45ec7bSml29623 1136f45ec7bSml29623 /* 1146f45ec7bSml29623 * Add tunable to reduce the amount of time spent in the 1156f45ec7bSml29623 * ISR doing Rx Processing. 1166f45ec7bSml29623 */ 1176f45ec7bSml29623 uint32_t nxge_max_rx_pkts = 1024; 1186f45ec7bSml29623 1196f45ec7bSml29623 /* 1206f45ec7bSml29623 * Tunables to manage the receive buffer blocks. 1216f45ec7bSml29623 * 1226f45ec7bSml29623 * nxge_rx_threshold_hi: copy all buffers. 1236f45ec7bSml29623 * nxge_rx_bcopy_size_type: receive buffer block size type. 1246f45ec7bSml29623 * nxge_rx_threshold_lo: copy only up to tunable block size type. 1256f45ec7bSml29623 */ 1266f45ec7bSml29623 nxge_rxbuf_threshold_t nxge_rx_threshold_hi = NXGE_RX_COPY_6; 1276f45ec7bSml29623 nxge_rxbuf_type_t nxge_rx_buf_size_type = RCR_PKTBUFSZ_0; 1286f45ec7bSml29623 nxge_rxbuf_threshold_t nxge_rx_threshold_lo = NXGE_RX_COPY_3; 1296f45ec7bSml29623 130678453a8Sspeer /* Use kmem_alloc() to allocate data buffers. */ 131ef523517SMichael Speer #if defined(__sparc) 132678453a8Sspeer uint32_t nxge_use_kmem_alloc = 1; 133ef523517SMichael Speer #elif defined(__i386) 134678453a8Sspeer uint32_t nxge_use_kmem_alloc = 0; 135ef523517SMichael Speer #else 136ef523517SMichael Speer uint32_t nxge_use_kmem_alloc = 1; 137678453a8Sspeer #endif 138678453a8Sspeer 1396f45ec7bSml29623 rtrace_t npi_rtracebuf; 1406f45ec7bSml29623 141d6d3405fSml29623 /* 142d6d3405fSml29623 * The hardware sometimes fails to allow enough time for the link partner 143d6d3405fSml29623 * to send an acknowledgement for packets that the hardware sent to it. The 144d6d3405fSml29623 * hardware resends the packets earlier than it should be in those instances. 145d6d3405fSml29623 * This behavior caused some switches to acknowledge the wrong packets 146d6d3405fSml29623 * and it triggered the fatal error. 147d6d3405fSml29623 * This software workaround is to set the replay timer to a value 148d6d3405fSml29623 * suggested by the hardware team. 149d6d3405fSml29623 * 150d6d3405fSml29623 * PCI config space replay timer register: 151d6d3405fSml29623 * The following replay timeout value is 0xc 152d6d3405fSml29623 * for bit 14:18. 153d6d3405fSml29623 */ 154d6d3405fSml29623 #define PCI_REPLAY_TIMEOUT_CFG_OFFSET 0xb8 155d6d3405fSml29623 #define PCI_REPLAY_TIMEOUT_SHIFT 14 156d6d3405fSml29623 157d6d3405fSml29623 uint32_t nxge_set_replay_timer = 1; 158d6d3405fSml29623 uint32_t nxge_replay_timeout = 0xc; 159d6d3405fSml29623 160cf020df9Sml29623 /* 161cf020df9Sml29623 * The transmit serialization sometimes causes 162cf020df9Sml29623 * longer sleep before calling the driver transmit 163cf020df9Sml29623 * function as it sleeps longer than it should. 164cf020df9Sml29623 * The performace group suggests that a time wait tunable 165cf020df9Sml29623 * can be used to set the maximum wait time when needed 166cf020df9Sml29623 * and the default is set to 1 tick. 167cf020df9Sml29623 */ 168cf020df9Sml29623 uint32_t nxge_tx_serial_maxsleep = 1; 169cf020df9Sml29623 1706f45ec7bSml29623 #if defined(sun4v) 1716f45ec7bSml29623 /* 1726f45ec7bSml29623 * Hypervisor N2/NIU services information. 1736f45ec7bSml29623 */ 1744df55fdeSJanie Lu /* 1754df55fdeSJanie Lu * The following is the default API supported: 1764df55fdeSJanie Lu * major 1 and minor 1. 1774df55fdeSJanie Lu * 1784df55fdeSJanie Lu * Please update the MAX_NIU_MAJORS, 1794df55fdeSJanie Lu * MAX_NIU_MINORS, and minor number supported 1804df55fdeSJanie Lu * when the newer Hypervior API interfaces 1814df55fdeSJanie Lu * are added. Also, please update nxge_hsvc_register() 1824df55fdeSJanie Lu * if needed. 1834df55fdeSJanie Lu */ 1846f45ec7bSml29623 static hsvc_info_t niu_hsvc = { 1856f45ec7bSml29623 HSVC_REV_1, NULL, HSVC_GROUP_NIU, NIU_MAJOR_VER, 1866f45ec7bSml29623 NIU_MINOR_VER, "nxge" 1876f45ec7bSml29623 }; 188678453a8Sspeer 189678453a8Sspeer static int nxge_hsvc_register(p_nxge_t); 1906f45ec7bSml29623 #endif 1916f45ec7bSml29623 1926f45ec7bSml29623 /* 1936f45ec7bSml29623 * Function Prototypes 1946f45ec7bSml29623 */ 1956f45ec7bSml29623 static int nxge_attach(dev_info_t *, ddi_attach_cmd_t); 1966f45ec7bSml29623 static int nxge_detach(dev_info_t *, ddi_detach_cmd_t); 1976f45ec7bSml29623 static void nxge_unattach(p_nxge_t); 19819397407SSherry Moore static int nxge_quiesce(dev_info_t *); 1996f45ec7bSml29623 2006f45ec7bSml29623 #if NXGE_PROPERTY 2016f45ec7bSml29623 static void nxge_remove_hard_properties(p_nxge_t); 2026f45ec7bSml29623 #endif 2036f45ec7bSml29623 204678453a8Sspeer /* 205678453a8Sspeer * These two functions are required by nxge_hio.c 206678453a8Sspeer */ 207da14cebeSEric Cheng extern int nxge_m_mmac_remove(void *arg, int slot); 208651ce697SMichael Speer extern void nxge_grp_cleanup(p_nxge_t nxge); 209678453a8Sspeer 2106f45ec7bSml29623 static nxge_status_t nxge_setup_system_dma_pages(p_nxge_t); 2116f45ec7bSml29623 2126f45ec7bSml29623 static nxge_status_t nxge_setup_mutexes(p_nxge_t); 2136f45ec7bSml29623 static void nxge_destroy_mutexes(p_nxge_t); 2146f45ec7bSml29623 2156f45ec7bSml29623 static nxge_status_t nxge_map_regs(p_nxge_t nxgep); 2166f45ec7bSml29623 static void nxge_unmap_regs(p_nxge_t nxgep); 2176f45ec7bSml29623 #ifdef NXGE_DEBUG 2186f45ec7bSml29623 static void nxge_test_map_regs(p_nxge_t nxgep); 2196f45ec7bSml29623 #endif 2206f45ec7bSml29623 2216f45ec7bSml29623 static nxge_status_t nxge_add_intrs(p_nxge_t nxgep); 2226f45ec7bSml29623 static void nxge_remove_intrs(p_nxge_t nxgep); 2236f45ec7bSml29623 2246f45ec7bSml29623 static nxge_status_t nxge_add_intrs_adv(p_nxge_t nxgep); 2256f45ec7bSml29623 static nxge_status_t nxge_add_intrs_adv_type(p_nxge_t, uint32_t); 2266f45ec7bSml29623 static nxge_status_t nxge_add_intrs_adv_type_fix(p_nxge_t, uint32_t); 2276f45ec7bSml29623 static void nxge_intrs_enable(p_nxge_t nxgep); 2286f45ec7bSml29623 static void nxge_intrs_disable(p_nxge_t nxgep); 2296f45ec7bSml29623 2306f45ec7bSml29623 static void nxge_suspend(p_nxge_t); 2316f45ec7bSml29623 static nxge_status_t nxge_resume(p_nxge_t); 2326f45ec7bSml29623 2336f45ec7bSml29623 static nxge_status_t nxge_setup_dev(p_nxge_t); 2346f45ec7bSml29623 static void nxge_destroy_dev(p_nxge_t); 2356f45ec7bSml29623 2366f45ec7bSml29623 static nxge_status_t nxge_alloc_mem_pool(p_nxge_t); 2376f45ec7bSml29623 static void nxge_free_mem_pool(p_nxge_t); 2386f45ec7bSml29623 239678453a8Sspeer nxge_status_t nxge_alloc_rx_mem_pool(p_nxge_t); 2406f45ec7bSml29623 static void nxge_free_rx_mem_pool(p_nxge_t); 2416f45ec7bSml29623 242678453a8Sspeer nxge_status_t nxge_alloc_tx_mem_pool(p_nxge_t); 2436f45ec7bSml29623 static void nxge_free_tx_mem_pool(p_nxge_t); 2446f45ec7bSml29623 2456f45ec7bSml29623 static nxge_status_t nxge_dma_mem_alloc(p_nxge_t, dma_method_t, 2466f45ec7bSml29623 struct ddi_dma_attr *, 2476f45ec7bSml29623 size_t, ddi_device_acc_attr_t *, uint_t, 2486f45ec7bSml29623 p_nxge_dma_common_t); 2496f45ec7bSml29623 2506f45ec7bSml29623 static void nxge_dma_mem_free(p_nxge_dma_common_t); 251678453a8Sspeer static void nxge_dma_free_rx_data_buf(p_nxge_dma_common_t); 2526f45ec7bSml29623 2536f45ec7bSml29623 static nxge_status_t nxge_alloc_rx_buf_dma(p_nxge_t, uint16_t, 2546f45ec7bSml29623 p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 2556f45ec7bSml29623 static void nxge_free_rx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 2566f45ec7bSml29623 2576f45ec7bSml29623 static nxge_status_t nxge_alloc_rx_cntl_dma(p_nxge_t, uint16_t, 2586f45ec7bSml29623 p_nxge_dma_common_t *, size_t); 2596f45ec7bSml29623 static void nxge_free_rx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 2606f45ec7bSml29623 261678453a8Sspeer extern nxge_status_t nxge_alloc_tx_buf_dma(p_nxge_t, uint16_t, 2626f45ec7bSml29623 p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 2636f45ec7bSml29623 static void nxge_free_tx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 2646f45ec7bSml29623 265678453a8Sspeer extern nxge_status_t nxge_alloc_tx_cntl_dma(p_nxge_t, uint16_t, 2666f45ec7bSml29623 p_nxge_dma_common_t *, 2676f45ec7bSml29623 size_t); 2686f45ec7bSml29623 static void nxge_free_tx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 2696f45ec7bSml29623 2706f45ec7bSml29623 static int nxge_init_common_dev(p_nxge_t); 2716f45ec7bSml29623 static void nxge_uninit_common_dev(p_nxge_t); 2724045d941Ssowmini extern int nxge_param_set_mac(p_nxge_t, queue_t *, mblk_t *, 2734045d941Ssowmini char *, caddr_t); 274e759c33aSMichael Speer #if defined(sun4v) 275e759c33aSMichael Speer extern nxge_status_t nxge_hio_rdc_enable(p_nxge_t nxgep); 276e759c33aSMichael Speer extern nxge_status_t nxge_hio_rdc_intr_arm(p_nxge_t nxge, boolean_t arm); 277e759c33aSMichael Speer #endif 2786f45ec7bSml29623 2796f45ec7bSml29623 /* 2806f45ec7bSml29623 * The next declarations are for the GLDv3 interface. 2816f45ec7bSml29623 */ 2826f45ec7bSml29623 static int nxge_m_start(void *); 2836f45ec7bSml29623 static void nxge_m_stop(void *); 2846f45ec7bSml29623 static int nxge_m_multicst(void *, boolean_t, const uint8_t *); 2856f45ec7bSml29623 static int nxge_m_promisc(void *, boolean_t); 2866f45ec7bSml29623 static void nxge_m_ioctl(void *, queue_t *, mblk_t *); 28763f531d1SSriharsha Basavapatna nxge_status_t nxge_mac_register(p_nxge_t); 288da14cebeSEric Cheng static int nxge_altmac_set(p_nxge_t nxgep, uint8_t *mac_addr, 289da14cebeSEric Cheng int slot, int rdctbl, boolean_t usetbl); 290da14cebeSEric Cheng void nxge_mmac_kstat_update(p_nxge_t nxgep, int slot, 2916f45ec7bSml29623 boolean_t factory); 292da14cebeSEric Cheng 293da14cebeSEric Cheng static void nxge_m_getfactaddr(void *, uint_t, uint8_t *); 2941bd6825cSml29623 static boolean_t nxge_m_getcapab(void *, mac_capab_t, void *); 2951bd6825cSml29623 static int nxge_m_setprop(void *, const char *, mac_prop_id_t, 2961bd6825cSml29623 uint_t, const void *); 2971bd6825cSml29623 static int nxge_m_getprop(void *, const char *, mac_prop_id_t, 2980dc2366fSVenugopal Iyer uint_t, void *); 2990dc2366fSVenugopal Iyer static void nxge_m_propinfo(void *, const char *, mac_prop_id_t, 3000dc2366fSVenugopal Iyer mac_prop_info_handle_t); 3010dc2366fSVenugopal Iyer static void nxge_priv_propinfo(const char *, mac_prop_info_handle_t); 3021bd6825cSml29623 static int nxge_set_priv_prop(nxge_t *, const char *, uint_t, 3031bd6825cSml29623 const void *); 3040dc2366fSVenugopal Iyer static int nxge_get_priv_prop(nxge_t *, const char *, uint_t, void *); 305da14cebeSEric Cheng static void nxge_fill_ring(void *, mac_ring_type_t, const int, const int, 306da14cebeSEric Cheng mac_ring_info_t *, mac_ring_handle_t); 307da14cebeSEric Cheng static void nxge_group_add_ring(mac_group_driver_t, mac_ring_driver_t, 308da14cebeSEric Cheng mac_ring_type_t); 309da14cebeSEric Cheng static void nxge_group_rem_ring(mac_group_driver_t, mac_ring_driver_t, 310da14cebeSEric Cheng mac_ring_type_t); 3114045d941Ssowmini 3126f157acbSml29623 static void nxge_niu_peu_reset(p_nxge_t nxgep); 313d6d3405fSml29623 static void nxge_set_pci_replay_timeout(nxge_t *); 3144045d941Ssowmini 3150dc2366fSVenugopal Iyer char *nxge_priv_props[] = { 3160dc2366fSVenugopal Iyer "_adv_10gfdx_cap", 3170dc2366fSVenugopal Iyer "_adv_pause_cap", 3180dc2366fSVenugopal Iyer "_function_number", 3190dc2366fSVenugopal Iyer "_fw_version", 3200dc2366fSVenugopal Iyer "_port_mode", 3210dc2366fSVenugopal Iyer "_hot_swap_phy", 3220dc2366fSVenugopal Iyer "_rxdma_intr_time", 3230dc2366fSVenugopal Iyer "_rxdma_intr_pkts", 3240dc2366fSVenugopal Iyer "_class_opt_ipv4_tcp", 3250dc2366fSVenugopal Iyer "_class_opt_ipv4_udp", 3260dc2366fSVenugopal Iyer "_class_opt_ipv4_ah", 3270dc2366fSVenugopal Iyer "_class_opt_ipv4_sctp", 3280dc2366fSVenugopal Iyer "_class_opt_ipv6_tcp", 3290dc2366fSVenugopal Iyer "_class_opt_ipv6_udp", 3300dc2366fSVenugopal Iyer "_class_opt_ipv6_ah", 3310dc2366fSVenugopal Iyer "_class_opt_ipv6_sctp", 3320dc2366fSVenugopal Iyer "_soft_lso_enable", 3330dc2366fSVenugopal Iyer NULL 3344045d941Ssowmini }; 3354045d941Ssowmini 3366f45ec7bSml29623 #define NXGE_NEPTUNE_MAGIC 0x4E584745UL 3376f45ec7bSml29623 #define MAX_DUMP_SZ 256 3386f45ec7bSml29623 3391bd6825cSml29623 #define NXGE_M_CALLBACK_FLAGS \ 3400dc2366fSVenugopal Iyer (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO) 3416f45ec7bSml29623 342678453a8Sspeer mac_callbacks_t nxge_m_callbacks = { 3436f45ec7bSml29623 NXGE_M_CALLBACK_FLAGS, 3446f45ec7bSml29623 nxge_m_stat, 3456f45ec7bSml29623 nxge_m_start, 3466f45ec7bSml29623 nxge_m_stop, 3476f45ec7bSml29623 nxge_m_promisc, 3486f45ec7bSml29623 nxge_m_multicst, 349da14cebeSEric Cheng NULL, 350da14cebeSEric Cheng NULL, 3510dc2366fSVenugopal Iyer NULL, 3526f45ec7bSml29623 nxge_m_ioctl, 3531bd6825cSml29623 nxge_m_getcapab, 3541bd6825cSml29623 NULL, 3551bd6825cSml29623 NULL, 3561bd6825cSml29623 nxge_m_setprop, 3570dc2366fSVenugopal Iyer nxge_m_getprop, 3580dc2366fSVenugopal Iyer nxge_m_propinfo 3596f45ec7bSml29623 }; 3606f45ec7bSml29623 3616f45ec7bSml29623 void 3626f45ec7bSml29623 nxge_err_inject(p_nxge_t, queue_t *, mblk_t *); 3636f45ec7bSml29623 364ec090658Sml29623 /* PSARC/2007/453 MSI-X interrupt limit override. */ 365ec090658Sml29623 #define NXGE_MSIX_REQUEST_10G 8 366ec090658Sml29623 #define NXGE_MSIX_REQUEST_1G 2 367ec090658Sml29623 static int nxge_create_msi_property(p_nxge_t); 368ef755e7aStc99174@train /* 369ef755e7aStc99174@train * For applications that care about the 370ef755e7aStc99174@train * latency, it was requested by PAE and the 371ef755e7aStc99174@train * customers that the driver has tunables that 372ef755e7aStc99174@train * allow the user to tune it to a higher number 373ef755e7aStc99174@train * interrupts to spread the interrupts among 374ef755e7aStc99174@train * multiple channels. The DDI framework limits 375ef755e7aStc99174@train * the maximum number of MSI-X resources to allocate 376ef755e7aStc99174@train * to 8 (ddi_msix_alloc_limit). If more than 8 377ef755e7aStc99174@train * is set, ddi_msix_alloc_limit must be set accordingly. 378ef755e7aStc99174@train * The default number of MSI interrupts are set to 379ef755e7aStc99174@train * 8 for 10G and 2 for 1G link. 380ef755e7aStc99174@train */ 381ef755e7aStc99174@train #define NXGE_MSIX_MAX_ALLOWED 32 382ef755e7aStc99174@train uint32_t nxge_msix_10g_intrs = NXGE_MSIX_REQUEST_10G; 383ef755e7aStc99174@train uint32_t nxge_msix_1g_intrs = NXGE_MSIX_REQUEST_1G; 384ec090658Sml29623 3856f45ec7bSml29623 /* 3866f45ec7bSml29623 * These global variables control the message 3876f45ec7bSml29623 * output. 3886f45ec7bSml29623 */ 3896f45ec7bSml29623 out_dbgmsg_t nxge_dbgmsg_out = DBG_CONSOLE | STR_LOG; 390678453a8Sspeer uint64_t nxge_debug_level; 3916f45ec7bSml29623 3926f45ec7bSml29623 /* 3936f45ec7bSml29623 * This list contains the instance structures for the Neptune 3946f45ec7bSml29623 * devices present in the system. The lock exists to guarantee 3956f45ec7bSml29623 * mutually exclusive access to the list. 3966f45ec7bSml29623 */ 3976f45ec7bSml29623 void *nxge_list = NULL; 3986f45ec7bSml29623 void *nxge_hw_list = NULL; 3996f45ec7bSml29623 nxge_os_mutex_t nxge_common_lock; 4003b2d9860SMichael Speer nxge_os_mutex_t nxgedebuglock; 4016f45ec7bSml29623 4026f45ec7bSml29623 extern uint64_t npi_debug_level; 4036f45ec7bSml29623 4046f45ec7bSml29623 extern nxge_status_t nxge_ldgv_init(p_nxge_t, int *, int *); 4056f45ec7bSml29623 extern nxge_status_t nxge_ldgv_init_n2(p_nxge_t, int *, int *); 4066f45ec7bSml29623 extern nxge_status_t nxge_ldgv_uninit(p_nxge_t); 4076f45ec7bSml29623 extern nxge_status_t nxge_intr_ldgv_init(p_nxge_t); 4086f45ec7bSml29623 extern void nxge_fm_init(p_nxge_t, 4096f45ec7bSml29623 ddi_device_acc_attr_t *, 4106f45ec7bSml29623 ddi_dma_attr_t *); 4116f45ec7bSml29623 extern void nxge_fm_fini(p_nxge_t); 4126f45ec7bSml29623 extern npi_status_t npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t); 4136f45ec7bSml29623 4146f45ec7bSml29623 /* 4156f45ec7bSml29623 * Count used to maintain the number of buffers being used 4166f45ec7bSml29623 * by Neptune instances and loaned up to the upper layers. 4176f45ec7bSml29623 */ 4186f45ec7bSml29623 uint32_t nxge_mblks_pending = 0; 4196f45ec7bSml29623 4206f45ec7bSml29623 /* 4216f45ec7bSml29623 * Device register access attributes for PIO. 4226f45ec7bSml29623 */ 4236f45ec7bSml29623 static ddi_device_acc_attr_t nxge_dev_reg_acc_attr = { 424837c1ac4SStephen Hanson DDI_DEVICE_ATTR_V1, 4256f45ec7bSml29623 DDI_STRUCTURE_LE_ACC, 4266f45ec7bSml29623 DDI_STRICTORDER_ACC, 427837c1ac4SStephen Hanson DDI_DEFAULT_ACC 4286f45ec7bSml29623 }; 4296f45ec7bSml29623 4306f45ec7bSml29623 /* 4316f45ec7bSml29623 * Device descriptor access attributes for DMA. 4326f45ec7bSml29623 */ 4336f45ec7bSml29623 static ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr = { 4346f45ec7bSml29623 DDI_DEVICE_ATTR_V0, 4356f45ec7bSml29623 DDI_STRUCTURE_LE_ACC, 4366f45ec7bSml29623 DDI_STRICTORDER_ACC 4376f45ec7bSml29623 }; 4386f45ec7bSml29623 4396f45ec7bSml29623 /* 4406f45ec7bSml29623 * Device buffer access attributes for DMA. 4416f45ec7bSml29623 */ 4426f45ec7bSml29623 static ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr = { 4436f45ec7bSml29623 DDI_DEVICE_ATTR_V0, 4446f45ec7bSml29623 DDI_STRUCTURE_BE_ACC, 4456f45ec7bSml29623 DDI_STRICTORDER_ACC 4466f45ec7bSml29623 }; 4476f45ec7bSml29623 4486f45ec7bSml29623 ddi_dma_attr_t nxge_desc_dma_attr = { 4496f45ec7bSml29623 DMA_ATTR_V0, /* version number. */ 4506f45ec7bSml29623 0, /* low address */ 4516f45ec7bSml29623 0xffffffffffffffff, /* high address */ 4526f45ec7bSml29623 0xffffffffffffffff, /* address counter max */ 4536f45ec7bSml29623 #ifndef NIU_PA_WORKAROUND 4546f45ec7bSml29623 0x100000, /* alignment */ 4556f45ec7bSml29623 #else 4566f45ec7bSml29623 0x2000, 4576f45ec7bSml29623 #endif 4586f45ec7bSml29623 0xfc00fc, /* dlim_burstsizes */ 4596f45ec7bSml29623 0x1, /* minimum transfer size */ 4606f45ec7bSml29623 0xffffffffffffffff, /* maximum transfer size */ 4616f45ec7bSml29623 0xffffffffffffffff, /* maximum segment size */ 4626f45ec7bSml29623 1, /* scatter/gather list length */ 4636f45ec7bSml29623 (unsigned int) 1, /* granularity */ 4646f45ec7bSml29623 0 /* attribute flags */ 4656f45ec7bSml29623 }; 4666f45ec7bSml29623 4676f45ec7bSml29623 ddi_dma_attr_t nxge_tx_dma_attr = { 4686f45ec7bSml29623 DMA_ATTR_V0, /* version number. */ 4696f45ec7bSml29623 0, /* low address */ 4706f45ec7bSml29623 0xffffffffffffffff, /* high address */ 4716f45ec7bSml29623 0xffffffffffffffff, /* address counter max */ 4726f45ec7bSml29623 #if defined(_BIG_ENDIAN) 4736f45ec7bSml29623 0x2000, /* alignment */ 4746f45ec7bSml29623 #else 4756f45ec7bSml29623 0x1000, /* alignment */ 4766f45ec7bSml29623 #endif 4776f45ec7bSml29623 0xfc00fc, /* dlim_burstsizes */ 4786f45ec7bSml29623 0x1, /* minimum transfer size */ 4796f45ec7bSml29623 0xffffffffffffffff, /* maximum transfer size */ 4806f45ec7bSml29623 0xffffffffffffffff, /* maximum segment size */ 4816f45ec7bSml29623 5, /* scatter/gather list length */ 4826f45ec7bSml29623 (unsigned int) 1, /* granularity */ 4836f45ec7bSml29623 0 /* attribute flags */ 4846f45ec7bSml29623 }; 4856f45ec7bSml29623 4866f45ec7bSml29623 ddi_dma_attr_t nxge_rx_dma_attr = { 4876f45ec7bSml29623 DMA_ATTR_V0, /* version number. */ 4886f45ec7bSml29623 0, /* low address */ 4896f45ec7bSml29623 0xffffffffffffffff, /* high address */ 4906f45ec7bSml29623 0xffffffffffffffff, /* address counter max */ 4916f45ec7bSml29623 0x2000, /* alignment */ 4926f45ec7bSml29623 0xfc00fc, /* dlim_burstsizes */ 4936f45ec7bSml29623 0x1, /* minimum transfer size */ 4946f45ec7bSml29623 0xffffffffffffffff, /* maximum transfer size */ 4956f45ec7bSml29623 0xffffffffffffffff, /* maximum segment size */ 4966f45ec7bSml29623 1, /* scatter/gather list length */ 4976f45ec7bSml29623 (unsigned int) 1, /* granularity */ 4980e2bd521Ssbehera DDI_DMA_RELAXED_ORDERING /* attribute flags */ 4996f45ec7bSml29623 }; 5006f45ec7bSml29623 5016f45ec7bSml29623 ddi_dma_lim_t nxge_dma_limits = { 5026f45ec7bSml29623 (uint_t)0, /* dlim_addr_lo */ 5036f45ec7bSml29623 (uint_t)0xffffffff, /* dlim_addr_hi */ 5046f45ec7bSml29623 (uint_t)0xffffffff, /* dlim_cntr_max */ 5056f45ec7bSml29623 (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */ 5066f45ec7bSml29623 0x1, /* dlim_minxfer */ 5076f45ec7bSml29623 1024 /* dlim_speed */ 5086f45ec7bSml29623 }; 5096f45ec7bSml29623 5106f45ec7bSml29623 dma_method_t nxge_force_dma = DVMA; 5116f45ec7bSml29623 5126f45ec7bSml29623 /* 5136f45ec7bSml29623 * dma chunk sizes. 5146f45ec7bSml29623 * 5156f45ec7bSml29623 * Try to allocate the largest possible size 5166f45ec7bSml29623 * so that fewer number of dma chunks would be managed 5176f45ec7bSml29623 */ 5186f45ec7bSml29623 #ifdef NIU_PA_WORKAROUND 5196f45ec7bSml29623 size_t alloc_sizes [] = {0x2000}; 5206f45ec7bSml29623 #else 5216f45ec7bSml29623 size_t alloc_sizes [] = {0x1000, 0x2000, 0x4000, 0x8000, 5226f45ec7bSml29623 0x10000, 0x20000, 0x40000, 0x80000, 52330ac2e7bSml29623 0x100000, 0x200000, 0x400000, 0x800000, 52430ac2e7bSml29623 0x1000000, 0x2000000, 0x4000000}; 5256f45ec7bSml29623 #endif 5266f45ec7bSml29623 5276f45ec7bSml29623 /* 5286f45ec7bSml29623 * Translate "dev_t" to a pointer to the associated "dev_info_t". 5296f45ec7bSml29623 */ 5306f45ec7bSml29623 531678453a8Sspeer extern void nxge_get_environs(nxge_t *); 532678453a8Sspeer 5336f45ec7bSml29623 static int 5346f45ec7bSml29623 nxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 5356f45ec7bSml29623 { 5366f45ec7bSml29623 p_nxge_t nxgep = NULL; 5376f45ec7bSml29623 int instance; 5386f45ec7bSml29623 int status = DDI_SUCCESS; 5396f45ec7bSml29623 uint8_t portn; 5406f45ec7bSml29623 nxge_mmac_t *mmac_info; 5416f45ec7bSml29623 5426f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_attach")); 5436f45ec7bSml29623 5446f45ec7bSml29623 /* 5456f45ec7bSml29623 * Get the device instance since we'll need to setup 5466f45ec7bSml29623 * or retrieve a soft state for this instance. 5476f45ec7bSml29623 */ 5486f45ec7bSml29623 instance = ddi_get_instance(dip); 5496f45ec7bSml29623 5506f45ec7bSml29623 switch (cmd) { 5516f45ec7bSml29623 case DDI_ATTACH: 5526f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_ATTACH")); 5536f45ec7bSml29623 break; 5546f45ec7bSml29623 5556f45ec7bSml29623 case DDI_RESUME: 5566f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_RESUME")); 5576f45ec7bSml29623 nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 5586f45ec7bSml29623 if (nxgep == NULL) { 5596f45ec7bSml29623 status = DDI_FAILURE; 5606f45ec7bSml29623 break; 5616f45ec7bSml29623 } 5626f45ec7bSml29623 if (nxgep->dip != dip) { 5636f45ec7bSml29623 status = DDI_FAILURE; 5646f45ec7bSml29623 break; 5656f45ec7bSml29623 } 5666f45ec7bSml29623 if (nxgep->suspended == DDI_PM_SUSPEND) { 5676f45ec7bSml29623 status = ddi_dev_is_needed(nxgep->dip, 0, 1); 5686f45ec7bSml29623 } else { 56956d930aeSspeer status = nxge_resume(nxgep); 5706f45ec7bSml29623 } 5716f45ec7bSml29623 goto nxge_attach_exit; 5726f45ec7bSml29623 5736f45ec7bSml29623 case DDI_PM_RESUME: 5746f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_RESUME")); 5756f45ec7bSml29623 nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 5766f45ec7bSml29623 if (nxgep == NULL) { 5776f45ec7bSml29623 status = DDI_FAILURE; 5786f45ec7bSml29623 break; 5796f45ec7bSml29623 } 5806f45ec7bSml29623 if (nxgep->dip != dip) { 5816f45ec7bSml29623 status = DDI_FAILURE; 5826f45ec7bSml29623 break; 5836f45ec7bSml29623 } 58456d930aeSspeer status = nxge_resume(nxgep); 5856f45ec7bSml29623 goto nxge_attach_exit; 5866f45ec7bSml29623 5876f45ec7bSml29623 default: 5886f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing unknown")); 5896f45ec7bSml29623 status = DDI_FAILURE; 5906f45ec7bSml29623 goto nxge_attach_exit; 5916f45ec7bSml29623 } 5926f45ec7bSml29623 5936f45ec7bSml29623 5946f45ec7bSml29623 if (ddi_soft_state_zalloc(nxge_list, instance) == DDI_FAILURE) { 5956f45ec7bSml29623 status = DDI_FAILURE; 5966f45ec7bSml29623 goto nxge_attach_exit; 5976f45ec7bSml29623 } 5986f45ec7bSml29623 5996f45ec7bSml29623 nxgep = ddi_get_soft_state(nxge_list, instance); 6006f45ec7bSml29623 if (nxgep == NULL) { 6012e59129aSraghus status = NXGE_ERROR; 6022e59129aSraghus goto nxge_attach_fail2; 6036f45ec7bSml29623 } 6046f45ec7bSml29623 60598ecde52Stm144005 nxgep->nxge_magic = NXGE_MAGIC; 60698ecde52Stm144005 6076f45ec7bSml29623 nxgep->drv_state = 0; 6086f45ec7bSml29623 nxgep->dip = dip; 6096f45ec7bSml29623 nxgep->instance = instance; 6106f45ec7bSml29623 nxgep->p_dip = ddi_get_parent(dip); 6116f45ec7bSml29623 nxgep->nxge_debug_level = nxge_debug_level; 6126f45ec7bSml29623 npi_debug_level = nxge_debug_level; 6136f45ec7bSml29623 614678453a8Sspeer /* Are we a guest running in a Hybrid I/O environment? */ 615678453a8Sspeer nxge_get_environs(nxgep); 6166f45ec7bSml29623 6176f45ec7bSml29623 status = nxge_map_regs(nxgep); 618678453a8Sspeer 6196f45ec7bSml29623 if (status != NXGE_OK) { 6206f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_map_regs failed")); 6212e59129aSraghus goto nxge_attach_fail3; 6226f45ec7bSml29623 } 6236f45ec7bSml29623 624837c1ac4SStephen Hanson nxge_fm_init(nxgep, &nxge_dev_reg_acc_attr, &nxge_rx_dma_attr); 625678453a8Sspeer 626678453a8Sspeer /* Create & initialize the per-Neptune data structure */ 627678453a8Sspeer /* (even if we're a guest). */ 6286f45ec7bSml29623 status = nxge_init_common_dev(nxgep); 6296f45ec7bSml29623 if (status != NXGE_OK) { 6306f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6316f45ec7bSml29623 "nxge_init_common_dev failed")); 6322e59129aSraghus goto nxge_attach_fail4; 6336f45ec7bSml29623 } 6346f45ec7bSml29623 635d6d3405fSml29623 /* 636d6d3405fSml29623 * Software workaround: set the replay timer. 637d6d3405fSml29623 */ 638d6d3405fSml29623 if (nxgep->niu_type != N2_NIU) { 639d6d3405fSml29623 nxge_set_pci_replay_timeout(nxgep); 640d6d3405fSml29623 } 641d6d3405fSml29623 642678453a8Sspeer #if defined(sun4v) 643678453a8Sspeer /* This is required by nxge_hio_init(), which follows. */ 644678453a8Sspeer if ((status = nxge_hsvc_register(nxgep)) != DDI_SUCCESS) 6459d5b8bc5SMichael Speer goto nxge_attach_fail4; 646678453a8Sspeer #endif 647678453a8Sspeer 648678453a8Sspeer if ((status = nxge_hio_init(nxgep)) != NXGE_OK) { 649678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 650678453a8Sspeer "nxge_hio_init failed")); 651678453a8Sspeer goto nxge_attach_fail4; 652678453a8Sspeer } 653678453a8Sspeer 65459ac0c16Sdavemq if (nxgep->niu_type == NEPTUNE_2_10GF) { 65559ac0c16Sdavemq if (nxgep->function_num > 1) { 6564202ea4bSsbehera NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Unsupported" 65759ac0c16Sdavemq " function %d. Only functions 0 and 1 are " 65859ac0c16Sdavemq "supported for this card.", nxgep->function_num)); 65959ac0c16Sdavemq status = NXGE_ERROR; 6602e59129aSraghus goto nxge_attach_fail4; 66159ac0c16Sdavemq } 66259ac0c16Sdavemq } 66359ac0c16Sdavemq 664678453a8Sspeer if (isLDOMguest(nxgep)) { 665678453a8Sspeer /* 666678453a8Sspeer * Use the function number here. 667678453a8Sspeer */ 668678453a8Sspeer nxgep->mac.portnum = nxgep->function_num; 669678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_LOGICAL; 670678453a8Sspeer 671678453a8Sspeer /* XXX We'll set the MAC address counts to 1 for now. */ 672678453a8Sspeer mmac_info = &nxgep->nxge_mmac_info; 673678453a8Sspeer mmac_info->num_mmac = 1; 674678453a8Sspeer mmac_info->naddrfree = 1; 675678453a8Sspeer } else { 6766f45ec7bSml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 6776f45ec7bSml29623 nxgep->mac.portnum = portn; 6786f45ec7bSml29623 if ((portn == 0) || (portn == 1)) 6796f45ec7bSml29623 nxgep->mac.porttype = PORT_TYPE_XMAC; 6806f45ec7bSml29623 else 6816f45ec7bSml29623 nxgep->mac.porttype = PORT_TYPE_BMAC; 6826f45ec7bSml29623 /* 6836f45ec7bSml29623 * Neptune has 4 ports, the first 2 ports use XMAC (10G MAC) 6846f45ec7bSml29623 * internally, the rest 2 ports use BMAC (1G "Big" MAC). 6856f45ec7bSml29623 * The two types of MACs have different characterizations. 6866f45ec7bSml29623 */ 6876f45ec7bSml29623 mmac_info = &nxgep->nxge_mmac_info; 6886f45ec7bSml29623 if (nxgep->function_num < 2) { 6896f45ec7bSml29623 mmac_info->num_mmac = XMAC_MAX_ALT_ADDR_ENTRY; 6906f45ec7bSml29623 mmac_info->naddrfree = XMAC_MAX_ALT_ADDR_ENTRY; 6916f45ec7bSml29623 } else { 6926f45ec7bSml29623 mmac_info->num_mmac = BMAC_MAX_ALT_ADDR_ENTRY; 6936f45ec7bSml29623 mmac_info->naddrfree = BMAC_MAX_ALT_ADDR_ENTRY; 6946f45ec7bSml29623 } 695678453a8Sspeer } 6966f45ec7bSml29623 /* 6976f45ec7bSml29623 * Setup the Ndd parameters for the this instance. 6986f45ec7bSml29623 */ 6996f45ec7bSml29623 nxge_init_param(nxgep); 7006f45ec7bSml29623 7016f45ec7bSml29623 /* 7026f45ec7bSml29623 * Setup Register Tracing Buffer. 7036f45ec7bSml29623 */ 7046f45ec7bSml29623 npi_rtrace_buf_init((rtrace_t *)&npi_rtracebuf); 7056f45ec7bSml29623 7066f45ec7bSml29623 /* init stats ptr */ 7076f45ec7bSml29623 nxge_init_statsp(nxgep); 70856d930aeSspeer 70956d930aeSspeer /* 710678453a8Sspeer * Copy the vpd info from eeprom to a local data 711678453a8Sspeer * structure, and then check its validity. 71256d930aeSspeer */ 713678453a8Sspeer if (!isLDOMguest(nxgep)) { 714678453a8Sspeer int *regp; 715678453a8Sspeer uint_t reglen; 716678453a8Sspeer int rv; 717678453a8Sspeer 7182e59129aSraghus nxge_vpd_info_get(nxgep); 71956d930aeSspeer 720678453a8Sspeer /* Find the NIU config handle. */ 721678453a8Sspeer rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, 722678453a8Sspeer ddi_get_parent(nxgep->dip), DDI_PROP_DONTPASS, 723678453a8Sspeer "reg", ®p, ®len); 724678453a8Sspeer 725678453a8Sspeer if (rv != DDI_PROP_SUCCESS) { 726678453a8Sspeer goto nxge_attach_fail5; 727678453a8Sspeer } 728678453a8Sspeer /* 729678453a8Sspeer * The address_hi, that is the first int, in the reg 730678453a8Sspeer * property consists of config handle, but need to remove 731678453a8Sspeer * the bits 28-31 which are OBP specific info. 732678453a8Sspeer */ 733678453a8Sspeer nxgep->niu_cfg_hdl = (*regp) & 0xFFFFFFF; 734678453a8Sspeer ddi_prop_free(regp); 735678453a8Sspeer } 736678453a8Sspeer 73748056c53SMichael Speer /* 73848056c53SMichael Speer * Set the defaults for the MTU size. 73948056c53SMichael Speer */ 74048056c53SMichael Speer nxge_hw_id_init(nxgep); 74148056c53SMichael Speer 742678453a8Sspeer if (isLDOMguest(nxgep)) { 743678453a8Sspeer uchar_t *prop_val; 744678453a8Sspeer uint_t prop_len; 7457b1f684aSSriharsha Basavapatna uint32_t max_frame_size; 746678453a8Sspeer 747678453a8Sspeer extern void nxge_get_logical_props(p_nxge_t); 748678453a8Sspeer 749678453a8Sspeer nxgep->statsp->mac_stats.xcvr_inuse = LOGICAL_XCVR; 750678453a8Sspeer nxgep->mac.portmode = PORT_LOGICAL; 751678453a8Sspeer (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 752678453a8Sspeer "phy-type", "virtual transceiver"); 753678453a8Sspeer 754678453a8Sspeer nxgep->nports = 1; 755678453a8Sspeer nxgep->board_ver = 0; /* XXX What? */ 756678453a8Sspeer 757678453a8Sspeer /* 758678453a8Sspeer * local-mac-address property gives us info on which 759678453a8Sspeer * specific MAC address the Hybrid resource is associated 760678453a8Sspeer * with. 761678453a8Sspeer */ 762678453a8Sspeer if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0, 763678453a8Sspeer "local-mac-address", &prop_val, 764678453a8Sspeer &prop_len) != DDI_PROP_SUCCESS) { 765678453a8Sspeer goto nxge_attach_fail5; 766678453a8Sspeer } 767678453a8Sspeer if (prop_len != ETHERADDRL) { 768678453a8Sspeer ddi_prop_free(prop_val); 769678453a8Sspeer goto nxge_attach_fail5; 770678453a8Sspeer } 771678453a8Sspeer ether_copy(prop_val, nxgep->hio_mac_addr); 772678453a8Sspeer ddi_prop_free(prop_val); 773678453a8Sspeer nxge_get_logical_props(nxgep); 774678453a8Sspeer 7757b1f684aSSriharsha Basavapatna /* 7767b1f684aSSriharsha Basavapatna * Enable Jumbo property based on the "max-frame-size" 7777b1f684aSSriharsha Basavapatna * property value. 7787b1f684aSSriharsha Basavapatna */ 7797b1f684aSSriharsha Basavapatna max_frame_size = ddi_prop_get_int(DDI_DEV_T_ANY, 7807b1f684aSSriharsha Basavapatna nxgep->dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 7817b1f684aSSriharsha Basavapatna "max-frame-size", NXGE_MTU_DEFAULT_MAX); 7827b1f684aSSriharsha Basavapatna if ((max_frame_size > NXGE_MTU_DEFAULT_MAX) && 7837b1f684aSSriharsha Basavapatna (max_frame_size <= TX_JUMBO_MTU)) { 7847b1f684aSSriharsha Basavapatna nxgep->mac.is_jumbo = B_TRUE; 7857b1f684aSSriharsha Basavapatna nxgep->mac.maxframesize = (uint16_t)max_frame_size; 7867b1f684aSSriharsha Basavapatna nxgep->mac.default_mtu = nxgep->mac.maxframesize - 7877b1f684aSSriharsha Basavapatna NXGE_EHEADER_VLAN_CRC; 7887b1f684aSSriharsha Basavapatna } 789678453a8Sspeer } else { 7902e59129aSraghus status = nxge_xcvr_find(nxgep); 7916f45ec7bSml29623 7926f45ec7bSml29623 if (status != NXGE_OK) { 79356d930aeSspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_attach: " 7946f45ec7bSml29623 " Couldn't determine card type" 7956f45ec7bSml29623 " .... exit ")); 7962e59129aSraghus goto nxge_attach_fail5; 7976f45ec7bSml29623 } 7986f45ec7bSml29623 7996f45ec7bSml29623 status = nxge_get_config_properties(nxgep); 8006f45ec7bSml29623 8016f45ec7bSml29623 if (status != NXGE_OK) { 802678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 803678453a8Sspeer "get_hw create failed")); 8046f45ec7bSml29623 goto nxge_attach_fail; 8056f45ec7bSml29623 } 806678453a8Sspeer } 8076f45ec7bSml29623 8086f45ec7bSml29623 /* 8096f45ec7bSml29623 * Setup the Kstats for the driver. 8106f45ec7bSml29623 */ 8116f45ec7bSml29623 nxge_setup_kstats(nxgep); 8126f45ec7bSml29623 813678453a8Sspeer if (!isLDOMguest(nxgep)) 8146f45ec7bSml29623 nxge_setup_param(nxgep); 8156f45ec7bSml29623 8166f45ec7bSml29623 status = nxge_setup_system_dma_pages(nxgep); 8176f45ec7bSml29623 if (status != NXGE_OK) { 8186f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "set dma page failed")); 8196f45ec7bSml29623 goto nxge_attach_fail; 8206f45ec7bSml29623 } 8216f45ec7bSml29623 822678453a8Sspeer 823678453a8Sspeer if (!isLDOMguest(nxgep)) 8246f45ec7bSml29623 nxge_hw_init_niu_common(nxgep); 8256f45ec7bSml29623 8266f45ec7bSml29623 status = nxge_setup_mutexes(nxgep); 8276f45ec7bSml29623 if (status != NXGE_OK) { 8286f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set mutex failed")); 8296f45ec7bSml29623 goto nxge_attach_fail; 8306f45ec7bSml29623 } 8316f45ec7bSml29623 832678453a8Sspeer #if defined(sun4v) 833678453a8Sspeer if (isLDOMguest(nxgep)) { 834678453a8Sspeer /* Find our VR & channel sets. */ 835678453a8Sspeer status = nxge_hio_vr_add(nxgep); 836ef523517SMichael Speer if (status != DDI_SUCCESS) { 837ef523517SMichael Speer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 838330cd344SMichael Speer "nxge_hio_vr_add failed")); 839330cd344SMichael Speer (void) hsvc_unregister(&nxgep->niu_hsvc); 840330cd344SMichael Speer nxgep->niu_hsvc_available = B_FALSE; 841ef523517SMichael Speer goto nxge_attach_fail; 842330cd344SMichael Speer } 843678453a8Sspeer goto nxge_attach_exit; 844678453a8Sspeer } 845678453a8Sspeer #endif 846678453a8Sspeer 8476f45ec7bSml29623 status = nxge_setup_dev(nxgep); 8486f45ec7bSml29623 if (status != DDI_SUCCESS) { 8496f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set dev failed")); 8506f45ec7bSml29623 goto nxge_attach_fail; 8516f45ec7bSml29623 } 8526f45ec7bSml29623 8536f45ec7bSml29623 status = nxge_add_intrs(nxgep); 8546f45ec7bSml29623 if (status != DDI_SUCCESS) { 8556f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "add_intr failed")); 8566f45ec7bSml29623 goto nxge_attach_fail; 8576f45ec7bSml29623 } 858330cd344SMichael Speer 85900161856Syc148097 /* If a guest, register with vio_net instead. */ 8602e59129aSraghus if ((status = nxge_mac_register(nxgep)) != NXGE_OK) { 8616f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 8626f45ec7bSml29623 "unable to register to mac layer (%d)", status)); 8636f45ec7bSml29623 goto nxge_attach_fail; 8646f45ec7bSml29623 } 8656f45ec7bSml29623 8666f45ec7bSml29623 mac_link_update(nxgep->mach, LINK_STATE_UNKNOWN); 8676f45ec7bSml29623 868678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DDI_CTL, 869678453a8Sspeer "registered to mac (instance %d)", instance)); 8706f45ec7bSml29623 87100161856Syc148097 /* nxge_link_monitor calls xcvr.check_link recursively */ 8726f45ec7bSml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 8736f45ec7bSml29623 8746f45ec7bSml29623 goto nxge_attach_exit; 8756f45ec7bSml29623 8766f45ec7bSml29623 nxge_attach_fail: 8776f45ec7bSml29623 nxge_unattach(nxgep); 8782e59129aSraghus goto nxge_attach_fail1; 8792e59129aSraghus 8802e59129aSraghus nxge_attach_fail5: 8812e59129aSraghus /* 8822e59129aSraghus * Tear down the ndd parameters setup. 8832e59129aSraghus */ 8842e59129aSraghus nxge_destroy_param(nxgep); 8852e59129aSraghus 8862e59129aSraghus /* 8872e59129aSraghus * Tear down the kstat setup. 8882e59129aSraghus */ 8892e59129aSraghus nxge_destroy_kstats(nxgep); 8902e59129aSraghus 8912e59129aSraghus nxge_attach_fail4: 8922e59129aSraghus if (nxgep->nxge_hw_p) { 8932e59129aSraghus nxge_uninit_common_dev(nxgep); 8942e59129aSraghus nxgep->nxge_hw_p = NULL; 8952e59129aSraghus } 8962e59129aSraghus 8972e59129aSraghus nxge_attach_fail3: 8982e59129aSraghus /* 8992e59129aSraghus * Unmap the register setup. 9002e59129aSraghus */ 9012e59129aSraghus nxge_unmap_regs(nxgep); 9022e59129aSraghus 9032e59129aSraghus nxge_fm_fini(nxgep); 9042e59129aSraghus 9052e59129aSraghus nxge_attach_fail2: 9062e59129aSraghus ddi_soft_state_free(nxge_list, nxgep->instance); 9072e59129aSraghus 9082e59129aSraghus nxge_attach_fail1: 90956d930aeSspeer if (status != NXGE_OK) 91056d930aeSspeer status = (NXGE_ERROR | NXGE_DDI_FAILED); 9116f45ec7bSml29623 nxgep = NULL; 9126f45ec7bSml29623 9136f45ec7bSml29623 nxge_attach_exit: 9146f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_attach status = 0x%08x", 9156f45ec7bSml29623 status)); 9166f45ec7bSml29623 9176f45ec7bSml29623 return (status); 9186f45ec7bSml29623 } 9196f45ec7bSml29623 9206f45ec7bSml29623 static int 9216f45ec7bSml29623 nxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 9226f45ec7bSml29623 { 9236f45ec7bSml29623 int status = DDI_SUCCESS; 9246f45ec7bSml29623 int instance; 9256f45ec7bSml29623 p_nxge_t nxgep = NULL; 9266f45ec7bSml29623 9276f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_detach")); 9286f45ec7bSml29623 instance = ddi_get_instance(dip); 9296f45ec7bSml29623 nxgep = ddi_get_soft_state(nxge_list, instance); 9306f45ec7bSml29623 if (nxgep == NULL) { 9316f45ec7bSml29623 status = DDI_FAILURE; 9326f45ec7bSml29623 goto nxge_detach_exit; 9336f45ec7bSml29623 } 9346f45ec7bSml29623 9356f45ec7bSml29623 switch (cmd) { 9366f45ec7bSml29623 case DDI_DETACH: 9376f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_DETACH")); 9386f45ec7bSml29623 break; 9396f45ec7bSml29623 9406f45ec7bSml29623 case DDI_PM_SUSPEND: 9416f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_SUSPEND")); 9426f45ec7bSml29623 nxgep->suspended = DDI_PM_SUSPEND; 9436f45ec7bSml29623 nxge_suspend(nxgep); 9446f45ec7bSml29623 break; 9456f45ec7bSml29623 9466f45ec7bSml29623 case DDI_SUSPEND: 9476f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_SUSPEND")); 9486f45ec7bSml29623 if (nxgep->suspended != DDI_PM_SUSPEND) { 9496f45ec7bSml29623 nxgep->suspended = DDI_SUSPEND; 9506f45ec7bSml29623 nxge_suspend(nxgep); 9516f45ec7bSml29623 } 9526f45ec7bSml29623 break; 9536f45ec7bSml29623 9546f45ec7bSml29623 default: 9556f45ec7bSml29623 status = DDI_FAILURE; 9566f45ec7bSml29623 } 9576f45ec7bSml29623 9586f45ec7bSml29623 if (cmd != DDI_DETACH) 9596f45ec7bSml29623 goto nxge_detach_exit; 9606f45ec7bSml29623 9616f45ec7bSml29623 /* 9626f45ec7bSml29623 * Stop the xcvr polling. 9636f45ec7bSml29623 */ 9646f45ec7bSml29623 nxgep->suspended = cmd; 9656f45ec7bSml29623 9666f45ec7bSml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 9676f45ec7bSml29623 96863f531d1SSriharsha Basavapatna if (nxgep->mach && (status = mac_unregister(nxgep->mach)) != 0) { 9696f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 9706f45ec7bSml29623 "<== nxge_detach status = 0x%08X", status)); 9716f45ec7bSml29623 return (DDI_FAILURE); 9726f45ec7bSml29623 } 9736f45ec7bSml29623 9746f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 9756f45ec7bSml29623 "<== nxge_detach (mac_unregister) status = 0x%08X", status)); 9766f45ec7bSml29623 9776f45ec7bSml29623 nxge_unattach(nxgep); 9786f45ec7bSml29623 nxgep = NULL; 9796f45ec7bSml29623 9806f45ec7bSml29623 nxge_detach_exit: 9816f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_detach status = 0x%08X", 9826f45ec7bSml29623 status)); 9836f45ec7bSml29623 9846f45ec7bSml29623 return (status); 9856f45ec7bSml29623 } 9866f45ec7bSml29623 9876f45ec7bSml29623 static void 9886f45ec7bSml29623 nxge_unattach(p_nxge_t nxgep) 9896f45ec7bSml29623 { 9906f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unattach")); 9916f45ec7bSml29623 9926f45ec7bSml29623 if (nxgep == NULL || nxgep->dev_regs == NULL) { 9936f45ec7bSml29623 return; 9946f45ec7bSml29623 } 9956f45ec7bSml29623 99698ecde52Stm144005 nxgep->nxge_magic = 0; 99798ecde52Stm144005 9986f45ec7bSml29623 if (nxgep->nxge_timerid) { 9996f45ec7bSml29623 nxge_stop_timer(nxgep, nxgep->nxge_timerid); 10006f45ec7bSml29623 nxgep->nxge_timerid = 0; 10016f45ec7bSml29623 } 10026f45ec7bSml29623 10036f157acbSml29623 /* 10046f157acbSml29623 * If this flag is set, it will affect the Neptune 10056f157acbSml29623 * only. 10066f157acbSml29623 */ 10076f157acbSml29623 if ((nxgep->niu_type != N2_NIU) && nxge_peu_reset_enable) { 10086f157acbSml29623 nxge_niu_peu_reset(nxgep); 10096f157acbSml29623 } 10106f157acbSml29623 1011678453a8Sspeer #if defined(sun4v) 1012678453a8Sspeer if (isLDOMguest(nxgep)) { 1013d00f30bbSspeer (void) nxge_hio_vr_release(nxgep); 1014678453a8Sspeer } 1015678453a8Sspeer #endif 1016678453a8Sspeer 101753560810Ssbehera if (nxgep->nxge_hw_p) { 101853560810Ssbehera nxge_uninit_common_dev(nxgep); 101953560810Ssbehera nxgep->nxge_hw_p = NULL; 102053560810Ssbehera } 102153560810Ssbehera 10226f45ec7bSml29623 #if defined(sun4v) 10236f45ec7bSml29623 if (nxgep->niu_type == N2_NIU && nxgep->niu_hsvc_available == B_TRUE) { 10246f45ec7bSml29623 (void) hsvc_unregister(&nxgep->niu_hsvc); 10256f45ec7bSml29623 nxgep->niu_hsvc_available = B_FALSE; 10266f45ec7bSml29623 } 10276f45ec7bSml29623 #endif 10286f45ec7bSml29623 /* 10296f45ec7bSml29623 * Stop any further interrupts. 10306f45ec7bSml29623 */ 10316f45ec7bSml29623 nxge_remove_intrs(nxgep); 10326f45ec7bSml29623 10336f45ec7bSml29623 /* 10346f45ec7bSml29623 * Stop the device and free resources. 10356f45ec7bSml29623 */ 1036678453a8Sspeer if (!isLDOMguest(nxgep)) { 10376f45ec7bSml29623 nxge_destroy_dev(nxgep); 1038678453a8Sspeer } 10396f45ec7bSml29623 10406f45ec7bSml29623 /* 10416f45ec7bSml29623 * Tear down the ndd parameters setup. 10426f45ec7bSml29623 */ 10436f45ec7bSml29623 nxge_destroy_param(nxgep); 10446f45ec7bSml29623 10456f45ec7bSml29623 /* 10466f45ec7bSml29623 * Tear down the kstat setup. 10476f45ec7bSml29623 */ 10486f45ec7bSml29623 nxge_destroy_kstats(nxgep); 10496f45ec7bSml29623 10506f45ec7bSml29623 /* 10519d587972SSantwona Behera * Free any memory allocated for PHY properties 10529d587972SSantwona Behera */ 10539d587972SSantwona Behera if (nxgep->phy_prop.cnt > 0) { 10549d587972SSantwona Behera KMEM_FREE(nxgep->phy_prop.arr, 10559d587972SSantwona Behera sizeof (nxge_phy_mdio_val_t) * nxgep->phy_prop.cnt); 10569d587972SSantwona Behera nxgep->phy_prop.cnt = 0; 10579d587972SSantwona Behera } 10589d587972SSantwona Behera 10599d587972SSantwona Behera /* 10606f45ec7bSml29623 * Destroy all mutexes. 10616f45ec7bSml29623 */ 10626f45ec7bSml29623 nxge_destroy_mutexes(nxgep); 10636f45ec7bSml29623 10646f45ec7bSml29623 /* 10656f45ec7bSml29623 * Remove the list of ndd parameters which 10666f45ec7bSml29623 * were setup during attach. 10676f45ec7bSml29623 */ 10686f45ec7bSml29623 if (nxgep->dip) { 10696f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, OBP_CTL, 10706f45ec7bSml29623 " nxge_unattach: remove all properties")); 10716f45ec7bSml29623 10726f45ec7bSml29623 (void) ddi_prop_remove_all(nxgep->dip); 10736f45ec7bSml29623 } 10746f45ec7bSml29623 10756f45ec7bSml29623 #if NXGE_PROPERTY 10766f45ec7bSml29623 nxge_remove_hard_properties(nxgep); 10776f45ec7bSml29623 #endif 10786f45ec7bSml29623 10796f45ec7bSml29623 /* 10806f45ec7bSml29623 * Unmap the register setup. 10816f45ec7bSml29623 */ 10826f45ec7bSml29623 nxge_unmap_regs(nxgep); 10836f45ec7bSml29623 10846f45ec7bSml29623 nxge_fm_fini(nxgep); 10856f45ec7bSml29623 10866f45ec7bSml29623 ddi_soft_state_free(nxge_list, nxgep->instance); 10876f45ec7bSml29623 10886f45ec7bSml29623 NXGE_DEBUG_MSG((NULL, DDI_CTL, "<== nxge_unattach")); 10896f45ec7bSml29623 } 10906f45ec7bSml29623 1091678453a8Sspeer #if defined(sun4v) 1092678453a8Sspeer int 10939d5b8bc5SMichael Speer nxge_hsvc_register(nxge_t *nxgep) 1094678453a8Sspeer { 1095678453a8Sspeer nxge_status_t status; 10964df55fdeSJanie Lu int i, j; 1097678453a8Sspeer 10984df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hsvc_register")); 10994df55fdeSJanie Lu if (nxgep->niu_type != N2_NIU) { 11004df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hsvc_register")); 11014df55fdeSJanie Lu return (DDI_SUCCESS); 11024df55fdeSJanie Lu } 11034df55fdeSJanie Lu 11044df55fdeSJanie Lu /* 11054df55fdeSJanie Lu * Currently, the NIU Hypervisor API supports two major versions: 11064df55fdeSJanie Lu * version 1 and 2. 11074df55fdeSJanie Lu * If Hypervisor introduces a higher major or minor version, 11084df55fdeSJanie Lu * please update NIU_MAJOR_HI and NIU_MINOR_HI accordingly. 11094df55fdeSJanie Lu */ 1110678453a8Sspeer nxgep->niu_hsvc_available = B_FALSE; 11114df55fdeSJanie Lu bcopy(&niu_hsvc, &nxgep->niu_hsvc, 11124df55fdeSJanie Lu sizeof (hsvc_info_t)); 11134df55fdeSJanie Lu 11144df55fdeSJanie Lu for (i = NIU_MAJOR_HI; i > 0; i--) { 11154df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_major = i; 11164df55fdeSJanie Lu for (j = NIU_MINOR_HI; j >= 0; j--) { 11174df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_minor = j; 11184df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11194df55fdeSJanie Lu "nxge_hsvc_register: %s: negotiating " 11204df55fdeSJanie Lu "hypervisor services revision %d " 11214df55fdeSJanie Lu "group: 0x%lx major: 0x%lx " 11224df55fdeSJanie Lu "minor: 0x%lx", 11234df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_modname, 11244df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_rev, 11254df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_group, 11264df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_major, 11274df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_minor, 11284df55fdeSJanie Lu nxgep->niu_min_ver)); 11294df55fdeSJanie Lu 1130678453a8Sspeer if ((status = hsvc_register(&nxgep->niu_hsvc, 11314df55fdeSJanie Lu &nxgep->niu_min_ver)) == 0) { 11324df55fdeSJanie Lu /* Use the supported minor */ 11334df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_minor = nxgep->niu_min_ver; 11344df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11354df55fdeSJanie Lu "nxge_hsvc_register: %s: negotiated " 11364df55fdeSJanie Lu "hypervisor services revision %d " 11374df55fdeSJanie Lu "group: 0x%lx major: 0x%lx " 11384df55fdeSJanie Lu "minor: 0x%lx (niu_min_ver 0x%lx)", 11394df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_modname, 11404df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_rev, 11414df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_group, 11424df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_major, 11434df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_minor, 11444df55fdeSJanie Lu nxgep->niu_min_ver)); 11454df55fdeSJanie Lu 11464df55fdeSJanie Lu nxgep->niu_hsvc_available = B_TRUE; 11474df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11484df55fdeSJanie Lu "<== nxge_hsvc_register: " 11494df55fdeSJanie Lu "NIU Hypervisor service enabled")); 11504df55fdeSJanie Lu return (DDI_SUCCESS); 11514df55fdeSJanie Lu } 11524df55fdeSJanie Lu 11534df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11544df55fdeSJanie Lu "nxge_hsvc_register: %s: negotiated failed - " 11554df55fdeSJanie Lu "try lower major number " 11564df55fdeSJanie Lu "hypervisor services revision %d " 11574df55fdeSJanie Lu "group: 0x%lx major: 0x%lx minor: 0x%lx " 11584df55fdeSJanie Lu "errno: %d", 11594df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_modname, 11604df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_rev, 11614df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_group, 11624df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_major, 11634df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_minor, status)); 11644df55fdeSJanie Lu } 11654df55fdeSJanie Lu } 11664df55fdeSJanie Lu 1167678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 11684df55fdeSJanie Lu "nxge_hsvc_register: %s: cannot negotiate " 1169678453a8Sspeer "hypervisor services revision %d group: 0x%lx " 1170678453a8Sspeer "major: 0x%lx minor: 0x%lx errno: %d", 1171678453a8Sspeer niu_hsvc.hsvc_modname, niu_hsvc.hsvc_rev, 1172678453a8Sspeer niu_hsvc.hsvc_group, niu_hsvc.hsvc_major, 1173678453a8Sspeer niu_hsvc.hsvc_minor, status)); 1174678453a8Sspeer 11754df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11764df55fdeSJanie Lu "<== nxge_hsvc_register: Register to NIU Hypervisor failed")); 11774df55fdeSJanie Lu 11784df55fdeSJanie Lu return (DDI_FAILURE); 1179678453a8Sspeer } 1180678453a8Sspeer #endif 1181678453a8Sspeer 11826f45ec7bSml29623 static char n2_siu_name[] = "niu"; 11836f45ec7bSml29623 11846f45ec7bSml29623 static nxge_status_t 11856f45ec7bSml29623 nxge_map_regs(p_nxge_t nxgep) 11866f45ec7bSml29623 { 11876f45ec7bSml29623 int ddi_status = DDI_SUCCESS; 11886f45ec7bSml29623 p_dev_regs_t dev_regs; 11896f45ec7bSml29623 char buf[MAXPATHLEN + 1]; 11906f45ec7bSml29623 char *devname; 11916f45ec7bSml29623 #ifdef NXGE_DEBUG 11926f45ec7bSml29623 char *sysname; 11936f45ec7bSml29623 #endif 11946f45ec7bSml29623 off_t regsize; 11956f45ec7bSml29623 nxge_status_t status = NXGE_OK; 11966f45ec7bSml29623 #if !defined(_BIG_ENDIAN) 11976f45ec7bSml29623 off_t pci_offset; 11986f45ec7bSml29623 uint16_t pcie_devctl; 11996f45ec7bSml29623 #endif 12006f45ec7bSml29623 1201678453a8Sspeer if (isLDOMguest(nxgep)) { 1202678453a8Sspeer return (nxge_guest_regs_map(nxgep)); 1203678453a8Sspeer } 1204678453a8Sspeer 12056f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_map_regs")); 12066f45ec7bSml29623 nxgep->dev_regs = NULL; 12076f45ec7bSml29623 dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP); 12086f45ec7bSml29623 dev_regs->nxge_regh = NULL; 12096f45ec7bSml29623 dev_regs->nxge_pciregh = NULL; 12106f45ec7bSml29623 dev_regs->nxge_msix_regh = NULL; 12116f45ec7bSml29623 dev_regs->nxge_vir_regh = NULL; 12126f45ec7bSml29623 dev_regs->nxge_vir2_regh = NULL; 121359ac0c16Sdavemq nxgep->niu_type = NIU_TYPE_NONE; 12146f45ec7bSml29623 12156f45ec7bSml29623 devname = ddi_pathname(nxgep->dip, buf); 12166f45ec7bSml29623 ASSERT(strlen(devname) > 0); 12176f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12186f45ec7bSml29623 "nxge_map_regs: pathname devname %s", devname)); 12196f45ec7bSml29623 122000161856Syc148097 /* 122100161856Syc148097 * The driver is running on a N2-NIU system if devname is something 122200161856Syc148097 * like "/niu@80/network@0" 122300161856Syc148097 */ 12246f45ec7bSml29623 if (strstr(devname, n2_siu_name)) { 12256f45ec7bSml29623 /* N2/NIU */ 12266f45ec7bSml29623 nxgep->niu_type = N2_NIU; 12276f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12286f45ec7bSml29623 "nxge_map_regs: N2/NIU devname %s", devname)); 12294df55fdeSJanie Lu /* 12304df55fdeSJanie Lu * Get function number: 12314df55fdeSJanie Lu * - N2/NIU: "/niu@80/network@0" and "/niu@80/network@1" 12324df55fdeSJanie Lu */ 12336f45ec7bSml29623 nxgep->function_num = 12346f45ec7bSml29623 (devname[strlen(devname) -1] == '1' ? 1 : 0); 12356f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12366f45ec7bSml29623 "nxge_map_regs: N2/NIU function number %d", 12376f45ec7bSml29623 nxgep->function_num)); 12386f45ec7bSml29623 } else { 12396f45ec7bSml29623 int *prop_val; 12406f45ec7bSml29623 uint_t prop_len; 12416f45ec7bSml29623 uint8_t func_num; 12426f45ec7bSml29623 12436f45ec7bSml29623 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 12446f45ec7bSml29623 0, "reg", 12456f45ec7bSml29623 &prop_val, &prop_len) != DDI_PROP_SUCCESS) { 12466f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, VPD_CTL, 12476f45ec7bSml29623 "Reg property not found")); 12486f45ec7bSml29623 ddi_status = DDI_FAILURE; 12496f45ec7bSml29623 goto nxge_map_regs_fail0; 12506f45ec7bSml29623 12516f45ec7bSml29623 } else { 12526f45ec7bSml29623 func_num = (prop_val[0] >> 8) & 0x7; 12536f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12546f45ec7bSml29623 "Reg property found: fun # %d", 12556f45ec7bSml29623 func_num)); 12566f45ec7bSml29623 nxgep->function_num = func_num; 1257678453a8Sspeer if (isLDOMguest(nxgep)) { 1258678453a8Sspeer nxgep->function_num /= 2; 1259678453a8Sspeer return (NXGE_OK); 1260678453a8Sspeer } 12616f45ec7bSml29623 ddi_prop_free(prop_val); 12626f45ec7bSml29623 } 12636f45ec7bSml29623 } 12646f45ec7bSml29623 12656f45ec7bSml29623 switch (nxgep->niu_type) { 12666f45ec7bSml29623 default: 12676f45ec7bSml29623 (void) ddi_dev_regsize(nxgep->dip, 0, ®size); 12686f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12696f45ec7bSml29623 "nxge_map_regs: pci config size 0x%x", regsize)); 12706f45ec7bSml29623 12716f45ec7bSml29623 ddi_status = ddi_regs_map_setup(nxgep->dip, 0, 12726f45ec7bSml29623 (caddr_t *)&(dev_regs->nxge_pciregp), 0, 0, 12736f45ec7bSml29623 &nxge_dev_reg_acc_attr, &dev_regs->nxge_pciregh); 12746f45ec7bSml29623 if (ddi_status != DDI_SUCCESS) { 12756f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12766f45ec7bSml29623 "ddi_map_regs, nxge bus config regs failed")); 12776f45ec7bSml29623 goto nxge_map_regs_fail0; 12786f45ec7bSml29623 } 12796f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12806f45ec7bSml29623 "nxge_map_reg: PCI config addr 0x%0llx " 12816f45ec7bSml29623 " handle 0x%0llx", dev_regs->nxge_pciregp, 12826f45ec7bSml29623 dev_regs->nxge_pciregh)); 12836f45ec7bSml29623 /* 12846f45ec7bSml29623 * IMP IMP 12856f45ec7bSml29623 * workaround for bit swapping bug in HW 12866f45ec7bSml29623 * which ends up in no-snoop = yes 12876f45ec7bSml29623 * resulting, in DMA not synched properly 12886f45ec7bSml29623 */ 12896f45ec7bSml29623 #if !defined(_BIG_ENDIAN) 12906f45ec7bSml29623 /* workarounds for x86 systems */ 12916f45ec7bSml29623 pci_offset = 0x80 + PCIE_DEVCTL; 129248056c53SMichael Speer pcie_devctl = pci_config_get16(dev_regs->nxge_pciregh, 129348056c53SMichael Speer pci_offset); 129448056c53SMichael Speer pcie_devctl &= ~PCIE_DEVCTL_ENABLE_NO_SNOOP; 12956f45ec7bSml29623 pcie_devctl |= PCIE_DEVCTL_RO_EN; 12966f45ec7bSml29623 pci_config_put16(dev_regs->nxge_pciregh, pci_offset, 12976f45ec7bSml29623 pcie_devctl); 12986f45ec7bSml29623 #endif 12996f45ec7bSml29623 13006f45ec7bSml29623 (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 13016f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13026f45ec7bSml29623 "nxge_map_regs: pio size 0x%x", regsize)); 13036f45ec7bSml29623 /* set up the device mapped register */ 13046f45ec7bSml29623 ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 13056f45ec7bSml29623 (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 13066f45ec7bSml29623 &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 13076f45ec7bSml29623 if (ddi_status != DDI_SUCCESS) { 13086f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13096f45ec7bSml29623 "ddi_map_regs for Neptune global reg failed")); 13106f45ec7bSml29623 goto nxge_map_regs_fail1; 13116f45ec7bSml29623 } 13126f45ec7bSml29623 13136f45ec7bSml29623 /* set up the msi/msi-x mapped register */ 13146f45ec7bSml29623 (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 13156f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13166f45ec7bSml29623 "nxge_map_regs: msix size 0x%x", regsize)); 13176f45ec7bSml29623 ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 13186f45ec7bSml29623 (caddr_t *)&(dev_regs->nxge_msix_regp), 0, 0, 13196f45ec7bSml29623 &nxge_dev_reg_acc_attr, &dev_regs->nxge_msix_regh); 13206f45ec7bSml29623 if (ddi_status != DDI_SUCCESS) { 13216f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13226f45ec7bSml29623 "ddi_map_regs for msi reg failed")); 13236f45ec7bSml29623 goto nxge_map_regs_fail2; 13246f45ec7bSml29623 } 13256f45ec7bSml29623 13266f45ec7bSml29623 /* set up the vio region mapped register */ 13276f45ec7bSml29623 (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 13286f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13296f45ec7bSml29623 "nxge_map_regs: vio size 0x%x", regsize)); 13306f45ec7bSml29623 ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 13316f45ec7bSml29623 (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 13326f45ec7bSml29623 &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 13336f45ec7bSml29623 13346f45ec7bSml29623 if (ddi_status != DDI_SUCCESS) { 13356f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13366f45ec7bSml29623 "ddi_map_regs for nxge vio reg failed")); 13376f45ec7bSml29623 goto nxge_map_regs_fail3; 13386f45ec7bSml29623 } 13396f45ec7bSml29623 nxgep->dev_regs = dev_regs; 13406f45ec7bSml29623 13416f45ec7bSml29623 NPI_PCI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_pciregh); 13426f45ec7bSml29623 NPI_PCI_ADD_HANDLE_SET(nxgep, 13436f45ec7bSml29623 (npi_reg_ptr_t)dev_regs->nxge_pciregp); 13446f45ec7bSml29623 NPI_MSI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_msix_regh); 13456f45ec7bSml29623 NPI_MSI_ADD_HANDLE_SET(nxgep, 13466f45ec7bSml29623 (npi_reg_ptr_t)dev_regs->nxge_msix_regp); 13476f45ec7bSml29623 13486f45ec7bSml29623 NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 13496f45ec7bSml29623 NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 13506f45ec7bSml29623 13516f45ec7bSml29623 NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 13526f45ec7bSml29623 NPI_REG_ADD_HANDLE_SET(nxgep, 13536f45ec7bSml29623 (npi_reg_ptr_t)dev_regs->nxge_regp); 13546f45ec7bSml29623 13556f45ec7bSml29623 NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 13566f45ec7bSml29623 NPI_VREG_ADD_HANDLE_SET(nxgep, 13576f45ec7bSml29623 (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 13586f45ec7bSml29623 13596f45ec7bSml29623 break; 13606f45ec7bSml29623 13616f45ec7bSml29623 case N2_NIU: 13626f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "ddi_map_regs, NIU")); 13636f45ec7bSml29623 /* 13646f45ec7bSml29623 * Set up the device mapped register (FWARC 2006/556) 13656f45ec7bSml29623 * (changed back to 1: reg starts at 1!) 13666f45ec7bSml29623 */ 13676f45ec7bSml29623 (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 13686f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13696f45ec7bSml29623 "nxge_map_regs: dev size 0x%x", regsize)); 13706f45ec7bSml29623 ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 13716f45ec7bSml29623 (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 13726f45ec7bSml29623 &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 13736f45ec7bSml29623 13746f45ec7bSml29623 if (ddi_status != DDI_SUCCESS) { 13756f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13766f45ec7bSml29623 "ddi_map_regs for N2/NIU, global reg failed ")); 13776f45ec7bSml29623 goto nxge_map_regs_fail1; 13786f45ec7bSml29623 } 13796f45ec7bSml29623 1380678453a8Sspeer /* set up the first vio region mapped register */ 13816f45ec7bSml29623 (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 13826f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13836f45ec7bSml29623 "nxge_map_regs: vio (1) size 0x%x", regsize)); 13846f45ec7bSml29623 ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 13856f45ec7bSml29623 (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 13866f45ec7bSml29623 &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 13876f45ec7bSml29623 13886f45ec7bSml29623 if (ddi_status != DDI_SUCCESS) { 13896f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13906f45ec7bSml29623 "ddi_map_regs for nxge vio reg failed")); 13916f45ec7bSml29623 goto nxge_map_regs_fail2; 13926f45ec7bSml29623 } 1393678453a8Sspeer /* set up the second vio region mapped register */ 13946f45ec7bSml29623 (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 13956f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13966f45ec7bSml29623 "nxge_map_regs: vio (3) size 0x%x", regsize)); 13976f45ec7bSml29623 ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 13986f45ec7bSml29623 (caddr_t *)&(dev_regs->nxge_vir2_regp), 0, 0, 13996f45ec7bSml29623 &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir2_regh); 14006f45ec7bSml29623 14016f45ec7bSml29623 if (ddi_status != DDI_SUCCESS) { 14026f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 14036f45ec7bSml29623 "ddi_map_regs for nxge vio2 reg failed")); 14046f45ec7bSml29623 goto nxge_map_regs_fail3; 14056f45ec7bSml29623 } 14066f45ec7bSml29623 nxgep->dev_regs = dev_regs; 14076f45ec7bSml29623 14086f45ec7bSml29623 NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 14096f45ec7bSml29623 NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 14106f45ec7bSml29623 14116f45ec7bSml29623 NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 14126f45ec7bSml29623 NPI_REG_ADD_HANDLE_SET(nxgep, 14136f45ec7bSml29623 (npi_reg_ptr_t)dev_regs->nxge_regp); 14146f45ec7bSml29623 14156f45ec7bSml29623 NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 14166f45ec7bSml29623 NPI_VREG_ADD_HANDLE_SET(nxgep, 14176f45ec7bSml29623 (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 14186f45ec7bSml29623 14196f45ec7bSml29623 NPI_V2REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir2_regh); 14206f45ec7bSml29623 NPI_V2REG_ADD_HANDLE_SET(nxgep, 14216f45ec7bSml29623 (npi_reg_ptr_t)dev_regs->nxge_vir2_regp); 14226f45ec7bSml29623 14236f45ec7bSml29623 break; 14246f45ec7bSml29623 } 14256f45ec7bSml29623 14266f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "nxge_map_reg: hardware addr 0x%0llx " 14276f45ec7bSml29623 " handle 0x%0llx", dev_regs->nxge_regp, dev_regs->nxge_regh)); 14286f45ec7bSml29623 14296f45ec7bSml29623 goto nxge_map_regs_exit; 14306f45ec7bSml29623 nxge_map_regs_fail3: 14316f45ec7bSml29623 if (dev_regs->nxge_msix_regh) { 14326f45ec7bSml29623 ddi_regs_map_free(&dev_regs->nxge_msix_regh); 14336f45ec7bSml29623 } 14346f45ec7bSml29623 if (dev_regs->nxge_vir_regh) { 14356f45ec7bSml29623 ddi_regs_map_free(&dev_regs->nxge_regh); 14366f45ec7bSml29623 } 14376f45ec7bSml29623 nxge_map_regs_fail2: 14386f45ec7bSml29623 if (dev_regs->nxge_regh) { 14396f45ec7bSml29623 ddi_regs_map_free(&dev_regs->nxge_regh); 14406f45ec7bSml29623 } 14416f45ec7bSml29623 nxge_map_regs_fail1: 14426f45ec7bSml29623 if (dev_regs->nxge_pciregh) { 14436f45ec7bSml29623 ddi_regs_map_free(&dev_regs->nxge_pciregh); 14446f45ec7bSml29623 } 14456f45ec7bSml29623 nxge_map_regs_fail0: 14466f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Freeing register set memory")); 14476f45ec7bSml29623 kmem_free(dev_regs, sizeof (dev_regs_t)); 14486f45ec7bSml29623 14496f45ec7bSml29623 nxge_map_regs_exit: 14506f45ec7bSml29623 if (ddi_status != DDI_SUCCESS) 14516f45ec7bSml29623 status |= (NXGE_ERROR | NXGE_DDI_FAILED); 14526f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_map_regs")); 14536f45ec7bSml29623 return (status); 14546f45ec7bSml29623 } 14556f45ec7bSml29623 14566f45ec7bSml29623 static void 14576f45ec7bSml29623 nxge_unmap_regs(p_nxge_t nxgep) 14586f45ec7bSml29623 { 14596f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unmap_regs")); 1460678453a8Sspeer 1461678453a8Sspeer if (isLDOMguest(nxgep)) { 1462678453a8Sspeer nxge_guest_regs_map_free(nxgep); 1463678453a8Sspeer return; 1464678453a8Sspeer } 1465678453a8Sspeer 14666f45ec7bSml29623 if (nxgep->dev_regs) { 14676f45ec7bSml29623 if (nxgep->dev_regs->nxge_pciregh) { 14686f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 14696f45ec7bSml29623 "==> nxge_unmap_regs: bus")); 14706f45ec7bSml29623 ddi_regs_map_free(&nxgep->dev_regs->nxge_pciregh); 14716f45ec7bSml29623 nxgep->dev_regs->nxge_pciregh = NULL; 14726f45ec7bSml29623 } 14736f45ec7bSml29623 if (nxgep->dev_regs->nxge_regh) { 14746f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 14756f45ec7bSml29623 "==> nxge_unmap_regs: device registers")); 14766f45ec7bSml29623 ddi_regs_map_free(&nxgep->dev_regs->nxge_regh); 14776f45ec7bSml29623 nxgep->dev_regs->nxge_regh = NULL; 14786f45ec7bSml29623 } 14796f45ec7bSml29623 if (nxgep->dev_regs->nxge_msix_regh) { 14806f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 14816f45ec7bSml29623 "==> nxge_unmap_regs: device interrupts")); 14826f45ec7bSml29623 ddi_regs_map_free(&nxgep->dev_regs->nxge_msix_regh); 14836f45ec7bSml29623 nxgep->dev_regs->nxge_msix_regh = NULL; 14846f45ec7bSml29623 } 14856f45ec7bSml29623 if (nxgep->dev_regs->nxge_vir_regh) { 14866f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 14876f45ec7bSml29623 "==> nxge_unmap_regs: vio region")); 14886f45ec7bSml29623 ddi_regs_map_free(&nxgep->dev_regs->nxge_vir_regh); 14896f45ec7bSml29623 nxgep->dev_regs->nxge_vir_regh = NULL; 14906f45ec7bSml29623 } 14916f45ec7bSml29623 if (nxgep->dev_regs->nxge_vir2_regh) { 14926f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 14936f45ec7bSml29623 "==> nxge_unmap_regs: vio2 region")); 14946f45ec7bSml29623 ddi_regs_map_free(&nxgep->dev_regs->nxge_vir2_regh); 14956f45ec7bSml29623 nxgep->dev_regs->nxge_vir2_regh = NULL; 14966f45ec7bSml29623 } 14976f45ec7bSml29623 14986f45ec7bSml29623 kmem_free(nxgep->dev_regs, sizeof (dev_regs_t)); 14996f45ec7bSml29623 nxgep->dev_regs = NULL; 15006f45ec7bSml29623 } 15016f45ec7bSml29623 15026f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_unmap_regs")); 15036f45ec7bSml29623 } 15046f45ec7bSml29623 15056f45ec7bSml29623 static nxge_status_t 15066f45ec7bSml29623 nxge_setup_mutexes(p_nxge_t nxgep) 15076f45ec7bSml29623 { 15086f45ec7bSml29623 int ddi_status = DDI_SUCCESS; 15096f45ec7bSml29623 nxge_status_t status = NXGE_OK; 15106f45ec7bSml29623 nxge_classify_t *classify_ptr; 15116f45ec7bSml29623 int partition; 15126f45ec7bSml29623 15136f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_mutexes")); 15146f45ec7bSml29623 15156f45ec7bSml29623 /* 15166f45ec7bSml29623 * Get the interrupt cookie so the mutexes can be 15176f45ec7bSml29623 * Initialized. 15186f45ec7bSml29623 */ 1519678453a8Sspeer if (isLDOMguest(nxgep)) { 1520678453a8Sspeer nxgep->interrupt_cookie = 0; 1521678453a8Sspeer } else { 15226f45ec7bSml29623 ddi_status = ddi_get_iblock_cookie(nxgep->dip, 0, 15236f45ec7bSml29623 &nxgep->interrupt_cookie); 1524678453a8Sspeer 15256f45ec7bSml29623 if (ddi_status != DDI_SUCCESS) { 15266f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1527678453a8Sspeer "<== nxge_setup_mutexes: failed 0x%x", 1528678453a8Sspeer ddi_status)); 15296f45ec7bSml29623 goto nxge_setup_mutexes_exit; 15306f45ec7bSml29623 } 1531678453a8Sspeer } 15326f45ec7bSml29623 153398ecde52Stm144005 cv_init(&nxgep->poll_cv, NULL, CV_DRIVER, NULL); 153498ecde52Stm144005 MUTEX_INIT(&nxgep->poll_lock, NULL, 153598ecde52Stm144005 MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 153698ecde52Stm144005 15376f45ec7bSml29623 /* 153898ecde52Stm144005 * Initialize mutexes for this device. 15396f45ec7bSml29623 */ 15406f45ec7bSml29623 MUTEX_INIT(nxgep->genlock, NULL, 15416f45ec7bSml29623 MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 15426f45ec7bSml29623 MUTEX_INIT(&nxgep->ouraddr_lock, NULL, 15436f45ec7bSml29623 MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 15446f45ec7bSml29623 MUTEX_INIT(&nxgep->mif_lock, NULL, 15456f45ec7bSml29623 MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 1546678453a8Sspeer MUTEX_INIT(&nxgep->group_lock, NULL, 1547678453a8Sspeer MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 15486f45ec7bSml29623 RW_INIT(&nxgep->filter_lock, NULL, 15496f45ec7bSml29623 RW_DRIVER, (void *)nxgep->interrupt_cookie); 15506f45ec7bSml29623 15516f45ec7bSml29623 classify_ptr = &nxgep->classifier; 15526f45ec7bSml29623 /* 15536f45ec7bSml29623 * FFLP Mutexes are never used in interrupt context 15546f45ec7bSml29623 * as fflp operation can take very long time to 15556f45ec7bSml29623 * complete and hence not suitable to invoke from interrupt 15566f45ec7bSml29623 * handlers. 15576f45ec7bSml29623 */ 15586f45ec7bSml29623 MUTEX_INIT(&classify_ptr->tcam_lock, NULL, 15596f45ec7bSml29623 NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 15602e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 15616f45ec7bSml29623 MUTEX_INIT(&classify_ptr->fcram_lock, NULL, 15626f45ec7bSml29623 NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 15636f45ec7bSml29623 for (partition = 0; partition < MAX_PARTITION; partition++) { 15646f45ec7bSml29623 MUTEX_INIT(&classify_ptr->hash_lock[partition], NULL, 15656f45ec7bSml29623 NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 15666f45ec7bSml29623 } 15676f45ec7bSml29623 } 15686f45ec7bSml29623 15696f45ec7bSml29623 nxge_setup_mutexes_exit: 15706f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 15716f45ec7bSml29623 "<== nxge_setup_mutexes status = %x", status)); 15726f45ec7bSml29623 15736f45ec7bSml29623 if (ddi_status != DDI_SUCCESS) 15746f45ec7bSml29623 status |= (NXGE_ERROR | NXGE_DDI_FAILED); 15756f45ec7bSml29623 15766f45ec7bSml29623 return (status); 15776f45ec7bSml29623 } 15786f45ec7bSml29623 15796f45ec7bSml29623 static void 15806f45ec7bSml29623 nxge_destroy_mutexes(p_nxge_t nxgep) 15816f45ec7bSml29623 { 15826f45ec7bSml29623 int partition; 15836f45ec7bSml29623 nxge_classify_t *classify_ptr; 15846f45ec7bSml29623 15856f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_mutexes")); 15866f45ec7bSml29623 RW_DESTROY(&nxgep->filter_lock); 1587678453a8Sspeer MUTEX_DESTROY(&nxgep->group_lock); 15886f45ec7bSml29623 MUTEX_DESTROY(&nxgep->mif_lock); 15896f45ec7bSml29623 MUTEX_DESTROY(&nxgep->ouraddr_lock); 15906f45ec7bSml29623 MUTEX_DESTROY(nxgep->genlock); 15916f45ec7bSml29623 15926f45ec7bSml29623 classify_ptr = &nxgep->classifier; 15936f45ec7bSml29623 MUTEX_DESTROY(&classify_ptr->tcam_lock); 15946f45ec7bSml29623 159598ecde52Stm144005 /* Destroy all polling resources. */ 159698ecde52Stm144005 MUTEX_DESTROY(&nxgep->poll_lock); 159798ecde52Stm144005 cv_destroy(&nxgep->poll_cv); 159898ecde52Stm144005 15996f45ec7bSml29623 /* free data structures, based on HW type */ 16002e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 16016f45ec7bSml29623 MUTEX_DESTROY(&classify_ptr->fcram_lock); 16026f45ec7bSml29623 for (partition = 0; partition < MAX_PARTITION; partition++) { 16036f45ec7bSml29623 MUTEX_DESTROY(&classify_ptr->hash_lock[partition]); 16046f45ec7bSml29623 } 16056f45ec7bSml29623 } 16066f45ec7bSml29623 16076f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_mutexes")); 16086f45ec7bSml29623 } 16096f45ec7bSml29623 16106f45ec7bSml29623 nxge_status_t 16116f45ec7bSml29623 nxge_init(p_nxge_t nxgep) 16126f45ec7bSml29623 { 16136f45ec7bSml29623 nxge_status_t status = NXGE_OK; 16146f45ec7bSml29623 16156f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_init")); 16166f45ec7bSml29623 16176f45ec7bSml29623 if (nxgep->drv_state & STATE_HW_INITIALIZED) { 16186f45ec7bSml29623 return (status); 16196f45ec7bSml29623 } 16206f45ec7bSml29623 16216f45ec7bSml29623 /* 16226f45ec7bSml29623 * Allocate system memory for the receive/transmit buffer blocks 16236f45ec7bSml29623 * and receive/transmit descriptor rings. 16246f45ec7bSml29623 */ 16256f45ec7bSml29623 status = nxge_alloc_mem_pool(nxgep); 16266f45ec7bSml29623 if (status != NXGE_OK) { 16276f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "alloc mem failed\n")); 16286f45ec7bSml29623 goto nxge_init_fail1; 16296f45ec7bSml29623 } 16306f45ec7bSml29623 1631678453a8Sspeer if (!isLDOMguest(nxgep)) { 16326f45ec7bSml29623 /* 1633678453a8Sspeer * Initialize and enable the TXC registers. 1634678453a8Sspeer * (Globally enable the Tx controller, 1635678453a8Sspeer * enable the port, configure the dma channel bitmap, 16366f45ec7bSml29623 * configure the max burst size). 16376f45ec7bSml29623 */ 16386f45ec7bSml29623 status = nxge_txc_init(nxgep); 16396f45ec7bSml29623 if (status != NXGE_OK) { 1640678453a8Sspeer NXGE_ERROR_MSG((nxgep, 1641678453a8Sspeer NXGE_ERR_CTL, "init txc failed\n")); 16426f45ec7bSml29623 goto nxge_init_fail2; 16436f45ec7bSml29623 } 1644678453a8Sspeer } 16456f45ec7bSml29623 16466f45ec7bSml29623 /* 16476f45ec7bSml29623 * Initialize and enable TXDMA channels. 16486f45ec7bSml29623 */ 16496f45ec7bSml29623 status = nxge_init_txdma_channels(nxgep); 16506f45ec7bSml29623 if (status != NXGE_OK) { 16516f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txdma failed\n")); 16526f45ec7bSml29623 goto nxge_init_fail3; 16536f45ec7bSml29623 } 16546f45ec7bSml29623 16556f45ec7bSml29623 /* 16566f45ec7bSml29623 * Initialize and enable RXDMA channels. 16576f45ec7bSml29623 */ 16586f45ec7bSml29623 status = nxge_init_rxdma_channels(nxgep); 16596f45ec7bSml29623 if (status != NXGE_OK) { 16606f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init rxdma failed\n")); 16616f45ec7bSml29623 goto nxge_init_fail4; 16626f45ec7bSml29623 } 16636f45ec7bSml29623 16646f45ec7bSml29623 /* 1665678453a8Sspeer * The guest domain is now done. 1666678453a8Sspeer */ 1667678453a8Sspeer if (isLDOMguest(nxgep)) { 1668678453a8Sspeer nxgep->drv_state |= STATE_HW_INITIALIZED; 1669678453a8Sspeer goto nxge_init_exit; 1670678453a8Sspeer } 1671678453a8Sspeer 1672678453a8Sspeer /* 16736f45ec7bSml29623 * Initialize TCAM and FCRAM (Neptune). 16746f45ec7bSml29623 */ 16756f45ec7bSml29623 status = nxge_classify_init(nxgep); 16766f45ec7bSml29623 if (status != NXGE_OK) { 16776f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init classify failed\n")); 16786f45ec7bSml29623 goto nxge_init_fail5; 16796f45ec7bSml29623 } 16806f45ec7bSml29623 16816f45ec7bSml29623 /* 16826f45ec7bSml29623 * Initialize ZCP 16836f45ec7bSml29623 */ 16846f45ec7bSml29623 status = nxge_zcp_init(nxgep); 16856f45ec7bSml29623 if (status != NXGE_OK) { 16866f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init ZCP failed\n")); 16876f45ec7bSml29623 goto nxge_init_fail5; 16886f45ec7bSml29623 } 16896f45ec7bSml29623 16906f45ec7bSml29623 /* 16916f45ec7bSml29623 * Initialize IPP. 16926f45ec7bSml29623 */ 16936f45ec7bSml29623 status = nxge_ipp_init(nxgep); 16946f45ec7bSml29623 if (status != NXGE_OK) { 16956f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init IPP failed\n")); 16966f45ec7bSml29623 goto nxge_init_fail5; 16976f45ec7bSml29623 } 16986f45ec7bSml29623 16996f45ec7bSml29623 /* 17006f45ec7bSml29623 * Initialize the MAC block. 17016f45ec7bSml29623 */ 17026f45ec7bSml29623 status = nxge_mac_init(nxgep); 17036f45ec7bSml29623 if (status != NXGE_OK) { 17046f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init MAC failed\n")); 17056f45ec7bSml29623 goto nxge_init_fail5; 17066f45ec7bSml29623 } 17076f45ec7bSml29623 17086f45ec7bSml29623 /* 1709e759c33aSMichael Speer * Enable the interrrupts for DDI. 17106f45ec7bSml29623 */ 1711e759c33aSMichael Speer nxge_intrs_enable(nxgep); 1712e759c33aSMichael Speer 17136f45ec7bSml29623 nxgep->drv_state |= STATE_HW_INITIALIZED; 17146f45ec7bSml29623 17156f45ec7bSml29623 goto nxge_init_exit; 17166f45ec7bSml29623 17176f45ec7bSml29623 nxge_init_fail5: 17186f45ec7bSml29623 nxge_uninit_rxdma_channels(nxgep); 17196f45ec7bSml29623 nxge_init_fail4: 17206f45ec7bSml29623 nxge_uninit_txdma_channels(nxgep); 17216f45ec7bSml29623 nxge_init_fail3: 1722678453a8Sspeer if (!isLDOMguest(nxgep)) { 17236f45ec7bSml29623 (void) nxge_txc_uninit(nxgep); 1724678453a8Sspeer } 17256f45ec7bSml29623 nxge_init_fail2: 17266f45ec7bSml29623 nxge_free_mem_pool(nxgep); 17276f45ec7bSml29623 nxge_init_fail1: 17286f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 17296f45ec7bSml29623 "<== nxge_init status (failed) = 0x%08x", status)); 17306f45ec7bSml29623 return (status); 17316f45ec7bSml29623 17326f45ec7bSml29623 nxge_init_exit: 17336f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_init status = 0x%08x", 17346f45ec7bSml29623 status)); 17356f45ec7bSml29623 return (status); 17366f45ec7bSml29623 } 17376f45ec7bSml29623 17386f45ec7bSml29623 17396f45ec7bSml29623 timeout_id_t 17406f45ec7bSml29623 nxge_start_timer(p_nxge_t nxgep, fptrv_t func, int msec) 17416f45ec7bSml29623 { 17424045d941Ssowmini if ((nxgep->suspended == 0) || (nxgep->suspended == DDI_RESUME)) { 17436f45ec7bSml29623 return (timeout(func, (caddr_t)nxgep, 17446f45ec7bSml29623 drv_usectohz(1000 * msec))); 17456f45ec7bSml29623 } 17466f45ec7bSml29623 return (NULL); 17476f45ec7bSml29623 } 17486f45ec7bSml29623 17496f45ec7bSml29623 /*ARGSUSED*/ 17506f45ec7bSml29623 void 17516f45ec7bSml29623 nxge_stop_timer(p_nxge_t nxgep, timeout_id_t timerid) 17526f45ec7bSml29623 { 17536f45ec7bSml29623 if (timerid) { 17546f45ec7bSml29623 (void) untimeout(timerid); 17556f45ec7bSml29623 } 17566f45ec7bSml29623 } 17576f45ec7bSml29623 17586f45ec7bSml29623 void 17596f45ec7bSml29623 nxge_uninit(p_nxge_t nxgep) 17606f45ec7bSml29623 { 17616f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_uninit")); 17626f45ec7bSml29623 17636f45ec7bSml29623 if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 17646f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 17656f45ec7bSml29623 "==> nxge_uninit: not initialized")); 17666f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 17676f45ec7bSml29623 "<== nxge_uninit")); 17686f45ec7bSml29623 return; 17696f45ec7bSml29623 } 17706f45ec7bSml29623 1771e759c33aSMichael Speer if (!isLDOMguest(nxgep)) { 1772e759c33aSMichael Speer /* 1773e759c33aSMichael Speer * Reset the receive MAC side. 1774e759c33aSMichael Speer */ 1775e759c33aSMichael Speer (void) nxge_rx_mac_disable(nxgep); 1776e759c33aSMichael Speer 1777e759c33aSMichael Speer /* 1778e759c33aSMichael Speer * Drain the IPP. 1779e759c33aSMichael Speer */ 1780e759c33aSMichael Speer (void) nxge_ipp_drain(nxgep); 1781e759c33aSMichael Speer } 1782e759c33aSMichael Speer 17836f45ec7bSml29623 /* stop timer */ 17846f45ec7bSml29623 if (nxgep->nxge_timerid) { 17856f45ec7bSml29623 nxge_stop_timer(nxgep, nxgep->nxge_timerid); 17866f45ec7bSml29623 nxgep->nxge_timerid = 0; 17876f45ec7bSml29623 } 17886f45ec7bSml29623 17896f45ec7bSml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 17906f45ec7bSml29623 (void) nxge_intr_hw_disable(nxgep); 17916f45ec7bSml29623 17926f45ec7bSml29623 17936f45ec7bSml29623 /* Disable and soft reset the IPP */ 1794678453a8Sspeer if (!isLDOMguest(nxgep)) 17956f45ec7bSml29623 (void) nxge_ipp_disable(nxgep); 17966f45ec7bSml29623 17976f45ec7bSml29623 /* Free classification resources */ 17986f45ec7bSml29623 (void) nxge_classify_uninit(nxgep); 17996f45ec7bSml29623 18006f45ec7bSml29623 /* 18016f45ec7bSml29623 * Reset the transmit/receive DMA side. 18026f45ec7bSml29623 */ 18036f45ec7bSml29623 (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 18046f45ec7bSml29623 (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 18056f45ec7bSml29623 18066f45ec7bSml29623 nxge_uninit_txdma_channels(nxgep); 18076f45ec7bSml29623 nxge_uninit_rxdma_channels(nxgep); 18086f45ec7bSml29623 18096f45ec7bSml29623 /* 18106f45ec7bSml29623 * Reset the transmit MAC side. 18116f45ec7bSml29623 */ 18126f45ec7bSml29623 (void) nxge_tx_mac_disable(nxgep); 18136f45ec7bSml29623 18146f45ec7bSml29623 nxge_free_mem_pool(nxgep); 18156f45ec7bSml29623 18166f157acbSml29623 /* 18176f157acbSml29623 * Start the timer if the reset flag is not set. 18186f157acbSml29623 * If this reset flag is set, the link monitor 18196f157acbSml29623 * will not be started in order to stop furthur bus 18206f157acbSml29623 * activities coming from this interface. 18216f157acbSml29623 * The driver will start the monitor function 18226f157acbSml29623 * if the interface was initialized again later. 18236f157acbSml29623 */ 18246f157acbSml29623 if (!nxge_peu_reset_enable) { 18256f45ec7bSml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 18266f157acbSml29623 } 18276f45ec7bSml29623 18286f45ec7bSml29623 nxgep->drv_state &= ~STATE_HW_INITIALIZED; 18296f45ec7bSml29623 18306f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_uninit: " 18316f45ec7bSml29623 "nxge_mblks_pending %d", nxge_mblks_pending)); 18326f45ec7bSml29623 } 18336f45ec7bSml29623 18346f45ec7bSml29623 void 18356f45ec7bSml29623 nxge_get64(p_nxge_t nxgep, p_mblk_t mp) 18366f45ec7bSml29623 { 18376f45ec7bSml29623 uint64_t reg; 18386f45ec7bSml29623 uint64_t regdata; 18396f45ec7bSml29623 int i, retry; 18406f45ec7bSml29623 18416f45ec7bSml29623 bcopy((char *)mp->b_rptr, (char *)®, sizeof (uint64_t)); 18426f45ec7bSml29623 regdata = 0; 18436f45ec7bSml29623 retry = 1; 18446f45ec7bSml29623 18456f45ec7bSml29623 for (i = 0; i < retry; i++) { 18466f45ec7bSml29623 NXGE_REG_RD64(nxgep->npi_handle, reg, ®data); 18476f45ec7bSml29623 } 18486f45ec7bSml29623 bcopy((char *)®data, (char *)mp->b_rptr, sizeof (uint64_t)); 18496f45ec7bSml29623 } 18506f45ec7bSml29623 18516f45ec7bSml29623 void 18526f45ec7bSml29623 nxge_put64(p_nxge_t nxgep, p_mblk_t mp) 18536f45ec7bSml29623 { 18546f45ec7bSml29623 uint64_t reg; 18556f45ec7bSml29623 uint64_t buf[2]; 18566f45ec7bSml29623 18576f45ec7bSml29623 bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t)); 18586f45ec7bSml29623 reg = buf[0]; 18596f45ec7bSml29623 18606f45ec7bSml29623 NXGE_NPI_PIO_WRITE64(nxgep->npi_handle, reg, buf[1]); 18616f45ec7bSml29623 } 18626f45ec7bSml29623 18636f45ec7bSml29623 /*ARGSUSED*/ 18646f45ec7bSml29623 /*VARARGS*/ 18656f45ec7bSml29623 void 18666f45ec7bSml29623 nxge_debug_msg(p_nxge_t nxgep, uint64_t level, char *fmt, ...) 18676f45ec7bSml29623 { 18686f45ec7bSml29623 char msg_buffer[1048]; 18696f45ec7bSml29623 char prefix_buffer[32]; 18706f45ec7bSml29623 int instance; 18716f45ec7bSml29623 uint64_t debug_level; 18726f45ec7bSml29623 int cmn_level = CE_CONT; 18736f45ec7bSml29623 va_list ap; 18746f45ec7bSml29623 1875678453a8Sspeer if (nxgep && nxgep->nxge_debug_level != nxge_debug_level) { 1876678453a8Sspeer /* In case a developer has changed nxge_debug_level. */ 1877678453a8Sspeer if (nxgep->nxge_debug_level != nxge_debug_level) 1878678453a8Sspeer nxgep->nxge_debug_level = nxge_debug_level; 1879678453a8Sspeer } 1880678453a8Sspeer 18816f45ec7bSml29623 debug_level = (nxgep == NULL) ? nxge_debug_level : 18826f45ec7bSml29623 nxgep->nxge_debug_level; 18836f45ec7bSml29623 18846f45ec7bSml29623 if ((level & debug_level) || 18856f45ec7bSml29623 (level == NXGE_NOTE) || 18866f45ec7bSml29623 (level == NXGE_ERR_CTL)) { 18876f45ec7bSml29623 /* do the msg processing */ 18886f45ec7bSml29623 MUTEX_ENTER(&nxgedebuglock); 18896f45ec7bSml29623 18906f45ec7bSml29623 if ((level & NXGE_NOTE)) { 18916f45ec7bSml29623 cmn_level = CE_NOTE; 18926f45ec7bSml29623 } 18936f45ec7bSml29623 18946f45ec7bSml29623 if (level & NXGE_ERR_CTL) { 18956f45ec7bSml29623 cmn_level = CE_WARN; 18966f45ec7bSml29623 } 18976f45ec7bSml29623 18986f45ec7bSml29623 va_start(ap, fmt); 18996f45ec7bSml29623 (void) vsprintf(msg_buffer, fmt, ap); 19006f45ec7bSml29623 va_end(ap); 19016f45ec7bSml29623 if (nxgep == NULL) { 19026f45ec7bSml29623 instance = -1; 19036f45ec7bSml29623 (void) sprintf(prefix_buffer, "%s :", "nxge"); 19046f45ec7bSml29623 } else { 19056f45ec7bSml29623 instance = nxgep->instance; 19066f45ec7bSml29623 (void) sprintf(prefix_buffer, 19076f45ec7bSml29623 "%s%d :", "nxge", instance); 19086f45ec7bSml29623 } 19096f45ec7bSml29623 19106f45ec7bSml29623 MUTEX_EXIT(&nxgedebuglock); 19116f45ec7bSml29623 cmn_err(cmn_level, "!%s %s\n", 19126f45ec7bSml29623 prefix_buffer, msg_buffer); 19136f45ec7bSml29623 19146f45ec7bSml29623 } 19156f45ec7bSml29623 } 19166f45ec7bSml29623 19176f45ec7bSml29623 char * 19186f45ec7bSml29623 nxge_dump_packet(char *addr, int size) 19196f45ec7bSml29623 { 19206f45ec7bSml29623 uchar_t *ap = (uchar_t *)addr; 19216f45ec7bSml29623 int i; 19226f45ec7bSml29623 static char etherbuf[1024]; 19236f45ec7bSml29623 char *cp = etherbuf; 19246f45ec7bSml29623 char digits[] = "0123456789abcdef"; 19256f45ec7bSml29623 19266f45ec7bSml29623 if (!size) 19276f45ec7bSml29623 size = 60; 19286f45ec7bSml29623 19296f45ec7bSml29623 if (size > MAX_DUMP_SZ) { 19306f45ec7bSml29623 /* Dump the leading bytes */ 19316f45ec7bSml29623 for (i = 0; i < MAX_DUMP_SZ/2; i++) { 19326f45ec7bSml29623 if (*ap > 0x0f) 19336f45ec7bSml29623 *cp++ = digits[*ap >> 4]; 19346f45ec7bSml29623 *cp++ = digits[*ap++ & 0xf]; 19356f45ec7bSml29623 *cp++ = ':'; 19366f45ec7bSml29623 } 19376f45ec7bSml29623 for (i = 0; i < 20; i++) 19386f45ec7bSml29623 *cp++ = '.'; 19396f45ec7bSml29623 /* Dump the last MAX_DUMP_SZ/2 bytes */ 19406f45ec7bSml29623 ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ/2)); 19416f45ec7bSml29623 for (i = 0; i < MAX_DUMP_SZ/2; i++) { 19426f45ec7bSml29623 if (*ap > 0x0f) 19436f45ec7bSml29623 *cp++ = digits[*ap >> 4]; 19446f45ec7bSml29623 *cp++ = digits[*ap++ & 0xf]; 19456f45ec7bSml29623 *cp++ = ':'; 19466f45ec7bSml29623 } 19476f45ec7bSml29623 } else { 19486f45ec7bSml29623 for (i = 0; i < size; i++) { 19496f45ec7bSml29623 if (*ap > 0x0f) 19506f45ec7bSml29623 *cp++ = digits[*ap >> 4]; 19516f45ec7bSml29623 *cp++ = digits[*ap++ & 0xf]; 19526f45ec7bSml29623 *cp++ = ':'; 19536f45ec7bSml29623 } 19546f45ec7bSml29623 } 19556f45ec7bSml29623 *--cp = 0; 19566f45ec7bSml29623 return (etherbuf); 19576f45ec7bSml29623 } 19586f45ec7bSml29623 19596f45ec7bSml29623 #ifdef NXGE_DEBUG 19606f45ec7bSml29623 static void 19616f45ec7bSml29623 nxge_test_map_regs(p_nxge_t nxgep) 19626f45ec7bSml29623 { 19636f45ec7bSml29623 ddi_acc_handle_t cfg_handle; 19646f45ec7bSml29623 p_pci_cfg_t cfg_ptr; 19656f45ec7bSml29623 ddi_acc_handle_t dev_handle; 19666f45ec7bSml29623 char *dev_ptr; 19676f45ec7bSml29623 ddi_acc_handle_t pci_config_handle; 19686f45ec7bSml29623 uint32_t regval; 19696f45ec7bSml29623 int i; 19706f45ec7bSml29623 19716f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_test_map_regs")); 19726f45ec7bSml29623 19736f45ec7bSml29623 dev_handle = nxgep->dev_regs->nxge_regh; 19746f45ec7bSml29623 dev_ptr = (char *)nxgep->dev_regs->nxge_regp; 19756f45ec7bSml29623 19762e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 19776f45ec7bSml29623 cfg_handle = nxgep->dev_regs->nxge_pciregh; 19786f45ec7bSml29623 cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 19796f45ec7bSml29623 19806f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 19816f45ec7bSml29623 "Neptune PCI regp cfg_ptr 0x%llx", (char *)cfg_ptr)); 19826f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 19836f45ec7bSml29623 "Neptune PCI cfg_ptr vendor id ptr 0x%llx", 19846f45ec7bSml29623 &cfg_ptr->vendorid)); 19856f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 19866f45ec7bSml29623 "\tvendorid 0x%x devid 0x%x", 19876f45ec7bSml29623 NXGE_PIO_READ16(cfg_handle, &cfg_ptr->vendorid, 0), 19886f45ec7bSml29623 NXGE_PIO_READ16(cfg_handle, &cfg_ptr->devid, 0))); 19896f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 19906f45ec7bSml29623 "PCI BAR: base 0x%x base14 0x%x base 18 0x%x " 19916f45ec7bSml29623 "bar1c 0x%x", 19926f45ec7bSml29623 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base, 0), 19936f45ec7bSml29623 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base14, 0), 19946f45ec7bSml29623 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base18, 0), 19956f45ec7bSml29623 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base1c, 0))); 19966f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 19976f45ec7bSml29623 "\nNeptune PCI BAR: base20 0x%x base24 0x%x " 19986f45ec7bSml29623 "base 28 0x%x bar2c 0x%x\n", 19996f45ec7bSml29623 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base20, 0), 20006f45ec7bSml29623 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base24, 0), 20016f45ec7bSml29623 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base28, 0), 20026f45ec7bSml29623 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base2c, 0))); 20036f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20046f45ec7bSml29623 "\nNeptune PCI BAR: base30 0x%x\n", 20056f45ec7bSml29623 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base30, 0))); 20066f45ec7bSml29623 20076f45ec7bSml29623 cfg_handle = nxgep->dev_regs->nxge_pciregh; 20086f45ec7bSml29623 cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 20096f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20106f45ec7bSml29623 "first 0x%llx second 0x%llx third 0x%llx " 20116f45ec7bSml29623 "last 0x%llx ", 20126f45ec7bSml29623 NXGE_PIO_READ64(dev_handle, 20136f45ec7bSml29623 (uint64_t *)(dev_ptr + 0), 0), 20146f45ec7bSml29623 NXGE_PIO_READ64(dev_handle, 20156f45ec7bSml29623 (uint64_t *)(dev_ptr + 8), 0), 20166f45ec7bSml29623 NXGE_PIO_READ64(dev_handle, 20176f45ec7bSml29623 (uint64_t *)(dev_ptr + 16), 0), 20186f45ec7bSml29623 NXGE_PIO_READ64(cfg_handle, 20196f45ec7bSml29623 (uint64_t *)(dev_ptr + 24), 0))); 20206f45ec7bSml29623 } 20216f45ec7bSml29623 } 20226f45ec7bSml29623 20236f45ec7bSml29623 #endif 20246f45ec7bSml29623 20256f45ec7bSml29623 static void 20266f45ec7bSml29623 nxge_suspend(p_nxge_t nxgep) 20276f45ec7bSml29623 { 20286f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_suspend")); 20296f45ec7bSml29623 20306f45ec7bSml29623 nxge_intrs_disable(nxgep); 20316f45ec7bSml29623 nxge_destroy_dev(nxgep); 20326f45ec7bSml29623 20336f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_suspend")); 20346f45ec7bSml29623 } 20356f45ec7bSml29623 20366f45ec7bSml29623 static nxge_status_t 20376f45ec7bSml29623 nxge_resume(p_nxge_t nxgep) 20386f45ec7bSml29623 { 20396f45ec7bSml29623 nxge_status_t status = NXGE_OK; 20406f45ec7bSml29623 20416f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_resume")); 20426f45ec7bSml29623 204391c98b31Sjoycey nxgep->suspended = DDI_RESUME; 204491c98b31Sjoycey (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 204591c98b31Sjoycey (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_START); 204691c98b31Sjoycey (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START); 204791c98b31Sjoycey (void) nxge_rx_mac_enable(nxgep); 204891c98b31Sjoycey (void) nxge_tx_mac_enable(nxgep); 204991c98b31Sjoycey nxge_intrs_enable(nxgep); 20506f45ec7bSml29623 nxgep->suspended = 0; 20516f45ec7bSml29623 20526f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20536f45ec7bSml29623 "<== nxge_resume status = 0x%x", status)); 20546f45ec7bSml29623 return (status); 20556f45ec7bSml29623 } 20566f45ec7bSml29623 20576f45ec7bSml29623 static nxge_status_t 20586f45ec7bSml29623 nxge_setup_dev(p_nxge_t nxgep) 20596f45ec7bSml29623 { 20606f45ec7bSml29623 nxge_status_t status = NXGE_OK; 20616f45ec7bSml29623 20626f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_dev port %d", 20636f45ec7bSml29623 nxgep->mac.portnum)); 20646f45ec7bSml29623 20656f45ec7bSml29623 status = nxge_link_init(nxgep); 20666f45ec7bSml29623 20676f45ec7bSml29623 if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) { 20686f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20696f45ec7bSml29623 "port%d Bad register acc handle", nxgep->mac.portnum)); 20706f45ec7bSml29623 status = NXGE_ERROR; 20716f45ec7bSml29623 } 20726f45ec7bSml29623 20736f45ec7bSml29623 if (status != NXGE_OK) { 20746f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20756f45ec7bSml29623 " nxge_setup_dev status " 20766f45ec7bSml29623 "(xcvr init 0x%08x)", status)); 20776f45ec7bSml29623 goto nxge_setup_dev_exit; 20786f45ec7bSml29623 } 20796f45ec7bSml29623 20806f45ec7bSml29623 nxge_setup_dev_exit: 20816f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20826f45ec7bSml29623 "<== nxge_setup_dev port %d status = 0x%08x", 20836f45ec7bSml29623 nxgep->mac.portnum, status)); 20846f45ec7bSml29623 20856f45ec7bSml29623 return (status); 20866f45ec7bSml29623 } 20876f45ec7bSml29623 20886f45ec7bSml29623 static void 20896f45ec7bSml29623 nxge_destroy_dev(p_nxge_t nxgep) 20906f45ec7bSml29623 { 20916f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_dev")); 20926f45ec7bSml29623 20936f45ec7bSml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 20946f45ec7bSml29623 20956f45ec7bSml29623 (void) nxge_hw_stop(nxgep); 20966f45ec7bSml29623 20976f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_dev")); 20986f45ec7bSml29623 } 20996f45ec7bSml29623 21006f45ec7bSml29623 static nxge_status_t 21016f45ec7bSml29623 nxge_setup_system_dma_pages(p_nxge_t nxgep) 21026f45ec7bSml29623 { 21036f45ec7bSml29623 int ddi_status = DDI_SUCCESS; 21046f45ec7bSml29623 uint_t count; 21056f45ec7bSml29623 ddi_dma_cookie_t cookie; 21066f45ec7bSml29623 uint_t iommu_pagesize; 21076f45ec7bSml29623 nxge_status_t status = NXGE_OK; 21086f45ec7bSml29623 2109678453a8Sspeer NXGE_ERROR_MSG((nxgep, DDI_CTL, "==> nxge_setup_system_dma_pages")); 21106f45ec7bSml29623 nxgep->sys_page_sz = ddi_ptob(nxgep->dip, (ulong_t)1); 21116f45ec7bSml29623 if (nxgep->niu_type != N2_NIU) { 21126f45ec7bSml29623 iommu_pagesize = dvma_pagesize(nxgep->dip); 21136f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 21146f45ec7bSml29623 " nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 21156f45ec7bSml29623 " default_block_size %d iommu_pagesize %d", 21166f45ec7bSml29623 nxgep->sys_page_sz, 21176f45ec7bSml29623 ddi_ptob(nxgep->dip, (ulong_t)1), 21186f45ec7bSml29623 nxgep->rx_default_block_size, 21196f45ec7bSml29623 iommu_pagesize)); 21206f45ec7bSml29623 21216f45ec7bSml29623 if (iommu_pagesize != 0) { 21226f45ec7bSml29623 if (nxgep->sys_page_sz == iommu_pagesize) { 21236f45ec7bSml29623 if (iommu_pagesize > 0x4000) 21246f45ec7bSml29623 nxgep->sys_page_sz = 0x4000; 21256f45ec7bSml29623 } else { 21266f45ec7bSml29623 if (nxgep->sys_page_sz > iommu_pagesize) 21276f45ec7bSml29623 nxgep->sys_page_sz = iommu_pagesize; 21286f45ec7bSml29623 } 21296f45ec7bSml29623 } 21306f45ec7bSml29623 } 21316f45ec7bSml29623 nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 21326f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 21336f45ec7bSml29623 "==> nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 21346f45ec7bSml29623 "default_block_size %d page mask %d", 21356f45ec7bSml29623 nxgep->sys_page_sz, 21366f45ec7bSml29623 ddi_ptob(nxgep->dip, (ulong_t)1), 21376f45ec7bSml29623 nxgep->rx_default_block_size, 21386f45ec7bSml29623 nxgep->sys_page_mask)); 21396f45ec7bSml29623 21406f45ec7bSml29623 21416f45ec7bSml29623 switch (nxgep->sys_page_sz) { 21426f45ec7bSml29623 default: 21436f45ec7bSml29623 nxgep->sys_page_sz = 0x1000; 21446f45ec7bSml29623 nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 21456f45ec7bSml29623 nxgep->rx_default_block_size = 0x1000; 21466f45ec7bSml29623 nxgep->rx_bksize_code = RBR_BKSIZE_4K; 21476f45ec7bSml29623 break; 21486f45ec7bSml29623 case 0x1000: 21496f45ec7bSml29623 nxgep->rx_default_block_size = 0x1000; 21506f45ec7bSml29623 nxgep->rx_bksize_code = RBR_BKSIZE_4K; 21516f45ec7bSml29623 break; 21526f45ec7bSml29623 case 0x2000: 21536f45ec7bSml29623 nxgep->rx_default_block_size = 0x2000; 21546f45ec7bSml29623 nxgep->rx_bksize_code = RBR_BKSIZE_8K; 21556f45ec7bSml29623 break; 21566f45ec7bSml29623 case 0x4000: 21576f45ec7bSml29623 nxgep->rx_default_block_size = 0x4000; 21586f45ec7bSml29623 nxgep->rx_bksize_code = RBR_BKSIZE_16K; 21596f45ec7bSml29623 break; 21606f45ec7bSml29623 case 0x8000: 21616f45ec7bSml29623 nxgep->rx_default_block_size = 0x8000; 21626f45ec7bSml29623 nxgep->rx_bksize_code = RBR_BKSIZE_32K; 21636f45ec7bSml29623 break; 21646f45ec7bSml29623 } 21656f45ec7bSml29623 21666f45ec7bSml29623 #ifndef USE_RX_BIG_BUF 21676f45ec7bSml29623 nxge_rx_dma_attr.dma_attr_align = nxgep->sys_page_sz; 21686f45ec7bSml29623 #else 21696f45ec7bSml29623 nxgep->rx_default_block_size = 0x2000; 21706f45ec7bSml29623 nxgep->rx_bksize_code = RBR_BKSIZE_8K; 21716f45ec7bSml29623 #endif 21726f45ec7bSml29623 /* 21736f45ec7bSml29623 * Get the system DMA burst size. 21746f45ec7bSml29623 */ 21756f45ec7bSml29623 ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr, 21766f45ec7bSml29623 DDI_DMA_DONTWAIT, 0, 21776f45ec7bSml29623 &nxgep->dmasparehandle); 21786f45ec7bSml29623 if (ddi_status != DDI_SUCCESS) { 21796f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 21806f45ec7bSml29623 "ddi_dma_alloc_handle: failed " 21816f45ec7bSml29623 " status 0x%x", ddi_status)); 21826f45ec7bSml29623 goto nxge_get_soft_properties_exit; 21836f45ec7bSml29623 } 21846f45ec7bSml29623 21856f45ec7bSml29623 ddi_status = ddi_dma_addr_bind_handle(nxgep->dmasparehandle, NULL, 21866f45ec7bSml29623 (caddr_t)nxgep->dmasparehandle, 21876f45ec7bSml29623 sizeof (nxgep->dmasparehandle), 21886f45ec7bSml29623 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 21896f45ec7bSml29623 DDI_DMA_DONTWAIT, 0, 21906f45ec7bSml29623 &cookie, &count); 21916f45ec7bSml29623 if (ddi_status != DDI_DMA_MAPPED) { 21926f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 21936f45ec7bSml29623 "Binding spare handle to find system" 21946f45ec7bSml29623 " burstsize failed.")); 21956f45ec7bSml29623 ddi_status = DDI_FAILURE; 21966f45ec7bSml29623 goto nxge_get_soft_properties_fail1; 21976f45ec7bSml29623 } 21986f45ec7bSml29623 21996f45ec7bSml29623 nxgep->sys_burst_sz = ddi_dma_burstsizes(nxgep->dmasparehandle); 22006f45ec7bSml29623 (void) ddi_dma_unbind_handle(nxgep->dmasparehandle); 22016f45ec7bSml29623 22026f45ec7bSml29623 nxge_get_soft_properties_fail1: 22036f45ec7bSml29623 ddi_dma_free_handle(&nxgep->dmasparehandle); 22046f45ec7bSml29623 22056f45ec7bSml29623 nxge_get_soft_properties_exit: 22066f45ec7bSml29623 22076f45ec7bSml29623 if (ddi_status != DDI_SUCCESS) 22086f45ec7bSml29623 status |= (NXGE_ERROR | NXGE_DDI_FAILED); 22096f45ec7bSml29623 22106f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 22116f45ec7bSml29623 "<== nxge_setup_system_dma_pages status = 0x%08x", status)); 22126f45ec7bSml29623 return (status); 22136f45ec7bSml29623 } 22146f45ec7bSml29623 22156f45ec7bSml29623 static nxge_status_t 22166f45ec7bSml29623 nxge_alloc_mem_pool(p_nxge_t nxgep) 22176f45ec7bSml29623 { 22186f45ec7bSml29623 nxge_status_t status = NXGE_OK; 22196f45ec7bSml29623 22206f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_alloc_mem_pool")); 22216f45ec7bSml29623 22226f45ec7bSml29623 status = nxge_alloc_rx_mem_pool(nxgep); 22236f45ec7bSml29623 if (status != NXGE_OK) { 22246f45ec7bSml29623 return (NXGE_ERROR); 22256f45ec7bSml29623 } 22266f45ec7bSml29623 22276f45ec7bSml29623 status = nxge_alloc_tx_mem_pool(nxgep); 22286f45ec7bSml29623 if (status != NXGE_OK) { 22296f45ec7bSml29623 nxge_free_rx_mem_pool(nxgep); 22306f45ec7bSml29623 return (NXGE_ERROR); 22316f45ec7bSml29623 } 22326f45ec7bSml29623 22336f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_alloc_mem_pool")); 22346f45ec7bSml29623 return (NXGE_OK); 22356f45ec7bSml29623 } 22366f45ec7bSml29623 22376f45ec7bSml29623 static void 22386f45ec7bSml29623 nxge_free_mem_pool(p_nxge_t nxgep) 22396f45ec7bSml29623 { 22406f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_mem_pool")); 22416f45ec7bSml29623 22426f45ec7bSml29623 nxge_free_rx_mem_pool(nxgep); 22436f45ec7bSml29623 nxge_free_tx_mem_pool(nxgep); 22446f45ec7bSml29623 22456f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_mem_pool")); 22466f45ec7bSml29623 } 22476f45ec7bSml29623 2248678453a8Sspeer nxge_status_t 22496f45ec7bSml29623 nxge_alloc_rx_mem_pool(p_nxge_t nxgep) 22506f45ec7bSml29623 { 2251678453a8Sspeer uint32_t rdc_max; 22526f45ec7bSml29623 p_nxge_dma_pt_cfg_t p_all_cfgp; 22536f45ec7bSml29623 p_nxge_hw_pt_cfg_t p_cfgp; 22546f45ec7bSml29623 p_nxge_dma_pool_t dma_poolp; 22556f45ec7bSml29623 p_nxge_dma_common_t *dma_buf_p; 22566f45ec7bSml29623 p_nxge_dma_pool_t dma_cntl_poolp; 22576f45ec7bSml29623 p_nxge_dma_common_t *dma_cntl_p; 22586f45ec7bSml29623 uint32_t *num_chunks; /* per dma */ 22596f45ec7bSml29623 nxge_status_t status = NXGE_OK; 22606f45ec7bSml29623 22616f45ec7bSml29623 uint32_t nxge_port_rbr_size; 22626f45ec7bSml29623 uint32_t nxge_port_rbr_spare_size; 22636f45ec7bSml29623 uint32_t nxge_port_rcr_size; 2264678453a8Sspeer uint32_t rx_cntl_alloc_size; 22656f45ec7bSml29623 22666f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_mem_pool")); 22676f45ec7bSml29623 22686f45ec7bSml29623 p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 22696f45ec7bSml29623 p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 2270678453a8Sspeer rdc_max = NXGE_MAX_RDCS; 22716f45ec7bSml29623 22726f45ec7bSml29623 /* 2273678453a8Sspeer * Allocate memory for the common DMA data structures. 22746f45ec7bSml29623 */ 22756f45ec7bSml29623 dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 22766f45ec7bSml29623 KM_SLEEP); 22776f45ec7bSml29623 dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 2278678453a8Sspeer sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP); 22796f45ec7bSml29623 22806f45ec7bSml29623 dma_cntl_poolp = (p_nxge_dma_pool_t) 22816f45ec7bSml29623 KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 22826f45ec7bSml29623 dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 2283678453a8Sspeer sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP); 22846f45ec7bSml29623 22856f45ec7bSml29623 num_chunks = (uint32_t *)KMEM_ZALLOC( 2286678453a8Sspeer sizeof (uint32_t) * rdc_max, KM_SLEEP); 22876f45ec7bSml29623 22886f45ec7bSml29623 /* 2289678453a8Sspeer * Assume that each DMA channel will be configured with 2290678453a8Sspeer * the default block size. 2291678453a8Sspeer * rbr block counts are modulo the batch count (16). 22926f45ec7bSml29623 */ 22936f45ec7bSml29623 nxge_port_rbr_size = p_all_cfgp->rbr_size; 22946f45ec7bSml29623 nxge_port_rcr_size = p_all_cfgp->rcr_size; 22956f45ec7bSml29623 22966f45ec7bSml29623 if (!nxge_port_rbr_size) { 22976f45ec7bSml29623 nxge_port_rbr_size = NXGE_RBR_RBB_DEFAULT; 22986f45ec7bSml29623 } 22996f45ec7bSml29623 if (nxge_port_rbr_size % NXGE_RXDMA_POST_BATCH) { 23006f45ec7bSml29623 nxge_port_rbr_size = (NXGE_RXDMA_POST_BATCH * 23016f45ec7bSml29623 (nxge_port_rbr_size / NXGE_RXDMA_POST_BATCH + 1)); 23026f45ec7bSml29623 } 23036f45ec7bSml29623 23046f45ec7bSml29623 p_all_cfgp->rbr_size = nxge_port_rbr_size; 23056f45ec7bSml29623 nxge_port_rbr_spare_size = nxge_rbr_spare_size; 23066f45ec7bSml29623 23076f45ec7bSml29623 if (nxge_port_rbr_spare_size % NXGE_RXDMA_POST_BATCH) { 23086f45ec7bSml29623 nxge_port_rbr_spare_size = (NXGE_RXDMA_POST_BATCH * 23096f45ec7bSml29623 (nxge_port_rbr_spare_size / NXGE_RXDMA_POST_BATCH + 1)); 23106f45ec7bSml29623 } 231130ac2e7bSml29623 if (nxge_port_rbr_size > RBR_DEFAULT_MAX_BLKS) { 231230ac2e7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM_CTL, 231330ac2e7bSml29623 "nxge_alloc_rx_mem_pool: RBR size too high %d, " 231430ac2e7bSml29623 "set to default %d", 231530ac2e7bSml29623 nxge_port_rbr_size, RBR_DEFAULT_MAX_BLKS)); 231630ac2e7bSml29623 nxge_port_rbr_size = RBR_DEFAULT_MAX_BLKS; 231730ac2e7bSml29623 } 231830ac2e7bSml29623 if (nxge_port_rcr_size > RCR_DEFAULT_MAX) { 231930ac2e7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM_CTL, 232030ac2e7bSml29623 "nxge_alloc_rx_mem_pool: RCR too high %d, " 232130ac2e7bSml29623 "set to default %d", 232230ac2e7bSml29623 nxge_port_rcr_size, RCR_DEFAULT_MAX)); 232330ac2e7bSml29623 nxge_port_rcr_size = RCR_DEFAULT_MAX; 232430ac2e7bSml29623 } 23256f45ec7bSml29623 23266f45ec7bSml29623 /* 23276f45ec7bSml29623 * N2/NIU has limitation on the descriptor sizes (contiguous 23286f45ec7bSml29623 * memory allocation on data buffers to 4M (contig_mem_alloc) 23296f45ec7bSml29623 * and little endian for control buffers (must use the ddi/dki mem alloc 23306f45ec7bSml29623 * function). 23316f45ec7bSml29623 */ 23326f45ec7bSml29623 #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 23336f45ec7bSml29623 if (nxgep->niu_type == N2_NIU) { 23346f45ec7bSml29623 nxge_port_rbr_spare_size = 0; 23356f45ec7bSml29623 if ((nxge_port_rbr_size > NXGE_NIU_CONTIG_RBR_MAX) || 23366f45ec7bSml29623 (!ISP2(nxge_port_rbr_size))) { 23376f45ec7bSml29623 nxge_port_rbr_size = NXGE_NIU_CONTIG_RBR_MAX; 23386f45ec7bSml29623 } 23396f45ec7bSml29623 if ((nxge_port_rcr_size > NXGE_NIU_CONTIG_RCR_MAX) || 23406f45ec7bSml29623 (!ISP2(nxge_port_rcr_size))) { 23416f45ec7bSml29623 nxge_port_rcr_size = NXGE_NIU_CONTIG_RCR_MAX; 23426f45ec7bSml29623 } 23436f45ec7bSml29623 } 23446f45ec7bSml29623 #endif 23456f45ec7bSml29623 23466f45ec7bSml29623 /* 23476f45ec7bSml29623 * Addresses of receive block ring, receive completion ring and the 23486f45ec7bSml29623 * mailbox must be all cache-aligned (64 bytes). 23496f45ec7bSml29623 */ 23506f45ec7bSml29623 rx_cntl_alloc_size = nxge_port_rbr_size + nxge_port_rbr_spare_size; 23516f45ec7bSml29623 rx_cntl_alloc_size *= (sizeof (rx_desc_t)); 23526f45ec7bSml29623 rx_cntl_alloc_size += (sizeof (rcr_entry_t) * nxge_port_rcr_size); 23536f45ec7bSml29623 rx_cntl_alloc_size += sizeof (rxdma_mailbox_t); 23546f45ec7bSml29623 23556f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_alloc_rx_mem_pool: " 23566f45ec7bSml29623 "nxge_port_rbr_size = %d nxge_port_rbr_spare_size = %d " 23576f45ec7bSml29623 "nxge_port_rcr_size = %d " 23586f45ec7bSml29623 "rx_cntl_alloc_size = %d", 23596f45ec7bSml29623 nxge_port_rbr_size, nxge_port_rbr_spare_size, 23606f45ec7bSml29623 nxge_port_rcr_size, 23616f45ec7bSml29623 rx_cntl_alloc_size)); 23626f45ec7bSml29623 23636f45ec7bSml29623 #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 23646f45ec7bSml29623 if (nxgep->niu_type == N2_NIU) { 2365678453a8Sspeer uint32_t rx_buf_alloc_size = (nxgep->rx_default_block_size * 2366678453a8Sspeer (nxge_port_rbr_size + nxge_port_rbr_spare_size)); 2367678453a8Sspeer 23686f45ec7bSml29623 if (!ISP2(rx_buf_alloc_size)) { 23696f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 23706f45ec7bSml29623 "==> nxge_alloc_rx_mem_pool: " 23716f45ec7bSml29623 " must be power of 2")); 23726f45ec7bSml29623 status |= (NXGE_ERROR | NXGE_DDI_FAILED); 23736f45ec7bSml29623 goto nxge_alloc_rx_mem_pool_exit; 23746f45ec7bSml29623 } 23756f45ec7bSml29623 23766f45ec7bSml29623 if (rx_buf_alloc_size > (1 << 22)) { 23776f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 23786f45ec7bSml29623 "==> nxge_alloc_rx_mem_pool: " 23796f45ec7bSml29623 " limit size to 4M")); 23806f45ec7bSml29623 status |= (NXGE_ERROR | NXGE_DDI_FAILED); 23816f45ec7bSml29623 goto nxge_alloc_rx_mem_pool_exit; 23826f45ec7bSml29623 } 23836f45ec7bSml29623 23846f45ec7bSml29623 if (rx_cntl_alloc_size < 0x2000) { 23856f45ec7bSml29623 rx_cntl_alloc_size = 0x2000; 23866f45ec7bSml29623 } 23876f45ec7bSml29623 } 23886f45ec7bSml29623 #endif 23896f45ec7bSml29623 nxgep->nxge_port_rbr_size = nxge_port_rbr_size; 23906f45ec7bSml29623 nxgep->nxge_port_rcr_size = nxge_port_rcr_size; 2391678453a8Sspeer nxgep->nxge_port_rbr_spare_size = nxge_port_rbr_spare_size; 2392678453a8Sspeer nxgep->nxge_port_rx_cntl_alloc_size = rx_cntl_alloc_size; 23936f45ec7bSml29623 2394678453a8Sspeer dma_poolp->ndmas = p_cfgp->max_rdcs; 23956f45ec7bSml29623 dma_poolp->num_chunks = num_chunks; 23966f45ec7bSml29623 dma_poolp->buf_allocated = B_TRUE; 23976f45ec7bSml29623 nxgep->rx_buf_pool_p = dma_poolp; 23986f45ec7bSml29623 dma_poolp->dma_buf_pool_p = dma_buf_p; 23996f45ec7bSml29623 2400678453a8Sspeer dma_cntl_poolp->ndmas = p_cfgp->max_rdcs; 24016f45ec7bSml29623 dma_cntl_poolp->buf_allocated = B_TRUE; 24026f45ec7bSml29623 nxgep->rx_cntl_pool_p = dma_cntl_poolp; 24036f45ec7bSml29623 dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 24046f45ec7bSml29623 2405678453a8Sspeer /* Allocate the receive rings, too. */ 2406678453a8Sspeer nxgep->rx_rbr_rings = 2407678453a8Sspeer KMEM_ZALLOC(sizeof (rx_rbr_rings_t), KM_SLEEP); 2408678453a8Sspeer nxgep->rx_rbr_rings->rbr_rings = 2409678453a8Sspeer KMEM_ZALLOC(sizeof (p_rx_rbr_ring_t) * rdc_max, KM_SLEEP); 2410678453a8Sspeer nxgep->rx_rcr_rings = 2411678453a8Sspeer KMEM_ZALLOC(sizeof (rx_rcr_rings_t), KM_SLEEP); 2412678453a8Sspeer nxgep->rx_rcr_rings->rcr_rings = 2413678453a8Sspeer KMEM_ZALLOC(sizeof (p_rx_rcr_ring_t) * rdc_max, KM_SLEEP); 2414678453a8Sspeer nxgep->rx_mbox_areas_p = 2415678453a8Sspeer KMEM_ZALLOC(sizeof (rx_mbox_areas_t), KM_SLEEP); 2416678453a8Sspeer nxgep->rx_mbox_areas_p->rxmbox_areas = 2417678453a8Sspeer KMEM_ZALLOC(sizeof (p_rx_mbox_t) * rdc_max, KM_SLEEP); 24186f45ec7bSml29623 2419678453a8Sspeer nxgep->rx_rbr_rings->ndmas = nxgep->rx_rcr_rings->ndmas = 2420678453a8Sspeer p_cfgp->max_rdcs; 24216f45ec7bSml29623 24226f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 2423678453a8Sspeer "<== nxge_alloc_rx_mem_pool:status 0x%08x", status)); 24246f45ec7bSml29623 24256f45ec7bSml29623 nxge_alloc_rx_mem_pool_exit: 2426678453a8Sspeer return (status); 2427678453a8Sspeer } 2428678453a8Sspeer 2429678453a8Sspeer /* 2430678453a8Sspeer * nxge_alloc_rxb 2431678453a8Sspeer * 2432678453a8Sspeer * Allocate buffers for an RDC. 2433678453a8Sspeer * 2434678453a8Sspeer * Arguments: 2435678453a8Sspeer * nxgep 2436678453a8Sspeer * channel The channel to map into our kernel space. 2437678453a8Sspeer * 2438678453a8Sspeer * Notes: 2439678453a8Sspeer * 2440678453a8Sspeer * NPI function calls: 2441678453a8Sspeer * 2442678453a8Sspeer * NXGE function calls: 2443678453a8Sspeer * 2444678453a8Sspeer * Registers accessed: 2445678453a8Sspeer * 2446678453a8Sspeer * Context: 2447678453a8Sspeer * 2448678453a8Sspeer * Taking apart: 2449678453a8Sspeer * 2450678453a8Sspeer * Open questions: 2451678453a8Sspeer * 2452678453a8Sspeer */ 2453678453a8Sspeer nxge_status_t 2454678453a8Sspeer nxge_alloc_rxb( 2455678453a8Sspeer p_nxge_t nxgep, 2456678453a8Sspeer int channel) 2457678453a8Sspeer { 2458678453a8Sspeer size_t rx_buf_alloc_size; 2459678453a8Sspeer nxge_status_t status = NXGE_OK; 2460678453a8Sspeer 2461678453a8Sspeer nxge_dma_common_t **data; 2462678453a8Sspeer nxge_dma_common_t **control; 2463678453a8Sspeer uint32_t *num_chunks; 2464678453a8Sspeer 2465678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb")); 2466678453a8Sspeer 2467678453a8Sspeer /* 2468678453a8Sspeer * Allocate memory for the receive buffers and descriptor rings. 2469678453a8Sspeer * Replace these allocation functions with the interface functions 2470678453a8Sspeer * provided by the partition manager if/when they are available. 2471678453a8Sspeer */ 2472678453a8Sspeer 2473678453a8Sspeer /* 2474678453a8Sspeer * Allocate memory for the receive buffer blocks. 2475678453a8Sspeer */ 2476678453a8Sspeer rx_buf_alloc_size = (nxgep->rx_default_block_size * 2477678453a8Sspeer (nxgep->nxge_port_rbr_size + nxgep->nxge_port_rbr_spare_size)); 2478678453a8Sspeer 2479678453a8Sspeer data = &nxgep->rx_buf_pool_p->dma_buf_pool_p[channel]; 2480678453a8Sspeer num_chunks = &nxgep->rx_buf_pool_p->num_chunks[channel]; 2481678453a8Sspeer 2482678453a8Sspeer if ((status = nxge_alloc_rx_buf_dma( 2483678453a8Sspeer nxgep, channel, data, rx_buf_alloc_size, 2484678453a8Sspeer nxgep->rx_default_block_size, num_chunks)) != NXGE_OK) { 2485678453a8Sspeer return (status); 2486678453a8Sspeer } 2487678453a8Sspeer 2488678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_alloc_rxb(): " 2489678453a8Sspeer "dma %d dma_buf_p %llx &dma_buf_p %llx", channel, *data, data)); 2490678453a8Sspeer 2491678453a8Sspeer /* 2492678453a8Sspeer * Allocate memory for descriptor rings and mailbox. 2493678453a8Sspeer */ 2494678453a8Sspeer control = &nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel]; 2495678453a8Sspeer 2496678453a8Sspeer if ((status = nxge_alloc_rx_cntl_dma( 2497678453a8Sspeer nxgep, channel, control, nxgep->nxge_port_rx_cntl_alloc_size)) 2498678453a8Sspeer != NXGE_OK) { 2499678453a8Sspeer nxge_free_rx_cntl_dma(nxgep, *control); 2500678453a8Sspeer (*data)->buf_alloc_state |= BUF_ALLOCATED_WAIT_FREE; 2501678453a8Sspeer nxge_free_rx_buf_dma(nxgep, *data, *num_chunks); 2502678453a8Sspeer return (status); 2503678453a8Sspeer } 2504678453a8Sspeer 25056f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 25066f45ec7bSml29623 "<== nxge_alloc_rx_mem_pool:status 0x%08x", status)); 25076f45ec7bSml29623 25086f45ec7bSml29623 return (status); 25096f45ec7bSml29623 } 25106f45ec7bSml29623 2511678453a8Sspeer void 2512678453a8Sspeer nxge_free_rxb( 2513678453a8Sspeer p_nxge_t nxgep, 2514678453a8Sspeer int channel) 2515678453a8Sspeer { 2516678453a8Sspeer nxge_dma_common_t *data; 2517678453a8Sspeer nxge_dma_common_t *control; 2518678453a8Sspeer uint32_t num_chunks; 2519678453a8Sspeer 2520678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb")); 2521678453a8Sspeer 2522678453a8Sspeer data = nxgep->rx_buf_pool_p->dma_buf_pool_p[channel]; 2523678453a8Sspeer num_chunks = nxgep->rx_buf_pool_p->num_chunks[channel]; 2524678453a8Sspeer nxge_free_rx_buf_dma(nxgep, data, num_chunks); 2525678453a8Sspeer 2526678453a8Sspeer nxgep->rx_buf_pool_p->dma_buf_pool_p[channel] = 0; 2527678453a8Sspeer nxgep->rx_buf_pool_p->num_chunks[channel] = 0; 2528678453a8Sspeer 2529678453a8Sspeer control = nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel]; 2530678453a8Sspeer nxge_free_rx_cntl_dma(nxgep, control); 2531678453a8Sspeer 2532678453a8Sspeer nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel] = 0; 2533678453a8Sspeer 2534678453a8Sspeer KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 2535678453a8Sspeer KMEM_FREE(control, sizeof (nxge_dma_common_t)); 2536678453a8Sspeer 2537678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_alloc_rbb")); 2538678453a8Sspeer } 2539678453a8Sspeer 25406f45ec7bSml29623 static void 25416f45ec7bSml29623 nxge_free_rx_mem_pool(p_nxge_t nxgep) 25426f45ec7bSml29623 { 2543678453a8Sspeer int rdc_max = NXGE_MAX_RDCS; 25446f45ec7bSml29623 25456f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_mem_pool")); 25466f45ec7bSml29623 2547678453a8Sspeer if (!nxgep->rx_buf_pool_p || !nxgep->rx_buf_pool_p->buf_allocated) { 25486f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 25496f45ec7bSml29623 "<== nxge_free_rx_mem_pool " 25506f45ec7bSml29623 "(null rx buf pool or buf not allocated")); 25516f45ec7bSml29623 return; 25526f45ec7bSml29623 } 2553678453a8Sspeer if (!nxgep->rx_cntl_pool_p || !nxgep->rx_cntl_pool_p->buf_allocated) { 25546f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 25556f45ec7bSml29623 "<== nxge_free_rx_mem_pool " 25566f45ec7bSml29623 "(null rx cntl buf pool or cntl buf not allocated")); 25576f45ec7bSml29623 return; 25586f45ec7bSml29623 } 25596f45ec7bSml29623 2560678453a8Sspeer KMEM_FREE(nxgep->rx_cntl_pool_p->dma_buf_pool_p, 2561678453a8Sspeer sizeof (p_nxge_dma_common_t) * rdc_max); 2562678453a8Sspeer KMEM_FREE(nxgep->rx_cntl_pool_p, sizeof (nxge_dma_pool_t)); 25636f45ec7bSml29623 2564678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p->num_chunks, 2565678453a8Sspeer sizeof (uint32_t) * rdc_max); 2566678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p->dma_buf_pool_p, 2567678453a8Sspeer sizeof (p_nxge_dma_common_t) * rdc_max); 2568678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p, sizeof (nxge_dma_pool_t)); 25696f45ec7bSml29623 2570678453a8Sspeer nxgep->rx_buf_pool_p = 0; 2571678453a8Sspeer nxgep->rx_cntl_pool_p = 0; 25726f45ec7bSml29623 2573678453a8Sspeer KMEM_FREE(nxgep->rx_rbr_rings->rbr_rings, 2574678453a8Sspeer sizeof (p_rx_rbr_ring_t) * rdc_max); 2575678453a8Sspeer KMEM_FREE(nxgep->rx_rbr_rings, sizeof (rx_rbr_rings_t)); 2576678453a8Sspeer KMEM_FREE(nxgep->rx_rcr_rings->rcr_rings, 2577678453a8Sspeer sizeof (p_rx_rcr_ring_t) * rdc_max); 2578678453a8Sspeer KMEM_FREE(nxgep->rx_rcr_rings, sizeof (rx_rcr_rings_t)); 2579678453a8Sspeer KMEM_FREE(nxgep->rx_mbox_areas_p->rxmbox_areas, 2580678453a8Sspeer sizeof (p_rx_mbox_t) * rdc_max); 2581678453a8Sspeer KMEM_FREE(nxgep->rx_mbox_areas_p, sizeof (rx_mbox_areas_t)); 25826f45ec7bSml29623 2583678453a8Sspeer nxgep->rx_rbr_rings = 0; 2584678453a8Sspeer nxgep->rx_rcr_rings = 0; 2585678453a8Sspeer nxgep->rx_mbox_areas_p = 0; 25866f45ec7bSml29623 25876f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_rx_mem_pool")); 25886f45ec7bSml29623 } 25896f45ec7bSml29623 25906f45ec7bSml29623 25916f45ec7bSml29623 static nxge_status_t 25926f45ec7bSml29623 nxge_alloc_rx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 25936f45ec7bSml29623 p_nxge_dma_common_t *dmap, 25946f45ec7bSml29623 size_t alloc_size, size_t block_size, uint32_t *num_chunks) 25956f45ec7bSml29623 { 25966f45ec7bSml29623 p_nxge_dma_common_t rx_dmap; 25976f45ec7bSml29623 nxge_status_t status = NXGE_OK; 25986f45ec7bSml29623 size_t total_alloc_size; 25996f45ec7bSml29623 size_t allocated = 0; 26006f45ec7bSml29623 int i, size_index, array_size; 2601678453a8Sspeer boolean_t use_kmem_alloc = B_FALSE; 26026f45ec7bSml29623 26036f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_buf_dma")); 26046f45ec7bSml29623 26056f45ec7bSml29623 rx_dmap = (p_nxge_dma_common_t) 26066f45ec7bSml29623 KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 26076f45ec7bSml29623 KM_SLEEP); 26086f45ec7bSml29623 26096f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 26106f45ec7bSml29623 " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ", 26116f45ec7bSml29623 dma_channel, alloc_size, block_size, dmap)); 26126f45ec7bSml29623 26136f45ec7bSml29623 total_alloc_size = alloc_size; 26146f45ec7bSml29623 26156f45ec7bSml29623 #if defined(RX_USE_RECLAIM_POST) 26166f45ec7bSml29623 total_alloc_size = alloc_size + alloc_size/4; 26176f45ec7bSml29623 #endif 26186f45ec7bSml29623 26196f45ec7bSml29623 i = 0; 26206f45ec7bSml29623 size_index = 0; 26216f45ec7bSml29623 array_size = sizeof (alloc_sizes)/sizeof (size_t); 26227b26d9ffSSantwona Behera while ((size_index < array_size) && 26237b26d9ffSSantwona Behera (alloc_sizes[size_index] < alloc_size)) 26246f45ec7bSml29623 size_index++; 26256f45ec7bSml29623 if (size_index >= array_size) { 26266f45ec7bSml29623 size_index = array_size - 1; 26276f45ec7bSml29623 } 26286f45ec7bSml29623 2629678453a8Sspeer /* For Neptune, use kmem_alloc if the kmem flag is set. */ 2630678453a8Sspeer if (nxgep->niu_type != N2_NIU && nxge_use_kmem_alloc) { 2631678453a8Sspeer use_kmem_alloc = B_TRUE; 2632678453a8Sspeer #if defined(__i386) || defined(__amd64) 2633678453a8Sspeer size_index = 0; 2634678453a8Sspeer #endif 2635678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2636678453a8Sspeer "==> nxge_alloc_rx_buf_dma: " 2637678453a8Sspeer "Neptune use kmem_alloc() - size_index %d", 2638678453a8Sspeer size_index)); 2639678453a8Sspeer } 2640678453a8Sspeer 26416f45ec7bSml29623 while ((allocated < total_alloc_size) && 26426f45ec7bSml29623 (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 26436f45ec7bSml29623 rx_dmap[i].dma_chunk_index = i; 26446f45ec7bSml29623 rx_dmap[i].block_size = block_size; 26456f45ec7bSml29623 rx_dmap[i].alength = alloc_sizes[size_index]; 26466f45ec7bSml29623 rx_dmap[i].orig_alength = rx_dmap[i].alength; 26476f45ec7bSml29623 rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 26486f45ec7bSml29623 rx_dmap[i].dma_channel = dma_channel; 26496f45ec7bSml29623 rx_dmap[i].contig_alloc_type = B_FALSE; 2650678453a8Sspeer rx_dmap[i].kmem_alloc_type = B_FALSE; 2651678453a8Sspeer rx_dmap[i].buf_alloc_type = DDI_MEM_ALLOC; 26526f45ec7bSml29623 26536f45ec7bSml29623 /* 26546f45ec7bSml29623 * N2/NIU: data buffers must be contiguous as the driver 26556f45ec7bSml29623 * needs to call Hypervisor api to set up 26566f45ec7bSml29623 * logical pages. 26576f45ec7bSml29623 */ 26586f45ec7bSml29623 if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 26596f45ec7bSml29623 rx_dmap[i].contig_alloc_type = B_TRUE; 2660678453a8Sspeer rx_dmap[i].buf_alloc_type = CONTIG_MEM_ALLOC; 2661678453a8Sspeer } else if (use_kmem_alloc) { 2662678453a8Sspeer /* For Neptune, use kmem_alloc */ 2663678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2664678453a8Sspeer "==> nxge_alloc_rx_buf_dma: " 2665678453a8Sspeer "Neptune use kmem_alloc()")); 2666678453a8Sspeer rx_dmap[i].kmem_alloc_type = B_TRUE; 2667678453a8Sspeer rx_dmap[i].buf_alloc_type = KMEM_ALLOC; 26686f45ec7bSml29623 } 26696f45ec7bSml29623 26706f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 26716f45ec7bSml29623 "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x " 26726f45ec7bSml29623 "i %d nblocks %d alength %d", 26736f45ec7bSml29623 dma_channel, i, &rx_dmap[i], block_size, 26746f45ec7bSml29623 i, rx_dmap[i].nblocks, 26756f45ec7bSml29623 rx_dmap[i].alength)); 26766f45ec7bSml29623 status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 26776f45ec7bSml29623 &nxge_rx_dma_attr, 26786f45ec7bSml29623 rx_dmap[i].alength, 26796f45ec7bSml29623 &nxge_dev_buf_dma_acc_attr, 26806f45ec7bSml29623 DDI_DMA_READ | DDI_DMA_STREAMING, 26816f45ec7bSml29623 (p_nxge_dma_common_t)(&rx_dmap[i])); 26826f45ec7bSml29623 if (status != NXGE_OK) { 26836f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2684678453a8Sspeer "nxge_alloc_rx_buf_dma: Alloc Failed: " 2685678453a8Sspeer "dma %d size_index %d size requested %d", 2686678453a8Sspeer dma_channel, 2687678453a8Sspeer size_index, 2688678453a8Sspeer rx_dmap[i].alength)); 26896f45ec7bSml29623 size_index--; 26906f45ec7bSml29623 } else { 2691678453a8Sspeer rx_dmap[i].buf_alloc_state = BUF_ALLOCATED; 2692678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2693678453a8Sspeer " nxge_alloc_rx_buf_dma DONE alloc mem: " 2694678453a8Sspeer "dma %d dma_buf_p $%p kaddrp $%p alength %d " 2695678453a8Sspeer "buf_alloc_state %d alloc_type %d", 2696678453a8Sspeer dma_channel, 2697678453a8Sspeer &rx_dmap[i], 2698678453a8Sspeer rx_dmap[i].kaddrp, 2699678453a8Sspeer rx_dmap[i].alength, 2700678453a8Sspeer rx_dmap[i].buf_alloc_state, 2701678453a8Sspeer rx_dmap[i].buf_alloc_type)); 2702678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 27036f45ec7bSml29623 " alloc_rx_buf_dma allocated rdc %d " 2704678453a8Sspeer "chunk %d size %x dvma %x bufp %llx kaddrp $%p", 27056f45ec7bSml29623 dma_channel, i, rx_dmap[i].alength, 2706678453a8Sspeer rx_dmap[i].ioaddr_pp, &rx_dmap[i], 2707678453a8Sspeer rx_dmap[i].kaddrp)); 27086f45ec7bSml29623 i++; 27096f45ec7bSml29623 allocated += alloc_sizes[size_index]; 27106f45ec7bSml29623 } 27116f45ec7bSml29623 } 27126f45ec7bSml29623 27136f45ec7bSml29623 if (allocated < total_alloc_size) { 271430ac2e7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2715678453a8Sspeer "==> nxge_alloc_rx_buf_dma: not enough for channel %d " 271630ac2e7bSml29623 "allocated 0x%x requested 0x%x", 271730ac2e7bSml29623 dma_channel, 271830ac2e7bSml29623 allocated, total_alloc_size)); 271930ac2e7bSml29623 status = NXGE_ERROR; 27206f45ec7bSml29623 goto nxge_alloc_rx_mem_fail1; 27216f45ec7bSml29623 } 27226f45ec7bSml29623 272330ac2e7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2724678453a8Sspeer "==> nxge_alloc_rx_buf_dma: Allocated for channel %d " 272530ac2e7bSml29623 "allocated 0x%x requested 0x%x", 272630ac2e7bSml29623 dma_channel, 272730ac2e7bSml29623 allocated, total_alloc_size)); 272830ac2e7bSml29623 27296f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 27306f45ec7bSml29623 " alloc_rx_buf_dma rdc %d allocated %d chunks", 27316f45ec7bSml29623 dma_channel, i)); 27326f45ec7bSml29623 *num_chunks = i; 27336f45ec7bSml29623 *dmap = rx_dmap; 27346f45ec7bSml29623 27356f45ec7bSml29623 goto nxge_alloc_rx_mem_exit; 27366f45ec7bSml29623 27376f45ec7bSml29623 nxge_alloc_rx_mem_fail1: 27386f45ec7bSml29623 KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 27396f45ec7bSml29623 27406f45ec7bSml29623 nxge_alloc_rx_mem_exit: 27416f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 27426f45ec7bSml29623 "<== nxge_alloc_rx_buf_dma status 0x%08x", status)); 27436f45ec7bSml29623 27446f45ec7bSml29623 return (status); 27456f45ec7bSml29623 } 27466f45ec7bSml29623 27476f45ec7bSml29623 /*ARGSUSED*/ 27486f45ec7bSml29623 static void 27496f45ec7bSml29623 nxge_free_rx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 27506f45ec7bSml29623 uint32_t num_chunks) 27516f45ec7bSml29623 { 27526f45ec7bSml29623 int i; 27536f45ec7bSml29623 27546f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 27556f45ec7bSml29623 "==> nxge_free_rx_buf_dma: # of chunks %d", num_chunks)); 27566f45ec7bSml29623 2757678453a8Sspeer if (dmap == 0) 2758678453a8Sspeer return; 2759678453a8Sspeer 27606f45ec7bSml29623 for (i = 0; i < num_chunks; i++) { 27616f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 27626f45ec7bSml29623 "==> nxge_free_rx_buf_dma: chunk %d dmap 0x%llx", 27636f45ec7bSml29623 i, dmap)); 2764678453a8Sspeer nxge_dma_free_rx_data_buf(dmap++); 27656f45ec7bSml29623 } 27666f45ec7bSml29623 27676f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_buf_dma")); 27686f45ec7bSml29623 } 27696f45ec7bSml29623 27706f45ec7bSml29623 /*ARGSUSED*/ 27716f45ec7bSml29623 static nxge_status_t 27726f45ec7bSml29623 nxge_alloc_rx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 27736f45ec7bSml29623 p_nxge_dma_common_t *dmap, size_t size) 27746f45ec7bSml29623 { 27756f45ec7bSml29623 p_nxge_dma_common_t rx_dmap; 27766f45ec7bSml29623 nxge_status_t status = NXGE_OK; 27776f45ec7bSml29623 27786f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_cntl_dma")); 27796f45ec7bSml29623 27806f45ec7bSml29623 rx_dmap = (p_nxge_dma_common_t) 27816f45ec7bSml29623 KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 27826f45ec7bSml29623 27836f45ec7bSml29623 rx_dmap->contig_alloc_type = B_FALSE; 2784678453a8Sspeer rx_dmap->kmem_alloc_type = B_FALSE; 27856f45ec7bSml29623 27866f45ec7bSml29623 status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 27876f45ec7bSml29623 &nxge_desc_dma_attr, 27886f45ec7bSml29623 size, 27896f45ec7bSml29623 &nxge_dev_desc_dma_acc_attr, 27906f45ec7bSml29623 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 27916f45ec7bSml29623 rx_dmap); 27926f45ec7bSml29623 if (status != NXGE_OK) { 27936f45ec7bSml29623 goto nxge_alloc_rx_cntl_dma_fail1; 27946f45ec7bSml29623 } 27956f45ec7bSml29623 27966f45ec7bSml29623 *dmap = rx_dmap; 27976f45ec7bSml29623 goto nxge_alloc_rx_cntl_dma_exit; 27986f45ec7bSml29623 27996f45ec7bSml29623 nxge_alloc_rx_cntl_dma_fail1: 28006f45ec7bSml29623 KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t)); 28016f45ec7bSml29623 28026f45ec7bSml29623 nxge_alloc_rx_cntl_dma_exit: 28036f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 28046f45ec7bSml29623 "<== nxge_alloc_rx_cntl_dma status 0x%08x", status)); 28056f45ec7bSml29623 28066f45ec7bSml29623 return (status); 28076f45ec7bSml29623 } 28086f45ec7bSml29623 28096f45ec7bSml29623 /*ARGSUSED*/ 28106f45ec7bSml29623 static void 28116f45ec7bSml29623 nxge_free_rx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 28126f45ec7bSml29623 { 28136f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_rx_cntl_dma")); 28146f45ec7bSml29623 2815678453a8Sspeer if (dmap == 0) 2816678453a8Sspeer return; 2817678453a8Sspeer 28186f45ec7bSml29623 nxge_dma_mem_free(dmap); 28196f45ec7bSml29623 28206f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_rx_cntl_dma")); 28216f45ec7bSml29623 } 28226f45ec7bSml29623 2823678453a8Sspeer typedef struct { 2824678453a8Sspeer size_t tx_size; 2825678453a8Sspeer size_t cr_size; 2826678453a8Sspeer size_t threshhold; 2827678453a8Sspeer } nxge_tdc_sizes_t; 2828678453a8Sspeer 2829678453a8Sspeer static 2830678453a8Sspeer nxge_status_t 2831678453a8Sspeer nxge_tdc_sizes( 2832678453a8Sspeer nxge_t *nxgep, 2833678453a8Sspeer nxge_tdc_sizes_t *sizes) 2834678453a8Sspeer { 2835678453a8Sspeer uint32_t threshhold; /* The bcopy() threshhold */ 2836678453a8Sspeer size_t tx_size; /* Transmit buffer size */ 2837678453a8Sspeer size_t cr_size; /* Completion ring size */ 2838678453a8Sspeer 2839678453a8Sspeer /* 2840678453a8Sspeer * Assume that each DMA channel will be configured with the 2841678453a8Sspeer * default transmit buffer size for copying transmit data. 2842678453a8Sspeer * (If a packet is bigger than this, it will not be copied.) 2843678453a8Sspeer */ 2844678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 2845678453a8Sspeer threshhold = TX_BCOPY_SIZE; 2846678453a8Sspeer } else { 2847678453a8Sspeer threshhold = nxge_bcopy_thresh; 2848678453a8Sspeer } 2849678453a8Sspeer tx_size = nxge_tx_ring_size * threshhold; 2850678453a8Sspeer 2851678453a8Sspeer cr_size = nxge_tx_ring_size * sizeof (tx_desc_t); 2852678453a8Sspeer cr_size += sizeof (txdma_mailbox_t); 2853678453a8Sspeer 2854678453a8Sspeer #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 2855678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 2856678453a8Sspeer if (!ISP2(tx_size)) { 2857678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2858678453a8Sspeer "==> nxge_tdc_sizes: Tx size" 2859678453a8Sspeer " must be power of 2")); 2860678453a8Sspeer return (NXGE_ERROR); 2861678453a8Sspeer } 2862678453a8Sspeer 2863678453a8Sspeer if (tx_size > (1 << 22)) { 2864678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2865678453a8Sspeer "==> nxge_tdc_sizes: Tx size" 2866678453a8Sspeer " limited to 4M")); 2867678453a8Sspeer return (NXGE_ERROR); 2868678453a8Sspeer } 2869678453a8Sspeer 2870678453a8Sspeer if (cr_size < 0x2000) 2871678453a8Sspeer cr_size = 0x2000; 2872678453a8Sspeer } 2873678453a8Sspeer #endif 2874678453a8Sspeer 2875678453a8Sspeer sizes->threshhold = threshhold; 2876678453a8Sspeer sizes->tx_size = tx_size; 2877678453a8Sspeer sizes->cr_size = cr_size; 2878678453a8Sspeer 2879678453a8Sspeer return (NXGE_OK); 2880678453a8Sspeer } 2881678453a8Sspeer /* 2882678453a8Sspeer * nxge_alloc_txb 2883678453a8Sspeer * 2884678453a8Sspeer * Allocate buffers for an TDC. 2885678453a8Sspeer * 2886678453a8Sspeer * Arguments: 2887678453a8Sspeer * nxgep 2888678453a8Sspeer * channel The channel to map into our kernel space. 2889678453a8Sspeer * 2890678453a8Sspeer * Notes: 2891678453a8Sspeer * 2892678453a8Sspeer * NPI function calls: 2893678453a8Sspeer * 2894678453a8Sspeer * NXGE function calls: 2895678453a8Sspeer * 2896678453a8Sspeer * Registers accessed: 2897678453a8Sspeer * 2898678453a8Sspeer * Context: 2899678453a8Sspeer * 2900678453a8Sspeer * Taking apart: 2901678453a8Sspeer * 2902678453a8Sspeer * Open questions: 2903678453a8Sspeer * 2904678453a8Sspeer */ 2905678453a8Sspeer nxge_status_t 2906678453a8Sspeer nxge_alloc_txb( 2907678453a8Sspeer p_nxge_t nxgep, 2908678453a8Sspeer int channel) 2909678453a8Sspeer { 2910678453a8Sspeer nxge_dma_common_t **dma_buf_p; 2911678453a8Sspeer nxge_dma_common_t **dma_cntl_p; 2912678453a8Sspeer uint32_t *num_chunks; 2913678453a8Sspeer nxge_status_t status = NXGE_OK; 2914678453a8Sspeer 2915678453a8Sspeer nxge_tdc_sizes_t sizes; 2916678453a8Sspeer 2917678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tbb")); 2918678453a8Sspeer 2919678453a8Sspeer if (nxge_tdc_sizes(nxgep, &sizes) != NXGE_OK) 2920678453a8Sspeer return (NXGE_ERROR); 2921678453a8Sspeer 2922678453a8Sspeer /* 2923678453a8Sspeer * Allocate memory for transmit buffers and descriptor rings. 2924678453a8Sspeer * Replace these allocation functions with the interface functions 2925678453a8Sspeer * provided by the partition manager Real Soon Now. 2926678453a8Sspeer */ 2927678453a8Sspeer dma_buf_p = &nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2928678453a8Sspeer num_chunks = &nxgep->tx_buf_pool_p->num_chunks[channel]; 2929678453a8Sspeer 2930678453a8Sspeer dma_cntl_p = &nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2931678453a8Sspeer 2932678453a8Sspeer /* 2933678453a8Sspeer * Allocate memory for transmit buffers and descriptor rings. 2934678453a8Sspeer * Replace allocation functions with interface functions provided 2935678453a8Sspeer * by the partition manager when it is available. 2936678453a8Sspeer * 2937678453a8Sspeer * Allocate memory for the transmit buffer pool. 2938678453a8Sspeer */ 2939678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 2940678453a8Sspeer "sizes: tx: %ld, cr:%ld, th:%ld", 2941678453a8Sspeer sizes.tx_size, sizes.cr_size, sizes.threshhold)); 2942678453a8Sspeer 2943678453a8Sspeer *num_chunks = 0; 2944678453a8Sspeer status = nxge_alloc_tx_buf_dma(nxgep, channel, dma_buf_p, 2945678453a8Sspeer sizes.tx_size, sizes.threshhold, num_chunks); 2946678453a8Sspeer if (status != NXGE_OK) { 2947678453a8Sspeer cmn_err(CE_NOTE, "nxge_alloc_tx_buf_dma failed!"); 2948678453a8Sspeer return (status); 2949678453a8Sspeer } 2950678453a8Sspeer 2951678453a8Sspeer /* 2952678453a8Sspeer * Allocate memory for descriptor rings and mailbox. 2953678453a8Sspeer */ 2954678453a8Sspeer status = nxge_alloc_tx_cntl_dma(nxgep, channel, dma_cntl_p, 2955678453a8Sspeer sizes.cr_size); 2956678453a8Sspeer if (status != NXGE_OK) { 2957678453a8Sspeer nxge_free_tx_buf_dma(nxgep, *dma_buf_p, *num_chunks); 2958678453a8Sspeer cmn_err(CE_NOTE, "nxge_alloc_tx_cntl_dma failed!"); 2959678453a8Sspeer return (status); 2960678453a8Sspeer } 2961678453a8Sspeer 2962678453a8Sspeer return (NXGE_OK); 2963678453a8Sspeer } 2964678453a8Sspeer 2965678453a8Sspeer void 2966678453a8Sspeer nxge_free_txb( 2967678453a8Sspeer p_nxge_t nxgep, 2968678453a8Sspeer int channel) 2969678453a8Sspeer { 2970678453a8Sspeer nxge_dma_common_t *data; 2971678453a8Sspeer nxge_dma_common_t *control; 2972678453a8Sspeer uint32_t num_chunks; 2973678453a8Sspeer 2974678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_txb")); 2975678453a8Sspeer 2976678453a8Sspeer data = nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2977678453a8Sspeer num_chunks = nxgep->tx_buf_pool_p->num_chunks[channel]; 2978678453a8Sspeer nxge_free_tx_buf_dma(nxgep, data, num_chunks); 2979678453a8Sspeer 2980678453a8Sspeer nxgep->tx_buf_pool_p->dma_buf_pool_p[channel] = 0; 2981678453a8Sspeer nxgep->tx_buf_pool_p->num_chunks[channel] = 0; 2982678453a8Sspeer 2983678453a8Sspeer control = nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2984678453a8Sspeer nxge_free_tx_cntl_dma(nxgep, control); 2985678453a8Sspeer 2986678453a8Sspeer nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel] = 0; 2987678453a8Sspeer 2988678453a8Sspeer KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 2989678453a8Sspeer KMEM_FREE(control, sizeof (nxge_dma_common_t)); 2990678453a8Sspeer 2991678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_txb")); 2992678453a8Sspeer } 2993678453a8Sspeer 2994678453a8Sspeer /* 2995678453a8Sspeer * nxge_alloc_tx_mem_pool 2996678453a8Sspeer * 2997678453a8Sspeer * This function allocates all of the per-port TDC control data structures. 2998678453a8Sspeer * The per-channel (TDC) data structures are allocated when needed. 2999678453a8Sspeer * 3000678453a8Sspeer * Arguments: 3001678453a8Sspeer * nxgep 3002678453a8Sspeer * 3003678453a8Sspeer * Notes: 3004678453a8Sspeer * 3005678453a8Sspeer * Context: 3006678453a8Sspeer * Any domain 3007678453a8Sspeer */ 3008678453a8Sspeer nxge_status_t 30096f45ec7bSml29623 nxge_alloc_tx_mem_pool(p_nxge_t nxgep) 30106f45ec7bSml29623 { 3011678453a8Sspeer nxge_hw_pt_cfg_t *p_cfgp; 3012678453a8Sspeer nxge_dma_pool_t *dma_poolp; 3013678453a8Sspeer nxge_dma_common_t **dma_buf_p; 3014678453a8Sspeer nxge_dma_pool_t *dma_cntl_poolp; 3015678453a8Sspeer nxge_dma_common_t **dma_cntl_p; 30166f45ec7bSml29623 uint32_t *num_chunks; /* per dma */ 3017678453a8Sspeer int tdc_max; 30186f45ec7bSml29623 30196f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool")); 30206f45ec7bSml29623 3021678453a8Sspeer p_cfgp = &nxgep->pt_config.hw_config; 3022678453a8Sspeer tdc_max = NXGE_MAX_TDCS; 30236f45ec7bSml29623 30246f45ec7bSml29623 /* 30256f45ec7bSml29623 * Allocate memory for each transmit DMA channel. 30266f45ec7bSml29623 */ 30276f45ec7bSml29623 dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 30286f45ec7bSml29623 KM_SLEEP); 30296f45ec7bSml29623 dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 3030678453a8Sspeer sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP); 30316f45ec7bSml29623 30326f45ec7bSml29623 dma_cntl_poolp = (p_nxge_dma_pool_t) 30336f45ec7bSml29623 KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 30346f45ec7bSml29623 dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 3035678453a8Sspeer sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP); 30366f45ec7bSml29623 303730ac2e7bSml29623 if (nxge_tx_ring_size > TDC_DEFAULT_MAX) { 303830ac2e7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM_CTL, 303930ac2e7bSml29623 "nxge_alloc_tx_mem_pool: TDC too high %d, " 304030ac2e7bSml29623 "set to default %d", 304130ac2e7bSml29623 nxge_tx_ring_size, TDC_DEFAULT_MAX)); 304230ac2e7bSml29623 nxge_tx_ring_size = TDC_DEFAULT_MAX; 304330ac2e7bSml29623 } 304430ac2e7bSml29623 30456f45ec7bSml29623 #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 30466f45ec7bSml29623 /* 30476f45ec7bSml29623 * N2/NIU has limitation on the descriptor sizes (contiguous 30486f45ec7bSml29623 * memory allocation on data buffers to 4M (contig_mem_alloc) 30496f45ec7bSml29623 * and little endian for control buffers (must use the ddi/dki mem alloc 30506f45ec7bSml29623 * function). The transmit ring is limited to 8K (includes the 30516f45ec7bSml29623 * mailbox). 30526f45ec7bSml29623 */ 30536f45ec7bSml29623 if (nxgep->niu_type == N2_NIU) { 30546f45ec7bSml29623 if ((nxge_tx_ring_size > NXGE_NIU_CONTIG_TX_MAX) || 30556f45ec7bSml29623 (!ISP2(nxge_tx_ring_size))) { 30566f45ec7bSml29623 nxge_tx_ring_size = NXGE_NIU_CONTIG_TX_MAX; 30576f45ec7bSml29623 } 30586f45ec7bSml29623 } 30596f45ec7bSml29623 #endif 30606f45ec7bSml29623 30616f45ec7bSml29623 nxgep->nxge_port_tx_ring_size = nxge_tx_ring_size; 30626f45ec7bSml29623 30636f45ec7bSml29623 num_chunks = (uint32_t *)KMEM_ZALLOC( 3064678453a8Sspeer sizeof (uint32_t) * tdc_max, KM_SLEEP); 30656f45ec7bSml29623 3066678453a8Sspeer dma_poolp->ndmas = p_cfgp->tdc.owned; 30676f45ec7bSml29623 dma_poolp->num_chunks = num_chunks; 30686f45ec7bSml29623 dma_poolp->dma_buf_pool_p = dma_buf_p; 30696f45ec7bSml29623 nxgep->tx_buf_pool_p = dma_poolp; 30706f45ec7bSml29623 3071678453a8Sspeer dma_poolp->buf_allocated = B_TRUE; 3072678453a8Sspeer 3073678453a8Sspeer dma_cntl_poolp->ndmas = p_cfgp->tdc.owned; 30746f45ec7bSml29623 dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 30756f45ec7bSml29623 nxgep->tx_cntl_pool_p = dma_cntl_poolp; 30766f45ec7bSml29623 3077678453a8Sspeer dma_cntl_poolp->buf_allocated = B_TRUE; 3078678453a8Sspeer 3079678453a8Sspeer nxgep->tx_rings = 3080678453a8Sspeer KMEM_ZALLOC(sizeof (tx_rings_t), KM_SLEEP); 3081678453a8Sspeer nxgep->tx_rings->rings = 3082678453a8Sspeer KMEM_ZALLOC(sizeof (p_tx_ring_t) * tdc_max, KM_SLEEP); 3083678453a8Sspeer nxgep->tx_mbox_areas_p = 3084678453a8Sspeer KMEM_ZALLOC(sizeof (tx_mbox_areas_t), KM_SLEEP); 3085678453a8Sspeer nxgep->tx_mbox_areas_p->txmbox_areas_p = 3086678453a8Sspeer KMEM_ZALLOC(sizeof (p_tx_mbox_t) * tdc_max, KM_SLEEP); 3087678453a8Sspeer 3088678453a8Sspeer nxgep->tx_rings->ndmas = p_cfgp->tdc.owned; 3089678453a8Sspeer 30906f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM_CTL, 3091678453a8Sspeer "==> nxge_alloc_tx_mem_pool: ndmas %d poolp->ndmas %d", 3092678453a8Sspeer tdc_max, dma_poolp->ndmas)); 30936f45ec7bSml29623 3094678453a8Sspeer return (NXGE_OK); 30956f45ec7bSml29623 } 30966f45ec7bSml29623 3097678453a8Sspeer nxge_status_t 30986f45ec7bSml29623 nxge_alloc_tx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 30996f45ec7bSml29623 p_nxge_dma_common_t *dmap, size_t alloc_size, 31006f45ec7bSml29623 size_t block_size, uint32_t *num_chunks) 31016f45ec7bSml29623 { 31026f45ec7bSml29623 p_nxge_dma_common_t tx_dmap; 31036f45ec7bSml29623 nxge_status_t status = NXGE_OK; 31046f45ec7bSml29623 size_t total_alloc_size; 31056f45ec7bSml29623 size_t allocated = 0; 31066f45ec7bSml29623 int i, size_index, array_size; 31076f45ec7bSml29623 31086f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_buf_dma")); 31096f45ec7bSml29623 31106f45ec7bSml29623 tx_dmap = (p_nxge_dma_common_t) 31116f45ec7bSml29623 KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 31126f45ec7bSml29623 KM_SLEEP); 31136f45ec7bSml29623 31146f45ec7bSml29623 total_alloc_size = alloc_size; 31156f45ec7bSml29623 i = 0; 31166f45ec7bSml29623 size_index = 0; 31176f45ec7bSml29623 array_size = sizeof (alloc_sizes) / sizeof (size_t); 31187b26d9ffSSantwona Behera while ((size_index < array_size) && 31197b26d9ffSSantwona Behera (alloc_sizes[size_index] < alloc_size)) 31206f45ec7bSml29623 size_index++; 31216f45ec7bSml29623 if (size_index >= array_size) { 31226f45ec7bSml29623 size_index = array_size - 1; 31236f45ec7bSml29623 } 31246f45ec7bSml29623 31256f45ec7bSml29623 while ((allocated < total_alloc_size) && 31266f45ec7bSml29623 (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 31276f45ec7bSml29623 31286f45ec7bSml29623 tx_dmap[i].dma_chunk_index = i; 31296f45ec7bSml29623 tx_dmap[i].block_size = block_size; 31306f45ec7bSml29623 tx_dmap[i].alength = alloc_sizes[size_index]; 31316f45ec7bSml29623 tx_dmap[i].orig_alength = tx_dmap[i].alength; 31326f45ec7bSml29623 tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 31336f45ec7bSml29623 tx_dmap[i].dma_channel = dma_channel; 31346f45ec7bSml29623 tx_dmap[i].contig_alloc_type = B_FALSE; 3135678453a8Sspeer tx_dmap[i].kmem_alloc_type = B_FALSE; 31366f45ec7bSml29623 31376f45ec7bSml29623 /* 31386f45ec7bSml29623 * N2/NIU: data buffers must be contiguous as the driver 31396f45ec7bSml29623 * needs to call Hypervisor api to set up 31406f45ec7bSml29623 * logical pages. 31416f45ec7bSml29623 */ 31426f45ec7bSml29623 if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 31436f45ec7bSml29623 tx_dmap[i].contig_alloc_type = B_TRUE; 31446f45ec7bSml29623 } 31456f45ec7bSml29623 31466f45ec7bSml29623 status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 31476f45ec7bSml29623 &nxge_tx_dma_attr, 31486f45ec7bSml29623 tx_dmap[i].alength, 31496f45ec7bSml29623 &nxge_dev_buf_dma_acc_attr, 31506f45ec7bSml29623 DDI_DMA_WRITE | DDI_DMA_STREAMING, 31516f45ec7bSml29623 (p_nxge_dma_common_t)(&tx_dmap[i])); 31526f45ec7bSml29623 if (status != NXGE_OK) { 31536f45ec7bSml29623 size_index--; 31546f45ec7bSml29623 } else { 31556f45ec7bSml29623 i++; 31566f45ec7bSml29623 allocated += alloc_sizes[size_index]; 31576f45ec7bSml29623 } 31586f45ec7bSml29623 } 31596f45ec7bSml29623 31606f45ec7bSml29623 if (allocated < total_alloc_size) { 316130ac2e7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 316230ac2e7bSml29623 "==> nxge_alloc_tx_buf_dma: not enough channel %d: " 316330ac2e7bSml29623 "allocated 0x%x requested 0x%x", 316430ac2e7bSml29623 dma_channel, 316530ac2e7bSml29623 allocated, total_alloc_size)); 316630ac2e7bSml29623 status = NXGE_ERROR; 31676f45ec7bSml29623 goto nxge_alloc_tx_mem_fail1; 31686f45ec7bSml29623 } 31696f45ec7bSml29623 317030ac2e7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 317130ac2e7bSml29623 "==> nxge_alloc_tx_buf_dma: Allocated for channel %d: " 317230ac2e7bSml29623 "allocated 0x%x requested 0x%x", 317330ac2e7bSml29623 dma_channel, 317430ac2e7bSml29623 allocated, total_alloc_size)); 317530ac2e7bSml29623 31766f45ec7bSml29623 *num_chunks = i; 31776f45ec7bSml29623 *dmap = tx_dmap; 31786f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 31796f45ec7bSml29623 "==> nxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d", 31806f45ec7bSml29623 *dmap, i)); 31816f45ec7bSml29623 goto nxge_alloc_tx_mem_exit; 31826f45ec7bSml29623 31836f45ec7bSml29623 nxge_alloc_tx_mem_fail1: 31846f45ec7bSml29623 KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 31856f45ec7bSml29623 31866f45ec7bSml29623 nxge_alloc_tx_mem_exit: 31876f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 31886f45ec7bSml29623 "<== nxge_alloc_tx_buf_dma status 0x%08x", status)); 31896f45ec7bSml29623 31906f45ec7bSml29623 return (status); 31916f45ec7bSml29623 } 31926f45ec7bSml29623 31936f45ec7bSml29623 /*ARGSUSED*/ 31946f45ec7bSml29623 static void 31956f45ec7bSml29623 nxge_free_tx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 31966f45ec7bSml29623 uint32_t num_chunks) 31976f45ec7bSml29623 { 31986f45ec7bSml29623 int i; 31996f45ec7bSml29623 32006f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_tx_buf_dma")); 32016f45ec7bSml29623 3202678453a8Sspeer if (dmap == 0) 3203678453a8Sspeer return; 3204678453a8Sspeer 32056f45ec7bSml29623 for (i = 0; i < num_chunks; i++) { 32066f45ec7bSml29623 nxge_dma_mem_free(dmap++); 32076f45ec7bSml29623 } 32086f45ec7bSml29623 32096f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_tx_buf_dma")); 32106f45ec7bSml29623 } 32116f45ec7bSml29623 32126f45ec7bSml29623 /*ARGSUSED*/ 3213678453a8Sspeer nxge_status_t 32146f45ec7bSml29623 nxge_alloc_tx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 32156f45ec7bSml29623 p_nxge_dma_common_t *dmap, size_t size) 32166f45ec7bSml29623 { 32176f45ec7bSml29623 p_nxge_dma_common_t tx_dmap; 32186f45ec7bSml29623 nxge_status_t status = NXGE_OK; 32196f45ec7bSml29623 32206f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_cntl_dma")); 32216f45ec7bSml29623 tx_dmap = (p_nxge_dma_common_t) 32226f45ec7bSml29623 KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 32236f45ec7bSml29623 32246f45ec7bSml29623 tx_dmap->contig_alloc_type = B_FALSE; 3225678453a8Sspeer tx_dmap->kmem_alloc_type = B_FALSE; 32266f45ec7bSml29623 32276f45ec7bSml29623 status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 32286f45ec7bSml29623 &nxge_desc_dma_attr, 32296f45ec7bSml29623 size, 32306f45ec7bSml29623 &nxge_dev_desc_dma_acc_attr, 32316f45ec7bSml29623 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 32326f45ec7bSml29623 tx_dmap); 32336f45ec7bSml29623 if (status != NXGE_OK) { 32346f45ec7bSml29623 goto nxge_alloc_tx_cntl_dma_fail1; 32356f45ec7bSml29623 } 32366f45ec7bSml29623 32376f45ec7bSml29623 *dmap = tx_dmap; 32386f45ec7bSml29623 goto nxge_alloc_tx_cntl_dma_exit; 32396f45ec7bSml29623 32406f45ec7bSml29623 nxge_alloc_tx_cntl_dma_fail1: 32416f45ec7bSml29623 KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t)); 32426f45ec7bSml29623 32436f45ec7bSml29623 nxge_alloc_tx_cntl_dma_exit: 32446f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 32456f45ec7bSml29623 "<== nxge_alloc_tx_cntl_dma status 0x%08x", status)); 32466f45ec7bSml29623 32476f45ec7bSml29623 return (status); 32486f45ec7bSml29623 } 32496f45ec7bSml29623 32506f45ec7bSml29623 /*ARGSUSED*/ 32516f45ec7bSml29623 static void 32526f45ec7bSml29623 nxge_free_tx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 32536f45ec7bSml29623 { 32546f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_tx_cntl_dma")); 32556f45ec7bSml29623 3256678453a8Sspeer if (dmap == 0) 3257678453a8Sspeer return; 3258678453a8Sspeer 32596f45ec7bSml29623 nxge_dma_mem_free(dmap); 32606f45ec7bSml29623 32616f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_tx_cntl_dma")); 32626f45ec7bSml29623 } 32636f45ec7bSml29623 3264678453a8Sspeer /* 3265678453a8Sspeer * nxge_free_tx_mem_pool 3266678453a8Sspeer * 3267678453a8Sspeer * This function frees all of the per-port TDC control data structures. 3268678453a8Sspeer * The per-channel (TDC) data structures are freed when the channel 3269678453a8Sspeer * is stopped. 3270678453a8Sspeer * 3271678453a8Sspeer * Arguments: 3272678453a8Sspeer * nxgep 3273678453a8Sspeer * 3274678453a8Sspeer * Notes: 3275678453a8Sspeer * 3276678453a8Sspeer * Context: 3277678453a8Sspeer * Any domain 3278678453a8Sspeer */ 32796f45ec7bSml29623 static void 32806f45ec7bSml29623 nxge_free_tx_mem_pool(p_nxge_t nxgep) 32816f45ec7bSml29623 { 3282678453a8Sspeer int tdc_max = NXGE_MAX_TDCS; 32836f45ec7bSml29623 3284678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_tx_mem_pool")); 32856f45ec7bSml29623 3286678453a8Sspeer if (!nxgep->tx_buf_pool_p || !nxgep->tx_buf_pool_p->buf_allocated) { 3287678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 32886f45ec7bSml29623 "<== nxge_free_tx_mem_pool " 3289678453a8Sspeer "(null tx buf pool or buf not allocated")); 32906f45ec7bSml29623 return; 32916f45ec7bSml29623 } 3292678453a8Sspeer if (!nxgep->tx_cntl_pool_p || !nxgep->tx_cntl_pool_p->buf_allocated) { 3293678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 32946f45ec7bSml29623 "<== nxge_free_tx_mem_pool " 32956f45ec7bSml29623 "(null tx cntl buf pool or cntl buf not allocated")); 32966f45ec7bSml29623 return; 32976f45ec7bSml29623 } 32986f45ec7bSml29623 3299678453a8Sspeer /* 1. Free the mailboxes. */ 3300678453a8Sspeer KMEM_FREE(nxgep->tx_mbox_areas_p->txmbox_areas_p, 3301678453a8Sspeer sizeof (p_tx_mbox_t) * tdc_max); 3302678453a8Sspeer KMEM_FREE(nxgep->tx_mbox_areas_p, sizeof (tx_mbox_areas_t)); 33036f45ec7bSml29623 3304678453a8Sspeer nxgep->tx_mbox_areas_p = 0; 33056f45ec7bSml29623 3306678453a8Sspeer /* 2. Free the transmit ring arrays. */ 3307678453a8Sspeer KMEM_FREE(nxgep->tx_rings->rings, 3308678453a8Sspeer sizeof (p_tx_ring_t) * tdc_max); 3309678453a8Sspeer KMEM_FREE(nxgep->tx_rings, sizeof (tx_rings_t)); 33106f45ec7bSml29623 3311678453a8Sspeer nxgep->tx_rings = 0; 33126f45ec7bSml29623 3313678453a8Sspeer /* 3. Free the completion ring data structures. */ 3314678453a8Sspeer KMEM_FREE(nxgep->tx_cntl_pool_p->dma_buf_pool_p, 3315678453a8Sspeer sizeof (p_nxge_dma_common_t) * tdc_max); 3316678453a8Sspeer KMEM_FREE(nxgep->tx_cntl_pool_p, sizeof (nxge_dma_pool_t)); 33176f45ec7bSml29623 3318678453a8Sspeer nxgep->tx_cntl_pool_p = 0; 33196f45ec7bSml29623 3320678453a8Sspeer /* 4. Free the data ring data structures. */ 3321678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p->num_chunks, 3322678453a8Sspeer sizeof (uint32_t) * tdc_max); 3323678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p->dma_buf_pool_p, 3324678453a8Sspeer sizeof (p_nxge_dma_common_t) * tdc_max); 3325678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p, sizeof (nxge_dma_pool_t)); 33266f45ec7bSml29623 3327678453a8Sspeer nxgep->tx_buf_pool_p = 0; 3328678453a8Sspeer 3329678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_tx_mem_pool")); 33306f45ec7bSml29623 } 33316f45ec7bSml29623 33326f45ec7bSml29623 /*ARGSUSED*/ 33336f45ec7bSml29623 static nxge_status_t 33346f45ec7bSml29623 nxge_dma_mem_alloc(p_nxge_t nxgep, dma_method_t method, 33356f45ec7bSml29623 struct ddi_dma_attr *dma_attrp, 33366f45ec7bSml29623 size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags, 33376f45ec7bSml29623 p_nxge_dma_common_t dma_p) 33386f45ec7bSml29623 { 33396f45ec7bSml29623 caddr_t kaddrp; 33406f45ec7bSml29623 int ddi_status = DDI_SUCCESS; 33416f45ec7bSml29623 boolean_t contig_alloc_type; 3342678453a8Sspeer boolean_t kmem_alloc_type; 33436f45ec7bSml29623 33446f45ec7bSml29623 contig_alloc_type = dma_p->contig_alloc_type; 33456f45ec7bSml29623 33466f45ec7bSml29623 if (contig_alloc_type && (nxgep->niu_type != N2_NIU)) { 33476f45ec7bSml29623 /* 33486f45ec7bSml29623 * contig_alloc_type for contiguous memory only allowed 33496f45ec7bSml29623 * for N2/NIU. 33506f45ec7bSml29623 */ 33516f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3352678453a8Sspeer "nxge_dma_mem_alloc: alloc type not allowed (%d)", 33536f45ec7bSml29623 dma_p->contig_alloc_type)); 33546f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 33556f45ec7bSml29623 } 33566f45ec7bSml29623 33576f45ec7bSml29623 dma_p->dma_handle = NULL; 33586f45ec7bSml29623 dma_p->acc_handle = NULL; 33596f45ec7bSml29623 dma_p->kaddrp = dma_p->last_kaddrp = NULL; 33606f45ec7bSml29623 dma_p->first_ioaddr_pp = dma_p->last_ioaddr_pp = NULL; 33616f45ec7bSml29623 ddi_status = ddi_dma_alloc_handle(nxgep->dip, dma_attrp, 33626f45ec7bSml29623 DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle); 33636f45ec7bSml29623 if (ddi_status != DDI_SUCCESS) { 33646f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 33656f45ec7bSml29623 "nxge_dma_mem_alloc:ddi_dma_alloc_handle failed.")); 33666f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 33676f45ec7bSml29623 } 33686f45ec7bSml29623 3369678453a8Sspeer kmem_alloc_type = dma_p->kmem_alloc_type; 3370678453a8Sspeer 33716f45ec7bSml29623 switch (contig_alloc_type) { 33726f45ec7bSml29623 case B_FALSE: 3373678453a8Sspeer switch (kmem_alloc_type) { 3374678453a8Sspeer case B_FALSE: 3375678453a8Sspeer ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, 3376678453a8Sspeer length, 33776f45ec7bSml29623 acc_attr_p, 33786f45ec7bSml29623 xfer_flags, 33796f45ec7bSml29623 DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength, 33806f45ec7bSml29623 &dma_p->acc_handle); 33816f45ec7bSml29623 if (ddi_status != DDI_SUCCESS) { 33826f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3383678453a8Sspeer "nxge_dma_mem_alloc: " 3384678453a8Sspeer "ddi_dma_mem_alloc failed")); 33856f45ec7bSml29623 ddi_dma_free_handle(&dma_p->dma_handle); 33866f45ec7bSml29623 dma_p->dma_handle = NULL; 33876f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 33886f45ec7bSml29623 } 33896f45ec7bSml29623 if (dma_p->alength < length) { 33906f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3391678453a8Sspeer "nxge_dma_mem_alloc:di_dma_mem_alloc " 33926f45ec7bSml29623 "< length.")); 33936f45ec7bSml29623 ddi_dma_mem_free(&dma_p->acc_handle); 33946f45ec7bSml29623 ddi_dma_free_handle(&dma_p->dma_handle); 33956f45ec7bSml29623 dma_p->acc_handle = NULL; 33966f45ec7bSml29623 dma_p->dma_handle = NULL; 33976f45ec7bSml29623 return (NXGE_ERROR); 33986f45ec7bSml29623 } 33996f45ec7bSml29623 3400678453a8Sspeer ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, 3401678453a8Sspeer NULL, 3402678453a8Sspeer kaddrp, dma_p->alength, xfer_flags, 3403678453a8Sspeer DDI_DMA_DONTWAIT, 3404678453a8Sspeer 0, &dma_p->dma_cookie, &dma_p->ncookies); 34056f45ec7bSml29623 if (ddi_status != DDI_DMA_MAPPED) { 34066f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3407678453a8Sspeer "nxge_dma_mem_alloc: ddi_dma_addr_bind " 3408678453a8Sspeer "failed " 34096f45ec7bSml29623 "(staus 0x%x ncookies %d.)", ddi_status, 34106f45ec7bSml29623 dma_p->ncookies)); 34116f45ec7bSml29623 if (dma_p->acc_handle) { 34126f45ec7bSml29623 ddi_dma_mem_free(&dma_p->acc_handle); 34136f45ec7bSml29623 dma_p->acc_handle = NULL; 34146f45ec7bSml29623 } 34156f45ec7bSml29623 ddi_dma_free_handle(&dma_p->dma_handle); 34166f45ec7bSml29623 dma_p->dma_handle = NULL; 34176f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 34186f45ec7bSml29623 } 34196f45ec7bSml29623 34206f45ec7bSml29623 if (dma_p->ncookies != 1) { 34216f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 34226f45ec7bSml29623 "nxge_dma_mem_alloc:ddi_dma_addr_bind " 34236f45ec7bSml29623 "> 1 cookie" 34246f45ec7bSml29623 "(staus 0x%x ncookies %d.)", ddi_status, 34256f45ec7bSml29623 dma_p->ncookies)); 3426330cd344SMichael Speer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 34276f45ec7bSml29623 if (dma_p->acc_handle) { 34286f45ec7bSml29623 ddi_dma_mem_free(&dma_p->acc_handle); 34296f45ec7bSml29623 dma_p->acc_handle = NULL; 34306f45ec7bSml29623 } 34316f45ec7bSml29623 ddi_dma_free_handle(&dma_p->dma_handle); 34326f45ec7bSml29623 dma_p->dma_handle = NULL; 3433330cd344SMichael Speer dma_p->acc_handle = NULL; 34346f45ec7bSml29623 return (NXGE_ERROR); 34356f45ec7bSml29623 } 34366f45ec7bSml29623 break; 34376f45ec7bSml29623 3438678453a8Sspeer case B_TRUE: 3439678453a8Sspeer kaddrp = KMEM_ALLOC(length, KM_NOSLEEP); 3440678453a8Sspeer if (kaddrp == NULL) { 3441678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3442678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_mem_alloc " 3443678453a8Sspeer "kmem alloc failed")); 3444678453a8Sspeer return (NXGE_ERROR); 3445678453a8Sspeer } 3446678453a8Sspeer 3447678453a8Sspeer dma_p->alength = length; 3448678453a8Sspeer ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, 3449678453a8Sspeer NULL, kaddrp, dma_p->alength, xfer_flags, 3450678453a8Sspeer DDI_DMA_DONTWAIT, 0, 3451678453a8Sspeer &dma_p->dma_cookie, &dma_p->ncookies); 3452678453a8Sspeer if (ddi_status != DDI_DMA_MAPPED) { 3453678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3454678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind: " 3455678453a8Sspeer "(kmem_alloc) failed kaddrp $%p length %d " 3456678453a8Sspeer "(staus 0x%x (%d) ncookies %d.)", 3457678453a8Sspeer kaddrp, length, 3458678453a8Sspeer ddi_status, ddi_status, dma_p->ncookies)); 3459678453a8Sspeer KMEM_FREE(kaddrp, length); 3460678453a8Sspeer dma_p->acc_handle = NULL; 3461678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3462678453a8Sspeer dma_p->dma_handle = NULL; 3463678453a8Sspeer dma_p->kaddrp = NULL; 3464678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3465678453a8Sspeer } 3466678453a8Sspeer 3467678453a8Sspeer if (dma_p->ncookies != 1) { 3468678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 3469678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind " 3470678453a8Sspeer "(kmem_alloc) > 1 cookie" 3471678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 3472678453a8Sspeer dma_p->ncookies)); 3473678453a8Sspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3474330cd344SMichael Speer KMEM_FREE(kaddrp, length); 3475678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3476678453a8Sspeer dma_p->dma_handle = NULL; 3477330cd344SMichael Speer dma_p->acc_handle = NULL; 3478678453a8Sspeer dma_p->kaddrp = NULL; 3479678453a8Sspeer return (NXGE_ERROR); 3480678453a8Sspeer } 3481678453a8Sspeer 3482678453a8Sspeer dma_p->kaddrp = kaddrp; 3483678453a8Sspeer 3484678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 3485678453a8Sspeer "nxge_dma_mem_alloc: kmem_alloc dmap $%p " 3486678453a8Sspeer "kaddr $%p alength %d", 3487678453a8Sspeer dma_p, 3488678453a8Sspeer kaddrp, 3489678453a8Sspeer dma_p->alength)); 3490678453a8Sspeer break; 3491678453a8Sspeer } 3492678453a8Sspeer break; 3493678453a8Sspeer 34946f45ec7bSml29623 #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 34956f45ec7bSml29623 case B_TRUE: 34966f45ec7bSml29623 kaddrp = (caddr_t)contig_mem_alloc(length); 34976f45ec7bSml29623 if (kaddrp == NULL) { 34986f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34996f45ec7bSml29623 "nxge_dma_mem_alloc:contig_mem_alloc failed.")); 35006f45ec7bSml29623 ddi_dma_free_handle(&dma_p->dma_handle); 35016f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 35026f45ec7bSml29623 } 35036f45ec7bSml29623 35046f45ec7bSml29623 dma_p->alength = length; 35056f45ec7bSml29623 ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL, 35066f45ec7bSml29623 kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0, 35076f45ec7bSml29623 &dma_p->dma_cookie, &dma_p->ncookies); 35086f45ec7bSml29623 if (ddi_status != DDI_DMA_MAPPED) { 35096f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 35106f45ec7bSml29623 "nxge_dma_mem_alloc:di_dma_addr_bind failed " 35116f45ec7bSml29623 "(status 0x%x ncookies %d.)", ddi_status, 35126f45ec7bSml29623 dma_p->ncookies)); 35136f45ec7bSml29623 35146f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 35156f45ec7bSml29623 "==> nxge_dma_mem_alloc: (not mapped)" 35166f45ec7bSml29623 "length %lu (0x%x) " 35176f45ec7bSml29623 "free contig kaddrp $%p " 35186f45ec7bSml29623 "va_to_pa $%p", 35196f45ec7bSml29623 length, length, 35206f45ec7bSml29623 kaddrp, 35216f45ec7bSml29623 va_to_pa(kaddrp))); 35226f45ec7bSml29623 35236f45ec7bSml29623 35246f45ec7bSml29623 contig_mem_free((void *)kaddrp, length); 35256f45ec7bSml29623 ddi_dma_free_handle(&dma_p->dma_handle); 35266f45ec7bSml29623 35276f45ec7bSml29623 dma_p->dma_handle = NULL; 35286f45ec7bSml29623 dma_p->acc_handle = NULL; 35296f45ec7bSml29623 dma_p->alength = NULL; 35306f45ec7bSml29623 dma_p->kaddrp = NULL; 35316f45ec7bSml29623 35326f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 35336f45ec7bSml29623 } 35346f45ec7bSml29623 35356f45ec7bSml29623 if (dma_p->ncookies != 1 || 35366f45ec7bSml29623 (dma_p->dma_cookie.dmac_laddress == NULL)) { 35376f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 35386f45ec7bSml29623 "nxge_dma_mem_alloc:di_dma_addr_bind > 1 " 35396f45ec7bSml29623 "cookie or " 35406f45ec7bSml29623 "dmac_laddress is NULL $%p size %d " 35416f45ec7bSml29623 " (status 0x%x ncookies %d.)", 35426f45ec7bSml29623 ddi_status, 35436f45ec7bSml29623 dma_p->dma_cookie.dmac_laddress, 35446f45ec7bSml29623 dma_p->dma_cookie.dmac_size, 35456f45ec7bSml29623 dma_p->ncookies)); 35466f45ec7bSml29623 35476f45ec7bSml29623 contig_mem_free((void *)kaddrp, length); 354856d930aeSspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 35496f45ec7bSml29623 ddi_dma_free_handle(&dma_p->dma_handle); 35506f45ec7bSml29623 35516f45ec7bSml29623 dma_p->alength = 0; 35526f45ec7bSml29623 dma_p->dma_handle = NULL; 35536f45ec7bSml29623 dma_p->acc_handle = NULL; 35546f45ec7bSml29623 dma_p->kaddrp = NULL; 35556f45ec7bSml29623 35566f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 35576f45ec7bSml29623 } 35586f45ec7bSml29623 break; 35596f45ec7bSml29623 35606f45ec7bSml29623 #else 35616f45ec7bSml29623 case B_TRUE: 35626f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 35636f45ec7bSml29623 "nxge_dma_mem_alloc: invalid alloc type for !sun4v")); 35646f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 35656f45ec7bSml29623 #endif 35666f45ec7bSml29623 } 35676f45ec7bSml29623 35686f45ec7bSml29623 dma_p->kaddrp = kaddrp; 35696f45ec7bSml29623 dma_p->last_kaddrp = (unsigned char *)kaddrp + 35706f45ec7bSml29623 dma_p->alength - RXBUF_64B_ALIGNED; 3571adfcba55Sjoycey #if defined(__i386) 3572adfcba55Sjoycey dma_p->ioaddr_pp = 3573adfcba55Sjoycey (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress; 3574adfcba55Sjoycey #else 35756f45ec7bSml29623 dma_p->ioaddr_pp = (unsigned char *)dma_p->dma_cookie.dmac_laddress; 3576adfcba55Sjoycey #endif 35776f45ec7bSml29623 dma_p->last_ioaddr_pp = 3578adfcba55Sjoycey #if defined(__i386) 3579adfcba55Sjoycey (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress + 3580adfcba55Sjoycey #else 35816f45ec7bSml29623 (unsigned char *)dma_p->dma_cookie.dmac_laddress + 3582adfcba55Sjoycey #endif 35836f45ec7bSml29623 dma_p->alength - RXBUF_64B_ALIGNED; 35846f45ec7bSml29623 35856f45ec7bSml29623 NPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle); 35866f45ec7bSml29623 35876f45ec7bSml29623 #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 35886f45ec7bSml29623 dma_p->orig_ioaddr_pp = 35896f45ec7bSml29623 (unsigned char *)dma_p->dma_cookie.dmac_laddress; 35906f45ec7bSml29623 dma_p->orig_alength = length; 35916f45ec7bSml29623 dma_p->orig_kaddrp = kaddrp; 35926f45ec7bSml29623 dma_p->orig_vatopa = (uint64_t)va_to_pa(kaddrp); 35936f45ec7bSml29623 #endif 35946f45ec7bSml29623 35956f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_dma_mem_alloc: " 35966f45ec7bSml29623 "dma buffer allocated: dma_p $%p " 35976f45ec7bSml29623 "return dmac_ladress from cookie $%p cookie dmac_size %d " 35986f45ec7bSml29623 "dma_p->ioaddr_p $%p " 35996f45ec7bSml29623 "dma_p->orig_ioaddr_p $%p " 36006f45ec7bSml29623 "orig_vatopa $%p " 36016f45ec7bSml29623 "alength %d (0x%x) " 36026f45ec7bSml29623 "kaddrp $%p " 36036f45ec7bSml29623 "length %d (0x%x)", 36046f45ec7bSml29623 dma_p, 36056f45ec7bSml29623 dma_p->dma_cookie.dmac_laddress, dma_p->dma_cookie.dmac_size, 36066f45ec7bSml29623 dma_p->ioaddr_pp, 36076f45ec7bSml29623 dma_p->orig_ioaddr_pp, 36086f45ec7bSml29623 dma_p->orig_vatopa, 36096f45ec7bSml29623 dma_p->alength, dma_p->alength, 36106f45ec7bSml29623 kaddrp, 36116f45ec7bSml29623 length, length)); 36126f45ec7bSml29623 36136f45ec7bSml29623 return (NXGE_OK); 36146f45ec7bSml29623 } 36156f45ec7bSml29623 36166f45ec7bSml29623 static void 36176f45ec7bSml29623 nxge_dma_mem_free(p_nxge_dma_common_t dma_p) 36186f45ec7bSml29623 { 36196f45ec7bSml29623 if (dma_p->dma_handle != NULL) { 36206f45ec7bSml29623 if (dma_p->ncookies) { 36216f45ec7bSml29623 (void) ddi_dma_unbind_handle(dma_p->dma_handle); 36226f45ec7bSml29623 dma_p->ncookies = 0; 36236f45ec7bSml29623 } 36246f45ec7bSml29623 ddi_dma_free_handle(&dma_p->dma_handle); 36256f45ec7bSml29623 dma_p->dma_handle = NULL; 36266f45ec7bSml29623 } 36276f45ec7bSml29623 36286f45ec7bSml29623 if (dma_p->acc_handle != NULL) { 36296f45ec7bSml29623 ddi_dma_mem_free(&dma_p->acc_handle); 36306f45ec7bSml29623 dma_p->acc_handle = NULL; 36316f45ec7bSml29623 NPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 36326f45ec7bSml29623 } 36336f45ec7bSml29623 36346f45ec7bSml29623 #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 36356f45ec7bSml29623 if (dma_p->contig_alloc_type && 36366f45ec7bSml29623 dma_p->orig_kaddrp && dma_p->orig_alength) { 36376f45ec7bSml29623 NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_mem_free: " 36386f45ec7bSml29623 "kaddrp $%p (orig_kaddrp $%p)" 36396f45ec7bSml29623 "mem type %d ", 36406f45ec7bSml29623 "orig_alength %d " 36416f45ec7bSml29623 "alength 0x%x (%d)", 36426f45ec7bSml29623 dma_p->kaddrp, 36436f45ec7bSml29623 dma_p->orig_kaddrp, 36446f45ec7bSml29623 dma_p->contig_alloc_type, 36456f45ec7bSml29623 dma_p->orig_alength, 36466f45ec7bSml29623 dma_p->alength, dma_p->alength)); 36476f45ec7bSml29623 36486f45ec7bSml29623 contig_mem_free(dma_p->orig_kaddrp, dma_p->orig_alength); 36496f45ec7bSml29623 dma_p->orig_alength = NULL; 36506f45ec7bSml29623 dma_p->orig_kaddrp = NULL; 36516f45ec7bSml29623 dma_p->contig_alloc_type = B_FALSE; 36526f45ec7bSml29623 } 36536f45ec7bSml29623 #endif 36546f45ec7bSml29623 dma_p->kaddrp = NULL; 36556f45ec7bSml29623 dma_p->alength = NULL; 36566f45ec7bSml29623 } 36576f45ec7bSml29623 3658678453a8Sspeer static void 3659678453a8Sspeer nxge_dma_free_rx_data_buf(p_nxge_dma_common_t dma_p) 3660678453a8Sspeer { 3661678453a8Sspeer uint64_t kaddr; 3662678453a8Sspeer uint32_t buf_size; 3663678453a8Sspeer 3664678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "==> nxge_dma_free_rx_data_buf")); 3665678453a8Sspeer 3666678453a8Sspeer if (dma_p->dma_handle != NULL) { 3667678453a8Sspeer if (dma_p->ncookies) { 3668678453a8Sspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3669678453a8Sspeer dma_p->ncookies = 0; 3670678453a8Sspeer } 3671678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3672678453a8Sspeer dma_p->dma_handle = NULL; 3673678453a8Sspeer } 3674678453a8Sspeer 3675678453a8Sspeer if (dma_p->acc_handle != NULL) { 3676678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3677678453a8Sspeer dma_p->acc_handle = NULL; 3678678453a8Sspeer NPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 3679678453a8Sspeer } 3680678453a8Sspeer 3681678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3682678453a8Sspeer "==> nxge_dma_free_rx_data_buf: dmap $%p buf_alloc_state %d", 3683678453a8Sspeer dma_p, 3684678453a8Sspeer dma_p->buf_alloc_state)); 3685678453a8Sspeer 3686678453a8Sspeer if (!(dma_p->buf_alloc_state & BUF_ALLOCATED_WAIT_FREE)) { 3687678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3688678453a8Sspeer "<== nxge_dma_free_rx_data_buf: " 3689678453a8Sspeer "outstanding data buffers")); 3690678453a8Sspeer return; 3691678453a8Sspeer } 3692678453a8Sspeer 3693678453a8Sspeer #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 3694678453a8Sspeer if (dma_p->contig_alloc_type && 3695678453a8Sspeer dma_p->orig_kaddrp && dma_p->orig_alength) { 3696678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_free_rx_data_buf: " 3697678453a8Sspeer "kaddrp $%p (orig_kaddrp $%p)" 3698678453a8Sspeer "mem type %d ", 3699678453a8Sspeer "orig_alength %d " 3700678453a8Sspeer "alength 0x%x (%d)", 3701678453a8Sspeer dma_p->kaddrp, 3702678453a8Sspeer dma_p->orig_kaddrp, 3703678453a8Sspeer dma_p->contig_alloc_type, 3704678453a8Sspeer dma_p->orig_alength, 3705678453a8Sspeer dma_p->alength, dma_p->alength)); 3706678453a8Sspeer 3707678453a8Sspeer kaddr = (uint64_t)dma_p->orig_kaddrp; 3708678453a8Sspeer buf_size = dma_p->orig_alength; 3709678453a8Sspeer nxge_free_buf(CONTIG_MEM_ALLOC, kaddr, buf_size); 3710678453a8Sspeer dma_p->orig_alength = NULL; 3711678453a8Sspeer dma_p->orig_kaddrp = NULL; 3712678453a8Sspeer dma_p->contig_alloc_type = B_FALSE; 3713678453a8Sspeer dma_p->kaddrp = NULL; 3714678453a8Sspeer dma_p->alength = NULL; 3715678453a8Sspeer return; 3716678453a8Sspeer } 3717678453a8Sspeer #endif 3718678453a8Sspeer 3719678453a8Sspeer if (dma_p->kmem_alloc_type) { 3720678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3721678453a8Sspeer "nxge_dma_free_rx_data_buf: free kmem " 3722678453a8Sspeer "kaddrp $%p (orig_kaddrp $%p)" 3723678453a8Sspeer "alloc type %d " 3724678453a8Sspeer "orig_alength %d " 3725678453a8Sspeer "alength 0x%x (%d)", 3726678453a8Sspeer dma_p->kaddrp, 3727678453a8Sspeer dma_p->orig_kaddrp, 3728678453a8Sspeer dma_p->kmem_alloc_type, 3729678453a8Sspeer dma_p->orig_alength, 3730678453a8Sspeer dma_p->alength, dma_p->alength)); 3731678453a8Sspeer #if defined(__i386) 3732678453a8Sspeer kaddr = (uint64_t)(uint32_t)dma_p->kaddrp; 3733678453a8Sspeer #else 3734678453a8Sspeer kaddr = (uint64_t)dma_p->kaddrp; 3735678453a8Sspeer #endif 3736678453a8Sspeer buf_size = dma_p->orig_alength; 3737678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3738678453a8Sspeer "nxge_dma_free_rx_data_buf: free dmap $%p " 3739678453a8Sspeer "kaddr $%p buf_size %d", 3740678453a8Sspeer dma_p, 3741678453a8Sspeer kaddr, buf_size)); 3742678453a8Sspeer nxge_free_buf(KMEM_ALLOC, kaddr, buf_size); 3743678453a8Sspeer dma_p->alength = 0; 3744678453a8Sspeer dma_p->orig_alength = 0; 3745678453a8Sspeer dma_p->kaddrp = NULL; 3746678453a8Sspeer dma_p->kmem_alloc_type = B_FALSE; 3747678453a8Sspeer } 3748678453a8Sspeer 3749678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_dma_free_rx_data_buf")); 3750678453a8Sspeer } 3751678453a8Sspeer 37526f45ec7bSml29623 /* 37536f45ec7bSml29623 * nxge_m_start() -- start transmitting and receiving. 37546f45ec7bSml29623 * 37556f45ec7bSml29623 * This function is called by the MAC layer when the first 37566f45ec7bSml29623 * stream is open to prepare the hardware ready for sending 37576f45ec7bSml29623 * and transmitting packets. 37586f45ec7bSml29623 */ 37596f45ec7bSml29623 static int 37606f45ec7bSml29623 nxge_m_start(void *arg) 37616f45ec7bSml29623 { 37626f45ec7bSml29623 p_nxge_t nxgep = (p_nxge_t)arg; 37636f45ec7bSml29623 37646f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_start")); 37656f45ec7bSml29623 3766e759c33aSMichael Speer /* 3767e759c33aSMichael Speer * Are we already started? 3768e759c33aSMichael Speer */ 3769e759c33aSMichael Speer if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 3770e759c33aSMichael Speer return (0); 3771e759c33aSMichael Speer } 3772e759c33aSMichael Speer 37736f157acbSml29623 if (nxge_peu_reset_enable && !nxgep->nxge_link_poll_timerid) { 37746f157acbSml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 37756f157acbSml29623 } 37766f157acbSml29623 3777e759c33aSMichael Speer /* 3778e759c33aSMichael Speer * Make sure RX MAC is disabled while we initialize. 3779e759c33aSMichael Speer */ 3780e759c33aSMichael Speer if (!isLDOMguest(nxgep)) { 3781e759c33aSMichael Speer (void) nxge_rx_mac_disable(nxgep); 3782e759c33aSMichael Speer } 3783e759c33aSMichael Speer 3784e759c33aSMichael Speer /* 3785e759c33aSMichael Speer * Grab the global lock. 3786e759c33aSMichael Speer */ 37876f45ec7bSml29623 MUTEX_ENTER(nxgep->genlock); 3788e759c33aSMichael Speer 3789e759c33aSMichael Speer /* 3790e759c33aSMichael Speer * Initialize the driver and hardware. 3791e759c33aSMichael Speer */ 37926f45ec7bSml29623 if (nxge_init(nxgep) != NXGE_OK) { 37936f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 37946f45ec7bSml29623 "<== nxge_m_start: initialization failed")); 37956f45ec7bSml29623 MUTEX_EXIT(nxgep->genlock); 37966f45ec7bSml29623 return (EIO); 37976f45ec7bSml29623 } 37986f45ec7bSml29623 37996f45ec7bSml29623 /* 38006f45ec7bSml29623 * Start timer to check the system error and tx hangs 38016f45ec7bSml29623 */ 3802678453a8Sspeer if (!isLDOMguest(nxgep)) 3803678453a8Sspeer nxgep->nxge_timerid = nxge_start_timer(nxgep, 3804678453a8Sspeer nxge_check_hw_state, NXGE_CHECK_TIMER); 3805678453a8Sspeer #if defined(sun4v) 3806678453a8Sspeer else 3807678453a8Sspeer nxge_hio_start_timer(nxgep); 3808678453a8Sspeer #endif 38096f45ec7bSml29623 38106f45ec7bSml29623 nxgep->link_notify = B_TRUE; 3811774da109Stc99174@train nxgep->link_check_count = 0; 38126f45ec7bSml29623 nxgep->nxge_mac_state = NXGE_MAC_STARTED; 38136f45ec7bSml29623 3814e759c33aSMichael Speer /* 3815e759c33aSMichael Speer * Let the global lock go, since we are intialized. 3816e759c33aSMichael Speer */ 38176f45ec7bSml29623 MUTEX_EXIT(nxgep->genlock); 3818e759c33aSMichael Speer 3819e759c33aSMichael Speer /* 3820e759c33aSMichael Speer * Let the MAC start receiving packets, now that 3821e759c33aSMichael Speer * we are initialized. 3822e759c33aSMichael Speer */ 3823e759c33aSMichael Speer if (!isLDOMguest(nxgep)) { 3824e759c33aSMichael Speer if (nxge_rx_mac_enable(nxgep) != NXGE_OK) { 3825e759c33aSMichael Speer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3826e759c33aSMichael Speer "<== nxge_m_start: enable of RX mac failed")); 3827e759c33aSMichael Speer return (EIO); 3828e759c33aSMichael Speer } 3829e759c33aSMichael Speer 3830e759c33aSMichael Speer /* 3831e759c33aSMichael Speer * Enable hardware interrupts. 3832e759c33aSMichael Speer */ 3833e759c33aSMichael Speer nxge_intr_hw_enable(nxgep); 3834e759c33aSMichael Speer } 3835e759c33aSMichael Speer #if defined(sun4v) 3836e759c33aSMichael Speer else { 3837e759c33aSMichael Speer /* 3838e759c33aSMichael Speer * In guest domain we enable RDCs and their interrupts as 3839e759c33aSMichael Speer * the last step. 3840e759c33aSMichael Speer */ 3841e759c33aSMichael Speer if (nxge_hio_rdc_enable(nxgep) != NXGE_OK) { 3842e759c33aSMichael Speer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3843e759c33aSMichael Speer "<== nxge_m_start: enable of RDCs failed")); 3844e759c33aSMichael Speer return (EIO); 3845e759c33aSMichael Speer } 3846e759c33aSMichael Speer 3847e759c33aSMichael Speer if (nxge_hio_rdc_intr_arm(nxgep, B_TRUE) != NXGE_OK) { 3848e759c33aSMichael Speer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3849e759c33aSMichael Speer "<== nxge_m_start: intrs enable for RDCs failed")); 3850e759c33aSMichael Speer return (EIO); 3851e759c33aSMichael Speer } 3852e759c33aSMichael Speer } 3853e759c33aSMichael Speer #endif 38546f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_start")); 38556f45ec7bSml29623 return (0); 38566f45ec7bSml29623 } 38576f45ec7bSml29623 3858da14cebeSEric Cheng static boolean_t 3859da14cebeSEric Cheng nxge_check_groups_stopped(p_nxge_t nxgep) 3860da14cebeSEric Cheng { 3861da14cebeSEric Cheng int i; 3862da14cebeSEric Cheng 3863da14cebeSEric Cheng for (i = 0; i < NXGE_MAX_RDC_GROUPS; i++) { 3864da14cebeSEric Cheng if (nxgep->rx_hio_groups[i].started) 3865da14cebeSEric Cheng return (B_FALSE); 3866da14cebeSEric Cheng } 3867da14cebeSEric Cheng 3868da14cebeSEric Cheng return (B_TRUE); 3869da14cebeSEric Cheng } 3870da14cebeSEric Cheng 38716f45ec7bSml29623 /* 38726f45ec7bSml29623 * nxge_m_stop(): stop transmitting and receiving. 38736f45ec7bSml29623 */ 38746f45ec7bSml29623 static void 38756f45ec7bSml29623 nxge_m_stop(void *arg) 38766f45ec7bSml29623 { 38776f45ec7bSml29623 p_nxge_t nxgep = (p_nxge_t)arg; 3878da14cebeSEric Cheng boolean_t groups_stopped; 38796f45ec7bSml29623 38806f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_stop")); 38816f45ec7bSml29623 3882e759c33aSMichael Speer /* 3883e759c33aSMichael Speer * Are the groups stopped? 3884e759c33aSMichael Speer */ 3885da14cebeSEric Cheng groups_stopped = nxge_check_groups_stopped(nxgep); 3886e759c33aSMichael Speer ASSERT(groups_stopped == B_TRUE); 3887da14cebeSEric Cheng if (!groups_stopped) { 3888da14cebeSEric Cheng cmn_err(CE_WARN, "nxge(%d): groups are not stopped!\n", 3889da14cebeSEric Cheng nxgep->instance); 3890da14cebeSEric Cheng return; 3891da14cebeSEric Cheng } 3892da14cebeSEric Cheng 3893e759c33aSMichael Speer if (!isLDOMguest(nxgep)) { 3894e759c33aSMichael Speer /* 3895e759c33aSMichael Speer * Disable the RX mac. 3896e759c33aSMichael Speer */ 3897e759c33aSMichael Speer (void) nxge_rx_mac_disable(nxgep); 3898d7cf53fcSmisaki Miyashita 3899e759c33aSMichael Speer /* 3900e759c33aSMichael Speer * Wait for the IPP to drain. 3901e759c33aSMichael Speer */ 3902e759c33aSMichael Speer (void) nxge_ipp_drain(nxgep); 3903e759c33aSMichael Speer 3904e759c33aSMichael Speer /* 3905e759c33aSMichael Speer * Disable hardware interrupts. 3906e759c33aSMichael Speer */ 3907e759c33aSMichael Speer nxge_intr_hw_disable(nxgep); 3908e759c33aSMichael Speer } 3909e759c33aSMichael Speer #if defined(sun4v) 3910e759c33aSMichael Speer else { 3911e759c33aSMichael Speer (void) nxge_hio_rdc_intr_arm(nxgep, B_FALSE); 3912e759c33aSMichael Speer } 3913e759c33aSMichael Speer #endif 3914e759c33aSMichael Speer 3915e759c33aSMichael Speer /* 3916e759c33aSMichael Speer * Grab the global lock. 3917e759c33aSMichael Speer */ 3918e759c33aSMichael Speer MUTEX_ENTER(nxgep->genlock); 3919e759c33aSMichael Speer 3920e759c33aSMichael Speer nxgep->nxge_mac_state = NXGE_MAC_STOPPING; 39216f45ec7bSml29623 if (nxgep->nxge_timerid) { 39226f45ec7bSml29623 nxge_stop_timer(nxgep, nxgep->nxge_timerid); 39236f45ec7bSml29623 nxgep->nxge_timerid = 0; 39246f45ec7bSml29623 } 39256f45ec7bSml29623 3926e759c33aSMichael Speer /* 3927e759c33aSMichael Speer * Clean up. 3928e759c33aSMichael Speer */ 39296f45ec7bSml29623 nxge_uninit(nxgep); 39306f45ec7bSml29623 39316f45ec7bSml29623 nxgep->nxge_mac_state = NXGE_MAC_STOPPED; 39326f45ec7bSml29623 3933e759c33aSMichael Speer /* 3934e759c33aSMichael Speer * Let go of the global lock. 3935e759c33aSMichael Speer */ 39366f45ec7bSml29623 MUTEX_EXIT(nxgep->genlock); 39376f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_stop")); 39386f45ec7bSml29623 } 39396f45ec7bSml29623 39406f45ec7bSml29623 static int 39416f45ec7bSml29623 nxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 39426f45ec7bSml29623 { 39436f45ec7bSml29623 p_nxge_t nxgep = (p_nxge_t)arg; 39446f45ec7bSml29623 struct ether_addr addrp; 39456f45ec7bSml29623 39466f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 39476f45ec7bSml29623 "==> nxge_m_multicst: add %d", add)); 39486f45ec7bSml29623 39496f45ec7bSml29623 bcopy(mca, (uint8_t *)&addrp, ETHERADDRL); 39506f45ec7bSml29623 if (add) { 39516f45ec7bSml29623 if (nxge_add_mcast_addr(nxgep, &addrp)) { 39526f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 39536f45ec7bSml29623 "<== nxge_m_multicst: add multicast failed")); 39546f45ec7bSml29623 return (EINVAL); 39556f45ec7bSml29623 } 39566f45ec7bSml29623 } else { 39576f45ec7bSml29623 if (nxge_del_mcast_addr(nxgep, &addrp)) { 39586f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 39596f45ec7bSml29623 "<== nxge_m_multicst: del multicast failed")); 39606f45ec7bSml29623 return (EINVAL); 39616f45ec7bSml29623 } 39626f45ec7bSml29623 } 39636f45ec7bSml29623 39646f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_multicst")); 39656f45ec7bSml29623 39666f45ec7bSml29623 return (0); 39676f45ec7bSml29623 } 39686f45ec7bSml29623 39696f45ec7bSml29623 static int 39706f45ec7bSml29623 nxge_m_promisc(void *arg, boolean_t on) 39716f45ec7bSml29623 { 39726f45ec7bSml29623 p_nxge_t nxgep = (p_nxge_t)arg; 39736f45ec7bSml29623 39746f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 39756f45ec7bSml29623 "==> nxge_m_promisc: on %d", on)); 39766f45ec7bSml29623 39776f45ec7bSml29623 if (nxge_set_promisc(nxgep, on)) { 39786f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 39796f45ec7bSml29623 "<== nxge_m_promisc: set promisc failed")); 39806f45ec7bSml29623 return (EINVAL); 39816f45ec7bSml29623 } 39826f45ec7bSml29623 39836f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 39846f45ec7bSml29623 "<== nxge_m_promisc: on %d", on)); 39856f45ec7bSml29623 39866f45ec7bSml29623 return (0); 39876f45ec7bSml29623 } 39886f45ec7bSml29623 39896f45ec7bSml29623 static void 39906f45ec7bSml29623 nxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 39916f45ec7bSml29623 { 39926f45ec7bSml29623 p_nxge_t nxgep = (p_nxge_t)arg; 399356d930aeSspeer struct iocblk *iocp; 39946f45ec7bSml29623 boolean_t need_privilege; 39956f45ec7bSml29623 int err; 39966f45ec7bSml29623 int cmd; 39976f45ec7bSml29623 39986f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl")); 39996f45ec7bSml29623 40006f45ec7bSml29623 iocp = (struct iocblk *)mp->b_rptr; 40016f45ec7bSml29623 iocp->ioc_error = 0; 40026f45ec7bSml29623 need_privilege = B_TRUE; 40036f45ec7bSml29623 cmd = iocp->ioc_cmd; 40046f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl: cmd 0x%08x", cmd)); 40056f45ec7bSml29623 switch (cmd) { 40066f45ec7bSml29623 default: 40076f45ec7bSml29623 miocnak(wq, mp, 0, EINVAL); 40086f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl: invalid")); 40096f45ec7bSml29623 return; 40106f45ec7bSml29623 40116f45ec7bSml29623 case LB_GET_INFO_SIZE: 40126f45ec7bSml29623 case LB_GET_INFO: 40136f45ec7bSml29623 case LB_GET_MODE: 40146f45ec7bSml29623 need_privilege = B_FALSE; 40156f45ec7bSml29623 break; 40166f45ec7bSml29623 case LB_SET_MODE: 40176f45ec7bSml29623 break; 40186f45ec7bSml29623 40196f45ec7bSml29623 40206f45ec7bSml29623 case NXGE_GET_MII: 40216f45ec7bSml29623 case NXGE_PUT_MII: 40226f45ec7bSml29623 case NXGE_GET64: 40236f45ec7bSml29623 case NXGE_PUT64: 40246f45ec7bSml29623 case NXGE_GET_TX_RING_SZ: 40256f45ec7bSml29623 case NXGE_GET_TX_DESC: 40266f45ec7bSml29623 case NXGE_TX_SIDE_RESET: 40276f45ec7bSml29623 case NXGE_RX_SIDE_RESET: 40286f45ec7bSml29623 case NXGE_GLOBAL_RESET: 40296f45ec7bSml29623 case NXGE_RESET_MAC: 40306f45ec7bSml29623 case NXGE_TX_REGS_DUMP: 40316f45ec7bSml29623 case NXGE_RX_REGS_DUMP: 40326f45ec7bSml29623 case NXGE_INT_REGS_DUMP: 40336f45ec7bSml29623 case NXGE_VIR_INT_REGS_DUMP: 40346f45ec7bSml29623 case NXGE_PUT_TCAM: 40356f45ec7bSml29623 case NXGE_GET_TCAM: 40366f45ec7bSml29623 case NXGE_RTRACE: 40376f45ec7bSml29623 case NXGE_RDUMP: 40384df55fdeSJanie Lu case NXGE_RX_CLASS: 40394df55fdeSJanie Lu case NXGE_RX_HASH: 40406f45ec7bSml29623 40416f45ec7bSml29623 need_privilege = B_FALSE; 40426f45ec7bSml29623 break; 40436f45ec7bSml29623 case NXGE_INJECT_ERR: 40446f45ec7bSml29623 cmn_err(CE_NOTE, "!nxge_m_ioctl: Inject error\n"); 40456f45ec7bSml29623 nxge_err_inject(nxgep, wq, mp); 40466f45ec7bSml29623 break; 40476f45ec7bSml29623 } 40486f45ec7bSml29623 40496f45ec7bSml29623 if (need_privilege) { 40506f45ec7bSml29623 err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 40516f45ec7bSml29623 if (err != 0) { 40526f45ec7bSml29623 miocnak(wq, mp, 0, err); 40536f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 40546f45ec7bSml29623 "<== nxge_m_ioctl: no priv")); 40556f45ec7bSml29623 return; 40566f45ec7bSml29623 } 40576f45ec7bSml29623 } 40586f45ec7bSml29623 40596f45ec7bSml29623 switch (cmd) { 40606f45ec7bSml29623 40616f45ec7bSml29623 case LB_GET_MODE: 40626f45ec7bSml29623 case LB_SET_MODE: 40636f45ec7bSml29623 case LB_GET_INFO_SIZE: 40646f45ec7bSml29623 case LB_GET_INFO: 40656f45ec7bSml29623 nxge_loopback_ioctl(nxgep, wq, mp, iocp); 40666f45ec7bSml29623 break; 40676f45ec7bSml29623 40686f45ec7bSml29623 case NXGE_GET_MII: 40696f45ec7bSml29623 case NXGE_PUT_MII: 40706f45ec7bSml29623 case NXGE_PUT_TCAM: 40716f45ec7bSml29623 case NXGE_GET_TCAM: 40726f45ec7bSml29623 case NXGE_GET64: 40736f45ec7bSml29623 case NXGE_PUT64: 40746f45ec7bSml29623 case NXGE_GET_TX_RING_SZ: 40756f45ec7bSml29623 case NXGE_GET_TX_DESC: 40766f45ec7bSml29623 case NXGE_TX_SIDE_RESET: 40776f45ec7bSml29623 case NXGE_RX_SIDE_RESET: 40786f45ec7bSml29623 case NXGE_GLOBAL_RESET: 40796f45ec7bSml29623 case NXGE_RESET_MAC: 40806f45ec7bSml29623 case NXGE_TX_REGS_DUMP: 40816f45ec7bSml29623 case NXGE_RX_REGS_DUMP: 40826f45ec7bSml29623 case NXGE_INT_REGS_DUMP: 40836f45ec7bSml29623 case NXGE_VIR_INT_REGS_DUMP: 40846f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 40856f45ec7bSml29623 "==> nxge_m_ioctl: cmd 0x%x", cmd)); 40866f45ec7bSml29623 nxge_hw_ioctl(nxgep, wq, mp, iocp); 40876f45ec7bSml29623 break; 40884df55fdeSJanie Lu case NXGE_RX_CLASS: 40894df55fdeSJanie Lu if (nxge_rxclass_ioctl(nxgep, wq, mp->b_cont) < 0) 40904df55fdeSJanie Lu miocnak(wq, mp, 0, EINVAL); 40914df55fdeSJanie Lu else 40924df55fdeSJanie Lu miocack(wq, mp, sizeof (rx_class_cfg_t), 0); 40934df55fdeSJanie Lu break; 40944df55fdeSJanie Lu case NXGE_RX_HASH: 40954df55fdeSJanie Lu 40964df55fdeSJanie Lu if (nxge_rxhash_ioctl(nxgep, wq, mp->b_cont) < 0) 40974df55fdeSJanie Lu miocnak(wq, mp, 0, EINVAL); 40984df55fdeSJanie Lu else 40994df55fdeSJanie Lu miocack(wq, mp, sizeof (cfg_cmd_t), 0); 41004df55fdeSJanie Lu break; 41016f45ec7bSml29623 } 41026f45ec7bSml29623 41036f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl")); 41046f45ec7bSml29623 } 41056f45ec7bSml29623 41066f45ec7bSml29623 extern void nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count); 41076f45ec7bSml29623 4108678453a8Sspeer void 4109da14cebeSEric Cheng nxge_mmac_kstat_update(p_nxge_t nxgep, int slot, boolean_t factory) 41106f45ec7bSml29623 { 41116f45ec7bSml29623 p_nxge_mmac_stats_t mmac_stats; 41126f45ec7bSml29623 int i; 41136f45ec7bSml29623 nxge_mmac_t *mmac_info; 41146f45ec7bSml29623 41156f45ec7bSml29623 mmac_info = &nxgep->nxge_mmac_info; 41166f45ec7bSml29623 41176f45ec7bSml29623 mmac_stats = &nxgep->statsp->mmac_stats; 41186f45ec7bSml29623 mmac_stats->mmac_max_cnt = mmac_info->num_mmac; 41196f45ec7bSml29623 mmac_stats->mmac_avail_cnt = mmac_info->naddrfree; 41206f45ec7bSml29623 41216f45ec7bSml29623 for (i = 0; i < ETHERADDRL; i++) { 41226f45ec7bSml29623 if (factory) { 41236f45ec7bSml29623 mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 41244045d941Ssowmini = mmac_info->factory_mac_pool[slot][ 41254045d941Ssowmini (ETHERADDRL-1) - i]; 41266f45ec7bSml29623 } else { 41276f45ec7bSml29623 mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 41284045d941Ssowmini = mmac_info->mac_pool[slot].addr[ 41294045d941Ssowmini (ETHERADDRL - 1) - i]; 41306f45ec7bSml29623 } 41316f45ec7bSml29623 } 41326f45ec7bSml29623 } 41336f45ec7bSml29623 41346f45ec7bSml29623 /* 41356f45ec7bSml29623 * nxge_altmac_set() -- Set an alternate MAC address 41366f45ec7bSml29623 */ 4137da14cebeSEric Cheng static int 4138da14cebeSEric Cheng nxge_altmac_set(p_nxge_t nxgep, uint8_t *maddr, int slot, 4139da14cebeSEric Cheng int rdctbl, boolean_t usetbl) 41406f45ec7bSml29623 { 41416f45ec7bSml29623 uint8_t addrn; 41426f45ec7bSml29623 uint8_t portn; 41436f45ec7bSml29623 npi_mac_addr_t altmac; 41447b9fa28bSspeer hostinfo_t mac_rdc; 41457b9fa28bSspeer p_nxge_class_pt_cfg_t clscfgp; 41466f45ec7bSml29623 4147da14cebeSEric Cheng 41486f45ec7bSml29623 altmac.w2 = ((uint16_t)maddr[0] << 8) | ((uint16_t)maddr[1] & 0x0ff); 41496f45ec7bSml29623 altmac.w1 = ((uint16_t)maddr[2] << 8) | ((uint16_t)maddr[3] & 0x0ff); 41506f45ec7bSml29623 altmac.w0 = ((uint16_t)maddr[4] << 8) | ((uint16_t)maddr[5] & 0x0ff); 41516f45ec7bSml29623 41526f45ec7bSml29623 portn = nxgep->mac.portnum; 41536f45ec7bSml29623 addrn = (uint8_t)slot - 1; 41546f45ec7bSml29623 4155da14cebeSEric Cheng if (npi_mac_altaddr_entry(nxgep->npi_handle, OP_SET, 4156da14cebeSEric Cheng nxgep->function_num, addrn, &altmac) != NPI_SUCCESS) 41576f45ec7bSml29623 return (EIO); 41587b9fa28bSspeer 41597b9fa28bSspeer /* 41607b9fa28bSspeer * Set the rdc table number for the host info entry 41617b9fa28bSspeer * for this mac address slot. 41627b9fa28bSspeer */ 41637b9fa28bSspeer clscfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config; 41647b9fa28bSspeer mac_rdc.value = 0; 4165da14cebeSEric Cheng if (usetbl) 4166e857d0f3SMichael Speer mac_rdc.bits.w0.rdc_tbl_num = rdctbl; 4167da14cebeSEric Cheng else 4168da14cebeSEric Cheng mac_rdc.bits.w0.rdc_tbl_num = 4169da14cebeSEric Cheng clscfgp->mac_host_info[addrn].rdctbl; 41707b9fa28bSspeer mac_rdc.bits.w0.mac_pref = clscfgp->mac_host_info[addrn].mpr_npr; 41717b9fa28bSspeer 41727b9fa28bSspeer if (npi_mac_hostinfo_entry(nxgep->npi_handle, OP_SET, 41737b9fa28bSspeer nxgep->function_num, addrn, &mac_rdc) != NPI_SUCCESS) { 41747b9fa28bSspeer return (EIO); 41757b9fa28bSspeer } 41767b9fa28bSspeer 41776f45ec7bSml29623 /* 41786f45ec7bSml29623 * Enable comparison with the alternate MAC address. 41796f45ec7bSml29623 * While the first alternate addr is enabled by bit 1 of register 41806f45ec7bSml29623 * BMAC_ALTAD_CMPEN, it is enabled by bit 0 of register 41816f45ec7bSml29623 * XMAC_ADDR_CMPEN, so slot needs to be converted to addrn 41826f45ec7bSml29623 * accordingly before calling npi_mac_altaddr_entry. 41836f45ec7bSml29623 */ 41846f45ec7bSml29623 if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 41856f45ec7bSml29623 addrn = (uint8_t)slot - 1; 41866f45ec7bSml29623 else 41876f45ec7bSml29623 addrn = (uint8_t)slot; 41886f45ec7bSml29623 4189da14cebeSEric Cheng if (npi_mac_altaddr_enable(nxgep->npi_handle, 4190da14cebeSEric Cheng nxgep->function_num, addrn) != NPI_SUCCESS) { 41916f45ec7bSml29623 return (EIO); 4192da14cebeSEric Cheng } 4193da14cebeSEric Cheng 41946f45ec7bSml29623 return (0); 41956f45ec7bSml29623 } 41966f45ec7bSml29623 41976f45ec7bSml29623 /* 4198da14cebeSEric Cheng * nxeg_m_mmac_add_g() - find an unused address slot, set the address 41996f45ec7bSml29623 * value to the one specified, enable the port to start filtering on 42006f45ec7bSml29623 * the new MAC address. Returns 0 on success. 42016f45ec7bSml29623 */ 4202678453a8Sspeer int 4203da14cebeSEric Cheng nxge_m_mmac_add_g(void *arg, const uint8_t *maddr, int rdctbl, 4204da14cebeSEric Cheng boolean_t usetbl) 42056f45ec7bSml29623 { 42066f45ec7bSml29623 p_nxge_t nxgep = arg; 4207da14cebeSEric Cheng int slot; 42086f45ec7bSml29623 nxge_mmac_t *mmac_info; 42096f45ec7bSml29623 int err; 42106f45ec7bSml29623 nxge_status_t status; 42116f45ec7bSml29623 42126f45ec7bSml29623 mutex_enter(nxgep->genlock); 42136f45ec7bSml29623 42146f45ec7bSml29623 /* 42156f45ec7bSml29623 * Make sure that nxge is initialized, if _start() has 42166f45ec7bSml29623 * not been called. 42176f45ec7bSml29623 */ 42186f45ec7bSml29623 if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 42196f45ec7bSml29623 status = nxge_init(nxgep); 42206f45ec7bSml29623 if (status != NXGE_OK) { 42216f45ec7bSml29623 mutex_exit(nxgep->genlock); 42226f45ec7bSml29623 return (ENXIO); 42236f45ec7bSml29623 } 42246f45ec7bSml29623 } 42256f45ec7bSml29623 42266f45ec7bSml29623 mmac_info = &nxgep->nxge_mmac_info; 42276f45ec7bSml29623 if (mmac_info->naddrfree == 0) { 42286f45ec7bSml29623 mutex_exit(nxgep->genlock); 42296f45ec7bSml29623 return (ENOSPC); 42306f45ec7bSml29623 } 4231da14cebeSEric Cheng 42326f45ec7bSml29623 /* 42336f45ec7bSml29623 * Search for the first available slot. Because naddrfree 42346f45ec7bSml29623 * is not zero, we are guaranteed to find one. 42356f45ec7bSml29623 * Each of the first two ports of Neptune has 16 alternate 4236678453a8Sspeer * MAC slots but only the first 7 (of 15) slots have assigned factory 42376f45ec7bSml29623 * MAC addresses. We first search among the slots without bundled 42386f45ec7bSml29623 * factory MACs. If we fail to find one in that range, then we 42396f45ec7bSml29623 * search the slots with bundled factory MACs. A factory MAC 42406f45ec7bSml29623 * will be wasted while the slot is used with a user MAC address. 42416f45ec7bSml29623 * But the slot could be used by factory MAC again after calling 42426f45ec7bSml29623 * nxge_m_mmac_remove and nxge_m_mmac_reserve. 42436f45ec7bSml29623 */ 4244da14cebeSEric Cheng for (slot = 0; slot <= mmac_info->num_mmac; slot++) { 42456f45ec7bSml29623 if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 42466f45ec7bSml29623 break; 42476f45ec7bSml29623 } 4248da14cebeSEric Cheng 42496f45ec7bSml29623 ASSERT(slot <= mmac_info->num_mmac); 4250e857d0f3SMichael Speer 4251da14cebeSEric Cheng if ((err = nxge_altmac_set(nxgep, (uint8_t *)maddr, slot, rdctbl, 4252da14cebeSEric Cheng usetbl)) != 0) { 42536f45ec7bSml29623 mutex_exit(nxgep->genlock); 42546f45ec7bSml29623 return (err); 42556f45ec7bSml29623 } 4256e857d0f3SMichael Speer 4257da14cebeSEric Cheng bcopy(maddr, mmac_info->mac_pool[slot].addr, ETHERADDRL); 42586f45ec7bSml29623 mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED; 42596f45ec7bSml29623 mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR; 42606f45ec7bSml29623 mmac_info->naddrfree--; 42616f45ec7bSml29623 nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 42626f45ec7bSml29623 42636f45ec7bSml29623 mutex_exit(nxgep->genlock); 42646f45ec7bSml29623 return (0); 42656f45ec7bSml29623 } 42666f45ec7bSml29623 42676f45ec7bSml29623 /* 42686f45ec7bSml29623 * Remove the specified mac address and update the HW not to filter 42696f45ec7bSml29623 * the mac address anymore. 42706f45ec7bSml29623 */ 4271678453a8Sspeer int 4272da14cebeSEric Cheng nxge_m_mmac_remove(void *arg, int slot) 42736f45ec7bSml29623 { 42746f45ec7bSml29623 p_nxge_t nxgep = arg; 42756f45ec7bSml29623 nxge_mmac_t *mmac_info; 42766f45ec7bSml29623 uint8_t addrn; 42776f45ec7bSml29623 uint8_t portn; 42786f45ec7bSml29623 int err = 0; 42796f45ec7bSml29623 nxge_status_t status; 42806f45ec7bSml29623 42816f45ec7bSml29623 mutex_enter(nxgep->genlock); 42826f45ec7bSml29623 42836f45ec7bSml29623 /* 42846f45ec7bSml29623 * Make sure that nxge is initialized, if _start() has 42856f45ec7bSml29623 * not been called. 42866f45ec7bSml29623 */ 42876f45ec7bSml29623 if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 42886f45ec7bSml29623 status = nxge_init(nxgep); 42896f45ec7bSml29623 if (status != NXGE_OK) { 42906f45ec7bSml29623 mutex_exit(nxgep->genlock); 42916f45ec7bSml29623 return (ENXIO); 42926f45ec7bSml29623 } 42936f45ec7bSml29623 } 42946f45ec7bSml29623 42956f45ec7bSml29623 mmac_info = &nxgep->nxge_mmac_info; 42966f45ec7bSml29623 if (slot < 1 || slot > mmac_info->num_mmac) { 42976f45ec7bSml29623 mutex_exit(nxgep->genlock); 42986f45ec7bSml29623 return (EINVAL); 42996f45ec7bSml29623 } 43006f45ec7bSml29623 43016f45ec7bSml29623 portn = nxgep->mac.portnum; 43026f45ec7bSml29623 if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 43036f45ec7bSml29623 addrn = (uint8_t)slot - 1; 43046f45ec7bSml29623 else 43056f45ec7bSml29623 addrn = (uint8_t)slot; 43066f45ec7bSml29623 43076f45ec7bSml29623 if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 43086f45ec7bSml29623 if (npi_mac_altaddr_disable(nxgep->npi_handle, portn, addrn) 43096f45ec7bSml29623 == NPI_SUCCESS) { 43106f45ec7bSml29623 mmac_info->naddrfree++; 43116f45ec7bSml29623 mmac_info->mac_pool[slot].flags &= ~MMAC_SLOT_USED; 43126f45ec7bSml29623 /* 43136f45ec7bSml29623 * Regardless if the MAC we just stopped filtering 43146f45ec7bSml29623 * is a user addr or a facory addr, we must set 43156f45ec7bSml29623 * the MMAC_VENDOR_ADDR flag if this slot has an 43166f45ec7bSml29623 * associated factory MAC to indicate that a factory 43176f45ec7bSml29623 * MAC is available. 43186f45ec7bSml29623 */ 43196f45ec7bSml29623 if (slot <= mmac_info->num_factory_mmac) { 43206f45ec7bSml29623 mmac_info->mac_pool[slot].flags 43216f45ec7bSml29623 |= MMAC_VENDOR_ADDR; 43226f45ec7bSml29623 } 43236f45ec7bSml29623 /* 43246f45ec7bSml29623 * Clear mac_pool[slot].addr so that kstat shows 0 43256f45ec7bSml29623 * alternate MAC address if the slot is not used. 43266f45ec7bSml29623 * (But nxge_m_mmac_get returns the factory MAC even 43276f45ec7bSml29623 * when the slot is not used!) 43286f45ec7bSml29623 */ 43296f45ec7bSml29623 bzero(mmac_info->mac_pool[slot].addr, ETHERADDRL); 43306f45ec7bSml29623 nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 43316f45ec7bSml29623 } else { 43326f45ec7bSml29623 err = EIO; 43336f45ec7bSml29623 } 43346f45ec7bSml29623 } else { 43356f45ec7bSml29623 err = EINVAL; 43366f45ec7bSml29623 } 43376f45ec7bSml29623 43386f45ec7bSml29623 mutex_exit(nxgep->genlock); 43396f45ec7bSml29623 return (err); 43406f45ec7bSml29623 } 43416f45ec7bSml29623 43426f45ec7bSml29623 /* 4343da14cebeSEric Cheng * The callback to query all the factory addresses. naddr must be the same as 4344da14cebeSEric Cheng * the number of factory addresses (returned by MAC_CAPAB_MULTIFACTADDR), and 4345da14cebeSEric Cheng * mcm_addr is the space allocated for keep all the addresses, whose size is 4346da14cebeSEric Cheng * naddr * MAXMACADDRLEN. 43476f45ec7bSml29623 */ 4348da14cebeSEric Cheng static void 4349da14cebeSEric Cheng nxge_m_getfactaddr(void *arg, uint_t naddr, uint8_t *addr) 43506f45ec7bSml29623 { 43516f45ec7bSml29623 nxge_t *nxgep = arg; 43526f45ec7bSml29623 nxge_mmac_t *mmac_info; 4353da14cebeSEric Cheng int i; 43546f45ec7bSml29623 43556f45ec7bSml29623 mutex_enter(nxgep->genlock); 43566f45ec7bSml29623 43576f45ec7bSml29623 mmac_info = &nxgep->nxge_mmac_info; 4358da14cebeSEric Cheng ASSERT(naddr == mmac_info->num_factory_mmac); 43596f45ec7bSml29623 4360da14cebeSEric Cheng for (i = 0; i < naddr; i++) { 4361da14cebeSEric Cheng bcopy(mmac_info->factory_mac_pool[i + 1], 4362da14cebeSEric Cheng addr + i * MAXMACADDRLEN, ETHERADDRL); 43636f45ec7bSml29623 } 43646f45ec7bSml29623 43656f45ec7bSml29623 mutex_exit(nxgep->genlock); 43666f45ec7bSml29623 } 43676f45ec7bSml29623 4368da14cebeSEric Cheng 43696f45ec7bSml29623 static boolean_t 43706f45ec7bSml29623 nxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 43716f45ec7bSml29623 { 43726f45ec7bSml29623 nxge_t *nxgep = arg; 43736f45ec7bSml29623 uint32_t *txflags = cap_data; 43746f45ec7bSml29623 43756f45ec7bSml29623 switch (cap) { 43766f45ec7bSml29623 case MAC_CAPAB_HCKSUM: 4377678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4378b4d05839Sml29623 "==> nxge_m_getcapab: checksum %d", nxge_cksum_offload)); 4379b4d05839Sml29623 if (nxge_cksum_offload <= 1) { 43806f45ec7bSml29623 *txflags = HCKSUM_INET_PARTIAL; 4381678453a8Sspeer } 43826f45ec7bSml29623 break; 4383678453a8Sspeer 4384da14cebeSEric Cheng case MAC_CAPAB_MULTIFACTADDR: { 4385da14cebeSEric Cheng mac_capab_multifactaddr_t *mfacp = cap_data; 43866f45ec7bSml29623 438763f531d1SSriharsha Basavapatna if (!isLDOMguest(nxgep)) { 43886f45ec7bSml29623 mutex_enter(nxgep->genlock); 438963f531d1SSriharsha Basavapatna mfacp->mcm_naddr = 439063f531d1SSriharsha Basavapatna nxgep->nxge_mmac_info.num_factory_mmac; 4391da14cebeSEric Cheng mfacp->mcm_getaddr = nxge_m_getfactaddr; 43926f45ec7bSml29623 mutex_exit(nxgep->genlock); 439363f531d1SSriharsha Basavapatna } 43946f45ec7bSml29623 break; 4395da14cebeSEric Cheng } 4396678453a8Sspeer 439730ac2e7bSml29623 case MAC_CAPAB_LSO: { 439830ac2e7bSml29623 mac_capab_lso_t *cap_lso = cap_data; 439930ac2e7bSml29623 44003d16f8e7Sml29623 if (nxgep->soft_lso_enable) { 4401b4d05839Sml29623 if (nxge_cksum_offload <= 1) { 440230ac2e7bSml29623 cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 440330ac2e7bSml29623 if (nxge_lso_max > NXGE_LSO_MAXLEN) { 440430ac2e7bSml29623 nxge_lso_max = NXGE_LSO_MAXLEN; 440530ac2e7bSml29623 } 4406b4d05839Sml29623 cap_lso->lso_basic_tcp_ipv4.lso_max = 4407b4d05839Sml29623 nxge_lso_max; 4408b4d05839Sml29623 } 440930ac2e7bSml29623 break; 441030ac2e7bSml29623 } else { 441130ac2e7bSml29623 return (B_FALSE); 441230ac2e7bSml29623 } 441330ac2e7bSml29623 } 441430ac2e7bSml29623 4415678453a8Sspeer case MAC_CAPAB_RINGS: { 4416da14cebeSEric Cheng mac_capab_rings_t *cap_rings = cap_data; 4417da14cebeSEric Cheng p_nxge_hw_pt_cfg_t p_cfgp = &nxgep->pt_config.hw_config; 4418678453a8Sspeer 4419da14cebeSEric Cheng mutex_enter(nxgep->genlock); 4420da14cebeSEric Cheng if (cap_rings->mr_type == MAC_RING_TYPE_RX) { 442163f531d1SSriharsha Basavapatna if (isLDOMguest(nxgep)) { 442263f531d1SSriharsha Basavapatna cap_rings->mr_group_type = 442363f531d1SSriharsha Basavapatna MAC_GROUP_TYPE_STATIC; 442463f531d1SSriharsha Basavapatna cap_rings->mr_rnum = 442563f531d1SSriharsha Basavapatna NXGE_HIO_SHARE_MAX_CHANNELS; 442663f531d1SSriharsha Basavapatna cap_rings->mr_rget = nxge_fill_ring; 442763f531d1SSriharsha Basavapatna cap_rings->mr_gnum = 1; 442863f531d1SSriharsha Basavapatna cap_rings->mr_gget = nxge_hio_group_get; 442963f531d1SSriharsha Basavapatna cap_rings->mr_gaddring = NULL; 443063f531d1SSriharsha Basavapatna cap_rings->mr_gremring = NULL; 443163f531d1SSriharsha Basavapatna } else { 443263f531d1SSriharsha Basavapatna /* 443363f531d1SSriharsha Basavapatna * Service Domain. 443463f531d1SSriharsha Basavapatna */ 443563f531d1SSriharsha Basavapatna cap_rings->mr_group_type = 443663f531d1SSriharsha Basavapatna MAC_GROUP_TYPE_DYNAMIC; 4437da14cebeSEric Cheng cap_rings->mr_rnum = p_cfgp->max_rdcs; 4438da14cebeSEric Cheng cap_rings->mr_rget = nxge_fill_ring; 4439da14cebeSEric Cheng cap_rings->mr_gnum = p_cfgp->max_rdc_grpids; 4440da14cebeSEric Cheng cap_rings->mr_gget = nxge_hio_group_get; 4441da14cebeSEric Cheng cap_rings->mr_gaddring = nxge_group_add_ring; 4442da14cebeSEric Cheng cap_rings->mr_gremring = nxge_group_rem_ring; 444363f531d1SSriharsha Basavapatna } 4444678453a8Sspeer 4445da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, RX_CTL, 4446da14cebeSEric Cheng "==> nxge_m_getcapab: rx nrings[%d] ngroups[%d]", 4447da14cebeSEric Cheng p_cfgp->max_rdcs, p_cfgp->max_rdc_grpids)); 4448678453a8Sspeer } else { 444963f531d1SSriharsha Basavapatna /* 445063f531d1SSriharsha Basavapatna * TX Rings. 445163f531d1SSriharsha Basavapatna */ 445263f531d1SSriharsha Basavapatna if (isLDOMguest(nxgep)) { 445363f531d1SSriharsha Basavapatna cap_rings->mr_group_type = 445463f531d1SSriharsha Basavapatna MAC_GROUP_TYPE_STATIC; 445563f531d1SSriharsha Basavapatna cap_rings->mr_rnum = 445663f531d1SSriharsha Basavapatna NXGE_HIO_SHARE_MAX_CHANNELS; 445763f531d1SSriharsha Basavapatna cap_rings->mr_rget = nxge_fill_ring; 445863f531d1SSriharsha Basavapatna cap_rings->mr_gnum = 0; 445963f531d1SSriharsha Basavapatna cap_rings->mr_gget = NULL; 446063f531d1SSriharsha Basavapatna cap_rings->mr_gaddring = NULL; 446163f531d1SSriharsha Basavapatna cap_rings->mr_gremring = NULL; 446263f531d1SSriharsha Basavapatna } else { 446363f531d1SSriharsha Basavapatna /* 446463f531d1SSriharsha Basavapatna * Service Domain. 446563f531d1SSriharsha Basavapatna */ 446663f531d1SSriharsha Basavapatna cap_rings->mr_group_type = 446763f531d1SSriharsha Basavapatna MAC_GROUP_TYPE_DYNAMIC; 4468da14cebeSEric Cheng cap_rings->mr_rnum = p_cfgp->tdc.count; 4469da14cebeSEric Cheng cap_rings->mr_rget = nxge_fill_ring; 447063f531d1SSriharsha Basavapatna 447163f531d1SSriharsha Basavapatna /* 447263f531d1SSriharsha Basavapatna * Share capable. 447363f531d1SSriharsha Basavapatna * 447463f531d1SSriharsha Basavapatna * Do not report the default group: hence -1 447563f531d1SSriharsha Basavapatna */ 4476da14cebeSEric Cheng cap_rings->mr_gnum = 4477da14cebeSEric Cheng NXGE_MAX_TDC_GROUPS / nxgep->nports - 1; 4478da14cebeSEric Cheng cap_rings->mr_gget = nxge_hio_group_get; 4479da14cebeSEric Cheng cap_rings->mr_gaddring = nxge_group_add_ring; 4480da14cebeSEric Cheng cap_rings->mr_gremring = nxge_group_rem_ring; 448163f531d1SSriharsha Basavapatna } 4482da14cebeSEric Cheng 4483da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, TX_CTL, 4484da14cebeSEric Cheng "==> nxge_m_getcapab: tx rings # of rings %d", 4485da14cebeSEric Cheng p_cfgp->tdc.count)); 4486da14cebeSEric Cheng } 4487da14cebeSEric Cheng mutex_exit(nxgep->genlock); 4488678453a8Sspeer break; 4489678453a8Sspeer } 4490678453a8Sspeer 4491da14cebeSEric Cheng #if defined(sun4v) 4492678453a8Sspeer case MAC_CAPAB_SHARES: { 4493678453a8Sspeer mac_capab_share_t *mshares = (mac_capab_share_t *)cap_data; 4494678453a8Sspeer 4495678453a8Sspeer /* 4496678453a8Sspeer * Only the service domain driver responds to 4497678453a8Sspeer * this capability request. 4498678453a8Sspeer */ 4499da14cebeSEric Cheng mutex_enter(nxgep->genlock); 4500678453a8Sspeer if (isLDOMservice(nxgep)) { 4501678453a8Sspeer mshares->ms_snum = 3; 4502678453a8Sspeer mshares->ms_handle = (void *)nxgep; 4503678453a8Sspeer mshares->ms_salloc = nxge_hio_share_alloc; 4504678453a8Sspeer mshares->ms_sfree = nxge_hio_share_free; 4505da14cebeSEric Cheng mshares->ms_sadd = nxge_hio_share_add_group; 4506da14cebeSEric Cheng mshares->ms_sremove = nxge_hio_share_rem_group; 4507678453a8Sspeer mshares->ms_squery = nxge_hio_share_query; 4508da14cebeSEric Cheng mshares->ms_sbind = nxge_hio_share_bind; 4509da14cebeSEric Cheng mshares->ms_sunbind = nxge_hio_share_unbind; 4510da14cebeSEric Cheng mutex_exit(nxgep->genlock); 4511da14cebeSEric Cheng } else { 4512da14cebeSEric Cheng mutex_exit(nxgep->genlock); 4513678453a8Sspeer return (B_FALSE); 4514da14cebeSEric Cheng } 4515678453a8Sspeer break; 4516678453a8Sspeer } 4517678453a8Sspeer #endif 45186f45ec7bSml29623 default: 45196f45ec7bSml29623 return (B_FALSE); 45206f45ec7bSml29623 } 45216f45ec7bSml29623 return (B_TRUE); 45226f45ec7bSml29623 } 45236f45ec7bSml29623 45241bd6825cSml29623 static boolean_t 45251bd6825cSml29623 nxge_param_locked(mac_prop_id_t pr_num) 45261bd6825cSml29623 { 45271bd6825cSml29623 /* 45281bd6825cSml29623 * All adv_* parameters are locked (read-only) while 45291bd6825cSml29623 * the device is in any sort of loopback mode ... 45301bd6825cSml29623 */ 45311bd6825cSml29623 switch (pr_num) { 45323fd94f8cSam223141 case MAC_PROP_ADV_1000FDX_CAP: 45333fd94f8cSam223141 case MAC_PROP_EN_1000FDX_CAP: 45343fd94f8cSam223141 case MAC_PROP_ADV_1000HDX_CAP: 45353fd94f8cSam223141 case MAC_PROP_EN_1000HDX_CAP: 45363fd94f8cSam223141 case MAC_PROP_ADV_100FDX_CAP: 45373fd94f8cSam223141 case MAC_PROP_EN_100FDX_CAP: 45383fd94f8cSam223141 case MAC_PROP_ADV_100HDX_CAP: 45393fd94f8cSam223141 case MAC_PROP_EN_100HDX_CAP: 45403fd94f8cSam223141 case MAC_PROP_ADV_10FDX_CAP: 45413fd94f8cSam223141 case MAC_PROP_EN_10FDX_CAP: 45423fd94f8cSam223141 case MAC_PROP_ADV_10HDX_CAP: 45433fd94f8cSam223141 case MAC_PROP_EN_10HDX_CAP: 45443fd94f8cSam223141 case MAC_PROP_AUTONEG: 45453fd94f8cSam223141 case MAC_PROP_FLOWCTRL: 45461bd6825cSml29623 return (B_TRUE); 45471bd6825cSml29623 } 45481bd6825cSml29623 return (B_FALSE); 45491bd6825cSml29623 } 45501bd6825cSml29623 45511bd6825cSml29623 /* 45521bd6825cSml29623 * callback functions for set/get of properties 45531bd6825cSml29623 */ 45541bd6825cSml29623 static int 45551bd6825cSml29623 nxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 45561bd6825cSml29623 uint_t pr_valsize, const void *pr_val) 45571bd6825cSml29623 { 45581bd6825cSml29623 nxge_t *nxgep = barg; 45590dc2366fSVenugopal Iyer p_nxge_param_t param_arr = nxgep->param_arr; 45600dc2366fSVenugopal Iyer p_nxge_stats_t statsp = nxgep->statsp; 45611bd6825cSml29623 int err = 0; 45621bd6825cSml29623 45631bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_setprop")); 45640dc2366fSVenugopal Iyer 45651bd6825cSml29623 mutex_enter(nxgep->genlock); 45661bd6825cSml29623 if (statsp->port_stats.lb_mode != nxge_lb_normal && 45671bd6825cSml29623 nxge_param_locked(pr_num)) { 45681bd6825cSml29623 /* 45691bd6825cSml29623 * All adv_* parameters are locked (read-only) 45701bd6825cSml29623 * while the device is in any sort of loopback mode. 45711bd6825cSml29623 */ 45721bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 45731bd6825cSml29623 "==> nxge_m_setprop: loopback mode: read only")); 45741bd6825cSml29623 mutex_exit(nxgep->genlock); 45751bd6825cSml29623 return (EBUSY); 45761bd6825cSml29623 } 45771bd6825cSml29623 45781bd6825cSml29623 switch (pr_num) { 45793fd94f8cSam223141 case MAC_PROP_EN_1000FDX_CAP: 45800dc2366fSVenugopal Iyer nxgep->param_en_1000fdx = 45810dc2366fSVenugopal Iyer param_arr[param_anar_1000fdx].value = *(uint8_t *)pr_val; 45821bd6825cSml29623 goto reprogram; 45831bd6825cSml29623 45843fd94f8cSam223141 case MAC_PROP_EN_100FDX_CAP: 45850dc2366fSVenugopal Iyer nxgep->param_en_100fdx = 45860dc2366fSVenugopal Iyer param_arr[param_anar_100fdx].value = *(uint8_t *)pr_val; 45871bd6825cSml29623 goto reprogram; 45881bd6825cSml29623 45893fd94f8cSam223141 case MAC_PROP_EN_10FDX_CAP: 45900dc2366fSVenugopal Iyer nxgep->param_en_10fdx = 45910dc2366fSVenugopal Iyer param_arr[param_anar_10fdx].value = *(uint8_t *)pr_val; 45921bd6825cSml29623 goto reprogram; 45931bd6825cSml29623 45943fd94f8cSam223141 case MAC_PROP_AUTONEG: 45950dc2366fSVenugopal Iyer param_arr[param_autoneg].value = *(uint8_t *)pr_val; 45961bd6825cSml29623 goto reprogram; 45971bd6825cSml29623 45980dc2366fSVenugopal Iyer case MAC_PROP_MTU: { 45990dc2366fSVenugopal Iyer uint32_t cur_mtu, new_mtu, old_framesize; 46000dc2366fSVenugopal Iyer 46011bd6825cSml29623 cur_mtu = nxgep->mac.default_mtu; 46020dc2366fSVenugopal Iyer ASSERT(pr_valsize >= sizeof (new_mtu)); 46031bd6825cSml29623 bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 46040dc2366fSVenugopal Iyer 46051bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46061bd6825cSml29623 "==> nxge_m_setprop: set MTU: %d is_jumbo %d", 46071bd6825cSml29623 new_mtu, nxgep->mac.is_jumbo)); 46081bd6825cSml29623 46091bd6825cSml29623 if (new_mtu == cur_mtu) { 46101bd6825cSml29623 err = 0; 46111bd6825cSml29623 break; 46121bd6825cSml29623 } 461348056c53SMichael Speer 4614afdda45fSVasumathi Sundaram - Sun Microsystems if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 4615afdda45fSVasumathi Sundaram - Sun Microsystems err = EBUSY; 4616afdda45fSVasumathi Sundaram - Sun Microsystems break; 4617afdda45fSVasumathi Sundaram - Sun Microsystems } 46181bd6825cSml29623 461948056c53SMichael Speer if ((new_mtu < NXGE_DEFAULT_MTU) || 462048056c53SMichael Speer (new_mtu > NXGE_MAXIMUM_MTU)) { 46211bd6825cSml29623 err = EINVAL; 46221bd6825cSml29623 break; 46231bd6825cSml29623 } 46241bd6825cSml29623 46251bd6825cSml29623 old_framesize = (uint32_t)nxgep->mac.maxframesize; 46261bd6825cSml29623 nxgep->mac.maxframesize = (uint16_t) 46271bd6825cSml29623 (new_mtu + NXGE_EHEADER_VLAN_CRC); 46281bd6825cSml29623 if (nxge_mac_set_framesize(nxgep)) { 4629c2d37b8bSml29623 nxgep->mac.maxframesize = 4630c2d37b8bSml29623 (uint16_t)old_framesize; 46311bd6825cSml29623 err = EINVAL; 46321bd6825cSml29623 break; 46331bd6825cSml29623 } 46341bd6825cSml29623 46351bd6825cSml29623 nxgep->mac.default_mtu = new_mtu; 46360dc2366fSVenugopal Iyer nxgep->mac.is_jumbo = (new_mtu > NXGE_DEFAULT_MTU); 463748056c53SMichael Speer 46381bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46391bd6825cSml29623 "==> nxge_m_setprop: set MTU: %d maxframe %d", 46401bd6825cSml29623 new_mtu, nxgep->mac.maxframesize)); 46411bd6825cSml29623 break; 46420dc2366fSVenugopal Iyer } 46431bd6825cSml29623 46440dc2366fSVenugopal Iyer case MAC_PROP_FLOWCTRL: { 46450dc2366fSVenugopal Iyer link_flowctrl_t fl; 46460dc2366fSVenugopal Iyer 46470dc2366fSVenugopal Iyer ASSERT(pr_valsize >= sizeof (fl)); 46481bd6825cSml29623 bcopy(pr_val, &fl, sizeof (fl)); 46491bd6825cSml29623 46500dc2366fSVenugopal Iyer switch (fl) { 46511bd6825cSml29623 case LINK_FLOWCTRL_NONE: 46521bd6825cSml29623 param_arr[param_anar_pause].value = 0; 46531bd6825cSml29623 break; 46541bd6825cSml29623 46551bd6825cSml29623 case LINK_FLOWCTRL_RX: 46561bd6825cSml29623 param_arr[param_anar_pause].value = 1; 46571bd6825cSml29623 break; 46581bd6825cSml29623 46591bd6825cSml29623 case LINK_FLOWCTRL_TX: 46601bd6825cSml29623 case LINK_FLOWCTRL_BI: 46611bd6825cSml29623 err = EINVAL; 46621bd6825cSml29623 break; 46630dc2366fSVenugopal Iyer default: 46640dc2366fSVenugopal Iyer err = EINVAL; 46650dc2366fSVenugopal Iyer break; 46661bd6825cSml29623 } 46671bd6825cSml29623 reprogram: 46680dc2366fSVenugopal Iyer if ((err == 0) && !isLDOMguest(nxgep)) { 46691bd6825cSml29623 if (!nxge_param_link_update(nxgep)) { 46701bd6825cSml29623 err = EINVAL; 46711bd6825cSml29623 } 46720dc2366fSVenugopal Iyer } else { 46730dc2366fSVenugopal Iyer err = EINVAL; 46741bd6825cSml29623 } 46751bd6825cSml29623 break; 46760dc2366fSVenugopal Iyer } 46770dc2366fSVenugopal Iyer 46783fd94f8cSam223141 case MAC_PROP_PRIVATE: 46791bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46801bd6825cSml29623 "==> nxge_m_setprop: private property")); 46810dc2366fSVenugopal Iyer err = nxge_set_priv_prop(nxgep, pr_name, pr_valsize, pr_val); 46821bd6825cSml29623 break; 46834045d941Ssowmini 46844045d941Ssowmini default: 46854045d941Ssowmini err = ENOTSUP; 46864045d941Ssowmini break; 46871bd6825cSml29623 } 46881bd6825cSml29623 46891bd6825cSml29623 mutex_exit(nxgep->genlock); 46901bd6825cSml29623 46911bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46921bd6825cSml29623 "<== nxge_m_setprop (return %d)", err)); 46931bd6825cSml29623 return (err); 46941bd6825cSml29623 } 46951bd6825cSml29623 46961bd6825cSml29623 static int 46971bd6825cSml29623 nxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 46980dc2366fSVenugopal Iyer uint_t pr_valsize, void *pr_val) 46991bd6825cSml29623 { 47001bd6825cSml29623 nxge_t *nxgep = barg; 47011bd6825cSml29623 p_nxge_param_t param_arr = nxgep->param_arr; 47021bd6825cSml29623 p_nxge_stats_t statsp = nxgep->statsp; 47031bd6825cSml29623 47041bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 47051bd6825cSml29623 "==> nxge_m_getprop: pr_num %d", pr_num)); 47064045d941Ssowmini 47071bd6825cSml29623 switch (pr_num) { 47083fd94f8cSam223141 case MAC_PROP_DUPLEX: 47091bd6825cSml29623 *(uint8_t *)pr_val = statsp->mac_stats.link_duplex; 47101bd6825cSml29623 break; 47111bd6825cSml29623 47120dc2366fSVenugopal Iyer case MAC_PROP_SPEED: { 47130dc2366fSVenugopal Iyer uint64_t val = statsp->mac_stats.link_speed * 1000000ull; 47141bd6825cSml29623 47150dc2366fSVenugopal Iyer ASSERT(pr_valsize >= sizeof (val)); 47160dc2366fSVenugopal Iyer bcopy(&val, pr_val, sizeof (val)); 47171bd6825cSml29623 break; 47180dc2366fSVenugopal Iyer } 47190dc2366fSVenugopal Iyer 47200dc2366fSVenugopal Iyer case MAC_PROP_STATUS: { 47210dc2366fSVenugopal Iyer link_state_t state = statsp->mac_stats.link_up ? 47220dc2366fSVenugopal Iyer LINK_STATE_UP : LINK_STATE_DOWN; 47230dc2366fSVenugopal Iyer 47240dc2366fSVenugopal Iyer ASSERT(pr_valsize >= sizeof (state)); 47250dc2366fSVenugopal Iyer bcopy(&state, pr_val, sizeof (state)); 47260dc2366fSVenugopal Iyer break; 47270dc2366fSVenugopal Iyer } 47281bd6825cSml29623 47293fd94f8cSam223141 case MAC_PROP_AUTONEG: 47300dc2366fSVenugopal Iyer *(uint8_t *)pr_val = param_arr[param_autoneg].value; 47311bd6825cSml29623 break; 47321bd6825cSml29623 47330dc2366fSVenugopal Iyer case MAC_PROP_FLOWCTRL: { 47340dc2366fSVenugopal Iyer link_flowctrl_t fl = param_arr[param_anar_pause].value != 0 ? 47350dc2366fSVenugopal Iyer LINK_FLOWCTRL_RX : LINK_FLOWCTRL_NONE; 47361bd6825cSml29623 47370dc2366fSVenugopal Iyer ASSERT(pr_valsize >= sizeof (fl)); 47381bd6825cSml29623 bcopy(&fl, pr_val, sizeof (fl)); 47391bd6825cSml29623 break; 47400dc2366fSVenugopal Iyer } 47411bd6825cSml29623 47423fd94f8cSam223141 case MAC_PROP_ADV_1000FDX_CAP: 47430dc2366fSVenugopal Iyer *(uint8_t *)pr_val = param_arr[param_anar_1000fdx].value; 47441bd6825cSml29623 break; 47451bd6825cSml29623 47463fd94f8cSam223141 case MAC_PROP_EN_1000FDX_CAP: 47471bd6825cSml29623 *(uint8_t *)pr_val = nxgep->param_en_1000fdx; 47481bd6825cSml29623 break; 47491bd6825cSml29623 47503fd94f8cSam223141 case MAC_PROP_ADV_100FDX_CAP: 47510dc2366fSVenugopal Iyer *(uint8_t *)pr_val = param_arr[param_anar_100fdx].value; 47521bd6825cSml29623 break; 47531bd6825cSml29623 47543fd94f8cSam223141 case MAC_PROP_EN_100FDX_CAP: 47551bd6825cSml29623 *(uint8_t *)pr_val = nxgep->param_en_100fdx; 47561bd6825cSml29623 break; 47571bd6825cSml29623 47583fd94f8cSam223141 case MAC_PROP_ADV_10FDX_CAP: 47590dc2366fSVenugopal Iyer *(uint8_t *)pr_val = param_arr[param_anar_10fdx].value; 47601bd6825cSml29623 break; 47611bd6825cSml29623 47623fd94f8cSam223141 case MAC_PROP_EN_10FDX_CAP: 47631bd6825cSml29623 *(uint8_t *)pr_val = nxgep->param_en_10fdx; 47641bd6825cSml29623 break; 47651bd6825cSml29623 47660dc2366fSVenugopal Iyer case MAC_PROP_PRIVATE: 47670dc2366fSVenugopal Iyer return (nxge_get_priv_prop(nxgep, pr_name, pr_valsize, 47680dc2366fSVenugopal Iyer pr_val)); 47690dc2366fSVenugopal Iyer 47700dc2366fSVenugopal Iyer default: 47710dc2366fSVenugopal Iyer return (ENOTSUP); 47720dc2366fSVenugopal Iyer } 47730dc2366fSVenugopal Iyer 47740dc2366fSVenugopal Iyer return (0); 47750dc2366fSVenugopal Iyer } 47760dc2366fSVenugopal Iyer 47770dc2366fSVenugopal Iyer static void 47780dc2366fSVenugopal Iyer nxge_m_propinfo(void *barg, const char *pr_name, mac_prop_id_t pr_num, 47790dc2366fSVenugopal Iyer mac_prop_info_handle_t prh) 47800dc2366fSVenugopal Iyer { 47810dc2366fSVenugopal Iyer nxge_t *nxgep = barg; 47820dc2366fSVenugopal Iyer p_nxge_stats_t statsp = nxgep->statsp; 47830dc2366fSVenugopal Iyer 47840dc2366fSVenugopal Iyer /* 47850dc2366fSVenugopal Iyer * By default permissions are read/write unless specified 47860dc2366fSVenugopal Iyer * otherwise by the driver. 47870dc2366fSVenugopal Iyer */ 47880dc2366fSVenugopal Iyer 47890dc2366fSVenugopal Iyer switch (pr_num) { 47900dc2366fSVenugopal Iyer case MAC_PROP_DUPLEX: 47910dc2366fSVenugopal Iyer case MAC_PROP_SPEED: 47920dc2366fSVenugopal Iyer case MAC_PROP_STATUS: 47933fd94f8cSam223141 case MAC_PROP_EN_1000HDX_CAP: 47943fd94f8cSam223141 case MAC_PROP_EN_100HDX_CAP: 47953fd94f8cSam223141 case MAC_PROP_EN_10HDX_CAP: 47960dc2366fSVenugopal Iyer case MAC_PROP_ADV_1000FDX_CAP: 47973fd94f8cSam223141 case MAC_PROP_ADV_1000HDX_CAP: 47980dc2366fSVenugopal Iyer case MAC_PROP_ADV_100FDX_CAP: 47993fd94f8cSam223141 case MAC_PROP_ADV_100HDX_CAP: 48000dc2366fSVenugopal Iyer case MAC_PROP_ADV_10FDX_CAP: 48013fd94f8cSam223141 case MAC_PROP_ADV_10HDX_CAP: 48020dc2366fSVenugopal Iyer /* 48030dc2366fSVenugopal Iyer * Note that read-only properties don't need to 48040dc2366fSVenugopal Iyer * provide default values since they cannot be 48050dc2366fSVenugopal Iyer * changed by the administrator. 48060dc2366fSVenugopal Iyer */ 48070dc2366fSVenugopal Iyer mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 48080dc2366fSVenugopal Iyer break; 48090dc2366fSVenugopal Iyer 48100dc2366fSVenugopal Iyer case MAC_PROP_EN_1000FDX_CAP: 48110dc2366fSVenugopal Iyer case MAC_PROP_EN_100FDX_CAP: 48120dc2366fSVenugopal Iyer case MAC_PROP_EN_10FDX_CAP: 48130dc2366fSVenugopal Iyer mac_prop_info_set_default_uint8(prh, 1); 48140dc2366fSVenugopal Iyer break; 48150dc2366fSVenugopal Iyer 48160dc2366fSVenugopal Iyer case MAC_PROP_AUTONEG: 48170dc2366fSVenugopal Iyer mac_prop_info_set_default_uint8(prh, 1); 48180dc2366fSVenugopal Iyer break; 48190dc2366fSVenugopal Iyer 48200dc2366fSVenugopal Iyer case MAC_PROP_FLOWCTRL: 48210dc2366fSVenugopal Iyer mac_prop_info_set_default_link_flowctrl(prh, LINK_FLOWCTRL_RX); 48220dc2366fSVenugopal Iyer break; 48230dc2366fSVenugopal Iyer 48240dc2366fSVenugopal Iyer case MAC_PROP_MTU: 48250dc2366fSVenugopal Iyer mac_prop_info_set_range_uint32(prh, 48260dc2366fSVenugopal Iyer NXGE_DEFAULT_MTU, NXGE_MAXIMUM_MTU); 48271bd6825cSml29623 break; 48281bd6825cSml29623 48293fd94f8cSam223141 case MAC_PROP_PRIVATE: 48300dc2366fSVenugopal Iyer nxge_priv_propinfo(pr_name, prh); 48314045d941Ssowmini break; 48321bd6825cSml29623 } 48331bd6825cSml29623 48340dc2366fSVenugopal Iyer mutex_enter(nxgep->genlock); 48350dc2366fSVenugopal Iyer if (statsp->port_stats.lb_mode != nxge_lb_normal && 48360dc2366fSVenugopal Iyer nxge_param_locked(pr_num)) { 48370dc2366fSVenugopal Iyer /* 48380dc2366fSVenugopal Iyer * Some properties are locked (read-only) while the 48390dc2366fSVenugopal Iyer * device is in any sort of loopback mode. 48400dc2366fSVenugopal Iyer */ 48410dc2366fSVenugopal Iyer mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 48420dc2366fSVenugopal Iyer } 48430dc2366fSVenugopal Iyer mutex_exit(nxgep->genlock); 48440dc2366fSVenugopal Iyer } 48451bd6825cSml29623 48460dc2366fSVenugopal Iyer static void 48470dc2366fSVenugopal Iyer nxge_priv_propinfo(const char *pr_name, mac_prop_info_handle_t prh) 48480dc2366fSVenugopal Iyer { 48490dc2366fSVenugopal Iyer char valstr[64]; 48500dc2366fSVenugopal Iyer 48510dc2366fSVenugopal Iyer bzero(valstr, sizeof (valstr)); 48520dc2366fSVenugopal Iyer 48530dc2366fSVenugopal Iyer if (strcmp(pr_name, "_function_number") == 0 || 48540dc2366fSVenugopal Iyer strcmp(pr_name, "_fw_version") == 0 || 48550dc2366fSVenugopal Iyer strcmp(pr_name, "_port_mode") == 0 || 48560dc2366fSVenugopal Iyer strcmp(pr_name, "_hot_swap_phy") == 0) { 48570dc2366fSVenugopal Iyer mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 48580dc2366fSVenugopal Iyer 48590dc2366fSVenugopal Iyer } else if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 48600dc2366fSVenugopal Iyer (void) snprintf(valstr, sizeof (valstr), 48610dc2366fSVenugopal Iyer "%d", RXDMA_RCR_TO_DEFAULT); 48620dc2366fSVenugopal Iyer 48630dc2366fSVenugopal Iyer } else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 48640dc2366fSVenugopal Iyer (void) snprintf(valstr, sizeof (valstr), 48650dc2366fSVenugopal Iyer "%d", RXDMA_RCR_PTHRES_DEFAULT); 48660dc2366fSVenugopal Iyer 48670dc2366fSVenugopal Iyer } else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0 || 48680dc2366fSVenugopal Iyer strcmp(pr_name, "_class_opt_ipv4_udp") == 0 || 48690dc2366fSVenugopal Iyer strcmp(pr_name, "_class_opt_ipv4_ah") == 0 || 48700dc2366fSVenugopal Iyer strcmp(pr_name, "_class_opt_ipv4_sctp") == 0 || 48710dc2366fSVenugopal Iyer strcmp(pr_name, "_class_opt_ipv6_tcp") == 0 || 48720dc2366fSVenugopal Iyer strcmp(pr_name, "_class_opt_ipv6_udp") == 0 || 48730dc2366fSVenugopal Iyer strcmp(pr_name, "_class_opt_ipv6_ah") == 0 || 48740dc2366fSVenugopal Iyer strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 48750dc2366fSVenugopal Iyer (void) snprintf(valstr, sizeof (valstr), "%x", 48760dc2366fSVenugopal Iyer NXGE_CLASS_FLOW_GEN_SERVER); 48770dc2366fSVenugopal Iyer 48780dc2366fSVenugopal Iyer } else if (strcmp(pr_name, "_soft_lso_enable") == 0) { 48790dc2366fSVenugopal Iyer (void) snprintf(valstr, sizeof (valstr), "%d", 0); 48800dc2366fSVenugopal Iyer 48810dc2366fSVenugopal Iyer } else if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) { 48820dc2366fSVenugopal Iyer (void) snprintf(valstr, sizeof (valstr), "%d", 1); 48830dc2366fSVenugopal Iyer 48840dc2366fSVenugopal Iyer } else if (strcmp(pr_name, "_adv_pause_cap") == 0) { 48850dc2366fSVenugopal Iyer (void) snprintf(valstr, sizeof (valstr), "%d", 1); 48860dc2366fSVenugopal Iyer } 48870dc2366fSVenugopal Iyer 48880dc2366fSVenugopal Iyer if (strlen(valstr) > 0) 48890dc2366fSVenugopal Iyer mac_prop_info_set_default_str(prh, valstr); 48901bd6825cSml29623 } 48911bd6825cSml29623 48921bd6825cSml29623 /* ARGSUSED */ 48931bd6825cSml29623 static int 48941bd6825cSml29623 nxge_set_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_valsize, 48951bd6825cSml29623 const void *pr_val) 48961bd6825cSml29623 { 48971bd6825cSml29623 p_nxge_param_t param_arr = nxgep->param_arr; 48981bd6825cSml29623 int err = 0; 48991bd6825cSml29623 long result; 49001bd6825cSml29623 49011bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49021bd6825cSml29623 "==> nxge_set_priv_prop: name %s", pr_name)); 49031bd6825cSml29623 49041bd6825cSml29623 /* Blanking */ 49051bd6825cSml29623 if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 49061bd6825cSml29623 err = nxge_param_rx_intr_time(nxgep, NULL, NULL, 49071bd6825cSml29623 (char *)pr_val, 49081bd6825cSml29623 (caddr_t)¶m_arr[param_rxdma_intr_time]); 49091bd6825cSml29623 if (err) { 49101bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49111bd6825cSml29623 "<== nxge_set_priv_prop: " 49121bd6825cSml29623 "unable to set (%s)", pr_name)); 49131bd6825cSml29623 err = EINVAL; 49141bd6825cSml29623 } else { 49151bd6825cSml29623 err = 0; 49161bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49171bd6825cSml29623 "<== nxge_set_priv_prop: " 49181bd6825cSml29623 "set (%s)", pr_name)); 49191bd6825cSml29623 } 49201bd6825cSml29623 49211bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49221bd6825cSml29623 "<== nxge_set_priv_prop: name %s (value %d)", 49231bd6825cSml29623 pr_name, result)); 49241bd6825cSml29623 49251bd6825cSml29623 return (err); 49261bd6825cSml29623 } 49271bd6825cSml29623 49281bd6825cSml29623 if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 49291bd6825cSml29623 err = nxge_param_rx_intr_pkts(nxgep, NULL, NULL, 49301bd6825cSml29623 (char *)pr_val, 49311bd6825cSml29623 (caddr_t)¶m_arr[param_rxdma_intr_pkts]); 49321bd6825cSml29623 if (err) { 49331bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49341bd6825cSml29623 "<== nxge_set_priv_prop: " 49351bd6825cSml29623 "unable to set (%s)", pr_name)); 49361bd6825cSml29623 err = EINVAL; 49371bd6825cSml29623 } else { 49381bd6825cSml29623 err = 0; 49391bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49401bd6825cSml29623 "<== nxge_set_priv_prop: " 49411bd6825cSml29623 "set (%s)", pr_name)); 49421bd6825cSml29623 } 49431bd6825cSml29623 49441bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49451bd6825cSml29623 "<== nxge_set_priv_prop: name %s (value %d)", 49461bd6825cSml29623 pr_name, result)); 49471bd6825cSml29623 49481bd6825cSml29623 return (err); 49491bd6825cSml29623 } 49501bd6825cSml29623 49511bd6825cSml29623 /* Classification */ 49521bd6825cSml29623 if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 49531bd6825cSml29623 if (pr_val == NULL) { 49541bd6825cSml29623 err = EINVAL; 49551bd6825cSml29623 return (err); 49561bd6825cSml29623 } 49571bd6825cSml29623 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49581bd6825cSml29623 49591bd6825cSml29623 err = nxge_param_set_ip_opt(nxgep, NULL, 49601bd6825cSml29623 NULL, (char *)pr_val, 49611bd6825cSml29623 (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 49621bd6825cSml29623 49631bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49641bd6825cSml29623 "<== nxge_set_priv_prop: name %s (value 0x%x)", 49651bd6825cSml29623 pr_name, result)); 49661bd6825cSml29623 49671bd6825cSml29623 return (err); 49681bd6825cSml29623 } 49691bd6825cSml29623 49701bd6825cSml29623 if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 49711bd6825cSml29623 if (pr_val == NULL) { 49721bd6825cSml29623 err = EINVAL; 49731bd6825cSml29623 return (err); 49741bd6825cSml29623 } 49751bd6825cSml29623 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49761bd6825cSml29623 49771bd6825cSml29623 err = nxge_param_set_ip_opt(nxgep, NULL, 49781bd6825cSml29623 NULL, (char *)pr_val, 49791bd6825cSml29623 (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 49801bd6825cSml29623 49811bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49821bd6825cSml29623 "<== nxge_set_priv_prop: name %s (value 0x%x)", 49831bd6825cSml29623 pr_name, result)); 49841bd6825cSml29623 49851bd6825cSml29623 return (err); 49861bd6825cSml29623 } 49871bd6825cSml29623 if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 49881bd6825cSml29623 if (pr_val == NULL) { 49891bd6825cSml29623 err = EINVAL; 49901bd6825cSml29623 return (err); 49911bd6825cSml29623 } 49921bd6825cSml29623 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49931bd6825cSml29623 49941bd6825cSml29623 err = nxge_param_set_ip_opt(nxgep, NULL, 49951bd6825cSml29623 NULL, (char *)pr_val, 49961bd6825cSml29623 (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 49971bd6825cSml29623 49981bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49991bd6825cSml29623 "<== nxge_set_priv_prop: name %s (value 0x%x)", 50001bd6825cSml29623 pr_name, result)); 50011bd6825cSml29623 50021bd6825cSml29623 return (err); 50031bd6825cSml29623 } 50041bd6825cSml29623 if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 50051bd6825cSml29623 if (pr_val == NULL) { 50061bd6825cSml29623 err = EINVAL; 50071bd6825cSml29623 return (err); 50081bd6825cSml29623 } 50091bd6825cSml29623 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50101bd6825cSml29623 50111bd6825cSml29623 err = nxge_param_set_ip_opt(nxgep, NULL, 50121bd6825cSml29623 NULL, (char *)pr_val, 50131bd6825cSml29623 (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 50141bd6825cSml29623 50151bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50161bd6825cSml29623 "<== nxge_set_priv_prop: name %s (value 0x%x)", 50171bd6825cSml29623 pr_name, result)); 50181bd6825cSml29623 50191bd6825cSml29623 return (err); 50201bd6825cSml29623 } 50211bd6825cSml29623 50221bd6825cSml29623 if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 50231bd6825cSml29623 if (pr_val == NULL) { 50241bd6825cSml29623 err = EINVAL; 50251bd6825cSml29623 return (err); 50261bd6825cSml29623 } 50271bd6825cSml29623 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50281bd6825cSml29623 50291bd6825cSml29623 err = nxge_param_set_ip_opt(nxgep, NULL, 50301bd6825cSml29623 NULL, (char *)pr_val, 50311bd6825cSml29623 (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 50321bd6825cSml29623 50331bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50341bd6825cSml29623 "<== nxge_set_priv_prop: name %s (value 0x%x)", 50351bd6825cSml29623 pr_name, result)); 50361bd6825cSml29623 50371bd6825cSml29623 return (err); 50381bd6825cSml29623 } 50391bd6825cSml29623 50401bd6825cSml29623 if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 50411bd6825cSml29623 if (pr_val == NULL) { 50421bd6825cSml29623 err = EINVAL; 50431bd6825cSml29623 return (err); 50441bd6825cSml29623 } 50451bd6825cSml29623 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50461bd6825cSml29623 50471bd6825cSml29623 err = nxge_param_set_ip_opt(nxgep, NULL, 50481bd6825cSml29623 NULL, (char *)pr_val, 50491bd6825cSml29623 (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 50501bd6825cSml29623 50511bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50521bd6825cSml29623 "<== nxge_set_priv_prop: name %s (value 0x%x)", 50531bd6825cSml29623 pr_name, result)); 50541bd6825cSml29623 50551bd6825cSml29623 return (err); 50561bd6825cSml29623 } 50571bd6825cSml29623 if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 50581bd6825cSml29623 if (pr_val == NULL) { 50591bd6825cSml29623 err = EINVAL; 50601bd6825cSml29623 return (err); 50611bd6825cSml29623 } 50621bd6825cSml29623 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50631bd6825cSml29623 50641bd6825cSml29623 err = nxge_param_set_ip_opt(nxgep, NULL, 50651bd6825cSml29623 NULL, (char *)pr_val, 50661bd6825cSml29623 (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 50671bd6825cSml29623 50681bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50691bd6825cSml29623 "<== nxge_set_priv_prop: name %s (value 0x%x)", 50701bd6825cSml29623 pr_name, result)); 50711bd6825cSml29623 50721bd6825cSml29623 return (err); 50731bd6825cSml29623 } 50741bd6825cSml29623 if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 50751bd6825cSml29623 if (pr_val == NULL) { 50761bd6825cSml29623 err = EINVAL; 50771bd6825cSml29623 return (err); 50781bd6825cSml29623 } 50791bd6825cSml29623 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50801bd6825cSml29623 50811bd6825cSml29623 err = nxge_param_set_ip_opt(nxgep, NULL, 50821bd6825cSml29623 NULL, (char *)pr_val, 50831bd6825cSml29623 (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 50841bd6825cSml29623 50851bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50861bd6825cSml29623 "<== nxge_set_priv_prop: name %s (value 0x%x)", 50871bd6825cSml29623 pr_name, result)); 50881bd6825cSml29623 50891bd6825cSml29623 return (err); 50901bd6825cSml29623 } 50911bd6825cSml29623 50921bd6825cSml29623 if (strcmp(pr_name, "_soft_lso_enable") == 0) { 50931bd6825cSml29623 if (pr_val == NULL) { 50941bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50951bd6825cSml29623 "==> nxge_set_priv_prop: name %s (null)", pr_name)); 50961bd6825cSml29623 err = EINVAL; 50971bd6825cSml29623 return (err); 50981bd6825cSml29623 } 50991bd6825cSml29623 51001bd6825cSml29623 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 51011bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51021bd6825cSml29623 "<== nxge_set_priv_prop: name %s " 51031bd6825cSml29623 "(lso %d pr_val %s value %d)", 51041bd6825cSml29623 pr_name, nxgep->soft_lso_enable, pr_val, result)); 51051bd6825cSml29623 51061bd6825cSml29623 if (result > 1 || result < 0) { 51071bd6825cSml29623 err = EINVAL; 51081bd6825cSml29623 } else { 51091bd6825cSml29623 if (nxgep->soft_lso_enable == (uint32_t)result) { 51101bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51111bd6825cSml29623 "no change (%d %d)", 51121bd6825cSml29623 nxgep->soft_lso_enable, result)); 51131bd6825cSml29623 return (0); 51141bd6825cSml29623 } 51151bd6825cSml29623 } 51161bd6825cSml29623 51171bd6825cSml29623 nxgep->soft_lso_enable = (int)result; 51181bd6825cSml29623 51191bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51201bd6825cSml29623 "<== nxge_set_priv_prop: name %s (value %d)", 51211bd6825cSml29623 pr_name, result)); 51221bd6825cSml29623 51231bd6825cSml29623 return (err); 51241bd6825cSml29623 } 512500161856Syc148097 /* 512600161856Syc148097 * Commands like "ndd -set /dev/nxge0 adv_10gfdx_cap 1" cause the 512700161856Syc148097 * following code to be executed. 512800161856Syc148097 */ 51294045d941Ssowmini if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) { 51304045d941Ssowmini err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val, 51314045d941Ssowmini (caddr_t)¶m_arr[param_anar_10gfdx]); 51324045d941Ssowmini return (err); 51334045d941Ssowmini } 51344045d941Ssowmini if (strcmp(pr_name, "_adv_pause_cap") == 0) { 51354045d941Ssowmini err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val, 51364045d941Ssowmini (caddr_t)¶m_arr[param_anar_pause]); 51374045d941Ssowmini return (err); 51384045d941Ssowmini } 51391bd6825cSml29623 5140*238d8f47SDale Ghent return (ENOTSUP); 51411bd6825cSml29623 } 51421bd6825cSml29623 51431bd6825cSml29623 static int 51440dc2366fSVenugopal Iyer nxge_get_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_valsize, 51450dc2366fSVenugopal Iyer void *pr_val) 51461bd6825cSml29623 { 51471bd6825cSml29623 p_nxge_param_t param_arr = nxgep->param_arr; 51481bd6825cSml29623 char valstr[MAXNAMELEN]; 5149*238d8f47SDale Ghent int err = ENOTSUP; 51501bd6825cSml29623 uint_t strsize; 51511bd6825cSml29623 51521bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51531bd6825cSml29623 "==> nxge_get_priv_prop: property %s", pr_name)); 51541bd6825cSml29623 51551bd6825cSml29623 /* function number */ 51561bd6825cSml29623 if (strcmp(pr_name, "_function_number") == 0) { 51574045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 51584045d941Ssowmini nxgep->function_num); 51591bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51601bd6825cSml29623 "==> nxge_get_priv_prop: name %s " 51611bd6825cSml29623 "(value %d valstr %s)", 51621bd6825cSml29623 pr_name, nxgep->function_num, valstr)); 51631bd6825cSml29623 51641bd6825cSml29623 err = 0; 51651bd6825cSml29623 goto done; 51661bd6825cSml29623 } 51671bd6825cSml29623 51681bd6825cSml29623 /* Neptune firmware version */ 51691bd6825cSml29623 if (strcmp(pr_name, "_fw_version") == 0) { 51704045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%s", 51714045d941Ssowmini nxgep->vpd_info.ver); 51721bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51731bd6825cSml29623 "==> nxge_get_priv_prop: name %s " 51741bd6825cSml29623 "(value %d valstr %s)", 51751bd6825cSml29623 pr_name, nxgep->vpd_info.ver, valstr)); 51761bd6825cSml29623 51771bd6825cSml29623 err = 0; 51781bd6825cSml29623 goto done; 51791bd6825cSml29623 } 51801bd6825cSml29623 51811bd6825cSml29623 /* port PHY mode */ 51821bd6825cSml29623 if (strcmp(pr_name, "_port_mode") == 0) { 51831bd6825cSml29623 switch (nxgep->mac.portmode) { 51841bd6825cSml29623 case PORT_1G_COPPER: 51854045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G copper %s", 51861bd6825cSml29623 nxgep->hot_swappable_phy ? 51871bd6825cSml29623 "[Hot Swappable]" : ""); 51881bd6825cSml29623 break; 51891bd6825cSml29623 case PORT_1G_FIBER: 51904045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G fiber %s", 51911bd6825cSml29623 nxgep->hot_swappable_phy ? 51921bd6825cSml29623 "[hot swappable]" : ""); 51931bd6825cSml29623 break; 51941bd6825cSml29623 case PORT_10G_COPPER: 51954045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 51964045d941Ssowmini "10G copper %s", 51971bd6825cSml29623 nxgep->hot_swappable_phy ? 51981bd6825cSml29623 "[hot swappable]" : ""); 51991bd6825cSml29623 break; 52001bd6825cSml29623 case PORT_10G_FIBER: 52014045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "10G fiber %s", 52021bd6825cSml29623 nxgep->hot_swappable_phy ? 52031bd6825cSml29623 "[hot swappable]" : ""); 52041bd6825cSml29623 break; 52051bd6825cSml29623 case PORT_10G_SERDES: 52064045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 52074045d941Ssowmini "10G serdes %s", nxgep->hot_swappable_phy ? 52081bd6825cSml29623 "[hot swappable]" : ""); 52091bd6825cSml29623 break; 52101bd6825cSml29623 case PORT_1G_SERDES: 52114045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G serdes %s", 52121bd6825cSml29623 nxgep->hot_swappable_phy ? 52131bd6825cSml29623 "[hot swappable]" : ""); 52141bd6825cSml29623 break; 521500161856Syc148097 case PORT_1G_TN1010: 521600161856Syc148097 (void) snprintf(valstr, sizeof (valstr), 521700161856Syc148097 "1G TN1010 copper %s", nxgep->hot_swappable_phy ? 521800161856Syc148097 "[hot swappable]" : ""); 521900161856Syc148097 break; 522000161856Syc148097 case PORT_10G_TN1010: 522100161856Syc148097 (void) snprintf(valstr, sizeof (valstr), 522200161856Syc148097 "10G TN1010 copper %s", nxgep->hot_swappable_phy ? 522300161856Syc148097 "[hot swappable]" : ""); 522400161856Syc148097 break; 52251bd6825cSml29623 case PORT_1G_RGMII_FIBER: 52264045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 52274045d941Ssowmini "1G rgmii fiber %s", nxgep->hot_swappable_phy ? 52281bd6825cSml29623 "[hot swappable]" : ""); 52291bd6825cSml29623 break; 52301bd6825cSml29623 case PORT_HSP_MODE: 52314045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 5232c2d37b8bSml29623 "phy not present[hot swappable]"); 52331bd6825cSml29623 break; 52341bd6825cSml29623 default: 52354045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "unknown %s", 52361bd6825cSml29623 nxgep->hot_swappable_phy ? 52371bd6825cSml29623 "[hot swappable]" : ""); 52381bd6825cSml29623 break; 52391bd6825cSml29623 } 52401bd6825cSml29623 52411bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52421bd6825cSml29623 "==> nxge_get_priv_prop: name %s (value %s)", 52431bd6825cSml29623 pr_name, valstr)); 52441bd6825cSml29623 52451bd6825cSml29623 err = 0; 52461bd6825cSml29623 goto done; 52471bd6825cSml29623 } 52481bd6825cSml29623 52491bd6825cSml29623 /* Hot swappable PHY */ 52501bd6825cSml29623 if (strcmp(pr_name, "_hot_swap_phy") == 0) { 52514045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%s", 52521bd6825cSml29623 nxgep->hot_swappable_phy ? 52531bd6825cSml29623 "yes" : "no"); 52541bd6825cSml29623 52551bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52561bd6825cSml29623 "==> nxge_get_priv_prop: name %s " 52571bd6825cSml29623 "(value %d valstr %s)", 52581bd6825cSml29623 pr_name, nxgep->hot_swappable_phy, valstr)); 52591bd6825cSml29623 52601bd6825cSml29623 err = 0; 52611bd6825cSml29623 goto done; 52621bd6825cSml29623 } 52631bd6825cSml29623 52641bd6825cSml29623 52651bd6825cSml29623 /* Receive Interrupt Blanking Parameters */ 52661bd6825cSml29623 if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 52674045d941Ssowmini err = 0; 52684045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 52694045d941Ssowmini nxgep->intr_timeout); 52701bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52711bd6825cSml29623 "==> nxge_get_priv_prop: name %s (value %d)", 52721bd6825cSml29623 pr_name, 52731bd6825cSml29623 (uint32_t)nxgep->intr_timeout)); 52741bd6825cSml29623 goto done; 52751bd6825cSml29623 } 52761bd6825cSml29623 52771bd6825cSml29623 if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 52784045d941Ssowmini err = 0; 52794045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 52804045d941Ssowmini nxgep->intr_threshold); 52811bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52821bd6825cSml29623 "==> nxge_get_priv_prop: name %s (value %d)", 52831bd6825cSml29623 pr_name, (uint32_t)nxgep->intr_threshold)); 52841bd6825cSml29623 52851bd6825cSml29623 goto done; 52861bd6825cSml29623 } 52871bd6825cSml29623 52881bd6825cSml29623 /* Classification and Load Distribution Configuration */ 52891bd6825cSml29623 if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 52901bd6825cSml29623 err = nxge_dld_get_ip_opt(nxgep, 52911bd6825cSml29623 (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 52921bd6825cSml29623 52934045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52941bd6825cSml29623 (int)param_arr[param_class_opt_ipv4_tcp].value); 52951bd6825cSml29623 52961bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52971bd6825cSml29623 "==> nxge_get_priv_prop: %s", valstr)); 52981bd6825cSml29623 goto done; 52991bd6825cSml29623 } 53001bd6825cSml29623 53011bd6825cSml29623 if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 53021bd6825cSml29623 err = nxge_dld_get_ip_opt(nxgep, 53031bd6825cSml29623 (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 53041bd6825cSml29623 53054045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53061bd6825cSml29623 (int)param_arr[param_class_opt_ipv4_udp].value); 53071bd6825cSml29623 53081bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53091bd6825cSml29623 "==> nxge_get_priv_prop: %s", valstr)); 53101bd6825cSml29623 goto done; 53111bd6825cSml29623 } 53121bd6825cSml29623 if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 53131bd6825cSml29623 err = nxge_dld_get_ip_opt(nxgep, 53141bd6825cSml29623 (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 53151bd6825cSml29623 53164045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53171bd6825cSml29623 (int)param_arr[param_class_opt_ipv4_ah].value); 53181bd6825cSml29623 53191bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53201bd6825cSml29623 "==> nxge_get_priv_prop: %s", valstr)); 53211bd6825cSml29623 goto done; 53221bd6825cSml29623 } 53231bd6825cSml29623 53241bd6825cSml29623 if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 53251bd6825cSml29623 err = nxge_dld_get_ip_opt(nxgep, 53261bd6825cSml29623 (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 53271bd6825cSml29623 53284045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53291bd6825cSml29623 (int)param_arr[param_class_opt_ipv4_sctp].value); 53301bd6825cSml29623 53311bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53321bd6825cSml29623 "==> nxge_get_priv_prop: %s", valstr)); 53331bd6825cSml29623 goto done; 53341bd6825cSml29623 } 53351bd6825cSml29623 53361bd6825cSml29623 if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 53371bd6825cSml29623 err = nxge_dld_get_ip_opt(nxgep, 53381bd6825cSml29623 (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 53391bd6825cSml29623 53404045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53411bd6825cSml29623 (int)param_arr[param_class_opt_ipv6_tcp].value); 53421bd6825cSml29623 53431bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53441bd6825cSml29623 "==> nxge_get_priv_prop: %s", valstr)); 53451bd6825cSml29623 goto done; 53461bd6825cSml29623 } 53471bd6825cSml29623 53481bd6825cSml29623 if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 53491bd6825cSml29623 err = nxge_dld_get_ip_opt(nxgep, 53501bd6825cSml29623 (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 53511bd6825cSml29623 53524045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53531bd6825cSml29623 (int)param_arr[param_class_opt_ipv6_udp].value); 53541bd6825cSml29623 53551bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53561bd6825cSml29623 "==> nxge_get_priv_prop: %s", valstr)); 53571bd6825cSml29623 goto done; 53581bd6825cSml29623 } 53591bd6825cSml29623 53601bd6825cSml29623 if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 53611bd6825cSml29623 err = nxge_dld_get_ip_opt(nxgep, 53621bd6825cSml29623 (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 53631bd6825cSml29623 53644045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53651bd6825cSml29623 (int)param_arr[param_class_opt_ipv6_ah].value); 53661bd6825cSml29623 53671bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53681bd6825cSml29623 "==> nxge_get_priv_prop: %s", valstr)); 53691bd6825cSml29623 goto done; 53701bd6825cSml29623 } 53711bd6825cSml29623 53721bd6825cSml29623 if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 53731bd6825cSml29623 err = nxge_dld_get_ip_opt(nxgep, 53741bd6825cSml29623 (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 53751bd6825cSml29623 53764045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53771bd6825cSml29623 (int)param_arr[param_class_opt_ipv6_sctp].value); 53781bd6825cSml29623 53791bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53801bd6825cSml29623 "==> nxge_get_priv_prop: %s", valstr)); 53811bd6825cSml29623 goto done; 53821bd6825cSml29623 } 53831bd6825cSml29623 53841bd6825cSml29623 /* Software LSO */ 53851bd6825cSml29623 if (strcmp(pr_name, "_soft_lso_enable") == 0) { 53864045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 53874045d941Ssowmini "%d", nxgep->soft_lso_enable); 53881bd6825cSml29623 err = 0; 53891bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53901bd6825cSml29623 "==> nxge_get_priv_prop: name %s (value %d)", 53911bd6825cSml29623 pr_name, nxgep->soft_lso_enable)); 53921bd6825cSml29623 53931bd6825cSml29623 goto done; 53941bd6825cSml29623 } 53954045d941Ssowmini if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) { 53964045d941Ssowmini err = 0; 53970dc2366fSVenugopal Iyer if (nxgep->param_arr[param_anar_10gfdx].value != 0) { 53984045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 1); 53994045d941Ssowmini goto done; 54004045d941Ssowmini } else { 54014045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 54024045d941Ssowmini goto done; 54034045d941Ssowmini } 54044045d941Ssowmini } 54054045d941Ssowmini if (strcmp(pr_name, "_adv_pause_cap") == 0) { 54064045d941Ssowmini err = 0; 54070dc2366fSVenugopal Iyer if (nxgep->param_arr[param_anar_pause].value != 0) { 54084045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 1); 54094045d941Ssowmini goto done; 54104045d941Ssowmini } else { 54114045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 54124045d941Ssowmini goto done; 54134045d941Ssowmini } 54144045d941Ssowmini } 54151bd6825cSml29623 54161bd6825cSml29623 done: 54171bd6825cSml29623 if (err == 0) { 54181bd6825cSml29623 strsize = (uint_t)strlen(valstr); 54191bd6825cSml29623 if (pr_valsize < strsize) { 54201bd6825cSml29623 err = ENOBUFS; 54211bd6825cSml29623 } else { 54221bd6825cSml29623 (void) strlcpy(pr_val, valstr, pr_valsize); 54231bd6825cSml29623 } 54241bd6825cSml29623 } 54251bd6825cSml29623 54261bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 54271bd6825cSml29623 "<== nxge_get_priv_prop: return %d", err)); 54281bd6825cSml29623 return (err); 54291bd6825cSml29623 } 54301bd6825cSml29623 54316f45ec7bSml29623 /* 54326f45ec7bSml29623 * Module loading and removing entry points. 54336f45ec7bSml29623 */ 54346f45ec7bSml29623 54356f157acbSml29623 DDI_DEFINE_STREAM_OPS(nxge_dev_ops, nulldev, nulldev, nxge_attach, nxge_detach, 543619397407SSherry Moore nodev, NULL, D_MP, NULL, nxge_quiesce); 54376f45ec7bSml29623 54382e59129aSraghus #define NXGE_DESC_VER "Sun NIU 10Gb Ethernet" 54396f45ec7bSml29623 54406f45ec7bSml29623 /* 54416f45ec7bSml29623 * Module linkage information for the kernel. 54426f45ec7bSml29623 */ 54436f45ec7bSml29623 static struct modldrv nxge_modldrv = { 54446f45ec7bSml29623 &mod_driverops, 54456f45ec7bSml29623 NXGE_DESC_VER, 54466f45ec7bSml29623 &nxge_dev_ops 54476f45ec7bSml29623 }; 54486f45ec7bSml29623 54496f45ec7bSml29623 static struct modlinkage modlinkage = { 54506f45ec7bSml29623 MODREV_1, (void *) &nxge_modldrv, NULL 54516f45ec7bSml29623 }; 54526f45ec7bSml29623 54536f45ec7bSml29623 int 54546f45ec7bSml29623 _init(void) 54556f45ec7bSml29623 { 54566f45ec7bSml29623 int status; 54576f45ec7bSml29623 54583b2d9860SMichael Speer MUTEX_INIT(&nxgedebuglock, NULL, MUTEX_DRIVER, NULL); 54593b2d9860SMichael Speer 54606f45ec7bSml29623 NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init")); 54613b2d9860SMichael Speer 54626f45ec7bSml29623 mac_init_ops(&nxge_dev_ops, "nxge"); 54633b2d9860SMichael Speer 54646f45ec7bSml29623 status = ddi_soft_state_init(&nxge_list, sizeof (nxge_t), 0); 54656f45ec7bSml29623 if (status != 0) { 54666f45ec7bSml29623 NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, 54676f45ec7bSml29623 "failed to init device soft state")); 54686f45ec7bSml29623 goto _init_exit; 54696f45ec7bSml29623 } 54703b2d9860SMichael Speer 54716f45ec7bSml29623 status = mod_install(&modlinkage); 54726f45ec7bSml29623 if (status != 0) { 54736f45ec7bSml29623 ddi_soft_state_fini(&nxge_list); 54746f45ec7bSml29623 NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, "Mod install failed")); 54756f45ec7bSml29623 goto _init_exit; 54766f45ec7bSml29623 } 54776f45ec7bSml29623 54786f45ec7bSml29623 MUTEX_INIT(&nxge_common_lock, NULL, MUTEX_DRIVER, NULL); 54796f45ec7bSml29623 54803b2d9860SMichael Speer NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _init status = 0x%X", status)); 54813b2d9860SMichael Speer return (status); 54826f45ec7bSml29623 54833b2d9860SMichael Speer _init_exit: 54843b2d9860SMichael Speer NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _init status = 0x%X", status)); 54853b2d9860SMichael Speer MUTEX_DESTROY(&nxgedebuglock); 54866f45ec7bSml29623 return (status); 54876f45ec7bSml29623 } 54886f45ec7bSml29623 54896f45ec7bSml29623 int 54906f45ec7bSml29623 _fini(void) 54916f45ec7bSml29623 { 54926f45ec7bSml29623 int status; 54936f45ec7bSml29623 54946f45ec7bSml29623 NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini")); 54956f45ec7bSml29623 NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove")); 54966f45ec7bSml29623 54976f45ec7bSml29623 if (nxge_mblks_pending) 54986f45ec7bSml29623 return (EBUSY); 54996f45ec7bSml29623 55006f45ec7bSml29623 status = mod_remove(&modlinkage); 55016f45ec7bSml29623 if (status != DDI_SUCCESS) { 55026f45ec7bSml29623 NXGE_DEBUG_MSG((NULL, MOD_CTL, 55036f45ec7bSml29623 "Module removal failed 0x%08x", 55046f45ec7bSml29623 status)); 55056f45ec7bSml29623 goto _fini_exit; 55066f45ec7bSml29623 } 55076f45ec7bSml29623 55086f45ec7bSml29623 mac_fini_ops(&nxge_dev_ops); 55096f45ec7bSml29623 55106f45ec7bSml29623 ddi_soft_state_fini(&nxge_list); 55116f45ec7bSml29623 55123b2d9860SMichael Speer NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _fini status = 0x%08x", status)); 55136f45ec7bSml29623 55143b2d9860SMichael Speer MUTEX_DESTROY(&nxge_common_lock); 55153b2d9860SMichael Speer MUTEX_DESTROY(&nxgedebuglock); 55163b2d9860SMichael Speer return (status); 55173b2d9860SMichael Speer 55183b2d9860SMichael Speer _fini_exit: 55193b2d9860SMichael Speer NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _fini status = 0x%08x", status)); 55206f45ec7bSml29623 return (status); 55216f45ec7bSml29623 } 55226f45ec7bSml29623 55236f45ec7bSml29623 int 55246f45ec7bSml29623 _info(struct modinfo *modinfop) 55256f45ec7bSml29623 { 55266f45ec7bSml29623 int status; 55276f45ec7bSml29623 55286f45ec7bSml29623 NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info")); 55296f45ec7bSml29623 status = mod_info(&modlinkage, modinfop); 55306f45ec7bSml29623 NXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status)); 55316f45ec7bSml29623 55326f45ec7bSml29623 return (status); 55336f45ec7bSml29623 } 55346f45ec7bSml29623 55356f45ec7bSml29623 /*ARGSUSED*/ 5536da14cebeSEric Cheng static int 5537da14cebeSEric Cheng nxge_tx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num) 5538da14cebeSEric Cheng { 5539da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5540da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5541da14cebeSEric Cheng uint32_t channel; 5542da14cebeSEric Cheng p_tx_ring_t ring; 5543da14cebeSEric Cheng 5544da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.tdc.start + rhp->index; 5545da14cebeSEric Cheng ring = nxgep->tx_rings->rings[channel]; 5546da14cebeSEric Cheng 5547da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 55480dc2366fSVenugopal Iyer ASSERT(ring->tx_ring_handle == NULL); 5549da14cebeSEric Cheng ring->tx_ring_handle = rhp->ring_handle; 5550da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5551da14cebeSEric Cheng 5552da14cebeSEric Cheng return (0); 5553da14cebeSEric Cheng } 5554da14cebeSEric Cheng 5555da14cebeSEric Cheng static void 5556da14cebeSEric Cheng nxge_tx_ring_stop(mac_ring_driver_t rdriver) 5557da14cebeSEric Cheng { 5558da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5559da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5560da14cebeSEric Cheng uint32_t channel; 5561da14cebeSEric Cheng p_tx_ring_t ring; 5562da14cebeSEric Cheng 5563da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.tdc.start + rhp->index; 5564da14cebeSEric Cheng ring = nxgep->tx_rings->rings[channel]; 5565da14cebeSEric Cheng 5566da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 55670dc2366fSVenugopal Iyer ASSERT(ring->tx_ring_handle != NULL); 5568da14cebeSEric Cheng ring->tx_ring_handle = (mac_ring_handle_t)NULL; 5569da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5570da14cebeSEric Cheng } 5571da14cebeSEric Cheng 55720dc2366fSVenugopal Iyer int 5573da14cebeSEric Cheng nxge_rx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num) 5574da14cebeSEric Cheng { 5575da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5576da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5577da14cebeSEric Cheng uint32_t channel; 5578da14cebeSEric Cheng p_rx_rcr_ring_t ring; 5579da14cebeSEric Cheng int i; 5580da14cebeSEric Cheng 5581da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.start_rdc + rhp->index; 5582da14cebeSEric Cheng ring = nxgep->rx_rcr_rings->rcr_rings[channel]; 5583da14cebeSEric Cheng 5584da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 5585da14cebeSEric Cheng 55860dc2366fSVenugopal Iyer if (ring->started) { 55870dc2366fSVenugopal Iyer ASSERT(ring->started == B_FALSE); 5588da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5589da14cebeSEric Cheng return (0); 5590da14cebeSEric Cheng } 5591da14cebeSEric Cheng 5592da14cebeSEric Cheng /* set rcr_ring */ 5593da14cebeSEric Cheng for (i = 0; i < nxgep->ldgvp->maxldvs; i++) { 55940dc2366fSVenugopal Iyer if ((nxgep->ldgvp->ldvp[i].is_rxdma) && 5595da14cebeSEric Cheng (nxgep->ldgvp->ldvp[i].channel == channel)) { 5596da14cebeSEric Cheng ring->ldvp = &nxgep->ldgvp->ldvp[i]; 5597da14cebeSEric Cheng ring->ldgp = nxgep->ldgvp->ldvp[i].ldgp; 5598da14cebeSEric Cheng } 5599da14cebeSEric Cheng } 5600da14cebeSEric Cheng 5601da14cebeSEric Cheng ring->rcr_mac_handle = rhp->ring_handle; 5602da14cebeSEric Cheng ring->rcr_gen_num = mr_gen_num; 56030dc2366fSVenugopal Iyer ring->started = B_TRUE; 56040dc2366fSVenugopal Iyer rhp->ring_gen_num = mr_gen_num; 5605da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5606da14cebeSEric Cheng 5607da14cebeSEric Cheng return (0); 5608da14cebeSEric Cheng } 5609da14cebeSEric Cheng 5610da14cebeSEric Cheng static void 5611da14cebeSEric Cheng nxge_rx_ring_stop(mac_ring_driver_t rdriver) 5612da14cebeSEric Cheng { 5613da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5614da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5615da14cebeSEric Cheng uint32_t channel; 5616da14cebeSEric Cheng p_rx_rcr_ring_t ring; 5617da14cebeSEric Cheng 5618da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.start_rdc + rhp->index; 5619da14cebeSEric Cheng ring = nxgep->rx_rcr_rings->rcr_rings[channel]; 5620da14cebeSEric Cheng 5621da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 56220dc2366fSVenugopal Iyer ASSERT(ring->started == B_TRUE); 5623da14cebeSEric Cheng ring->rcr_mac_handle = NULL; 56240dc2366fSVenugopal Iyer ring->ldvp = NULL; 56250dc2366fSVenugopal Iyer ring->ldgp = NULL; 56260dc2366fSVenugopal Iyer ring->started = B_FALSE; 5627da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5628da14cebeSEric Cheng } 5629da14cebeSEric Cheng 56300dc2366fSVenugopal Iyer static int 56310dc2366fSVenugopal Iyer nxge_ring_get_htable_idx(p_nxge_t nxgep, mac_ring_type_t type, uint32_t channel) 56320dc2366fSVenugopal Iyer { 56330dc2366fSVenugopal Iyer int i; 56340dc2366fSVenugopal Iyer 56350dc2366fSVenugopal Iyer #if defined(sun4v) 56360dc2366fSVenugopal Iyer if (isLDOMguest(nxgep)) { 56370dc2366fSVenugopal Iyer return (nxge_hio_get_dc_htable_idx(nxgep, 56380dc2366fSVenugopal Iyer (type == MAC_RING_TYPE_TX) ? VP_BOUND_TX : VP_BOUND_RX, 56390dc2366fSVenugopal Iyer channel)); 56400dc2366fSVenugopal Iyer } 56410dc2366fSVenugopal Iyer #endif 56420dc2366fSVenugopal Iyer 56430dc2366fSVenugopal Iyer ASSERT(nxgep->ldgvp != NULL); 56440dc2366fSVenugopal Iyer 56450dc2366fSVenugopal Iyer switch (type) { 56460dc2366fSVenugopal Iyer case MAC_RING_TYPE_TX: 56470dc2366fSVenugopal Iyer for (i = 0; i < nxgep->ldgvp->maxldvs; i++) { 56480dc2366fSVenugopal Iyer if ((nxgep->ldgvp->ldvp[i].is_txdma) && 56490dc2366fSVenugopal Iyer (nxgep->ldgvp->ldvp[i].channel == channel)) { 56500dc2366fSVenugopal Iyer return ((int) 56510dc2366fSVenugopal Iyer nxgep->ldgvp->ldvp[i].ldgp->htable_idx); 56520dc2366fSVenugopal Iyer } 56530dc2366fSVenugopal Iyer } 56540dc2366fSVenugopal Iyer break; 56550dc2366fSVenugopal Iyer 56560dc2366fSVenugopal Iyer case MAC_RING_TYPE_RX: 56570dc2366fSVenugopal Iyer for (i = 0; i < nxgep->ldgvp->maxldvs; i++) { 56580dc2366fSVenugopal Iyer if ((nxgep->ldgvp->ldvp[i].is_rxdma) && 56590dc2366fSVenugopal Iyer (nxgep->ldgvp->ldvp[i].channel == channel)) { 56600dc2366fSVenugopal Iyer return ((int) 56610dc2366fSVenugopal Iyer nxgep->ldgvp->ldvp[i].ldgp->htable_idx); 56620dc2366fSVenugopal Iyer } 56630dc2366fSVenugopal Iyer } 56640dc2366fSVenugopal Iyer } 56650dc2366fSVenugopal Iyer 56660dc2366fSVenugopal Iyer return (-1); 56670dc2366fSVenugopal Iyer } 56680dc2366fSVenugopal Iyer 5669da14cebeSEric Cheng /* 5670da14cebeSEric Cheng * Callback funtion for MAC layer to register all rings. 5671da14cebeSEric Cheng */ 5672da14cebeSEric Cheng static void 5673da14cebeSEric Cheng nxge_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index, 5674da14cebeSEric Cheng const int index, mac_ring_info_t *infop, mac_ring_handle_t rh) 5675da14cebeSEric Cheng { 5676da14cebeSEric Cheng p_nxge_t nxgep = (p_nxge_t)arg; 5677da14cebeSEric Cheng p_nxge_hw_pt_cfg_t p_cfgp = &nxgep->pt_config.hw_config; 56780dc2366fSVenugopal Iyer p_nxge_intr_t intrp; 56790dc2366fSVenugopal Iyer uint32_t channel; 56800dc2366fSVenugopal Iyer int htable_idx; 56810dc2366fSVenugopal Iyer p_nxge_ring_handle_t rhandlep; 5682da14cebeSEric Cheng 56830dc2366fSVenugopal Iyer ASSERT(nxgep != NULL); 56840dc2366fSVenugopal Iyer ASSERT(p_cfgp != NULL); 56850dc2366fSVenugopal Iyer ASSERT(infop != NULL); 56860dc2366fSVenugopal Iyer 56870dc2366fSVenugopal Iyer NXGE_DEBUG_MSG((nxgep, DDI_CTL, 5688da14cebeSEric Cheng "==> nxge_fill_ring 0x%x index %d", rtype, index)); 5689da14cebeSEric Cheng 56900dc2366fSVenugopal Iyer 5691da14cebeSEric Cheng switch (rtype) { 5692da14cebeSEric Cheng case MAC_RING_TYPE_TX: { 56930dc2366fSVenugopal Iyer mac_intr_t *mintr = &infop->mri_intr; 5694da14cebeSEric Cheng 5695da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, TX_CTL, 5696da14cebeSEric Cheng "==> nxge_fill_ring (TX) 0x%x index %d ntdcs %d", 5697da14cebeSEric Cheng rtype, index, p_cfgp->tdc.count)); 5698da14cebeSEric Cheng 5699da14cebeSEric Cheng ASSERT((index >= 0) && (index < p_cfgp->tdc.count)); 5700da14cebeSEric Cheng rhandlep = &nxgep->tx_ring_handles[index]; 5701da14cebeSEric Cheng rhandlep->nxgep = nxgep; 5702da14cebeSEric Cheng rhandlep->index = index; 5703da14cebeSEric Cheng rhandlep->ring_handle = rh; 5704da14cebeSEric Cheng 57050dc2366fSVenugopal Iyer channel = nxgep->pt_config.hw_config.tdc.start + index; 57060dc2366fSVenugopal Iyer rhandlep->channel = channel; 57070dc2366fSVenugopal Iyer intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 57080dc2366fSVenugopal Iyer htable_idx = nxge_ring_get_htable_idx(nxgep, rtype, 57090dc2366fSVenugopal Iyer channel); 57100dc2366fSVenugopal Iyer if (htable_idx >= 0) 57110dc2366fSVenugopal Iyer mintr->mi_ddi_handle = intrp->htable[htable_idx]; 57120dc2366fSVenugopal Iyer else 57130dc2366fSVenugopal Iyer mintr->mi_ddi_handle = NULL; 57140dc2366fSVenugopal Iyer 5715da14cebeSEric Cheng infop->mri_driver = (mac_ring_driver_t)rhandlep; 5716da14cebeSEric Cheng infop->mri_start = nxge_tx_ring_start; 5717da14cebeSEric Cheng infop->mri_stop = nxge_tx_ring_stop; 5718da14cebeSEric Cheng infop->mri_tx = nxge_tx_ring_send; 57190dc2366fSVenugopal Iyer infop->mri_stat = nxge_tx_ring_stat; 57200dc2366fSVenugopal Iyer infop->mri_flags = MAC_RING_TX_SERIALIZE; 5721da14cebeSEric Cheng break; 5722da14cebeSEric Cheng } 57230dc2366fSVenugopal Iyer 5724da14cebeSEric Cheng case MAC_RING_TYPE_RX: { 5725da14cebeSEric Cheng mac_intr_t nxge_mac_intr; 57260dc2366fSVenugopal Iyer int nxge_rindex; 57270dc2366fSVenugopal Iyer p_nxge_intr_t intrp; 57280dc2366fSVenugopal Iyer 57290dc2366fSVenugopal Iyer intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 5730da14cebeSEric Cheng 5731da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, RX_CTL, 5732da14cebeSEric Cheng "==> nxge_fill_ring (RX) 0x%x index %d nrdcs %d", 5733da14cebeSEric Cheng rtype, index, p_cfgp->max_rdcs)); 5734da14cebeSEric Cheng 5735da14cebeSEric Cheng /* 5736da14cebeSEric Cheng * 'index' is the ring index within the group. 5737da14cebeSEric Cheng * Find the ring index in the nxge instance. 5738da14cebeSEric Cheng */ 5739da14cebeSEric Cheng nxge_rindex = nxge_get_rxring_index(nxgep, rg_index, index); 57400dc2366fSVenugopal Iyer channel = nxgep->pt_config.hw_config.start_rdc + index; 57410dc2366fSVenugopal Iyer intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 5742da14cebeSEric Cheng 5743da14cebeSEric Cheng ASSERT((nxge_rindex >= 0) && (nxge_rindex < p_cfgp->max_rdcs)); 5744da14cebeSEric Cheng rhandlep = &nxgep->rx_ring_handles[nxge_rindex]; 5745da14cebeSEric Cheng rhandlep->nxgep = nxgep; 5746da14cebeSEric Cheng rhandlep->index = nxge_rindex; 5747da14cebeSEric Cheng rhandlep->ring_handle = rh; 57480dc2366fSVenugopal Iyer rhandlep->channel = channel; 5749da14cebeSEric Cheng 5750da14cebeSEric Cheng /* 5751da14cebeSEric Cheng * Entrypoint to enable interrupt (disable poll) and 5752da14cebeSEric Cheng * disable interrupt (enable poll). 5753da14cebeSEric Cheng */ 57540dc2366fSVenugopal Iyer bzero(&nxge_mac_intr, sizeof (nxge_mac_intr)); 5755da14cebeSEric Cheng nxge_mac_intr.mi_handle = (mac_intr_handle_t)rhandlep; 5756da14cebeSEric Cheng nxge_mac_intr.mi_enable = (mac_intr_enable_t)nxge_disable_poll; 5757da14cebeSEric Cheng nxge_mac_intr.mi_disable = (mac_intr_disable_t)nxge_enable_poll; 57580dc2366fSVenugopal Iyer 57590dc2366fSVenugopal Iyer htable_idx = nxge_ring_get_htable_idx(nxgep, rtype, 57600dc2366fSVenugopal Iyer channel); 57610dc2366fSVenugopal Iyer if (htable_idx >= 0) 57620dc2366fSVenugopal Iyer nxge_mac_intr.mi_ddi_handle = intrp->htable[htable_idx]; 57630dc2366fSVenugopal Iyer else 57640dc2366fSVenugopal Iyer nxge_mac_intr.mi_ddi_handle = NULL; 57650dc2366fSVenugopal Iyer 5766da14cebeSEric Cheng infop->mri_driver = (mac_ring_driver_t)rhandlep; 5767da14cebeSEric Cheng infop->mri_start = nxge_rx_ring_start; 5768da14cebeSEric Cheng infop->mri_stop = nxge_rx_ring_stop; 57690dc2366fSVenugopal Iyer infop->mri_intr = nxge_mac_intr; 5770da14cebeSEric Cheng infop->mri_poll = nxge_rx_poll; 57710dc2366fSVenugopal Iyer infop->mri_stat = nxge_rx_ring_stat; 57720dc2366fSVenugopal Iyer infop->mri_flags = MAC_RING_RX_ENQUEUE; 5773da14cebeSEric Cheng break; 5774da14cebeSEric Cheng } 57750dc2366fSVenugopal Iyer 5776da14cebeSEric Cheng default: 5777da14cebeSEric Cheng break; 5778da14cebeSEric Cheng } 5779da14cebeSEric Cheng 57800dc2366fSVenugopal Iyer NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_fill_ring 0x%x", rtype)); 5781da14cebeSEric Cheng } 5782da14cebeSEric Cheng 5783da14cebeSEric Cheng static void 5784da14cebeSEric Cheng nxge_group_add_ring(mac_group_driver_t gh, mac_ring_driver_t rh, 5785da14cebeSEric Cheng mac_ring_type_t type) 5786da14cebeSEric Cheng { 5787da14cebeSEric Cheng nxge_ring_group_t *rgroup = (nxge_ring_group_t *)gh; 5788da14cebeSEric Cheng nxge_ring_handle_t *rhandle = (nxge_ring_handle_t *)rh; 5789da14cebeSEric Cheng nxge_t *nxge; 5790da14cebeSEric Cheng nxge_grp_t *grp; 5791da14cebeSEric Cheng nxge_rdc_grp_t *rdc_grp; 5792da14cebeSEric Cheng uint16_t channel; /* device-wise ring id */ 5793da14cebeSEric Cheng int dev_gindex; 5794da14cebeSEric Cheng int rv; 5795da14cebeSEric Cheng 5796da14cebeSEric Cheng nxge = rgroup->nxgep; 5797da14cebeSEric Cheng 5798da14cebeSEric Cheng switch (type) { 5799da14cebeSEric Cheng case MAC_RING_TYPE_TX: 5800da14cebeSEric Cheng /* 5801da14cebeSEric Cheng * nxge_grp_dc_add takes a channel number which is a 5802da14cebeSEric Cheng * "devise" ring ID. 5803da14cebeSEric Cheng */ 5804da14cebeSEric Cheng channel = nxge->pt_config.hw_config.tdc.start + rhandle->index; 5805da14cebeSEric Cheng 5806da14cebeSEric Cheng /* 5807da14cebeSEric Cheng * Remove the ring from the default group 5808da14cebeSEric Cheng */ 5809da14cebeSEric Cheng if (rgroup->gindex != 0) { 5810da14cebeSEric Cheng (void) nxge_grp_dc_remove(nxge, VP_BOUND_TX, channel); 5811da14cebeSEric Cheng } 5812da14cebeSEric Cheng 5813da14cebeSEric Cheng /* 5814da14cebeSEric Cheng * nxge->tx_set.group[] is an array of groups indexed by 5815da14cebeSEric Cheng * a "port" group ID. 5816da14cebeSEric Cheng */ 5817da14cebeSEric Cheng grp = nxge->tx_set.group[rgroup->gindex]; 5818da14cebeSEric Cheng rv = nxge_grp_dc_add(nxge, grp, VP_BOUND_TX, channel); 5819da14cebeSEric Cheng if (rv != 0) { 5820da14cebeSEric Cheng NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 5821da14cebeSEric Cheng "nxge_group_add_ring: nxge_grp_dc_add failed")); 5822da14cebeSEric Cheng } 5823da14cebeSEric Cheng break; 5824da14cebeSEric Cheng 5825da14cebeSEric Cheng case MAC_RING_TYPE_RX: 5826da14cebeSEric Cheng /* 5827da14cebeSEric Cheng * nxge->rx_set.group[] is an array of groups indexed by 5828da14cebeSEric Cheng * a "port" group ID. 5829da14cebeSEric Cheng */ 5830da14cebeSEric Cheng grp = nxge->rx_set.group[rgroup->gindex]; 5831da14cebeSEric Cheng 5832da14cebeSEric Cheng dev_gindex = nxge->pt_config.hw_config.def_mac_rxdma_grpid + 5833da14cebeSEric Cheng rgroup->gindex; 5834da14cebeSEric Cheng rdc_grp = &nxge->pt_config.rdc_grps[dev_gindex]; 5835da14cebeSEric Cheng 5836da14cebeSEric Cheng /* 5837da14cebeSEric Cheng * nxge_grp_dc_add takes a channel number which is a 5838da14cebeSEric Cheng * "devise" ring ID. 5839da14cebeSEric Cheng */ 5840da14cebeSEric Cheng channel = nxge->pt_config.hw_config.start_rdc + rhandle->index; 5841da14cebeSEric Cheng rv = nxge_grp_dc_add(nxge, grp, VP_BOUND_RX, channel); 5842da14cebeSEric Cheng if (rv != 0) { 5843da14cebeSEric Cheng NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 5844da14cebeSEric Cheng "nxge_group_add_ring: nxge_grp_dc_add failed")); 5845da14cebeSEric Cheng } 5846da14cebeSEric Cheng 5847da14cebeSEric Cheng rdc_grp->map |= (1 << channel); 5848da14cebeSEric Cheng rdc_grp->max_rdcs++; 5849da14cebeSEric Cheng 58504ba491f5SMichael Speer (void) nxge_init_fzc_rdc_tbl(nxge, rdc_grp, rgroup->rdctbl); 5851da14cebeSEric Cheng break; 5852da14cebeSEric Cheng } 5853da14cebeSEric Cheng } 5854da14cebeSEric Cheng 5855da14cebeSEric Cheng static void 5856da14cebeSEric Cheng nxge_group_rem_ring(mac_group_driver_t gh, mac_ring_driver_t rh, 5857da14cebeSEric Cheng mac_ring_type_t type) 5858da14cebeSEric Cheng { 5859da14cebeSEric Cheng nxge_ring_group_t *rgroup = (nxge_ring_group_t *)gh; 5860da14cebeSEric Cheng nxge_ring_handle_t *rhandle = (nxge_ring_handle_t *)rh; 5861da14cebeSEric Cheng nxge_t *nxge; 5862da14cebeSEric Cheng uint16_t channel; /* device-wise ring id */ 5863da14cebeSEric Cheng nxge_rdc_grp_t *rdc_grp; 5864da14cebeSEric Cheng int dev_gindex; 5865da14cebeSEric Cheng 5866da14cebeSEric Cheng nxge = rgroup->nxgep; 5867da14cebeSEric Cheng 5868da14cebeSEric Cheng switch (type) { 5869da14cebeSEric Cheng case MAC_RING_TYPE_TX: 5870da14cebeSEric Cheng dev_gindex = nxge->pt_config.hw_config.def_mac_txdma_grpid + 5871da14cebeSEric Cheng rgroup->gindex; 5872da14cebeSEric Cheng channel = nxge->pt_config.hw_config.tdc.start + rhandle->index; 5873da14cebeSEric Cheng nxge_grp_dc_remove(nxge, VP_BOUND_TX, channel); 5874da14cebeSEric Cheng 5875da14cebeSEric Cheng /* 5876da14cebeSEric Cheng * Add the ring back to the default group 5877da14cebeSEric Cheng */ 5878da14cebeSEric Cheng if (rgroup->gindex != 0) { 5879da14cebeSEric Cheng nxge_grp_t *grp; 5880da14cebeSEric Cheng grp = nxge->tx_set.group[0]; 5881da14cebeSEric Cheng (void) nxge_grp_dc_add(nxge, grp, VP_BOUND_TX, channel); 5882da14cebeSEric Cheng } 5883da14cebeSEric Cheng break; 5884da14cebeSEric Cheng 5885da14cebeSEric Cheng case MAC_RING_TYPE_RX: 5886da14cebeSEric Cheng dev_gindex = nxge->pt_config.hw_config.def_mac_rxdma_grpid + 5887da14cebeSEric Cheng rgroup->gindex; 5888da14cebeSEric Cheng rdc_grp = &nxge->pt_config.rdc_grps[dev_gindex]; 5889da14cebeSEric Cheng channel = rdc_grp->start_rdc + rhandle->index; 5890da14cebeSEric Cheng nxge_grp_dc_remove(nxge, VP_BOUND_RX, channel); 5891da14cebeSEric Cheng 5892da14cebeSEric Cheng rdc_grp->map &= ~(1 << channel); 5893da14cebeSEric Cheng rdc_grp->max_rdcs--; 5894da14cebeSEric Cheng 58954ba491f5SMichael Speer (void) nxge_init_fzc_rdc_tbl(nxge, rdc_grp, rgroup->rdctbl); 5896da14cebeSEric Cheng break; 5897da14cebeSEric Cheng } 5898da14cebeSEric Cheng } 5899da14cebeSEric Cheng 5900da14cebeSEric Cheng 5901da14cebeSEric Cheng /*ARGSUSED*/ 59026f45ec7bSml29623 static nxge_status_t 59036f45ec7bSml29623 nxge_add_intrs(p_nxge_t nxgep) 59046f45ec7bSml29623 { 59056f45ec7bSml29623 59066f45ec7bSml29623 int intr_types; 59076f45ec7bSml29623 int type = 0; 59086f45ec7bSml29623 int ddi_status = DDI_SUCCESS; 59096f45ec7bSml29623 nxge_status_t status = NXGE_OK; 59106f45ec7bSml29623 59116f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs")); 59126f45ec7bSml29623 59136f45ec7bSml29623 nxgep->nxge_intr_type.intr_registered = B_FALSE; 59146f45ec7bSml29623 nxgep->nxge_intr_type.intr_enabled = B_FALSE; 59156f45ec7bSml29623 nxgep->nxge_intr_type.msi_intx_cnt = 0; 59166f45ec7bSml29623 nxgep->nxge_intr_type.intr_added = 0; 59176f45ec7bSml29623 nxgep->nxge_intr_type.niu_msi_enable = B_FALSE; 59186f45ec7bSml29623 nxgep->nxge_intr_type.intr_type = 0; 59196f45ec7bSml29623 59206f45ec7bSml29623 if (nxgep->niu_type == N2_NIU) { 59216f45ec7bSml29623 nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 59226f45ec7bSml29623 } else if (nxge_msi_enable) { 59236f45ec7bSml29623 nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 59246f45ec7bSml29623 } 59256f45ec7bSml29623 59266f45ec7bSml29623 /* Get the supported interrupt types */ 59276f45ec7bSml29623 if ((ddi_status = ddi_intr_get_supported_types(nxgep->dip, &intr_types)) 59286f45ec7bSml29623 != DDI_SUCCESS) { 59296f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_intrs: " 59306f45ec7bSml29623 "ddi_intr_get_supported_types failed: status 0x%08x", 59316f45ec7bSml29623 ddi_status)); 59326f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 59336f45ec7bSml29623 } 59346f45ec7bSml29623 nxgep->nxge_intr_type.intr_types = intr_types; 59356f45ec7bSml29623 59366f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 59376f45ec7bSml29623 "ddi_intr_get_supported_types: 0x%08x", intr_types)); 59386f45ec7bSml29623 59396f45ec7bSml29623 /* 59406f45ec7bSml29623 * Solaris MSIX is not supported yet. use MSI for now. 59416f45ec7bSml29623 * nxge_msi_enable (1): 59426f45ec7bSml29623 * 1 - MSI 2 - MSI-X others - FIXED 59436f45ec7bSml29623 */ 59446f45ec7bSml29623 switch (nxge_msi_enable) { 59456f45ec7bSml29623 default: 59466f45ec7bSml29623 type = DDI_INTR_TYPE_FIXED; 59476f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 59486f45ec7bSml29623 "use fixed (intx emulation) type %08x", 59496f45ec7bSml29623 type)); 59506f45ec7bSml29623 break; 59516f45ec7bSml29623 59526f45ec7bSml29623 case 2: 59536f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 59546f45ec7bSml29623 "ddi_intr_get_supported_types: 0x%08x", intr_types)); 59556f45ec7bSml29623 if (intr_types & DDI_INTR_TYPE_MSIX) { 59566f45ec7bSml29623 type = DDI_INTR_TYPE_MSIX; 59576f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 59586f45ec7bSml29623 "ddi_intr_get_supported_types: MSIX 0x%08x", 59596f45ec7bSml29623 type)); 59606f45ec7bSml29623 } else if (intr_types & DDI_INTR_TYPE_MSI) { 59616f45ec7bSml29623 type = DDI_INTR_TYPE_MSI; 59626f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 59636f45ec7bSml29623 "ddi_intr_get_supported_types: MSI 0x%08x", 59646f45ec7bSml29623 type)); 59656f45ec7bSml29623 } else if (intr_types & DDI_INTR_TYPE_FIXED) { 59666f45ec7bSml29623 type = DDI_INTR_TYPE_FIXED; 59676f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 59686f45ec7bSml29623 "ddi_intr_get_supported_types: MSXED0x%08x", 59696f45ec7bSml29623 type)); 59706f45ec7bSml29623 } 59716f45ec7bSml29623 break; 59726f45ec7bSml29623 59736f45ec7bSml29623 case 1: 59746f45ec7bSml29623 if (intr_types & DDI_INTR_TYPE_MSI) { 59756f45ec7bSml29623 type = DDI_INTR_TYPE_MSI; 59766f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 59776f45ec7bSml29623 "ddi_intr_get_supported_types: MSI 0x%08x", 59786f45ec7bSml29623 type)); 59796f45ec7bSml29623 } else if (intr_types & DDI_INTR_TYPE_MSIX) { 59806f45ec7bSml29623 type = DDI_INTR_TYPE_MSIX; 59816f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 59826f45ec7bSml29623 "ddi_intr_get_supported_types: MSIX 0x%08x", 59836f45ec7bSml29623 type)); 59846f45ec7bSml29623 } else if (intr_types & DDI_INTR_TYPE_FIXED) { 59856f45ec7bSml29623 type = DDI_INTR_TYPE_FIXED; 59866f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 59876f45ec7bSml29623 "ddi_intr_get_supported_types: MSXED0x%08x", 59886f45ec7bSml29623 type)); 59896f45ec7bSml29623 } 59906f45ec7bSml29623 } 59916f45ec7bSml29623 59926f45ec7bSml29623 nxgep->nxge_intr_type.intr_type = type; 59936f45ec7bSml29623 if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI || 59946f45ec7bSml29623 type == DDI_INTR_TYPE_FIXED) && 59956f45ec7bSml29623 nxgep->nxge_intr_type.niu_msi_enable) { 59966f45ec7bSml29623 if ((status = nxge_add_intrs_adv(nxgep)) != DDI_SUCCESS) { 59976f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59986f45ec7bSml29623 " nxge_add_intrs: " 59996f45ec7bSml29623 " nxge_add_intrs_adv failed: status 0x%08x", 60006f45ec7bSml29623 status)); 60016f45ec7bSml29623 return (status); 60026f45ec7bSml29623 } else { 60036f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 60046f45ec7bSml29623 "interrupts registered : type %d", type)); 60056f45ec7bSml29623 nxgep->nxge_intr_type.intr_registered = B_TRUE; 60066f45ec7bSml29623 60076f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 60086f45ec7bSml29623 "\nAdded advanced nxge add_intr_adv " 60096f45ec7bSml29623 "intr type 0x%x\n", type)); 60106f45ec7bSml29623 60116f45ec7bSml29623 return (status); 60126f45ec7bSml29623 } 60136f45ec7bSml29623 } 60146f45ec7bSml29623 60156f45ec7bSml29623 if (!nxgep->nxge_intr_type.intr_registered) { 60166f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_add_intrs: " 60176f45ec7bSml29623 "failed to register interrupts")); 60186f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 60196f45ec7bSml29623 } 60206f45ec7bSml29623 60216f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_add_intrs")); 60226f45ec7bSml29623 return (status); 60236f45ec7bSml29623 } 60246f45ec7bSml29623 60256f45ec7bSml29623 static nxge_status_t 60266f45ec7bSml29623 nxge_add_intrs_adv(p_nxge_t nxgep) 60276f45ec7bSml29623 { 60286f45ec7bSml29623 int intr_type; 60296f45ec7bSml29623 p_nxge_intr_t intrp; 60306f45ec7bSml29623 60316f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv")); 60326f45ec7bSml29623 60336f45ec7bSml29623 intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 60346f45ec7bSml29623 intr_type = intrp->intr_type; 60356f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv: type 0x%x", 60366f45ec7bSml29623 intr_type)); 60376f45ec7bSml29623 60386f45ec7bSml29623 switch (intr_type) { 60396f45ec7bSml29623 case DDI_INTR_TYPE_MSI: /* 0x2 */ 60406f45ec7bSml29623 case DDI_INTR_TYPE_MSIX: /* 0x4 */ 60416f45ec7bSml29623 return (nxge_add_intrs_adv_type(nxgep, intr_type)); 60426f45ec7bSml29623 60436f45ec7bSml29623 case DDI_INTR_TYPE_FIXED: /* 0x1 */ 60446f45ec7bSml29623 return (nxge_add_intrs_adv_type_fix(nxgep, intr_type)); 60456f45ec7bSml29623 60466f45ec7bSml29623 default: 60476f45ec7bSml29623 return (NXGE_ERROR); 60486f45ec7bSml29623 } 60496f45ec7bSml29623 } 60506f45ec7bSml29623 60516f45ec7bSml29623 60526f45ec7bSml29623 /*ARGSUSED*/ 60536f45ec7bSml29623 static nxge_status_t 60546f45ec7bSml29623 nxge_add_intrs_adv_type(p_nxge_t nxgep, uint32_t int_type) 60556f45ec7bSml29623 { 60566f45ec7bSml29623 dev_info_t *dip = nxgep->dip; 60576f45ec7bSml29623 p_nxge_ldg_t ldgp; 60586f45ec7bSml29623 p_nxge_intr_t intrp; 60596f45ec7bSml29623 uint_t *inthandler; 60606f45ec7bSml29623 void *arg1, *arg2; 60616f45ec7bSml29623 int behavior; 6062ec090658Sml29623 int nintrs, navail, nrequest; 60636f45ec7bSml29623 int nactual, nrequired; 60646f45ec7bSml29623 int inum = 0; 60656f45ec7bSml29623 int x, y; 60666f45ec7bSml29623 int ddi_status = DDI_SUCCESS; 60676f45ec7bSml29623 nxge_status_t status = NXGE_OK; 60686f45ec7bSml29623 60696f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type")); 60706f45ec7bSml29623 intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 60716f45ec7bSml29623 intrp->start_inum = 0; 60726f45ec7bSml29623 60736f45ec7bSml29623 ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 60746f45ec7bSml29623 if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 60756f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60766f45ec7bSml29623 "ddi_intr_get_nintrs() failed, status: 0x%x%, " 60776f45ec7bSml29623 "nintrs: %d", ddi_status, nintrs)); 60786f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 60796f45ec7bSml29623 } 60806f45ec7bSml29623 60816f45ec7bSml29623 ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 60826f45ec7bSml29623 if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 60836f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60846f45ec7bSml29623 "ddi_intr_get_navail() failed, status: 0x%x%, " 60856f45ec7bSml29623 "nintrs: %d", ddi_status, navail)); 60866f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 60876f45ec7bSml29623 } 60886f45ec7bSml29623 60896f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 60906f45ec7bSml29623 "ddi_intr_get_navail() returned: nintrs %d, navail %d", 60916f45ec7bSml29623 nintrs, navail)); 60926f45ec7bSml29623 6093ec090658Sml29623 /* PSARC/2007/453 MSI-X interrupt limit override */ 6094ec090658Sml29623 if (int_type == DDI_INTR_TYPE_MSIX) { 6095ec090658Sml29623 nrequest = nxge_create_msi_property(nxgep); 6096ec090658Sml29623 if (nrequest < navail) { 6097ec090658Sml29623 navail = nrequest; 6098ec090658Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 6099ec090658Sml29623 "nxge_add_intrs_adv_type: nintrs %d " 6100ec090658Sml29623 "navail %d (nrequest %d)", 6101ec090658Sml29623 nintrs, navail, nrequest)); 6102ec090658Sml29623 } 6103ec090658Sml29623 } 6104ec090658Sml29623 61056f45ec7bSml29623 if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) { 61066f45ec7bSml29623 /* MSI must be power of 2 */ 61076f45ec7bSml29623 if ((navail & 16) == 16) { 61086f45ec7bSml29623 navail = 16; 61096f45ec7bSml29623 } else if ((navail & 8) == 8) { 61106f45ec7bSml29623 navail = 8; 61116f45ec7bSml29623 } else if ((navail & 4) == 4) { 61126f45ec7bSml29623 navail = 4; 61136f45ec7bSml29623 } else if ((navail & 2) == 2) { 61146f45ec7bSml29623 navail = 2; 61156f45ec7bSml29623 } else { 61166f45ec7bSml29623 navail = 1; 61176f45ec7bSml29623 } 61186f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 61196f45ec7bSml29623 "ddi_intr_get_navail(): (msi power of 2) nintrs %d, " 61206f45ec7bSml29623 "navail %d", nintrs, navail)); 61216f45ec7bSml29623 } 61226f45ec7bSml29623 61236f45ec7bSml29623 behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 61246f45ec7bSml29623 DDI_INTR_ALLOC_NORMAL); 61256f45ec7bSml29623 intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 61266f45ec7bSml29623 intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 61276f45ec7bSml29623 ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 61286f45ec7bSml29623 navail, &nactual, behavior); 61296f45ec7bSml29623 if (ddi_status != DDI_SUCCESS || nactual == 0) { 61306f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61316f45ec7bSml29623 " ddi_intr_alloc() failed: %d", 61326f45ec7bSml29623 ddi_status)); 61336f45ec7bSml29623 kmem_free(intrp->htable, intrp->intr_size); 61346f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 61356f45ec7bSml29623 } 61366f45ec7bSml29623 61376f45ec7bSml29623 if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 61386f45ec7bSml29623 (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 61396f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61406f45ec7bSml29623 " ddi_intr_get_pri() failed: %d", 61416f45ec7bSml29623 ddi_status)); 61426f45ec7bSml29623 /* Free already allocated interrupts */ 61436f45ec7bSml29623 for (y = 0; y < nactual; y++) { 61446f45ec7bSml29623 (void) ddi_intr_free(intrp->htable[y]); 61456f45ec7bSml29623 } 61466f45ec7bSml29623 61476f45ec7bSml29623 kmem_free(intrp->htable, intrp->intr_size); 61486f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 61496f45ec7bSml29623 } 61506f45ec7bSml29623 61516f45ec7bSml29623 nrequired = 0; 61526f45ec7bSml29623 switch (nxgep->niu_type) { 61536f45ec7bSml29623 default: 61546f45ec7bSml29623 status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 61556f45ec7bSml29623 break; 61566f45ec7bSml29623 61576f45ec7bSml29623 case N2_NIU: 61586f45ec7bSml29623 status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 61596f45ec7bSml29623 break; 61606f45ec7bSml29623 } 61616f45ec7bSml29623 61626f45ec7bSml29623 if (status != NXGE_OK) { 61636f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61646f45ec7bSml29623 "nxge_add_intrs_adv_typ:nxge_ldgv_init " 61656f45ec7bSml29623 "failed: 0x%x", status)); 61666f45ec7bSml29623 /* Free already allocated interrupts */ 61676f45ec7bSml29623 for (y = 0; y < nactual; y++) { 61686f45ec7bSml29623 (void) ddi_intr_free(intrp->htable[y]); 61696f45ec7bSml29623 } 61706f45ec7bSml29623 61716f45ec7bSml29623 kmem_free(intrp->htable, intrp->intr_size); 61726f45ec7bSml29623 return (status); 61736f45ec7bSml29623 } 61746f45ec7bSml29623 61756f45ec7bSml29623 ldgp = nxgep->ldgvp->ldgp; 61766f45ec7bSml29623 for (x = 0; x < nrequired; x++, ldgp++) { 61776f45ec7bSml29623 ldgp->vector = (uint8_t)x; 61786f45ec7bSml29623 ldgp->intdata = SID_DATA(ldgp->func, x); 61796f45ec7bSml29623 arg1 = ldgp->ldvp; 61806f45ec7bSml29623 arg2 = nxgep; 61816f45ec7bSml29623 if (ldgp->nldvs == 1) { 61826f45ec7bSml29623 inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 61836f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 61846f45ec7bSml29623 "nxge_add_intrs_adv_type: " 61856f45ec7bSml29623 "arg1 0x%x arg2 0x%x: " 61866f45ec7bSml29623 "1-1 int handler (entry %d intdata 0x%x)\n", 61876f45ec7bSml29623 arg1, arg2, 61886f45ec7bSml29623 x, ldgp->intdata)); 61896f45ec7bSml29623 } else if (ldgp->nldvs > 1) { 61906f45ec7bSml29623 inthandler = (uint_t *)ldgp->sys_intr_handler; 61916f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 61926f45ec7bSml29623 "nxge_add_intrs_adv_type: " 61936f45ec7bSml29623 "arg1 0x%x arg2 0x%x: " 61946f45ec7bSml29623 "nldevs %d int handler " 61956f45ec7bSml29623 "(entry %d intdata 0x%x)\n", 61966f45ec7bSml29623 arg1, arg2, 61976f45ec7bSml29623 ldgp->nldvs, x, ldgp->intdata)); 61986f45ec7bSml29623 } 61996f45ec7bSml29623 62006f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 62016f45ec7bSml29623 "==> nxge_add_intrs_adv_type: ddi_add_intr(inum) #%d " 62026f45ec7bSml29623 "htable 0x%llx", x, intrp->htable[x])); 62036f45ec7bSml29623 62046f45ec7bSml29623 if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 62056f45ec7bSml29623 (ddi_intr_handler_t *)inthandler, arg1, arg2)) 62066f45ec7bSml29623 != DDI_SUCCESS) { 62076f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 62086f45ec7bSml29623 "==> nxge_add_intrs_adv_type: failed #%d " 62096f45ec7bSml29623 "status 0x%x", x, ddi_status)); 62106f45ec7bSml29623 for (y = 0; y < intrp->intr_added; y++) { 62116f45ec7bSml29623 (void) ddi_intr_remove_handler( 62126f45ec7bSml29623 intrp->htable[y]); 62136f45ec7bSml29623 } 62146f45ec7bSml29623 /* Free already allocated intr */ 62156f45ec7bSml29623 for (y = 0; y < nactual; y++) { 62166f45ec7bSml29623 (void) ddi_intr_free(intrp->htable[y]); 62176f45ec7bSml29623 } 62186f45ec7bSml29623 kmem_free(intrp->htable, intrp->intr_size); 62196f45ec7bSml29623 62206f45ec7bSml29623 (void) nxge_ldgv_uninit(nxgep); 62216f45ec7bSml29623 62226f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 62236f45ec7bSml29623 } 62240dc2366fSVenugopal Iyer 62250dc2366fSVenugopal Iyer ldgp->htable_idx = x; 62266f45ec7bSml29623 intrp->intr_added++; 62276f45ec7bSml29623 } 62286f45ec7bSml29623 62296f45ec7bSml29623 intrp->msi_intx_cnt = nactual; 62306f45ec7bSml29623 62316f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 62326f45ec7bSml29623 "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d", 62336f45ec7bSml29623 navail, nactual, 62346f45ec7bSml29623 intrp->msi_intx_cnt, 62356f45ec7bSml29623 intrp->intr_added)); 62366f45ec7bSml29623 62376f45ec7bSml29623 (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 62386f45ec7bSml29623 62396f45ec7bSml29623 (void) nxge_intr_ldgv_init(nxgep); 62406f45ec7bSml29623 62416f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type")); 62426f45ec7bSml29623 62436f45ec7bSml29623 return (status); 62446f45ec7bSml29623 } 62456f45ec7bSml29623 62466f45ec7bSml29623 /*ARGSUSED*/ 62476f45ec7bSml29623 static nxge_status_t 62486f45ec7bSml29623 nxge_add_intrs_adv_type_fix(p_nxge_t nxgep, uint32_t int_type) 62496f45ec7bSml29623 { 62506f45ec7bSml29623 dev_info_t *dip = nxgep->dip; 62516f45ec7bSml29623 p_nxge_ldg_t ldgp; 62526f45ec7bSml29623 p_nxge_intr_t intrp; 62536f45ec7bSml29623 uint_t *inthandler; 62546f45ec7bSml29623 void *arg1, *arg2; 62556f45ec7bSml29623 int behavior; 62566f45ec7bSml29623 int nintrs, navail; 62576f45ec7bSml29623 int nactual, nrequired; 62586f45ec7bSml29623 int inum = 0; 62596f45ec7bSml29623 int x, y; 62606f45ec7bSml29623 int ddi_status = DDI_SUCCESS; 62616f45ec7bSml29623 nxge_status_t status = NXGE_OK; 62626f45ec7bSml29623 62636f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type_fix")); 62646f45ec7bSml29623 intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 62656f45ec7bSml29623 intrp->start_inum = 0; 62666f45ec7bSml29623 62676f45ec7bSml29623 ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 62686f45ec7bSml29623 if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 62696f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 62706f45ec7bSml29623 "ddi_intr_get_nintrs() failed, status: 0x%x%, " 62716f45ec7bSml29623 "nintrs: %d", status, nintrs)); 62726f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 62736f45ec7bSml29623 } 62746f45ec7bSml29623 62756f45ec7bSml29623 ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 62766f45ec7bSml29623 if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 62776f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 62786f45ec7bSml29623 "ddi_intr_get_navail() failed, status: 0x%x%, " 62796f45ec7bSml29623 "nintrs: %d", ddi_status, navail)); 62806f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 62816f45ec7bSml29623 } 62826f45ec7bSml29623 62836f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 62846f45ec7bSml29623 "ddi_intr_get_navail() returned: nintrs %d, naavail %d", 62856f45ec7bSml29623 nintrs, navail)); 62866f45ec7bSml29623 62876f45ec7bSml29623 behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 62886f45ec7bSml29623 DDI_INTR_ALLOC_NORMAL); 62896f45ec7bSml29623 intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 62906f45ec7bSml29623 intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 62916f45ec7bSml29623 ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 62926f45ec7bSml29623 navail, &nactual, behavior); 62936f45ec7bSml29623 if (ddi_status != DDI_SUCCESS || nactual == 0) { 62946f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 62956f45ec7bSml29623 " ddi_intr_alloc() failed: %d", 62966f45ec7bSml29623 ddi_status)); 62976f45ec7bSml29623 kmem_free(intrp->htable, intrp->intr_size); 62986f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 62996f45ec7bSml29623 } 63006f45ec7bSml29623 63016f45ec7bSml29623 if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 63026f45ec7bSml29623 (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 63036f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 63046f45ec7bSml29623 " ddi_intr_get_pri() failed: %d", 63056f45ec7bSml29623 ddi_status)); 63066f45ec7bSml29623 /* Free already allocated interrupts */ 63076f45ec7bSml29623 for (y = 0; y < nactual; y++) { 63086f45ec7bSml29623 (void) ddi_intr_free(intrp->htable[y]); 63096f45ec7bSml29623 } 63106f45ec7bSml29623 63116f45ec7bSml29623 kmem_free(intrp->htable, intrp->intr_size); 63126f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 63136f45ec7bSml29623 } 63146f45ec7bSml29623 63156f45ec7bSml29623 nrequired = 0; 63166f45ec7bSml29623 switch (nxgep->niu_type) { 63176f45ec7bSml29623 default: 63186f45ec7bSml29623 status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 63196f45ec7bSml29623 break; 63206f45ec7bSml29623 63216f45ec7bSml29623 case N2_NIU: 63226f45ec7bSml29623 status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 63236f45ec7bSml29623 break; 63246f45ec7bSml29623 } 63256f45ec7bSml29623 63266f45ec7bSml29623 if (status != NXGE_OK) { 63276f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 63286f45ec7bSml29623 "nxge_add_intrs_adv_type_fix:nxge_ldgv_init " 63296f45ec7bSml29623 "failed: 0x%x", status)); 63306f45ec7bSml29623 /* Free already allocated interrupts */ 63316f45ec7bSml29623 for (y = 0; y < nactual; y++) { 63326f45ec7bSml29623 (void) ddi_intr_free(intrp->htable[y]); 63336f45ec7bSml29623 } 63346f45ec7bSml29623 63356f45ec7bSml29623 kmem_free(intrp->htable, intrp->intr_size); 63366f45ec7bSml29623 return (status); 63376f45ec7bSml29623 } 63386f45ec7bSml29623 63396f45ec7bSml29623 ldgp = nxgep->ldgvp->ldgp; 63406f45ec7bSml29623 for (x = 0; x < nrequired; x++, ldgp++) { 63416f45ec7bSml29623 ldgp->vector = (uint8_t)x; 63426f45ec7bSml29623 if (nxgep->niu_type != N2_NIU) { 63436f45ec7bSml29623 ldgp->intdata = SID_DATA(ldgp->func, x); 63446f45ec7bSml29623 } 63456f45ec7bSml29623 63466f45ec7bSml29623 arg1 = ldgp->ldvp; 63476f45ec7bSml29623 arg2 = nxgep; 63486f45ec7bSml29623 if (ldgp->nldvs == 1) { 63496f45ec7bSml29623 inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 63506f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 63516f45ec7bSml29623 "nxge_add_intrs_adv_type_fix: " 63526f45ec7bSml29623 "1-1 int handler(%d) ldg %d ldv %d " 63536f45ec7bSml29623 "arg1 $%p arg2 $%p\n", 63546f45ec7bSml29623 x, ldgp->ldg, ldgp->ldvp->ldv, 63556f45ec7bSml29623 arg1, arg2)); 63566f45ec7bSml29623 } else if (ldgp->nldvs > 1) { 63576f45ec7bSml29623 inthandler = (uint_t *)ldgp->sys_intr_handler; 63586f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 63596f45ec7bSml29623 "nxge_add_intrs_adv_type_fix: " 63606f45ec7bSml29623 "shared ldv %d int handler(%d) ldv %d ldg %d" 63616f45ec7bSml29623 "arg1 0x%016llx arg2 0x%016llx\n", 63626f45ec7bSml29623 x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv, 63636f45ec7bSml29623 arg1, arg2)); 63646f45ec7bSml29623 } 63656f45ec7bSml29623 63666f45ec7bSml29623 if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 63676f45ec7bSml29623 (ddi_intr_handler_t *)inthandler, arg1, arg2)) 63686f45ec7bSml29623 != DDI_SUCCESS) { 63696f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 63706f45ec7bSml29623 "==> nxge_add_intrs_adv_type_fix: failed #%d " 63716f45ec7bSml29623 "status 0x%x", x, ddi_status)); 63726f45ec7bSml29623 for (y = 0; y < intrp->intr_added; y++) { 63736f45ec7bSml29623 (void) ddi_intr_remove_handler( 63746f45ec7bSml29623 intrp->htable[y]); 63756f45ec7bSml29623 } 63766f45ec7bSml29623 for (y = 0; y < nactual; y++) { 63776f45ec7bSml29623 (void) ddi_intr_free(intrp->htable[y]); 63786f45ec7bSml29623 } 63796f45ec7bSml29623 /* Free already allocated intr */ 63806f45ec7bSml29623 kmem_free(intrp->htable, intrp->intr_size); 63816f45ec7bSml29623 63826f45ec7bSml29623 (void) nxge_ldgv_uninit(nxgep); 63836f45ec7bSml29623 63846f45ec7bSml29623 return (NXGE_ERROR | NXGE_DDI_FAILED); 63856f45ec7bSml29623 } 63860dc2366fSVenugopal Iyer 63870dc2366fSVenugopal Iyer ldgp->htable_idx = x; 63886f45ec7bSml29623 intrp->intr_added++; 63896f45ec7bSml29623 } 63906f45ec7bSml29623 63916f45ec7bSml29623 intrp->msi_intx_cnt = nactual; 63926f45ec7bSml29623 63936f45ec7bSml29623 (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 63946f45ec7bSml29623 63956f45ec7bSml29623 status = nxge_intr_ldgv_init(nxgep); 63966f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type_fix")); 63976f45ec7bSml29623 63986f45ec7bSml29623 return (status); 63996f45ec7bSml29623 } 64006f45ec7bSml29623 64016f45ec7bSml29623 static void 64026f45ec7bSml29623 nxge_remove_intrs(p_nxge_t nxgep) 64036f45ec7bSml29623 { 64046f45ec7bSml29623 int i, inum; 64056f45ec7bSml29623 p_nxge_intr_t intrp; 64066f45ec7bSml29623 64076f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs")); 64086f45ec7bSml29623 intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 64096f45ec7bSml29623 if (!intrp->intr_registered) { 64106f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 64116f45ec7bSml29623 "<== nxge_remove_intrs: interrupts not registered")); 64126f45ec7bSml29623 return; 64136f45ec7bSml29623 } 64146f45ec7bSml29623 64156f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs:advanced")); 64166f45ec7bSml29623 64176f45ec7bSml29623 if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 64186f45ec7bSml29623 (void) ddi_intr_block_disable(intrp->htable, 64196f45ec7bSml29623 intrp->intr_added); 64206f45ec7bSml29623 } else { 64216f45ec7bSml29623 for (i = 0; i < intrp->intr_added; i++) { 64226f45ec7bSml29623 (void) ddi_intr_disable(intrp->htable[i]); 64236f45ec7bSml29623 } 64246f45ec7bSml29623 } 64256f45ec7bSml29623 64266f45ec7bSml29623 for (inum = 0; inum < intrp->intr_added; inum++) { 64276f45ec7bSml29623 if (intrp->htable[inum]) { 64286f45ec7bSml29623 (void) ddi_intr_remove_handler(intrp->htable[inum]); 64296f45ec7bSml29623 } 64306f45ec7bSml29623 } 64316f45ec7bSml29623 64326f45ec7bSml29623 for (inum = 0; inum < intrp->msi_intx_cnt; inum++) { 64336f45ec7bSml29623 if (intrp->htable[inum]) { 64346f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 64356f45ec7bSml29623 "nxge_remove_intrs: ddi_intr_free inum %d " 64366f45ec7bSml29623 "msi_intx_cnt %d intr_added %d", 64376f45ec7bSml29623 inum, 64386f45ec7bSml29623 intrp->msi_intx_cnt, 64396f45ec7bSml29623 intrp->intr_added)); 64406f45ec7bSml29623 64416f45ec7bSml29623 (void) ddi_intr_free(intrp->htable[inum]); 64426f45ec7bSml29623 } 64436f45ec7bSml29623 } 64446f45ec7bSml29623 64456f45ec7bSml29623 kmem_free(intrp->htable, intrp->intr_size); 64466f45ec7bSml29623 intrp->intr_registered = B_FALSE; 64476f45ec7bSml29623 intrp->intr_enabled = B_FALSE; 64486f45ec7bSml29623 intrp->msi_intx_cnt = 0; 64496f45ec7bSml29623 intrp->intr_added = 0; 64506f45ec7bSml29623 64516f45ec7bSml29623 (void) nxge_ldgv_uninit(nxgep); 64526f45ec7bSml29623 6453ec090658Sml29623 (void) ddi_prop_remove(DDI_DEV_T_NONE, nxgep->dip, 6454ec090658Sml29623 "#msix-request"); 6455ec090658Sml29623 64566f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_intrs")); 64576f45ec7bSml29623 } 64586f45ec7bSml29623 64596f45ec7bSml29623 /*ARGSUSED*/ 64606f45ec7bSml29623 static void 64616f45ec7bSml29623 nxge_intrs_enable(p_nxge_t nxgep) 64626f45ec7bSml29623 { 64636f45ec7bSml29623 p_nxge_intr_t intrp; 64646f45ec7bSml29623 int i; 64656f45ec7bSml29623 int status; 64666f45ec7bSml29623 64676f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable")); 64686f45ec7bSml29623 64696f45ec7bSml29623 intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 64706f45ec7bSml29623 64716f45ec7bSml29623 if (!intrp->intr_registered) { 64726f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_intrs_enable: " 64736f45ec7bSml29623 "interrupts are not registered")); 64746f45ec7bSml29623 return; 64756f45ec7bSml29623 } 64766f45ec7bSml29623 64776f45ec7bSml29623 if (intrp->intr_enabled) { 64786f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 64796f45ec7bSml29623 "<== nxge_intrs_enable: already enabled")); 64806f45ec7bSml29623 return; 64816f45ec7bSml29623 } 64826f45ec7bSml29623 64836f45ec7bSml29623 if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 64846f45ec7bSml29623 status = ddi_intr_block_enable(intrp->htable, 64856f45ec7bSml29623 intrp->intr_added); 64866f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 64876f45ec7bSml29623 "block enable - status 0x%x total inums #%d\n", 64886f45ec7bSml29623 status, intrp->intr_added)); 64896f45ec7bSml29623 } else { 64906f45ec7bSml29623 for (i = 0; i < intrp->intr_added; i++) { 64916f45ec7bSml29623 status = ddi_intr_enable(intrp->htable[i]); 64926f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 64936f45ec7bSml29623 "ddi_intr_enable:enable - status 0x%x " 64946f45ec7bSml29623 "total inums %d enable inum #%d\n", 64956f45ec7bSml29623 status, intrp->intr_added, i)); 64966f45ec7bSml29623 if (status == DDI_SUCCESS) { 64976f45ec7bSml29623 intrp->intr_enabled = B_TRUE; 64986f45ec7bSml29623 } 64996f45ec7bSml29623 } 65006f45ec7bSml29623 } 65016f45ec7bSml29623 65026f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_enable")); 65036f45ec7bSml29623 } 65046f45ec7bSml29623 65056f45ec7bSml29623 /*ARGSUSED*/ 65066f45ec7bSml29623 static void 65076f45ec7bSml29623 nxge_intrs_disable(p_nxge_t nxgep) 65086f45ec7bSml29623 { 65096f45ec7bSml29623 p_nxge_intr_t intrp; 65106f45ec7bSml29623 int i; 65116f45ec7bSml29623 65126f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_disable")); 65136f45ec7bSml29623 65146f45ec7bSml29623 intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 65156f45ec7bSml29623 65166f45ec7bSml29623 if (!intrp->intr_registered) { 65176f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable: " 65186f45ec7bSml29623 "interrupts are not registered")); 65196f45ec7bSml29623 return; 65206f45ec7bSml29623 } 65216f45ec7bSml29623 65226f45ec7bSml29623 if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 65236f45ec7bSml29623 (void) ddi_intr_block_disable(intrp->htable, 65246f45ec7bSml29623 intrp->intr_added); 65256f45ec7bSml29623 } else { 65266f45ec7bSml29623 for (i = 0; i < intrp->intr_added; i++) { 65276f45ec7bSml29623 (void) ddi_intr_disable(intrp->htable[i]); 65286f45ec7bSml29623 } 65296f45ec7bSml29623 } 65306f45ec7bSml29623 65316f45ec7bSml29623 intrp->intr_enabled = B_FALSE; 65326f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable")); 65336f45ec7bSml29623 } 65346f45ec7bSml29623 653563f531d1SSriharsha Basavapatna nxge_status_t 65366f45ec7bSml29623 nxge_mac_register(p_nxge_t nxgep) 65376f45ec7bSml29623 { 65386f45ec7bSml29623 mac_register_t *macp; 65396f45ec7bSml29623 int status; 65406f45ec7bSml29623 65416f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_mac_register")); 65426f45ec7bSml29623 65436f45ec7bSml29623 if ((macp = mac_alloc(MAC_VERSION)) == NULL) 65446f45ec7bSml29623 return (NXGE_ERROR); 65456f45ec7bSml29623 65466f45ec7bSml29623 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 65476f45ec7bSml29623 macp->m_driver = nxgep; 65486f45ec7bSml29623 macp->m_dip = nxgep->dip; 654963f531d1SSriharsha Basavapatna if (!isLDOMguest(nxgep)) { 65506f45ec7bSml29623 macp->m_src_addr = nxgep->ouraddr.ether_addr_octet; 655163f531d1SSriharsha Basavapatna } else { 655263f531d1SSriharsha Basavapatna macp->m_src_addr = KMEM_ZALLOC(MAXMACADDRLEN, KM_SLEEP); 655363f531d1SSriharsha Basavapatna macp->m_dst_addr = KMEM_ZALLOC(MAXMACADDRLEN, KM_SLEEP); 655463f531d1SSriharsha Basavapatna (void) memset(macp->m_src_addr, 0xff, sizeof (MAXMACADDRLEN)); 655563f531d1SSriharsha Basavapatna } 65566f45ec7bSml29623 macp->m_callbacks = &nxge_m_callbacks; 65576f45ec7bSml29623 macp->m_min_sdu = 0; 65581bd6825cSml29623 nxgep->mac.default_mtu = nxgep->mac.maxframesize - 65591bd6825cSml29623 NXGE_EHEADER_VLAN_CRC; 65601bd6825cSml29623 macp->m_max_sdu = nxgep->mac.default_mtu; 6561d62bc4baSyz147064 macp->m_margin = VLAN_TAGSZ; 65624045d941Ssowmini macp->m_priv_props = nxge_priv_props; 65630dc2366fSVenugopal Iyer if (isLDOMguest(nxgep)) 65640dc2366fSVenugopal Iyer macp->m_v12n = MAC_VIRT_LEVEL1; 65650dc2366fSVenugopal Iyer else 65660dc2366fSVenugopal Iyer macp->m_v12n = MAC_VIRT_HIO | MAC_VIRT_LEVEL1; 65676f45ec7bSml29623 65681bd6825cSml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 65691bd6825cSml29623 "==> nxge_mac_register: instance %d " 65701bd6825cSml29623 "max_sdu %d margin %d maxframe %d (header %d)", 65711bd6825cSml29623 nxgep->instance, 65721bd6825cSml29623 macp->m_max_sdu, macp->m_margin, 65731bd6825cSml29623 nxgep->mac.maxframesize, 65741bd6825cSml29623 NXGE_EHEADER_VLAN_CRC)); 65751bd6825cSml29623 65766f45ec7bSml29623 status = mac_register(macp, &nxgep->mach); 657763f531d1SSriharsha Basavapatna if (isLDOMguest(nxgep)) { 657863f531d1SSriharsha Basavapatna KMEM_FREE(macp->m_src_addr, MAXMACADDRLEN); 657963f531d1SSriharsha Basavapatna KMEM_FREE(macp->m_dst_addr, MAXMACADDRLEN); 658063f531d1SSriharsha Basavapatna } 65816f45ec7bSml29623 mac_free(macp); 65826f45ec7bSml29623 65836f45ec7bSml29623 if (status != 0) { 65846f45ec7bSml29623 cmn_err(CE_WARN, 65856f45ec7bSml29623 "!nxge_mac_register failed (status %d instance %d)", 65866f45ec7bSml29623 status, nxgep->instance); 65876f45ec7bSml29623 return (NXGE_ERROR); 65886f45ec7bSml29623 } 65896f45ec7bSml29623 65906f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_mac_register success " 65916f45ec7bSml29623 "(instance %d)", nxgep->instance)); 65926f45ec7bSml29623 65936f45ec7bSml29623 return (NXGE_OK); 65946f45ec7bSml29623 } 65956f45ec7bSml29623 65966f45ec7bSml29623 void 65976f45ec7bSml29623 nxge_err_inject(p_nxge_t nxgep, queue_t *wq, mblk_t *mp) 65986f45ec7bSml29623 { 65996f45ec7bSml29623 ssize_t size; 66006f45ec7bSml29623 mblk_t *nmp; 66016f45ec7bSml29623 uint8_t blk_id; 66026f45ec7bSml29623 uint8_t chan; 66036f45ec7bSml29623 uint32_t err_id; 66046f45ec7bSml29623 err_inject_t *eip; 66056f45ec7bSml29623 66066f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_err_inject")); 66076f45ec7bSml29623 66086f45ec7bSml29623 size = 1024; 66096f45ec7bSml29623 nmp = mp->b_cont; 66106f45ec7bSml29623 eip = (err_inject_t *)nmp->b_rptr; 66116f45ec7bSml29623 blk_id = eip->blk_id; 66126f45ec7bSml29623 err_id = eip->err_id; 66136f45ec7bSml29623 chan = eip->chan; 66146f45ec7bSml29623 cmn_err(CE_NOTE, "!blk_id = 0x%x\n", blk_id); 66156f45ec7bSml29623 cmn_err(CE_NOTE, "!err_id = 0x%x\n", err_id); 66166f45ec7bSml29623 cmn_err(CE_NOTE, "!chan = 0x%x\n", chan); 66176f45ec7bSml29623 switch (blk_id) { 66186f45ec7bSml29623 case MAC_BLK_ID: 66196f45ec7bSml29623 break; 66206f45ec7bSml29623 case TXMAC_BLK_ID: 66216f45ec7bSml29623 break; 66226f45ec7bSml29623 case RXMAC_BLK_ID: 66236f45ec7bSml29623 break; 66246f45ec7bSml29623 case MIF_BLK_ID: 66256f45ec7bSml29623 break; 66266f45ec7bSml29623 case IPP_BLK_ID: 66276f45ec7bSml29623 nxge_ipp_inject_err(nxgep, err_id); 66286f45ec7bSml29623 break; 66296f45ec7bSml29623 case TXC_BLK_ID: 66306f45ec7bSml29623 nxge_txc_inject_err(nxgep, err_id); 66316f45ec7bSml29623 break; 66326f45ec7bSml29623 case TXDMA_BLK_ID: 66336f45ec7bSml29623 nxge_txdma_inject_err(nxgep, err_id, chan); 66346f45ec7bSml29623 break; 66356f45ec7bSml29623 case RXDMA_BLK_ID: 66366f45ec7bSml29623 nxge_rxdma_inject_err(nxgep, err_id, chan); 66376f45ec7bSml29623 break; 66386f45ec7bSml29623 case ZCP_BLK_ID: 66396f45ec7bSml29623 nxge_zcp_inject_err(nxgep, err_id); 66406f45ec7bSml29623 break; 66416f45ec7bSml29623 case ESPC_BLK_ID: 66426f45ec7bSml29623 break; 66436f45ec7bSml29623 case FFLP_BLK_ID: 66446f45ec7bSml29623 break; 66456f45ec7bSml29623 case PHY_BLK_ID: 66466f45ec7bSml29623 break; 66476f45ec7bSml29623 case ETHER_SERDES_BLK_ID: 66486f45ec7bSml29623 break; 66496f45ec7bSml29623 case PCIE_SERDES_BLK_ID: 66506f45ec7bSml29623 break; 66516f45ec7bSml29623 case VIR_BLK_ID: 66526f45ec7bSml29623 break; 66536f45ec7bSml29623 } 66546f45ec7bSml29623 66556f45ec7bSml29623 nmp->b_wptr = nmp->b_rptr + size; 66566f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_err_inject")); 66576f45ec7bSml29623 66586f45ec7bSml29623 miocack(wq, mp, (int)size, 0); 66596f45ec7bSml29623 } 66606f45ec7bSml29623 66616f45ec7bSml29623 static int 66626f45ec7bSml29623 nxge_init_common_dev(p_nxge_t nxgep) 66636f45ec7bSml29623 { 66646f45ec7bSml29623 p_nxge_hw_list_t hw_p; 66656f45ec7bSml29623 dev_info_t *p_dip; 66666f45ec7bSml29623 6667ef523517SMichael Speer ASSERT(nxgep != NULL); 6668ef523517SMichael Speer 66696f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_init_common_device")); 66706f45ec7bSml29623 66716f45ec7bSml29623 p_dip = nxgep->p_dip; 66726f45ec7bSml29623 MUTEX_ENTER(&nxge_common_lock); 66736f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66746f45ec7bSml29623 "==> nxge_init_common_dev:func # %d", 66756f45ec7bSml29623 nxgep->function_num)); 66766f45ec7bSml29623 /* 66776f45ec7bSml29623 * Loop through existing per neptune hardware list. 66786f45ec7bSml29623 */ 66796f45ec7bSml29623 for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 66806f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66816f45ec7bSml29623 "==> nxge_init_common_device:func # %d " 66826f45ec7bSml29623 "hw_p $%p parent dip $%p", 66836f45ec7bSml29623 nxgep->function_num, 66846f45ec7bSml29623 hw_p, 66856f45ec7bSml29623 p_dip)); 66866f45ec7bSml29623 if (hw_p->parent_devp == p_dip) { 66876f45ec7bSml29623 nxgep->nxge_hw_p = hw_p; 66886f45ec7bSml29623 hw_p->ndevs++; 66896f45ec7bSml29623 hw_p->nxge_p[nxgep->function_num] = nxgep; 66906f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66916f45ec7bSml29623 "==> nxge_init_common_device:func # %d " 66926f45ec7bSml29623 "hw_p $%p parent dip $%p " 66936f45ec7bSml29623 "ndevs %d (found)", 66946f45ec7bSml29623 nxgep->function_num, 66956f45ec7bSml29623 hw_p, 66966f45ec7bSml29623 p_dip, 66976f45ec7bSml29623 hw_p->ndevs)); 66986f45ec7bSml29623 break; 66996f45ec7bSml29623 } 67006f45ec7bSml29623 } 67016f45ec7bSml29623 67026f45ec7bSml29623 if (hw_p == NULL) { 670323b952a3SSantwona Behera 670423b952a3SSantwona Behera char **prop_val; 670523b952a3SSantwona Behera uint_t prop_len; 670623b952a3SSantwona Behera int i; 670723b952a3SSantwona Behera 67086f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, 67096f45ec7bSml29623 "==> nxge_init_common_device:func # %d " 67106f45ec7bSml29623 "parent dip $%p (new)", 67116f45ec7bSml29623 nxgep->function_num, 67126f45ec7bSml29623 p_dip)); 67136f45ec7bSml29623 hw_p = kmem_zalloc(sizeof (nxge_hw_list_t), KM_SLEEP); 67146f45ec7bSml29623 hw_p->parent_devp = p_dip; 67156f45ec7bSml29623 hw_p->magic = NXGE_NEPTUNE_MAGIC; 67166f45ec7bSml29623 nxgep->nxge_hw_p = hw_p; 67176f45ec7bSml29623 hw_p->ndevs++; 67186f45ec7bSml29623 hw_p->nxge_p[nxgep->function_num] = nxgep; 67196f45ec7bSml29623 hw_p->next = nxge_hw_list; 672059ac0c16Sdavemq if (nxgep->niu_type == N2_NIU) { 672159ac0c16Sdavemq hw_p->niu_type = N2_NIU; 672259ac0c16Sdavemq hw_p->platform_type = P_NEPTUNE_NIU; 67234df55fdeSJanie Lu hw_p->tcam_size = TCAM_NIU_TCAM_MAX_ENTRY; 672459ac0c16Sdavemq } else { 672559ac0c16Sdavemq hw_p->niu_type = NIU_TYPE_NONE; 67262e59129aSraghus hw_p->platform_type = P_NEPTUNE_NONE; 67274df55fdeSJanie Lu hw_p->tcam_size = TCAM_NXGE_TCAM_MAX_ENTRY; 672859ac0c16Sdavemq } 67296f45ec7bSml29623 67304df55fdeSJanie Lu hw_p->tcam = KMEM_ZALLOC(sizeof (tcam_flow_spec_t) * 67314df55fdeSJanie Lu hw_p->tcam_size, KM_SLEEP); 67324df55fdeSJanie Lu 67336f45ec7bSml29623 MUTEX_INIT(&hw_p->nxge_cfg_lock, NULL, MUTEX_DRIVER, NULL); 67346f45ec7bSml29623 MUTEX_INIT(&hw_p->nxge_tcam_lock, NULL, MUTEX_DRIVER, NULL); 67356f45ec7bSml29623 MUTEX_INIT(&hw_p->nxge_vlan_lock, NULL, MUTEX_DRIVER, NULL); 67366f45ec7bSml29623 MUTEX_INIT(&hw_p->nxge_mdio_lock, NULL, MUTEX_DRIVER, NULL); 67376f45ec7bSml29623 67386f45ec7bSml29623 nxge_hw_list = hw_p; 673959ac0c16Sdavemq 674023b952a3SSantwona Behera if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, nxgep->dip, 0, 674123b952a3SSantwona Behera "compatible", &prop_val, &prop_len) == DDI_PROP_SUCCESS) { 674223b952a3SSantwona Behera for (i = 0; i < prop_len; i++) { 674323b952a3SSantwona Behera if ((strcmp((caddr_t)prop_val[i], 674423b952a3SSantwona Behera NXGE_ROCK_COMPATIBLE) == 0)) { 674523b952a3SSantwona Behera hw_p->platform_type = P_NEPTUNE_ROCK; 674623b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MOD_CTL, 674723b952a3SSantwona Behera "ROCK hw_p->platform_type %d", 674823b952a3SSantwona Behera hw_p->platform_type)); 674923b952a3SSantwona Behera break; 675023b952a3SSantwona Behera } 675123b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MOD_CTL, 675223b952a3SSantwona Behera "nxge_init_common_dev: read compatible" 675323b952a3SSantwona Behera " property[%d] val[%s]", 675423b952a3SSantwona Behera i, (caddr_t)prop_val[i])); 675523b952a3SSantwona Behera } 675623b952a3SSantwona Behera } 675723b952a3SSantwona Behera 675823b952a3SSantwona Behera ddi_prop_free(prop_val); 675923b952a3SSantwona Behera 676059ac0c16Sdavemq (void) nxge_scan_ports_phy(nxgep, nxge_hw_list); 67616f45ec7bSml29623 } 67626f45ec7bSml29623 67636f45ec7bSml29623 MUTEX_EXIT(&nxge_common_lock); 676459ac0c16Sdavemq 67652e59129aSraghus nxgep->platform_type = hw_p->platform_type; 676623b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MOD_CTL, "nxgep->platform_type %d", 676723b952a3SSantwona Behera nxgep->platform_type)); 676859ac0c16Sdavemq if (nxgep->niu_type != N2_NIU) { 676959ac0c16Sdavemq nxgep->niu_type = hw_p->niu_type; 677059ac0c16Sdavemq } 677159ac0c16Sdavemq 67726f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, 67736f45ec7bSml29623 "==> nxge_init_common_device (nxge_hw_list) $%p", 67746f45ec7bSml29623 nxge_hw_list)); 67756f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<== nxge_init_common_device")); 67766f45ec7bSml29623 67776f45ec7bSml29623 return (NXGE_OK); 67786f45ec7bSml29623 } 67796f45ec7bSml29623 67806f45ec7bSml29623 static void 67816f45ec7bSml29623 nxge_uninit_common_dev(p_nxge_t nxgep) 67826f45ec7bSml29623 { 67836f45ec7bSml29623 p_nxge_hw_list_t hw_p, h_hw_p; 67840b0beae0Sspeer p_nxge_dma_pt_cfg_t p_dma_cfgp; 67850b0beae0Sspeer p_nxge_hw_pt_cfg_t p_cfgp; 67866f45ec7bSml29623 dev_info_t *p_dip; 67876f45ec7bSml29623 6788ef523517SMichael Speer ASSERT(nxgep != NULL); 6789ef523517SMichael Speer 67906f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_uninit_common_device")); 67916f45ec7bSml29623 if (nxgep->nxge_hw_p == NULL) { 67926f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, 67936f45ec7bSml29623 "<== nxge_uninit_common_device (no common)")); 67946f45ec7bSml29623 return; 67956f45ec7bSml29623 } 67966f45ec7bSml29623 67976f45ec7bSml29623 MUTEX_ENTER(&nxge_common_lock); 67986f45ec7bSml29623 h_hw_p = nxge_hw_list; 67996f45ec7bSml29623 for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 68006f45ec7bSml29623 p_dip = hw_p->parent_devp; 68016f45ec7bSml29623 if (nxgep->nxge_hw_p == hw_p && 68026f45ec7bSml29623 p_dip == nxgep->p_dip && 68036f45ec7bSml29623 nxgep->nxge_hw_p->magic == NXGE_NEPTUNE_MAGIC && 68046f45ec7bSml29623 hw_p->magic == NXGE_NEPTUNE_MAGIC) { 68056f45ec7bSml29623 68066f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, 68076f45ec7bSml29623 "==> nxge_uninit_common_device:func # %d " 68086f45ec7bSml29623 "hw_p $%p parent dip $%p " 68096f45ec7bSml29623 "ndevs %d (found)", 68106f45ec7bSml29623 nxgep->function_num, 68116f45ec7bSml29623 hw_p, 68126f45ec7bSml29623 p_dip, 68136f45ec7bSml29623 hw_p->ndevs)); 68146f45ec7bSml29623 68150b0beae0Sspeer /* 68160b0beae0Sspeer * Release the RDC table, a shared resoruce 68170b0beae0Sspeer * of the nxge hardware. The RDC table was 68180b0beae0Sspeer * assigned to this instance of nxge in 68190b0beae0Sspeer * nxge_use_cfg_dma_config(). 68200b0beae0Sspeer */ 68219d5b8bc5SMichael Speer if (!isLDOMguest(nxgep)) { 68229d5b8bc5SMichael Speer p_dma_cfgp = 68239d5b8bc5SMichael Speer (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 68249d5b8bc5SMichael Speer p_cfgp = 68259d5b8bc5SMichael Speer (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; 68260b0beae0Sspeer (void) nxge_fzc_rdc_tbl_unbind(nxgep, 68270b0beae0Sspeer p_cfgp->def_mac_rxdma_grpid); 6828651ce697SMichael Speer 6829651ce697SMichael Speer /* Cleanup any outstanding groups. */ 6830651ce697SMichael Speer nxge_grp_cleanup(nxgep); 68319d5b8bc5SMichael Speer } 68320b0beae0Sspeer 68336f45ec7bSml29623 if (hw_p->ndevs) { 68346f45ec7bSml29623 hw_p->ndevs--; 68356f45ec7bSml29623 } 68366f45ec7bSml29623 hw_p->nxge_p[nxgep->function_num] = NULL; 68376f45ec7bSml29623 if (!hw_p->ndevs) { 68384df55fdeSJanie Lu KMEM_FREE(hw_p->tcam, 68394df55fdeSJanie Lu sizeof (tcam_flow_spec_t) * 68404df55fdeSJanie Lu hw_p->tcam_size); 68416f45ec7bSml29623 MUTEX_DESTROY(&hw_p->nxge_vlan_lock); 68426f45ec7bSml29623 MUTEX_DESTROY(&hw_p->nxge_tcam_lock); 68436f45ec7bSml29623 MUTEX_DESTROY(&hw_p->nxge_cfg_lock); 68446f45ec7bSml29623 MUTEX_DESTROY(&hw_p->nxge_mdio_lock); 68456f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, 68466f45ec7bSml29623 "==> nxge_uninit_common_device: " 68476f45ec7bSml29623 "func # %d " 68486f45ec7bSml29623 "hw_p $%p parent dip $%p " 68496f45ec7bSml29623 "ndevs %d (last)", 68506f45ec7bSml29623 nxgep->function_num, 68516f45ec7bSml29623 hw_p, 68526f45ec7bSml29623 p_dip, 68536f45ec7bSml29623 hw_p->ndevs)); 68546f45ec7bSml29623 6855678453a8Sspeer nxge_hio_uninit(nxgep); 6856678453a8Sspeer 68576f45ec7bSml29623 if (hw_p == nxge_hw_list) { 68586f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, 68596f45ec7bSml29623 "==> nxge_uninit_common_device:" 68606f45ec7bSml29623 "remove head func # %d " 68616f45ec7bSml29623 "hw_p $%p parent dip $%p " 68626f45ec7bSml29623 "ndevs %d (head)", 68636f45ec7bSml29623 nxgep->function_num, 68646f45ec7bSml29623 hw_p, 68656f45ec7bSml29623 p_dip, 68666f45ec7bSml29623 hw_p->ndevs)); 68676f45ec7bSml29623 nxge_hw_list = hw_p->next; 68686f45ec7bSml29623 } else { 68696f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, 68706f45ec7bSml29623 "==> nxge_uninit_common_device:" 68716f45ec7bSml29623 "remove middle func # %d " 68726f45ec7bSml29623 "hw_p $%p parent dip $%p " 68736f45ec7bSml29623 "ndevs %d (middle)", 68746f45ec7bSml29623 nxgep->function_num, 68756f45ec7bSml29623 hw_p, 68766f45ec7bSml29623 p_dip, 68776f45ec7bSml29623 hw_p->ndevs)); 68786f45ec7bSml29623 h_hw_p->next = hw_p->next; 68796f45ec7bSml29623 } 68806f45ec7bSml29623 6881678453a8Sspeer nxgep->nxge_hw_p = NULL; 68826f45ec7bSml29623 KMEM_FREE(hw_p, sizeof (nxge_hw_list_t)); 68836f45ec7bSml29623 } 68846f45ec7bSml29623 break; 68856f45ec7bSml29623 } else { 68866f45ec7bSml29623 h_hw_p = hw_p; 68876f45ec7bSml29623 } 68886f45ec7bSml29623 } 68896f45ec7bSml29623 68906f45ec7bSml29623 MUTEX_EXIT(&nxge_common_lock); 68916f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, 68926f45ec7bSml29623 "==> nxge_uninit_common_device (nxge_hw_list) $%p", 68936f45ec7bSml29623 nxge_hw_list)); 68946f45ec7bSml29623 68956f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<= nxge_uninit_common_device")); 68966f45ec7bSml29623 } 689759ac0c16Sdavemq 689859ac0c16Sdavemq /* 68992e59129aSraghus * Determines the number of ports from the niu_type or the platform type. 690059ac0c16Sdavemq * Returns the number of ports, or returns zero on failure. 690159ac0c16Sdavemq */ 690259ac0c16Sdavemq 690359ac0c16Sdavemq int 69042e59129aSraghus nxge_get_nports(p_nxge_t nxgep) 690559ac0c16Sdavemq { 690659ac0c16Sdavemq int nports = 0; 690759ac0c16Sdavemq 69082e59129aSraghus switch (nxgep->niu_type) { 690959ac0c16Sdavemq case N2_NIU: 691059ac0c16Sdavemq case NEPTUNE_2_10GF: 691159ac0c16Sdavemq nports = 2; 691259ac0c16Sdavemq break; 691359ac0c16Sdavemq case NEPTUNE_4_1GC: 691459ac0c16Sdavemq case NEPTUNE_2_10GF_2_1GC: 691559ac0c16Sdavemq case NEPTUNE_1_10GF_3_1GC: 691659ac0c16Sdavemq case NEPTUNE_1_1GC_1_10GF_2_1GC: 691759a835ddSjoycey case NEPTUNE_2_10GF_2_1GRF: 691859ac0c16Sdavemq nports = 4; 691959ac0c16Sdavemq break; 692059ac0c16Sdavemq default: 69212e59129aSraghus switch (nxgep->platform_type) { 69222e59129aSraghus case P_NEPTUNE_NIU: 69232e59129aSraghus case P_NEPTUNE_ATLAS_2PORT: 69242e59129aSraghus nports = 2; 69252e59129aSraghus break; 69262e59129aSraghus case P_NEPTUNE_ATLAS_4PORT: 69272e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 69282e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 692923b952a3SSantwona Behera case P_NEPTUNE_ROCK: 6930d81011f0Ssbehera case P_NEPTUNE_ALONSO: 69312e59129aSraghus nports = 4; 69322e59129aSraghus break; 69332e59129aSraghus default: 69342e59129aSraghus break; 69352e59129aSraghus } 693659ac0c16Sdavemq break; 693759ac0c16Sdavemq } 693859ac0c16Sdavemq 693959ac0c16Sdavemq return (nports); 694059ac0c16Sdavemq } 6941ec090658Sml29623 6942ec090658Sml29623 /* 6943ec090658Sml29623 * The following two functions are to support 6944ec090658Sml29623 * PSARC/2007/453 MSI-X interrupt limit override. 6945ec090658Sml29623 */ 6946ec090658Sml29623 static int 6947ec090658Sml29623 nxge_create_msi_property(p_nxge_t nxgep) 6948ec090658Sml29623 { 6949ec090658Sml29623 int nmsi; 6950ec090658Sml29623 extern int ncpus; 6951ec090658Sml29623 6952ec090658Sml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==>nxge_create_msi_property")); 6953ec090658Sml29623 6954ec090658Sml29623 switch (nxgep->mac.portmode) { 6955ec090658Sml29623 case PORT_10G_COPPER: 6956ec090658Sml29623 case PORT_10G_FIBER: 695700161856Syc148097 case PORT_10G_TN1010: 6958ec090658Sml29623 (void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip, 6959ec090658Sml29623 DDI_PROP_CANSLEEP, "#msix-request", NULL, 0); 6960ec090658Sml29623 /* 6961ec090658Sml29623 * The maximum MSI-X requested will be 8. 6962ef755e7aStc99174@train * If the # of CPUs is less than 8, we will request 6963ef755e7aStc99174@train * # MSI-X based on the # of CPUs (default). 6964ec090658Sml29623 */ 6965ef755e7aStc99174@train NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6966ef755e7aStc99174@train "==>nxge_create_msi_property (10G): nxge_msix_10g_intrs %d", 6967ef755e7aStc99174@train nxge_msix_10g_intrs)); 6968ef755e7aStc99174@train if ((nxge_msix_10g_intrs == 0) || 6969ef755e7aStc99174@train (nxge_msix_10g_intrs > NXGE_MSIX_MAX_ALLOWED)) { 6970ec090658Sml29623 nmsi = NXGE_MSIX_REQUEST_10G; 6971ef755e7aStc99174@train NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6972ef755e7aStc99174@train "==>nxge_create_msi_property (10G): reset to 8")); 6973ec090658Sml29623 } else { 6974ef755e7aStc99174@train nmsi = nxge_msix_10g_intrs; 6975ef755e7aStc99174@train } 6976ef755e7aStc99174@train 6977ef755e7aStc99174@train /* 6978ef755e7aStc99174@train * If # of interrupts requested is 8 (default), 6979ef755e7aStc99174@train * the checking of the number of cpus will be 6980ef755e7aStc99174@train * be maintained. 6981ef755e7aStc99174@train */ 6982ef755e7aStc99174@train if ((nmsi == NXGE_MSIX_REQUEST_10G) && 6983ef755e7aStc99174@train (ncpus < nmsi)) { 6984ef755e7aStc99174@train NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6985ef755e7aStc99174@train "==>nxge_create_msi_property (10G): reset to 8")); 6986ec090658Sml29623 nmsi = ncpus; 6987ec090658Sml29623 } 6988ec090658Sml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6989ec090658Sml29623 "==>nxge_create_msi_property(10G): exists 0x%x (nmsi %d)", 6990ec090658Sml29623 ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 6991ec090658Sml29623 DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 6992ec090658Sml29623 break; 6993ec090658Sml29623 6994ec090658Sml29623 default: 6995ef755e7aStc99174@train (void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip, 6996ef755e7aStc99174@train DDI_PROP_CANSLEEP, "#msix-request", NULL, 0); 6997ef755e7aStc99174@train NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6998ef755e7aStc99174@train "==>nxge_create_msi_property (1G): nxge_msix_1g_intrs %d", 6999ef755e7aStc99174@train nxge_msix_1g_intrs)); 7000ef755e7aStc99174@train if ((nxge_msix_1g_intrs == 0) || 7001ef755e7aStc99174@train (nxge_msix_1g_intrs > NXGE_MSIX_MAX_ALLOWED)) { 7002ec090658Sml29623 nmsi = NXGE_MSIX_REQUEST_1G; 7003ec090658Sml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, 7004ef755e7aStc99174@train "==>nxge_create_msi_property (1G): reset to 2")); 7005ef755e7aStc99174@train } else { 7006ef755e7aStc99174@train nmsi = nxge_msix_1g_intrs; 7007ef755e7aStc99174@train } 7008ef755e7aStc99174@train NXGE_DEBUG_MSG((nxgep, MOD_CTL, 7009ec090658Sml29623 "==>nxge_create_msi_property(1G): exists 0x%x (nmsi %d)", 7010ec090658Sml29623 ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 7011ec090658Sml29623 DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 7012ec090658Sml29623 break; 7013ec090658Sml29623 } 7014ec090658Sml29623 7015ec090658Sml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<==nxge_create_msi_property")); 7016ec090658Sml29623 return (nmsi); 7017ec090658Sml29623 } 70184045d941Ssowmini 70196f157acbSml29623 /* 70206f157acbSml29623 * The following is a software around for the Neptune hardware's 70216f157acbSml29623 * interrupt bugs; The Neptune hardware may generate spurious interrupts when 70226f157acbSml29623 * an interrupr handler is removed. 70236f157acbSml29623 */ 70246f157acbSml29623 #define NXGE_PCI_PORT_LOGIC_OFFSET 0x98 70256f157acbSml29623 #define NXGE_PIM_RESET (1ULL << 29) 70266f157acbSml29623 #define NXGE_GLU_RESET (1ULL << 30) 70276f157acbSml29623 #define NXGE_NIU_RESET (1ULL << 31) 70286f157acbSml29623 #define NXGE_PCI_RESET_ALL (NXGE_PIM_RESET | \ 70296f157acbSml29623 NXGE_GLU_RESET | \ 70306f157acbSml29623 NXGE_NIU_RESET) 70316f157acbSml29623 70326f157acbSml29623 #define NXGE_WAIT_QUITE_TIME 200000 70336f157acbSml29623 #define NXGE_WAIT_QUITE_RETRY 40 70346f157acbSml29623 #define NXGE_PCI_RESET_WAIT 1000000 /* one second */ 70356f157acbSml29623 70366f157acbSml29623 static void 70376f157acbSml29623 nxge_niu_peu_reset(p_nxge_t nxgep) 70386f157acbSml29623 { 70396f157acbSml29623 uint32_t rvalue; 70406f157acbSml29623 p_nxge_hw_list_t hw_p; 70416f157acbSml29623 p_nxge_t fnxgep; 70426f157acbSml29623 int i, j; 70436f157acbSml29623 70446f157acbSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_niu_peu_reset")); 70456f157acbSml29623 if ((hw_p = nxgep->nxge_hw_p) == NULL) { 70466f157acbSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 70476f157acbSml29623 "==> nxge_niu_peu_reset: NULL hardware pointer")); 70486f157acbSml29623 return; 70496f157acbSml29623 } 70506f157acbSml29623 70516f157acbSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 70526f157acbSml29623 "==> nxge_niu_peu_reset: flags 0x%x link timer id %d timer id %d", 70536f157acbSml29623 hw_p->flags, nxgep->nxge_link_poll_timerid, 70546f157acbSml29623 nxgep->nxge_timerid)); 70556f157acbSml29623 70566f157acbSml29623 MUTEX_ENTER(&hw_p->nxge_cfg_lock); 70576f157acbSml29623 /* 70586f157acbSml29623 * Make sure other instances from the same hardware 70596f157acbSml29623 * stop sending PIO and in quiescent state. 70606f157acbSml29623 */ 70616f157acbSml29623 for (i = 0; i < NXGE_MAX_PORTS; i++) { 70626f157acbSml29623 fnxgep = hw_p->nxge_p[i]; 70636f157acbSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 70646f157acbSml29623 "==> nxge_niu_peu_reset: checking entry %d " 70656f157acbSml29623 "nxgep $%p", i, fnxgep)); 70666f157acbSml29623 #ifdef NXGE_DEBUG 70676f157acbSml29623 if (fnxgep) { 70686f157acbSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 70696f157acbSml29623 "==> nxge_niu_peu_reset: entry %d (function %d) " 70706f157acbSml29623 "link timer id %d hw timer id %d", 70716f157acbSml29623 i, fnxgep->function_num, 70726f157acbSml29623 fnxgep->nxge_link_poll_timerid, 70736f157acbSml29623 fnxgep->nxge_timerid)); 70746f157acbSml29623 } 70756f157acbSml29623 #endif 70766f157acbSml29623 if (fnxgep && fnxgep != nxgep && 70776f157acbSml29623 (fnxgep->nxge_timerid || fnxgep->nxge_link_poll_timerid)) { 70786f157acbSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 70796f157acbSml29623 "==> nxge_niu_peu_reset: checking $%p " 70806f157acbSml29623 "(function %d) timer ids", 70816f157acbSml29623 fnxgep, fnxgep->function_num)); 70826f157acbSml29623 for (j = 0; j < NXGE_WAIT_QUITE_RETRY; j++) { 70836f157acbSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 70846f157acbSml29623 "==> nxge_niu_peu_reset: waiting")); 70856f157acbSml29623 NXGE_DELAY(NXGE_WAIT_QUITE_TIME); 70866f157acbSml29623 if (!fnxgep->nxge_timerid && 70876f157acbSml29623 !fnxgep->nxge_link_poll_timerid) { 70886f157acbSml29623 break; 70896f157acbSml29623 } 70906f157acbSml29623 } 70916f157acbSml29623 NXGE_DELAY(NXGE_WAIT_QUITE_TIME); 70926f157acbSml29623 if (fnxgep->nxge_timerid || 70936f157acbSml29623 fnxgep->nxge_link_poll_timerid) { 70946f157acbSml29623 MUTEX_EXIT(&hw_p->nxge_cfg_lock); 70956f157acbSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 70966f157acbSml29623 "<== nxge_niu_peu_reset: cannot reset " 70976f157acbSml29623 "hardware (devices are still in use)")); 70986f157acbSml29623 return; 70996f157acbSml29623 } 71006f157acbSml29623 } 71016f157acbSml29623 } 71026f157acbSml29623 71036f157acbSml29623 if ((hw_p->flags & COMMON_RESET_NIU_PCI) != COMMON_RESET_NIU_PCI) { 71046f157acbSml29623 hw_p->flags |= COMMON_RESET_NIU_PCI; 71056f157acbSml29623 rvalue = pci_config_get32(nxgep->dev_regs->nxge_pciregh, 71066f157acbSml29623 NXGE_PCI_PORT_LOGIC_OFFSET); 71076f157acbSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 71086f157acbSml29623 "nxge_niu_peu_reset: read offset 0x%x (%d) " 71096f157acbSml29623 "(data 0x%x)", 71106f157acbSml29623 NXGE_PCI_PORT_LOGIC_OFFSET, 71116f157acbSml29623 NXGE_PCI_PORT_LOGIC_OFFSET, 71126f157acbSml29623 rvalue)); 71136f157acbSml29623 71146f157acbSml29623 rvalue |= NXGE_PCI_RESET_ALL; 71156f157acbSml29623 pci_config_put32(nxgep->dev_regs->nxge_pciregh, 71166f157acbSml29623 NXGE_PCI_PORT_LOGIC_OFFSET, rvalue); 71176f157acbSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 71186f157acbSml29623 "nxge_niu_peu_reset: RESETTING NIU: write NIU reset 0x%x", 71196f157acbSml29623 rvalue)); 71206f157acbSml29623 71216f157acbSml29623 NXGE_DELAY(NXGE_PCI_RESET_WAIT); 71226f157acbSml29623 } 71236f157acbSml29623 71246f157acbSml29623 MUTEX_EXIT(&hw_p->nxge_cfg_lock); 71256f157acbSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_niu_peu_reset")); 71266f157acbSml29623 } 7127d6d3405fSml29623 7128d6d3405fSml29623 static void 7129d6d3405fSml29623 nxge_set_pci_replay_timeout(p_nxge_t nxgep) 7130d6d3405fSml29623 { 7131d6d3405fSml29623 p_dev_regs_t dev_regs; 7132d6d3405fSml29623 uint32_t value; 7133d6d3405fSml29623 7134d6d3405fSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_set_pci_replay_timeout")); 7135d6d3405fSml29623 7136d6d3405fSml29623 if (!nxge_set_replay_timer) { 7137d6d3405fSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7138d6d3405fSml29623 "==> nxge_set_pci_replay_timeout: will not change " 7139d6d3405fSml29623 "the timeout")); 7140d6d3405fSml29623 return; 7141d6d3405fSml29623 } 7142d6d3405fSml29623 7143d6d3405fSml29623 dev_regs = nxgep->dev_regs; 7144d6d3405fSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7145d6d3405fSml29623 "==> nxge_set_pci_replay_timeout: dev_regs 0x%p pcireg 0x%p", 7146d6d3405fSml29623 dev_regs, dev_regs->nxge_pciregh)); 7147d6d3405fSml29623 7148d6d3405fSml29623 if (dev_regs == NULL || (dev_regs->nxge_pciregh == NULL)) { 7149f720bc57Syc148097 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7150d6d3405fSml29623 "==> nxge_set_pci_replay_timeout: NULL dev_regs $%p or " 7151d6d3405fSml29623 "no PCI handle", 7152d6d3405fSml29623 dev_regs)); 7153d6d3405fSml29623 return; 7154d6d3405fSml29623 } 7155d6d3405fSml29623 value = (pci_config_get32(dev_regs->nxge_pciregh, 7156d6d3405fSml29623 PCI_REPLAY_TIMEOUT_CFG_OFFSET) | 7157d6d3405fSml29623 (nxge_replay_timeout << PCI_REPLAY_TIMEOUT_SHIFT)); 7158d6d3405fSml29623 7159d6d3405fSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7160d6d3405fSml29623 "nxge_set_pci_replay_timeout: replay timeout value before set 0x%x " 7161d6d3405fSml29623 "(timeout value to set 0x%x at offset 0x%x) value 0x%x", 7162d6d3405fSml29623 pci_config_get32(dev_regs->nxge_pciregh, 7163d6d3405fSml29623 PCI_REPLAY_TIMEOUT_CFG_OFFSET), nxge_replay_timeout, 7164d6d3405fSml29623 PCI_REPLAY_TIMEOUT_CFG_OFFSET, value)); 7165d6d3405fSml29623 7166d6d3405fSml29623 pci_config_put32(dev_regs->nxge_pciregh, PCI_REPLAY_TIMEOUT_CFG_OFFSET, 7167d6d3405fSml29623 value); 7168d6d3405fSml29623 7169d6d3405fSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7170d6d3405fSml29623 "nxge_set_pci_replay_timeout: replay timeout value after set 0x%x", 7171d6d3405fSml29623 pci_config_get32(dev_regs->nxge_pciregh, 7172d6d3405fSml29623 PCI_REPLAY_TIMEOUT_CFG_OFFSET))); 7173d6d3405fSml29623 7174d6d3405fSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_set_pci_replay_timeout")); 7175d6d3405fSml29623 } 717619397407SSherry Moore 717719397407SSherry Moore /* 717819397407SSherry Moore * quiesce(9E) entry point. 717919397407SSherry Moore * 718019397407SSherry Moore * This function is called when the system is single-threaded at high 718119397407SSherry Moore * PIL with preemption disabled. Therefore, this function must not be 718219397407SSherry Moore * blocked. 718319397407SSherry Moore * 718419397407SSherry Moore * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 718519397407SSherry Moore * DDI_FAILURE indicates an error condition and should almost never happen. 718619397407SSherry Moore */ 718719397407SSherry Moore static int 718819397407SSherry Moore nxge_quiesce(dev_info_t *dip) 718919397407SSherry Moore { 719019397407SSherry Moore int instance = ddi_get_instance(dip); 719119397407SSherry Moore p_nxge_t nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 719219397407SSherry Moore 719319397407SSherry Moore if (nxgep == NULL) 719419397407SSherry Moore return (DDI_FAILURE); 719519397407SSherry Moore 719619397407SSherry Moore /* Turn off debugging */ 719719397407SSherry Moore nxge_debug_level = NO_DEBUG; 719819397407SSherry Moore nxgep->nxge_debug_level = NO_DEBUG; 719919397407SSherry Moore npi_debug_level = NO_DEBUG; 720019397407SSherry Moore 720119397407SSherry Moore /* 720219397407SSherry Moore * Stop link monitor only when linkchkmod is interrupt based 720319397407SSherry Moore */ 720419397407SSherry Moore if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 720519397407SSherry Moore (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 720619397407SSherry Moore } 720719397407SSherry Moore 720819397407SSherry Moore (void) nxge_intr_hw_disable(nxgep); 720919397407SSherry Moore 721019397407SSherry Moore /* 721119397407SSherry Moore * Reset the receive MAC side. 721219397407SSherry Moore */ 721319397407SSherry Moore (void) nxge_rx_mac_disable(nxgep); 721419397407SSherry Moore 721519397407SSherry Moore /* Disable and soft reset the IPP */ 721619397407SSherry Moore if (!isLDOMguest(nxgep)) 721719397407SSherry Moore (void) nxge_ipp_disable(nxgep); 721819397407SSherry Moore 721919397407SSherry Moore /* 722019397407SSherry Moore * Reset the transmit/receive DMA side. 722119397407SSherry Moore */ 722219397407SSherry Moore (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 722319397407SSherry Moore (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 722419397407SSherry Moore 722519397407SSherry Moore /* 722619397407SSherry Moore * Reset the transmit MAC side. 722719397407SSherry Moore */ 722819397407SSherry Moore (void) nxge_tx_mac_disable(nxgep); 722919397407SSherry Moore 723019397407SSherry Moore return (DDI_SUCCESS); 723119397407SSherry Moore } 7232