144961713Sgirish /* 244961713Sgirish * CDDL HEADER START 344961713Sgirish * 444961713Sgirish * The contents of this file are subject to the terms of the 544961713Sgirish * Common Development and Distribution License (the "License"). 644961713Sgirish * You may not use this file except in compliance with the License. 744961713Sgirish * 844961713Sgirish * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 944961713Sgirish * or http://www.opensolaris.org/os/licensing. 1044961713Sgirish * See the License for the specific language governing permissions 1144961713Sgirish * and limitations under the License. 1244961713Sgirish * 1344961713Sgirish * When distributing Covered Code, include this CDDL HEADER in each 1444961713Sgirish * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1544961713Sgirish * If applicable, add the following below this CDDL HEADER, with the 1644961713Sgirish * fields enclosed by brackets "[]" replaced with your own identifying 1744961713Sgirish * information: Portions Copyright [yyyy] [name of copyright owner] 1844961713Sgirish * 1944961713Sgirish * CDDL HEADER END 2044961713Sgirish */ 2148056c53SMichael Speer 2244961713Sgirish /* 23*0dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 2444961713Sgirish * Use is subject to license terms. 2544961713Sgirish */ 2644961713Sgirish 2744961713Sgirish /* 2844961713Sgirish * SunOs MT STREAMS NIU/Neptune 10Gb Ethernet Device Driver. 2944961713Sgirish */ 3044961713Sgirish #include <sys/nxge/nxge_impl.h> 31678453a8Sspeer #include <sys/nxge/nxge_hio.h> 32678453a8Sspeer #include <sys/nxge/nxge_rxdma.h> 3314ea4bb7Ssd #include <sys/pcie.h> 3444961713Sgirish 3544961713Sgirish uint32_t nxge_use_partition = 0; /* debug partition flag */ 3644961713Sgirish uint32_t nxge_dma_obp_props_only = 1; /* use obp published props */ 3744961713Sgirish uint32_t nxge_use_rdc_intr = 1; /* debug to assign rdc intr */ 3844961713Sgirish /* 39ec090658Sml * PSARC/2007/453 MSI-X interrupt limit override 4044961713Sgirish */ 41ec090658Sml uint32_t nxge_msi_enable = 2; 4244961713Sgirish 436f157acbSml /* 446f157acbSml * Software workaround for a Neptune (PCI-E) 456f157acbSml * hardware interrupt bug which the hardware 466f157acbSml * may generate spurious interrupts after the 476f157acbSml * device interrupt handler was removed. If this flag 486f157acbSml * is enabled, the driver will reset the 496f157acbSml * hardware when devices are being detached. 506f157acbSml */ 516f157acbSml uint32_t nxge_peu_reset_enable = 0; 526f157acbSml 53b4d05839Sml /* 54b4d05839Sml * Software workaround for the hardware 55b4d05839Sml * checksum bugs that affect packet transmission 56b4d05839Sml * and receive: 57b4d05839Sml * 58b4d05839Sml * Usage of nxge_cksum_offload: 59b4d05839Sml * 60b4d05839Sml * (1) nxge_cksum_offload = 0 (default): 61b4d05839Sml * - transmits packets: 62b4d05839Sml * TCP: uses the hardware checksum feature. 63b4d05839Sml * UDP: driver will compute the software checksum 64b4d05839Sml * based on the partial checksum computed 65b4d05839Sml * by the IP layer. 66b4d05839Sml * - receives packets 67b4d05839Sml * TCP: marks packets checksum flags based on hardware result. 68b4d05839Sml * UDP: will not mark checksum flags. 69b4d05839Sml * 70b4d05839Sml * (2) nxge_cksum_offload = 1: 71b4d05839Sml * - transmit packets: 72b4d05839Sml * TCP/UDP: uses the hardware checksum feature. 73b4d05839Sml * - receives packets 74b4d05839Sml * TCP/UDP: marks packet checksum flags based on hardware result. 75b4d05839Sml * 76b4d05839Sml * (3) nxge_cksum_offload = 2: 77b4d05839Sml * - The driver will not register its checksum capability. 78b4d05839Sml * Checksum for both TCP and UDP will be computed 79b4d05839Sml * by the stack. 80b4d05839Sml * - The software LSO is not allowed in this case. 81b4d05839Sml * 82b4d05839Sml * (4) nxge_cksum_offload > 2: 83b4d05839Sml * - Will be treated as it is set to 2 84b4d05839Sml * (stack will compute the checksum). 85b4d05839Sml * 86b4d05839Sml * (5) If the hardware bug is fixed, this workaround 87b4d05839Sml * needs to be updated accordingly to reflect 88b4d05839Sml * the new hardware revision. 89b4d05839Sml */ 90b4d05839Sml uint32_t nxge_cksum_offload = 0; 91678453a8Sspeer 9244961713Sgirish /* 9344961713Sgirish * Globals: tunable parameters (/etc/system or adb) 9444961713Sgirish * 9544961713Sgirish */ 9644961713Sgirish uint32_t nxge_rbr_size = NXGE_RBR_RBB_DEFAULT; 9744961713Sgirish uint32_t nxge_rbr_spare_size = 0; 9844961713Sgirish uint32_t nxge_rcr_size = NXGE_RCR_DEFAULT; 994df55fdeSJanie Lu uint16_t nxge_rdc_buf_offset = SW_OFFSET_NO_OFFSET; 10044961713Sgirish uint32_t nxge_tx_ring_size = NXGE_TX_RING_DEFAULT; 101b3a0105bSspeer boolean_t nxge_no_msg = B_TRUE; /* control message display */ 10244961713Sgirish uint32_t nxge_no_link_notify = 0; /* control DL_NOTIFY */ 10344961713Sgirish uint32_t nxge_bcopy_thresh = TX_BCOPY_MAX; 10444961713Sgirish uint32_t nxge_dvma_thresh = TX_FASTDVMA_MIN; 10544961713Sgirish uint32_t nxge_dma_stream_thresh = TX_STREAM_MIN; 10644961713Sgirish uint32_t nxge_jumbo_mtu = TX_JUMBO_MTU; 1071f8914d5Sml nxge_tx_mode_t nxge_tx_scheme = NXGE_USE_SERIAL; 10844961713Sgirish 10930ac2e7bSml /* MAX LSO size */ 11030ac2e7bSml #define NXGE_LSO_MAXLEN 65535 11130ac2e7bSml uint32_t nxge_lso_max = NXGE_LSO_MAXLEN; 11230ac2e7bSml 11344961713Sgirish 11444961713Sgirish /* 11544961713Sgirish * Add tunable to reduce the amount of time spent in the 11644961713Sgirish * ISR doing Rx Processing. 11744961713Sgirish */ 11844961713Sgirish uint32_t nxge_max_rx_pkts = 1024; 11944961713Sgirish 12044961713Sgirish /* 12144961713Sgirish * Tunables to manage the receive buffer blocks. 12244961713Sgirish * 12344961713Sgirish * nxge_rx_threshold_hi: copy all buffers. 12444961713Sgirish * nxge_rx_bcopy_size_type: receive buffer block size type. 12544961713Sgirish * nxge_rx_threshold_lo: copy only up to tunable block size type. 12644961713Sgirish */ 12744961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_hi = NXGE_RX_COPY_6; 12844961713Sgirish nxge_rxbuf_type_t nxge_rx_buf_size_type = RCR_PKTBUFSZ_0; 12944961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_lo = NXGE_RX_COPY_3; 13044961713Sgirish 131678453a8Sspeer /* Use kmem_alloc() to allocate data buffers. */ 132ef523517SMichael Speer #if defined(__sparc) 133d00f30bbSspeer uint32_t nxge_use_kmem_alloc = 1; 134ef523517SMichael Speer #elif defined(__i386) 135d00f30bbSspeer uint32_t nxge_use_kmem_alloc = 0; 136ef523517SMichael Speer #else 137ef523517SMichael Speer uint32_t nxge_use_kmem_alloc = 1; 138678453a8Sspeer #endif 139678453a8Sspeer 14044961713Sgirish rtrace_t npi_rtracebuf; 14144961713Sgirish 142d6d3405fSml /* 143d6d3405fSml * The hardware sometimes fails to allow enough time for the link partner 144d6d3405fSml * to send an acknowledgement for packets that the hardware sent to it. The 145d6d3405fSml * hardware resends the packets earlier than it should be in those instances. 146d6d3405fSml * This behavior caused some switches to acknowledge the wrong packets 147d6d3405fSml * and it triggered the fatal error. 148d6d3405fSml * This software workaround is to set the replay timer to a value 149d6d3405fSml * suggested by the hardware team. 150d6d3405fSml * 151d6d3405fSml * PCI config space replay timer register: 152d6d3405fSml * The following replay timeout value is 0xc 153d6d3405fSml * for bit 14:18. 154d6d3405fSml */ 155d6d3405fSml #define PCI_REPLAY_TIMEOUT_CFG_OFFSET 0xb8 156d6d3405fSml #define PCI_REPLAY_TIMEOUT_SHIFT 14 157d6d3405fSml 158d6d3405fSml uint32_t nxge_set_replay_timer = 1; 159d6d3405fSml uint32_t nxge_replay_timeout = 0xc; 160d6d3405fSml 161cf020df9Sml /* 162cf020df9Sml * The transmit serialization sometimes causes 163cf020df9Sml * longer sleep before calling the driver transmit 164cf020df9Sml * function as it sleeps longer than it should. 165cf020df9Sml * The performace group suggests that a time wait tunable 166cf020df9Sml * can be used to set the maximum wait time when needed 167cf020df9Sml * and the default is set to 1 tick. 168cf020df9Sml */ 169cf020df9Sml uint32_t nxge_tx_serial_maxsleep = 1; 170cf020df9Sml 17144961713Sgirish #if defined(sun4v) 17244961713Sgirish /* 17344961713Sgirish * Hypervisor N2/NIU services information. 17444961713Sgirish */ 1754df55fdeSJanie Lu /* 1764df55fdeSJanie Lu * The following is the default API supported: 1774df55fdeSJanie Lu * major 1 and minor 1. 1784df55fdeSJanie Lu * 1794df55fdeSJanie Lu * Please update the MAX_NIU_MAJORS, 1804df55fdeSJanie Lu * MAX_NIU_MINORS, and minor number supported 1814df55fdeSJanie Lu * when the newer Hypervior API interfaces 1824df55fdeSJanie Lu * are added. Also, please update nxge_hsvc_register() 1834df55fdeSJanie Lu * if needed. 1844df55fdeSJanie Lu */ 18544961713Sgirish static hsvc_info_t niu_hsvc = { 18644961713Sgirish HSVC_REV_1, NULL, HSVC_GROUP_NIU, NIU_MAJOR_VER, 18744961713Sgirish NIU_MINOR_VER, "nxge" 18844961713Sgirish }; 189678453a8Sspeer 190678453a8Sspeer static int nxge_hsvc_register(p_nxge_t); 19144961713Sgirish #endif 19244961713Sgirish 19344961713Sgirish /* 19444961713Sgirish * Function Prototypes 19544961713Sgirish */ 19644961713Sgirish static int nxge_attach(dev_info_t *, ddi_attach_cmd_t); 19744961713Sgirish static int nxge_detach(dev_info_t *, ddi_detach_cmd_t); 19844961713Sgirish static void nxge_unattach(p_nxge_t); 19919397407SSherry Moore static int nxge_quiesce(dev_info_t *); 20044961713Sgirish 20144961713Sgirish #if NXGE_PROPERTY 20244961713Sgirish static void nxge_remove_hard_properties(p_nxge_t); 20344961713Sgirish #endif 20444961713Sgirish 205678453a8Sspeer /* 206678453a8Sspeer * These two functions are required by nxge_hio.c 207678453a8Sspeer */ 208da14cebeSEric Cheng extern int nxge_m_mmac_remove(void *arg, int slot); 209651ce697SMichael Speer extern void nxge_grp_cleanup(p_nxge_t nxge); 210678453a8Sspeer 21144961713Sgirish static nxge_status_t nxge_setup_system_dma_pages(p_nxge_t); 21244961713Sgirish 21344961713Sgirish static nxge_status_t nxge_setup_mutexes(p_nxge_t); 21444961713Sgirish static void nxge_destroy_mutexes(p_nxge_t); 21544961713Sgirish 21644961713Sgirish static nxge_status_t nxge_map_regs(p_nxge_t nxgep); 21744961713Sgirish static void nxge_unmap_regs(p_nxge_t nxgep); 21844961713Sgirish #ifdef NXGE_DEBUG 21944961713Sgirish static void nxge_test_map_regs(p_nxge_t nxgep); 22044961713Sgirish #endif 22144961713Sgirish 22244961713Sgirish static nxge_status_t nxge_add_intrs(p_nxge_t nxgep); 22344961713Sgirish static void nxge_remove_intrs(p_nxge_t nxgep); 22444961713Sgirish 22544961713Sgirish static nxge_status_t nxge_add_intrs_adv(p_nxge_t nxgep); 22644961713Sgirish static nxge_status_t nxge_add_intrs_adv_type(p_nxge_t, uint32_t); 22744961713Sgirish static nxge_status_t nxge_add_intrs_adv_type_fix(p_nxge_t, uint32_t); 22844961713Sgirish static void nxge_intrs_enable(p_nxge_t nxgep); 22944961713Sgirish static void nxge_intrs_disable(p_nxge_t nxgep); 23044961713Sgirish 23144961713Sgirish static void nxge_suspend(p_nxge_t); 23244961713Sgirish static nxge_status_t nxge_resume(p_nxge_t); 23344961713Sgirish 23444961713Sgirish static nxge_status_t nxge_setup_dev(p_nxge_t); 23544961713Sgirish static void nxge_destroy_dev(p_nxge_t); 23644961713Sgirish 23744961713Sgirish static nxge_status_t nxge_alloc_mem_pool(p_nxge_t); 23844961713Sgirish static void nxge_free_mem_pool(p_nxge_t); 23944961713Sgirish 240678453a8Sspeer nxge_status_t nxge_alloc_rx_mem_pool(p_nxge_t); 24144961713Sgirish static void nxge_free_rx_mem_pool(p_nxge_t); 24244961713Sgirish 243678453a8Sspeer nxge_status_t nxge_alloc_tx_mem_pool(p_nxge_t); 24444961713Sgirish static void nxge_free_tx_mem_pool(p_nxge_t); 24544961713Sgirish 24644961713Sgirish static nxge_status_t nxge_dma_mem_alloc(p_nxge_t, dma_method_t, 24744961713Sgirish struct ddi_dma_attr *, 24844961713Sgirish size_t, ddi_device_acc_attr_t *, uint_t, 24944961713Sgirish p_nxge_dma_common_t); 25044961713Sgirish 25144961713Sgirish static void nxge_dma_mem_free(p_nxge_dma_common_t); 252678453a8Sspeer static void nxge_dma_free_rx_data_buf(p_nxge_dma_common_t); 25344961713Sgirish 25444961713Sgirish static nxge_status_t nxge_alloc_rx_buf_dma(p_nxge_t, uint16_t, 25544961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 25644961713Sgirish static void nxge_free_rx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 25744961713Sgirish 25844961713Sgirish static nxge_status_t nxge_alloc_rx_cntl_dma(p_nxge_t, uint16_t, 25944961713Sgirish p_nxge_dma_common_t *, size_t); 26044961713Sgirish static void nxge_free_rx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 26144961713Sgirish 262678453a8Sspeer extern nxge_status_t nxge_alloc_tx_buf_dma(p_nxge_t, uint16_t, 26344961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *); 26444961713Sgirish static void nxge_free_tx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t); 26544961713Sgirish 266678453a8Sspeer extern nxge_status_t nxge_alloc_tx_cntl_dma(p_nxge_t, uint16_t, 26744961713Sgirish p_nxge_dma_common_t *, 26844961713Sgirish size_t); 26944961713Sgirish static void nxge_free_tx_cntl_dma(p_nxge_t, p_nxge_dma_common_t); 27044961713Sgirish 27144961713Sgirish static int nxge_init_common_dev(p_nxge_t); 27244961713Sgirish static void nxge_uninit_common_dev(p_nxge_t); 2734045d941Ssowmini extern int nxge_param_set_mac(p_nxge_t, queue_t *, mblk_t *, 2744045d941Ssowmini char *, caddr_t); 275e759c33aSMichael Speer #if defined(sun4v) 276e759c33aSMichael Speer extern nxge_status_t nxge_hio_rdc_enable(p_nxge_t nxgep); 277e759c33aSMichael Speer extern nxge_status_t nxge_hio_rdc_intr_arm(p_nxge_t nxge, boolean_t arm); 278e759c33aSMichael Speer #endif 27944961713Sgirish 28044961713Sgirish /* 28144961713Sgirish * The next declarations are for the GLDv3 interface. 28244961713Sgirish */ 28344961713Sgirish static int nxge_m_start(void *); 28444961713Sgirish static void nxge_m_stop(void *); 28544961713Sgirish static int nxge_m_multicst(void *, boolean_t, const uint8_t *); 28644961713Sgirish static int nxge_m_promisc(void *, boolean_t); 28744961713Sgirish static void nxge_m_ioctl(void *, queue_t *, mblk_t *); 28863f531d1SSriharsha Basavapatna nxge_status_t nxge_mac_register(p_nxge_t); 289da14cebeSEric Cheng static int nxge_altmac_set(p_nxge_t nxgep, uint8_t *mac_addr, 290da14cebeSEric Cheng int slot, int rdctbl, boolean_t usetbl); 291da14cebeSEric Cheng void nxge_mmac_kstat_update(p_nxge_t nxgep, int slot, 29258324dfcSspeer boolean_t factory); 293da14cebeSEric Cheng 294da14cebeSEric Cheng static void nxge_m_getfactaddr(void *, uint_t, uint8_t *); 2951bd6825cSml static boolean_t nxge_m_getcapab(void *, mac_capab_t, void *); 2961bd6825cSml static int nxge_m_setprop(void *, const char *, mac_prop_id_t, 2971bd6825cSml uint_t, const void *); 2981bd6825cSml static int nxge_m_getprop(void *, const char *, mac_prop_id_t, 299*0dc2366fSVenugopal Iyer uint_t, void *); 300*0dc2366fSVenugopal Iyer static void nxge_m_propinfo(void *, const char *, mac_prop_id_t, 301*0dc2366fSVenugopal Iyer mac_prop_info_handle_t); 302*0dc2366fSVenugopal Iyer static void nxge_priv_propinfo(const char *, mac_prop_info_handle_t); 3031bd6825cSml static int nxge_set_priv_prop(nxge_t *, const char *, uint_t, 3041bd6825cSml const void *); 305*0dc2366fSVenugopal Iyer static int nxge_get_priv_prop(nxge_t *, const char *, uint_t, void *); 306da14cebeSEric Cheng static void nxge_fill_ring(void *, mac_ring_type_t, const int, const int, 307da14cebeSEric Cheng mac_ring_info_t *, mac_ring_handle_t); 308da14cebeSEric Cheng static void nxge_group_add_ring(mac_group_driver_t, mac_ring_driver_t, 309da14cebeSEric Cheng mac_ring_type_t); 310da14cebeSEric Cheng static void nxge_group_rem_ring(mac_group_driver_t, mac_ring_driver_t, 311da14cebeSEric Cheng mac_ring_type_t); 3124045d941Ssowmini 3136f157acbSml static void nxge_niu_peu_reset(p_nxge_t nxgep); 314d6d3405fSml static void nxge_set_pci_replay_timeout(nxge_t *); 3154045d941Ssowmini 316*0dc2366fSVenugopal Iyer char *nxge_priv_props[] = { 317*0dc2366fSVenugopal Iyer "_adv_10gfdx_cap", 318*0dc2366fSVenugopal Iyer "_adv_pause_cap", 319*0dc2366fSVenugopal Iyer "_function_number", 320*0dc2366fSVenugopal Iyer "_fw_version", 321*0dc2366fSVenugopal Iyer "_port_mode", 322*0dc2366fSVenugopal Iyer "_hot_swap_phy", 323*0dc2366fSVenugopal Iyer "_rxdma_intr_time", 324*0dc2366fSVenugopal Iyer "_rxdma_intr_pkts", 325*0dc2366fSVenugopal Iyer "_class_opt_ipv4_tcp", 326*0dc2366fSVenugopal Iyer "_class_opt_ipv4_udp", 327*0dc2366fSVenugopal Iyer "_class_opt_ipv4_ah", 328*0dc2366fSVenugopal Iyer "_class_opt_ipv4_sctp", 329*0dc2366fSVenugopal Iyer "_class_opt_ipv6_tcp", 330*0dc2366fSVenugopal Iyer "_class_opt_ipv6_udp", 331*0dc2366fSVenugopal Iyer "_class_opt_ipv6_ah", 332*0dc2366fSVenugopal Iyer "_class_opt_ipv6_sctp", 333*0dc2366fSVenugopal Iyer "_soft_lso_enable", 334*0dc2366fSVenugopal Iyer NULL 3354045d941Ssowmini }; 3364045d941Ssowmini 33744961713Sgirish #define NXGE_NEPTUNE_MAGIC 0x4E584745UL 33844961713Sgirish #define MAX_DUMP_SZ 256 33944961713Sgirish 3401bd6825cSml #define NXGE_M_CALLBACK_FLAGS \ 341*0dc2366fSVenugopal Iyer (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO) 34244961713Sgirish 343678453a8Sspeer mac_callbacks_t nxge_m_callbacks = { 34444961713Sgirish NXGE_M_CALLBACK_FLAGS, 34544961713Sgirish nxge_m_stat, 34644961713Sgirish nxge_m_start, 34744961713Sgirish nxge_m_stop, 34844961713Sgirish nxge_m_promisc, 34944961713Sgirish nxge_m_multicst, 350da14cebeSEric Cheng NULL, 351da14cebeSEric Cheng NULL, 352*0dc2366fSVenugopal Iyer NULL, 35344961713Sgirish nxge_m_ioctl, 3541bd6825cSml nxge_m_getcapab, 3551bd6825cSml NULL, 3561bd6825cSml NULL, 3571bd6825cSml nxge_m_setprop, 358*0dc2366fSVenugopal Iyer nxge_m_getprop, 359*0dc2366fSVenugopal Iyer nxge_m_propinfo 36044961713Sgirish }; 36144961713Sgirish 36244961713Sgirish void 36344961713Sgirish nxge_err_inject(p_nxge_t, queue_t *, mblk_t *); 36444961713Sgirish 365ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override. */ 366ec090658Sml #define NXGE_MSIX_REQUEST_10G 8 367ec090658Sml #define NXGE_MSIX_REQUEST_1G 2 368ec090658Sml static int nxge_create_msi_property(p_nxge_t); 369ef755e7aStc /* 370ef755e7aStc * For applications that care about the 371ef755e7aStc * latency, it was requested by PAE and the 372ef755e7aStc * customers that the driver has tunables that 373ef755e7aStc * allow the user to tune it to a higher number 374ef755e7aStc * interrupts to spread the interrupts among 375ef755e7aStc * multiple channels. The DDI framework limits 376ef755e7aStc * the maximum number of MSI-X resources to allocate 377ef755e7aStc * to 8 (ddi_msix_alloc_limit). If more than 8 378ef755e7aStc * is set, ddi_msix_alloc_limit must be set accordingly. 379ef755e7aStc * The default number of MSI interrupts are set to 380ef755e7aStc * 8 for 10G and 2 for 1G link. 381ef755e7aStc */ 382ef755e7aStc #define NXGE_MSIX_MAX_ALLOWED 32 383ef755e7aStc uint32_t nxge_msix_10g_intrs = NXGE_MSIX_REQUEST_10G; 384ef755e7aStc uint32_t nxge_msix_1g_intrs = NXGE_MSIX_REQUEST_1G; 385ec090658Sml 38644961713Sgirish /* 38744961713Sgirish * These global variables control the message 38844961713Sgirish * output. 38944961713Sgirish */ 39044961713Sgirish out_dbgmsg_t nxge_dbgmsg_out = DBG_CONSOLE | STR_LOG; 391678453a8Sspeer uint64_t nxge_debug_level; 39244961713Sgirish 39344961713Sgirish /* 39444961713Sgirish * This list contains the instance structures for the Neptune 39544961713Sgirish * devices present in the system. The lock exists to guarantee 39644961713Sgirish * mutually exclusive access to the list. 39744961713Sgirish */ 39844961713Sgirish void *nxge_list = NULL; 39944961713Sgirish void *nxge_hw_list = NULL; 40044961713Sgirish nxge_os_mutex_t nxge_common_lock; 4013b2d9860SMichael Speer nxge_os_mutex_t nxgedebuglock; 40244961713Sgirish 40344961713Sgirish extern uint64_t npi_debug_level; 40444961713Sgirish 40544961713Sgirish extern nxge_status_t nxge_ldgv_init(p_nxge_t, int *, int *); 40644961713Sgirish extern nxge_status_t nxge_ldgv_init_n2(p_nxge_t, int *, int *); 40744961713Sgirish extern nxge_status_t nxge_ldgv_uninit(p_nxge_t); 40844961713Sgirish extern nxge_status_t nxge_intr_ldgv_init(p_nxge_t); 40944961713Sgirish extern void nxge_fm_init(p_nxge_t, 41044961713Sgirish ddi_device_acc_attr_t *, 41144961713Sgirish ddi_dma_attr_t *); 41244961713Sgirish extern void nxge_fm_fini(p_nxge_t); 41358324dfcSspeer extern npi_status_t npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t); 41444961713Sgirish 41544961713Sgirish /* 41644961713Sgirish * Count used to maintain the number of buffers being used 41744961713Sgirish * by Neptune instances and loaned up to the upper layers. 41844961713Sgirish */ 41944961713Sgirish uint32_t nxge_mblks_pending = 0; 42044961713Sgirish 42144961713Sgirish /* 42244961713Sgirish * Device register access attributes for PIO. 42344961713Sgirish */ 42444961713Sgirish static ddi_device_acc_attr_t nxge_dev_reg_acc_attr = { 425837c1ac4SStephen Hanson DDI_DEVICE_ATTR_V1, 42644961713Sgirish DDI_STRUCTURE_LE_ACC, 42744961713Sgirish DDI_STRICTORDER_ACC, 428837c1ac4SStephen Hanson DDI_DEFAULT_ACC 42944961713Sgirish }; 43044961713Sgirish 43144961713Sgirish /* 43244961713Sgirish * Device descriptor access attributes for DMA. 43344961713Sgirish */ 43444961713Sgirish static ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr = { 43544961713Sgirish DDI_DEVICE_ATTR_V0, 43644961713Sgirish DDI_STRUCTURE_LE_ACC, 43744961713Sgirish DDI_STRICTORDER_ACC 43844961713Sgirish }; 43944961713Sgirish 44044961713Sgirish /* 44144961713Sgirish * Device buffer access attributes for DMA. 44244961713Sgirish */ 44344961713Sgirish static ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr = { 44444961713Sgirish DDI_DEVICE_ATTR_V0, 44544961713Sgirish DDI_STRUCTURE_BE_ACC, 44644961713Sgirish DDI_STRICTORDER_ACC 44744961713Sgirish }; 44844961713Sgirish 44944961713Sgirish ddi_dma_attr_t nxge_desc_dma_attr = { 45044961713Sgirish DMA_ATTR_V0, /* version number. */ 45144961713Sgirish 0, /* low address */ 45244961713Sgirish 0xffffffffffffffff, /* high address */ 45344961713Sgirish 0xffffffffffffffff, /* address counter max */ 45444961713Sgirish #ifndef NIU_PA_WORKAROUND 45544961713Sgirish 0x100000, /* alignment */ 45644961713Sgirish #else 45744961713Sgirish 0x2000, 45844961713Sgirish #endif 45944961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 46044961713Sgirish 0x1, /* minimum transfer size */ 46144961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 46244961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 46344961713Sgirish 1, /* scatter/gather list length */ 46444961713Sgirish (unsigned int) 1, /* granularity */ 46544961713Sgirish 0 /* attribute flags */ 46644961713Sgirish }; 46744961713Sgirish 46844961713Sgirish ddi_dma_attr_t nxge_tx_dma_attr = { 46944961713Sgirish DMA_ATTR_V0, /* version number. */ 47044961713Sgirish 0, /* low address */ 47144961713Sgirish 0xffffffffffffffff, /* high address */ 47244961713Sgirish 0xffffffffffffffff, /* address counter max */ 47344961713Sgirish #if defined(_BIG_ENDIAN) 47444961713Sgirish 0x2000, /* alignment */ 47544961713Sgirish #else 47644961713Sgirish 0x1000, /* alignment */ 47744961713Sgirish #endif 47844961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 47944961713Sgirish 0x1, /* minimum transfer size */ 48044961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 48144961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 48244961713Sgirish 5, /* scatter/gather list length */ 48344961713Sgirish (unsigned int) 1, /* granularity */ 48444961713Sgirish 0 /* attribute flags */ 48544961713Sgirish }; 48644961713Sgirish 48744961713Sgirish ddi_dma_attr_t nxge_rx_dma_attr = { 48844961713Sgirish DMA_ATTR_V0, /* version number. */ 48944961713Sgirish 0, /* low address */ 49044961713Sgirish 0xffffffffffffffff, /* high address */ 49144961713Sgirish 0xffffffffffffffff, /* address counter max */ 49244961713Sgirish 0x2000, /* alignment */ 49344961713Sgirish 0xfc00fc, /* dlim_burstsizes */ 49444961713Sgirish 0x1, /* minimum transfer size */ 49544961713Sgirish 0xffffffffffffffff, /* maximum transfer size */ 49644961713Sgirish 0xffffffffffffffff, /* maximum segment size */ 49744961713Sgirish 1, /* scatter/gather list length */ 49844961713Sgirish (unsigned int) 1, /* granularity */ 4990e2bd521Ssbehera DDI_DMA_RELAXED_ORDERING /* attribute flags */ 50044961713Sgirish }; 50144961713Sgirish 50244961713Sgirish ddi_dma_lim_t nxge_dma_limits = { 50344961713Sgirish (uint_t)0, /* dlim_addr_lo */ 50444961713Sgirish (uint_t)0xffffffff, /* dlim_addr_hi */ 50544961713Sgirish (uint_t)0xffffffff, /* dlim_cntr_max */ 50644961713Sgirish (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */ 50744961713Sgirish 0x1, /* dlim_minxfer */ 50844961713Sgirish 1024 /* dlim_speed */ 50944961713Sgirish }; 51044961713Sgirish 51144961713Sgirish dma_method_t nxge_force_dma = DVMA; 51244961713Sgirish 51344961713Sgirish /* 51444961713Sgirish * dma chunk sizes. 51544961713Sgirish * 51644961713Sgirish * Try to allocate the largest possible size 51744961713Sgirish * so that fewer number of dma chunks would be managed 51844961713Sgirish */ 51944961713Sgirish #ifdef NIU_PA_WORKAROUND 52044961713Sgirish size_t alloc_sizes [] = {0x2000}; 52144961713Sgirish #else 52244961713Sgirish size_t alloc_sizes [] = {0x1000, 0x2000, 0x4000, 0x8000, 52344961713Sgirish 0x10000, 0x20000, 0x40000, 0x80000, 52430ac2e7bSml 0x100000, 0x200000, 0x400000, 0x800000, 52530ac2e7bSml 0x1000000, 0x2000000, 0x4000000}; 52644961713Sgirish #endif 52744961713Sgirish 52844961713Sgirish /* 52944961713Sgirish * Translate "dev_t" to a pointer to the associated "dev_info_t". 53044961713Sgirish */ 53144961713Sgirish 532678453a8Sspeer extern void nxge_get_environs(nxge_t *); 533678453a8Sspeer 53444961713Sgirish static int 53544961713Sgirish nxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 53644961713Sgirish { 53744961713Sgirish p_nxge_t nxgep = NULL; 53844961713Sgirish int instance; 53944961713Sgirish int status = DDI_SUCCESS; 54044961713Sgirish uint8_t portn; 54158324dfcSspeer nxge_mmac_t *mmac_info; 54244961713Sgirish 54344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_attach")); 54444961713Sgirish 54544961713Sgirish /* 54644961713Sgirish * Get the device instance since we'll need to setup 54744961713Sgirish * or retrieve a soft state for this instance. 54844961713Sgirish */ 54944961713Sgirish instance = ddi_get_instance(dip); 55044961713Sgirish 55144961713Sgirish switch (cmd) { 55244961713Sgirish case DDI_ATTACH: 55344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_ATTACH")); 55444961713Sgirish break; 55544961713Sgirish 55644961713Sgirish case DDI_RESUME: 55744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_RESUME")); 55844961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 55944961713Sgirish if (nxgep == NULL) { 56044961713Sgirish status = DDI_FAILURE; 56144961713Sgirish break; 56244961713Sgirish } 56344961713Sgirish if (nxgep->dip != dip) { 56444961713Sgirish status = DDI_FAILURE; 56544961713Sgirish break; 56644961713Sgirish } 56744961713Sgirish if (nxgep->suspended == DDI_PM_SUSPEND) { 56844961713Sgirish status = ddi_dev_is_needed(nxgep->dip, 0, 1); 56944961713Sgirish } else { 57056d930aeSspeer status = nxge_resume(nxgep); 57144961713Sgirish } 57244961713Sgirish goto nxge_attach_exit; 57344961713Sgirish 57444961713Sgirish case DDI_PM_RESUME: 57544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_RESUME")); 57644961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 57744961713Sgirish if (nxgep == NULL) { 57844961713Sgirish status = DDI_FAILURE; 57944961713Sgirish break; 58044961713Sgirish } 58144961713Sgirish if (nxgep->dip != dip) { 58244961713Sgirish status = DDI_FAILURE; 58344961713Sgirish break; 58444961713Sgirish } 58556d930aeSspeer status = nxge_resume(nxgep); 58644961713Sgirish goto nxge_attach_exit; 58744961713Sgirish 58844961713Sgirish default: 58944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing unknown")); 59044961713Sgirish status = DDI_FAILURE; 59144961713Sgirish goto nxge_attach_exit; 59244961713Sgirish } 59344961713Sgirish 59444961713Sgirish 59544961713Sgirish if (ddi_soft_state_zalloc(nxge_list, instance) == DDI_FAILURE) { 59644961713Sgirish status = DDI_FAILURE; 59744961713Sgirish goto nxge_attach_exit; 59844961713Sgirish } 59944961713Sgirish 60044961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance); 60144961713Sgirish if (nxgep == NULL) { 6022e59129aSraghus status = NXGE_ERROR; 6032e59129aSraghus goto nxge_attach_fail2; 60444961713Sgirish } 60544961713Sgirish 60698ecde52Stm nxgep->nxge_magic = NXGE_MAGIC; 60798ecde52Stm 60844961713Sgirish nxgep->drv_state = 0; 60944961713Sgirish nxgep->dip = dip; 61044961713Sgirish nxgep->instance = instance; 61144961713Sgirish nxgep->p_dip = ddi_get_parent(dip); 61244961713Sgirish nxgep->nxge_debug_level = nxge_debug_level; 61344961713Sgirish npi_debug_level = nxge_debug_level; 61444961713Sgirish 615678453a8Sspeer /* Are we a guest running in a Hybrid I/O environment? */ 616678453a8Sspeer nxge_get_environs(nxgep); 61744961713Sgirish 61844961713Sgirish status = nxge_map_regs(nxgep); 619678453a8Sspeer 62044961713Sgirish if (status != NXGE_OK) { 62144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_map_regs failed")); 6222e59129aSraghus goto nxge_attach_fail3; 62344961713Sgirish } 62444961713Sgirish 625837c1ac4SStephen Hanson nxge_fm_init(nxgep, &nxge_dev_reg_acc_attr, &nxge_rx_dma_attr); 626678453a8Sspeer 627678453a8Sspeer /* Create & initialize the per-Neptune data structure */ 628678453a8Sspeer /* (even if we're a guest). */ 62944961713Sgirish status = nxge_init_common_dev(nxgep); 63044961713Sgirish if (status != NXGE_OK) { 63144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6324045d941Ssowmini "nxge_init_common_dev failed")); 6332e59129aSraghus goto nxge_attach_fail4; 63444961713Sgirish } 63544961713Sgirish 636d6d3405fSml /* 637d6d3405fSml * Software workaround: set the replay timer. 638d6d3405fSml */ 639d6d3405fSml if (nxgep->niu_type != N2_NIU) { 640d6d3405fSml nxge_set_pci_replay_timeout(nxgep); 641d6d3405fSml } 642d6d3405fSml 643678453a8Sspeer #if defined(sun4v) 644678453a8Sspeer /* This is required by nxge_hio_init(), which follows. */ 645678453a8Sspeer if ((status = nxge_hsvc_register(nxgep)) != DDI_SUCCESS) 6469d5b8bc5SMichael Speer goto nxge_attach_fail4; 647678453a8Sspeer #endif 648678453a8Sspeer 649678453a8Sspeer if ((status = nxge_hio_init(nxgep)) != NXGE_OK) { 650678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6514045d941Ssowmini "nxge_hio_init failed")); 652678453a8Sspeer goto nxge_attach_fail4; 653678453a8Sspeer } 654678453a8Sspeer 65559ac0c16Sdavemq if (nxgep->niu_type == NEPTUNE_2_10GF) { 65659ac0c16Sdavemq if (nxgep->function_num > 1) { 6574202ea4bSsbehera NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Unsupported" 65859ac0c16Sdavemq " function %d. Only functions 0 and 1 are " 65959ac0c16Sdavemq "supported for this card.", nxgep->function_num)); 66059ac0c16Sdavemq status = NXGE_ERROR; 6612e59129aSraghus goto nxge_attach_fail4; 66259ac0c16Sdavemq } 66359ac0c16Sdavemq } 66459ac0c16Sdavemq 665678453a8Sspeer if (isLDOMguest(nxgep)) { 666678453a8Sspeer /* 667678453a8Sspeer * Use the function number here. 668678453a8Sspeer */ 669678453a8Sspeer nxgep->mac.portnum = nxgep->function_num; 670678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_LOGICAL; 671678453a8Sspeer 672678453a8Sspeer /* XXX We'll set the MAC address counts to 1 for now. */ 673678453a8Sspeer mmac_info = &nxgep->nxge_mmac_info; 674678453a8Sspeer mmac_info->num_mmac = 1; 675678453a8Sspeer mmac_info->naddrfree = 1; 67658324dfcSspeer } else { 677678453a8Sspeer portn = NXGE_GET_PORT_NUM(nxgep->function_num); 678678453a8Sspeer nxgep->mac.portnum = portn; 679678453a8Sspeer if ((portn == 0) || (portn == 1)) 680678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_XMAC; 681678453a8Sspeer else 682678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_BMAC; 683678453a8Sspeer /* 684678453a8Sspeer * Neptune has 4 ports, the first 2 ports use XMAC (10G MAC) 685678453a8Sspeer * internally, the rest 2 ports use BMAC (1G "Big" MAC). 686678453a8Sspeer * The two types of MACs have different characterizations. 687678453a8Sspeer */ 688678453a8Sspeer mmac_info = &nxgep->nxge_mmac_info; 689678453a8Sspeer if (nxgep->function_num < 2) { 690678453a8Sspeer mmac_info->num_mmac = XMAC_MAX_ALT_ADDR_ENTRY; 691678453a8Sspeer mmac_info->naddrfree = XMAC_MAX_ALT_ADDR_ENTRY; 692678453a8Sspeer } else { 693678453a8Sspeer mmac_info->num_mmac = BMAC_MAX_ALT_ADDR_ENTRY; 694678453a8Sspeer mmac_info->naddrfree = BMAC_MAX_ALT_ADDR_ENTRY; 695678453a8Sspeer } 69658324dfcSspeer } 69744961713Sgirish /* 69844961713Sgirish * Setup the Ndd parameters for the this instance. 69944961713Sgirish */ 70044961713Sgirish nxge_init_param(nxgep); 70144961713Sgirish 70244961713Sgirish /* 70344961713Sgirish * Setup Register Tracing Buffer. 70444961713Sgirish */ 70544961713Sgirish npi_rtrace_buf_init((rtrace_t *)&npi_rtracebuf); 70644961713Sgirish 70744961713Sgirish /* init stats ptr */ 70844961713Sgirish nxge_init_statsp(nxgep); 70956d930aeSspeer 7102e59129aSraghus /* 711678453a8Sspeer * Copy the vpd info from eeprom to a local data 712678453a8Sspeer * structure, and then check its validity. 7132e59129aSraghus */ 714678453a8Sspeer if (!isLDOMguest(nxgep)) { 715678453a8Sspeer int *regp; 716678453a8Sspeer uint_t reglen; 717678453a8Sspeer int rv; 71856d930aeSspeer 719678453a8Sspeer nxge_vpd_info_get(nxgep); 72044961713Sgirish 721678453a8Sspeer /* Find the NIU config handle. */ 722678453a8Sspeer rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, 723678453a8Sspeer ddi_get_parent(nxgep->dip), DDI_PROP_DONTPASS, 724678453a8Sspeer "reg", ®p, ®len); 725678453a8Sspeer 726678453a8Sspeer if (rv != DDI_PROP_SUCCESS) { 727678453a8Sspeer goto nxge_attach_fail5; 728678453a8Sspeer } 729678453a8Sspeer /* 730678453a8Sspeer * The address_hi, that is the first int, in the reg 731678453a8Sspeer * property consists of config handle, but need to remove 732678453a8Sspeer * the bits 28-31 which are OBP specific info. 733678453a8Sspeer */ 734678453a8Sspeer nxgep->niu_cfg_hdl = (*regp) & 0xFFFFFFF; 735678453a8Sspeer ddi_prop_free(regp); 73644961713Sgirish } 73744961713Sgirish 73848056c53SMichael Speer /* 73948056c53SMichael Speer * Set the defaults for the MTU size. 74048056c53SMichael Speer */ 74148056c53SMichael Speer nxge_hw_id_init(nxgep); 74248056c53SMichael Speer 743678453a8Sspeer if (isLDOMguest(nxgep)) { 744678453a8Sspeer uchar_t *prop_val; 745678453a8Sspeer uint_t prop_len; 7467b1f684aSSriharsha Basavapatna uint32_t max_frame_size; 74744961713Sgirish 748678453a8Sspeer extern void nxge_get_logical_props(p_nxge_t); 749678453a8Sspeer 750678453a8Sspeer nxgep->statsp->mac_stats.xcvr_inuse = LOGICAL_XCVR; 751678453a8Sspeer nxgep->mac.portmode = PORT_LOGICAL; 752678453a8Sspeer (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 753678453a8Sspeer "phy-type", "virtual transceiver"); 754678453a8Sspeer 755678453a8Sspeer nxgep->nports = 1; 756678453a8Sspeer nxgep->board_ver = 0; /* XXX What? */ 757678453a8Sspeer 758678453a8Sspeer /* 759678453a8Sspeer * local-mac-address property gives us info on which 760678453a8Sspeer * specific MAC address the Hybrid resource is associated 761678453a8Sspeer * with. 762678453a8Sspeer */ 763678453a8Sspeer if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0, 764678453a8Sspeer "local-mac-address", &prop_val, 765678453a8Sspeer &prop_len) != DDI_PROP_SUCCESS) { 766678453a8Sspeer goto nxge_attach_fail5; 767678453a8Sspeer } 768678453a8Sspeer if (prop_len != ETHERADDRL) { 769678453a8Sspeer ddi_prop_free(prop_val); 770678453a8Sspeer goto nxge_attach_fail5; 771678453a8Sspeer } 772678453a8Sspeer ether_copy(prop_val, nxgep->hio_mac_addr); 773678453a8Sspeer ddi_prop_free(prop_val); 774678453a8Sspeer nxge_get_logical_props(nxgep); 775678453a8Sspeer 7767b1f684aSSriharsha Basavapatna /* 7777b1f684aSSriharsha Basavapatna * Enable Jumbo property based on the "max-frame-size" 7787b1f684aSSriharsha Basavapatna * property value. 7797b1f684aSSriharsha Basavapatna */ 7807b1f684aSSriharsha Basavapatna max_frame_size = ddi_prop_get_int(DDI_DEV_T_ANY, 7817b1f684aSSriharsha Basavapatna nxgep->dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 7827b1f684aSSriharsha Basavapatna "max-frame-size", NXGE_MTU_DEFAULT_MAX); 7837b1f684aSSriharsha Basavapatna if ((max_frame_size > NXGE_MTU_DEFAULT_MAX) && 7847b1f684aSSriharsha Basavapatna (max_frame_size <= TX_JUMBO_MTU)) { 7857b1f684aSSriharsha Basavapatna nxgep->mac.is_jumbo = B_TRUE; 7867b1f684aSSriharsha Basavapatna nxgep->mac.maxframesize = (uint16_t)max_frame_size; 7877b1f684aSSriharsha Basavapatna nxgep->mac.default_mtu = nxgep->mac.maxframesize - 7887b1f684aSSriharsha Basavapatna NXGE_EHEADER_VLAN_CRC; 7897b1f684aSSriharsha Basavapatna } 790678453a8Sspeer } else { 791678453a8Sspeer status = nxge_xcvr_find(nxgep); 792678453a8Sspeer 793678453a8Sspeer if (status != NXGE_OK) { 794678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_attach: " 7954045d941Ssowmini " Couldn't determine card type" 7964045d941Ssowmini " .... exit ")); 797678453a8Sspeer goto nxge_attach_fail5; 798678453a8Sspeer } 799678453a8Sspeer 800678453a8Sspeer status = nxge_get_config_properties(nxgep); 801678453a8Sspeer 802678453a8Sspeer if (status != NXGE_OK) { 803678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8044045d941Ssowmini "get_hw create failed")); 805678453a8Sspeer goto nxge_attach_fail; 806678453a8Sspeer } 80744961713Sgirish } 80844961713Sgirish 80944961713Sgirish /* 81044961713Sgirish * Setup the Kstats for the driver. 81144961713Sgirish */ 81244961713Sgirish nxge_setup_kstats(nxgep); 81344961713Sgirish 814678453a8Sspeer if (!isLDOMguest(nxgep)) 815678453a8Sspeer nxge_setup_param(nxgep); 81644961713Sgirish 81744961713Sgirish status = nxge_setup_system_dma_pages(nxgep); 81844961713Sgirish if (status != NXGE_OK) { 81944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "set dma page failed")); 82044961713Sgirish goto nxge_attach_fail; 82144961713Sgirish } 82244961713Sgirish 823678453a8Sspeer 824678453a8Sspeer if (!isLDOMguest(nxgep)) 825678453a8Sspeer nxge_hw_init_niu_common(nxgep); 82644961713Sgirish 82744961713Sgirish status = nxge_setup_mutexes(nxgep); 82844961713Sgirish if (status != NXGE_OK) { 82944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set mutex failed")); 83044961713Sgirish goto nxge_attach_fail; 83144961713Sgirish } 83244961713Sgirish 833678453a8Sspeer #if defined(sun4v) 834678453a8Sspeer if (isLDOMguest(nxgep)) { 835678453a8Sspeer /* Find our VR & channel sets. */ 836678453a8Sspeer status = nxge_hio_vr_add(nxgep); 837ef523517SMichael Speer if (status != DDI_SUCCESS) { 838ef523517SMichael Speer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 839330cd344SMichael Speer "nxge_hio_vr_add failed")); 840330cd344SMichael Speer (void) hsvc_unregister(&nxgep->niu_hsvc); 841330cd344SMichael Speer nxgep->niu_hsvc_available = B_FALSE; 842ef523517SMichael Speer goto nxge_attach_fail; 843330cd344SMichael Speer } 844678453a8Sspeer goto nxge_attach_exit; 845678453a8Sspeer } 846678453a8Sspeer #endif 847678453a8Sspeer 84844961713Sgirish status = nxge_setup_dev(nxgep); 84944961713Sgirish if (status != DDI_SUCCESS) { 85044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set dev failed")); 85144961713Sgirish goto nxge_attach_fail; 85244961713Sgirish } 85344961713Sgirish 85444961713Sgirish status = nxge_add_intrs(nxgep); 85544961713Sgirish if (status != DDI_SUCCESS) { 85644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "add_intr failed")); 85744961713Sgirish goto nxge_attach_fail; 85844961713Sgirish } 859330cd344SMichael Speer 86000161856Syc /* If a guest, register with vio_net instead. */ 8612e59129aSraghus if ((status = nxge_mac_register(nxgep)) != NXGE_OK) { 86244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 863678453a8Sspeer "unable to register to mac layer (%d)", status)); 86444961713Sgirish goto nxge_attach_fail; 86544961713Sgirish } 86644961713Sgirish 86744961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_UNKNOWN); 86844961713Sgirish 869678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DDI_CTL, 870678453a8Sspeer "registered to mac (instance %d)", instance)); 87144961713Sgirish 87200161856Syc /* nxge_link_monitor calls xcvr.check_link recursively */ 87344961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 87444961713Sgirish 87544961713Sgirish goto nxge_attach_exit; 87644961713Sgirish 87744961713Sgirish nxge_attach_fail: 87844961713Sgirish nxge_unattach(nxgep); 8792e59129aSraghus goto nxge_attach_fail1; 8802e59129aSraghus 8812e59129aSraghus nxge_attach_fail5: 8822e59129aSraghus /* 8832e59129aSraghus * Tear down the ndd parameters setup. 8842e59129aSraghus */ 8852e59129aSraghus nxge_destroy_param(nxgep); 8862e59129aSraghus 8872e59129aSraghus /* 8882e59129aSraghus * Tear down the kstat setup. 8892e59129aSraghus */ 8902e59129aSraghus nxge_destroy_kstats(nxgep); 8912e59129aSraghus 8922e59129aSraghus nxge_attach_fail4: 8932e59129aSraghus if (nxgep->nxge_hw_p) { 8942e59129aSraghus nxge_uninit_common_dev(nxgep); 8952e59129aSraghus nxgep->nxge_hw_p = NULL; 8962e59129aSraghus } 8972e59129aSraghus 8982e59129aSraghus nxge_attach_fail3: 8992e59129aSraghus /* 9002e59129aSraghus * Unmap the register setup. 9012e59129aSraghus */ 9022e59129aSraghus nxge_unmap_regs(nxgep); 9032e59129aSraghus 9042e59129aSraghus nxge_fm_fini(nxgep); 9052e59129aSraghus 9062e59129aSraghus nxge_attach_fail2: 9072e59129aSraghus ddi_soft_state_free(nxge_list, nxgep->instance); 9082e59129aSraghus 9092e59129aSraghus nxge_attach_fail1: 91056d930aeSspeer if (status != NXGE_OK) 91156d930aeSspeer status = (NXGE_ERROR | NXGE_DDI_FAILED); 91244961713Sgirish nxgep = NULL; 91344961713Sgirish 91444961713Sgirish nxge_attach_exit: 91544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_attach status = 0x%08x", 9164045d941Ssowmini status)); 91744961713Sgirish 91844961713Sgirish return (status); 91944961713Sgirish } 92044961713Sgirish 92144961713Sgirish static int 92244961713Sgirish nxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 92344961713Sgirish { 92444961713Sgirish int status = DDI_SUCCESS; 92544961713Sgirish int instance; 92644961713Sgirish p_nxge_t nxgep = NULL; 92744961713Sgirish 92844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_detach")); 92944961713Sgirish instance = ddi_get_instance(dip); 93044961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance); 93144961713Sgirish if (nxgep == NULL) { 93244961713Sgirish status = DDI_FAILURE; 93344961713Sgirish goto nxge_detach_exit; 93444961713Sgirish } 93544961713Sgirish 93644961713Sgirish switch (cmd) { 93744961713Sgirish case DDI_DETACH: 93844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_DETACH")); 93944961713Sgirish break; 94044961713Sgirish 94144961713Sgirish case DDI_PM_SUSPEND: 94244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_SUSPEND")); 94344961713Sgirish nxgep->suspended = DDI_PM_SUSPEND; 94444961713Sgirish nxge_suspend(nxgep); 94544961713Sgirish break; 94644961713Sgirish 94744961713Sgirish case DDI_SUSPEND: 94844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_SUSPEND")); 94944961713Sgirish if (nxgep->suspended != DDI_PM_SUSPEND) { 95044961713Sgirish nxgep->suspended = DDI_SUSPEND; 95144961713Sgirish nxge_suspend(nxgep); 95244961713Sgirish } 95344961713Sgirish break; 95444961713Sgirish 95544961713Sgirish default: 95644961713Sgirish status = DDI_FAILURE; 95744961713Sgirish } 95844961713Sgirish 95944961713Sgirish if (cmd != DDI_DETACH) 96044961713Sgirish goto nxge_detach_exit; 96144961713Sgirish 96244961713Sgirish /* 96344961713Sgirish * Stop the xcvr polling. 96444961713Sgirish */ 96544961713Sgirish nxgep->suspended = cmd; 96644961713Sgirish 96744961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 96844961713Sgirish 96963f531d1SSriharsha Basavapatna if (nxgep->mach && (status = mac_unregister(nxgep->mach)) != 0) { 97044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 9714045d941Ssowmini "<== nxge_detach status = 0x%08X", status)); 97244961713Sgirish return (DDI_FAILURE); 97344961713Sgirish } 97444961713Sgirish 97544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 9764045d941Ssowmini "<== nxge_detach (mac_unregister) status = 0x%08X", status)); 97744961713Sgirish 97844961713Sgirish nxge_unattach(nxgep); 97944961713Sgirish nxgep = NULL; 98044961713Sgirish 98144961713Sgirish nxge_detach_exit: 98244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_detach status = 0x%08X", 9834045d941Ssowmini status)); 98444961713Sgirish 98544961713Sgirish return (status); 98644961713Sgirish } 98744961713Sgirish 98844961713Sgirish static void 98944961713Sgirish nxge_unattach(p_nxge_t nxgep) 99044961713Sgirish { 99144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unattach")); 99244961713Sgirish 99344961713Sgirish if (nxgep == NULL || nxgep->dev_regs == NULL) { 99444961713Sgirish return; 99544961713Sgirish } 99644961713Sgirish 99798ecde52Stm nxgep->nxge_magic = 0; 99898ecde52Stm 99944961713Sgirish if (nxgep->nxge_timerid) { 100044961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 100144961713Sgirish nxgep->nxge_timerid = 0; 100244961713Sgirish } 100344961713Sgirish 10046f157acbSml /* 10056f157acbSml * If this flag is set, it will affect the Neptune 10066f157acbSml * only. 10076f157acbSml */ 10086f157acbSml if ((nxgep->niu_type != N2_NIU) && nxge_peu_reset_enable) { 10096f157acbSml nxge_niu_peu_reset(nxgep); 10106f157acbSml } 10116f157acbSml 1012678453a8Sspeer #if defined(sun4v) 1013678453a8Sspeer if (isLDOMguest(nxgep)) { 1014d00f30bbSspeer (void) nxge_hio_vr_release(nxgep); 1015678453a8Sspeer } 1016678453a8Sspeer #endif 1017678453a8Sspeer 101853560810Ssbehera if (nxgep->nxge_hw_p) { 101953560810Ssbehera nxge_uninit_common_dev(nxgep); 102053560810Ssbehera nxgep->nxge_hw_p = NULL; 102153560810Ssbehera } 102253560810Ssbehera 102344961713Sgirish #if defined(sun4v) 102444961713Sgirish if (nxgep->niu_type == N2_NIU && nxgep->niu_hsvc_available == B_TRUE) { 102544961713Sgirish (void) hsvc_unregister(&nxgep->niu_hsvc); 102644961713Sgirish nxgep->niu_hsvc_available = B_FALSE; 102744961713Sgirish } 102844961713Sgirish #endif 102944961713Sgirish /* 103044961713Sgirish * Stop any further interrupts. 103144961713Sgirish */ 103244961713Sgirish nxge_remove_intrs(nxgep); 103344961713Sgirish 103444961713Sgirish /* 103544961713Sgirish * Stop the device and free resources. 103644961713Sgirish */ 1037678453a8Sspeer if (!isLDOMguest(nxgep)) { 1038678453a8Sspeer nxge_destroy_dev(nxgep); 1039678453a8Sspeer } 104044961713Sgirish 104144961713Sgirish /* 104244961713Sgirish * Tear down the ndd parameters setup. 104344961713Sgirish */ 104444961713Sgirish nxge_destroy_param(nxgep); 104544961713Sgirish 104644961713Sgirish /* 104744961713Sgirish * Tear down the kstat setup. 104844961713Sgirish */ 104944961713Sgirish nxge_destroy_kstats(nxgep); 105044961713Sgirish 105144961713Sgirish /* 105244961713Sgirish * Destroy all mutexes. 105344961713Sgirish */ 105444961713Sgirish nxge_destroy_mutexes(nxgep); 105544961713Sgirish 105644961713Sgirish /* 105744961713Sgirish * Remove the list of ndd parameters which 105844961713Sgirish * were setup during attach. 105944961713Sgirish */ 106044961713Sgirish if (nxgep->dip) { 106144961713Sgirish NXGE_DEBUG_MSG((nxgep, OBP_CTL, 10624045d941Ssowmini " nxge_unattach: remove all properties")); 106344961713Sgirish 106444961713Sgirish (void) ddi_prop_remove_all(nxgep->dip); 106544961713Sgirish } 106644961713Sgirish 106744961713Sgirish #if NXGE_PROPERTY 106844961713Sgirish nxge_remove_hard_properties(nxgep); 106944961713Sgirish #endif 107044961713Sgirish 107144961713Sgirish /* 107244961713Sgirish * Unmap the register setup. 107344961713Sgirish */ 107444961713Sgirish nxge_unmap_regs(nxgep); 107544961713Sgirish 107644961713Sgirish nxge_fm_fini(nxgep); 107744961713Sgirish 107844961713Sgirish ddi_soft_state_free(nxge_list, nxgep->instance); 107944961713Sgirish 108044961713Sgirish NXGE_DEBUG_MSG((NULL, DDI_CTL, "<== nxge_unattach")); 108144961713Sgirish } 108244961713Sgirish 1083678453a8Sspeer #if defined(sun4v) 1084678453a8Sspeer int 10859d5b8bc5SMichael Speer nxge_hsvc_register(nxge_t *nxgep) 1086678453a8Sspeer { 1087678453a8Sspeer nxge_status_t status; 10884df55fdeSJanie Lu int i, j; 1089678453a8Sspeer 10904df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hsvc_register")); 10914df55fdeSJanie Lu if (nxgep->niu_type != N2_NIU) { 10924df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hsvc_register")); 10934df55fdeSJanie Lu return (DDI_SUCCESS); 1094678453a8Sspeer } 1095678453a8Sspeer 10964df55fdeSJanie Lu /* 10974df55fdeSJanie Lu * Currently, the NIU Hypervisor API supports two major versions: 10984df55fdeSJanie Lu * version 1 and 2. 10994df55fdeSJanie Lu * If Hypervisor introduces a higher major or minor version, 11004df55fdeSJanie Lu * please update NIU_MAJOR_HI and NIU_MINOR_HI accordingly. 11014df55fdeSJanie Lu */ 11024df55fdeSJanie Lu nxgep->niu_hsvc_available = B_FALSE; 11034df55fdeSJanie Lu bcopy(&niu_hsvc, &nxgep->niu_hsvc, 11044df55fdeSJanie Lu sizeof (hsvc_info_t)); 11054df55fdeSJanie Lu 11064df55fdeSJanie Lu for (i = NIU_MAJOR_HI; i > 0; i--) { 11074df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_major = i; 11084df55fdeSJanie Lu for (j = NIU_MINOR_HI; j >= 0; j--) { 11094df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_minor = j; 11104df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11114df55fdeSJanie Lu "nxge_hsvc_register: %s: negotiating " 11124df55fdeSJanie Lu "hypervisor services revision %d " 11134df55fdeSJanie Lu "group: 0x%lx major: 0x%lx " 11144df55fdeSJanie Lu "minor: 0x%lx", 11154df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_modname, 11164df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_rev, 11174df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_group, 11184df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_major, 11194df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_minor, 11204df55fdeSJanie Lu nxgep->niu_min_ver)); 11214df55fdeSJanie Lu 11224df55fdeSJanie Lu if ((status = hsvc_register(&nxgep->niu_hsvc, 11234df55fdeSJanie Lu &nxgep->niu_min_ver)) == 0) { 11244df55fdeSJanie Lu /* Use the supported minor */ 11254df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_minor = nxgep->niu_min_ver; 11264df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11274df55fdeSJanie Lu "nxge_hsvc_register: %s: negotiated " 11284df55fdeSJanie Lu "hypervisor services revision %d " 11294df55fdeSJanie Lu "group: 0x%lx major: 0x%lx " 11304df55fdeSJanie Lu "minor: 0x%lx (niu_min_ver 0x%lx)", 11314df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_modname, 11324df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_rev, 11334df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_group, 11344df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_major, 11354df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_minor, 11364df55fdeSJanie Lu nxgep->niu_min_ver)); 11374df55fdeSJanie Lu 11384df55fdeSJanie Lu nxgep->niu_hsvc_available = B_TRUE; 11394df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11404df55fdeSJanie Lu "<== nxge_hsvc_register: " 11414df55fdeSJanie Lu "NIU Hypervisor service enabled")); 11424df55fdeSJanie Lu return (DDI_SUCCESS); 11434df55fdeSJanie Lu } 11444df55fdeSJanie Lu 11454df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11464df55fdeSJanie Lu "nxge_hsvc_register: %s: negotiated failed - " 11474df55fdeSJanie Lu "try lower major number " 11484df55fdeSJanie Lu "hypervisor services revision %d " 11494df55fdeSJanie Lu "group: 0x%lx major: 0x%lx minor: 0x%lx " 11504df55fdeSJanie Lu "errno: %d", 11514df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_modname, 11524df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_rev, 11534df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_group, 11544df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_major, 11554df55fdeSJanie Lu nxgep->niu_hsvc.hsvc_minor, status)); 11564df55fdeSJanie Lu } 11574df55fdeSJanie Lu } 11584df55fdeSJanie Lu 11594df55fdeSJanie Lu NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 11604df55fdeSJanie Lu "nxge_hsvc_register: %s: cannot negotiate " 11614df55fdeSJanie Lu "hypervisor services revision %d group: 0x%lx " 11624df55fdeSJanie Lu "major: 0x%lx minor: 0x%lx errno: %d", 11634df55fdeSJanie Lu niu_hsvc.hsvc_modname, niu_hsvc.hsvc_rev, 11644df55fdeSJanie Lu niu_hsvc.hsvc_group, niu_hsvc.hsvc_major, 11654df55fdeSJanie Lu niu_hsvc.hsvc_minor, status)); 11664df55fdeSJanie Lu 11674df55fdeSJanie Lu NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11684df55fdeSJanie Lu "<== nxge_hsvc_register: Register to NIU Hypervisor failed")); 11694df55fdeSJanie Lu 11704df55fdeSJanie Lu return (DDI_FAILURE); 1171678453a8Sspeer } 1172678453a8Sspeer #endif 1173678453a8Sspeer 117444961713Sgirish static char n2_siu_name[] = "niu"; 117544961713Sgirish 117644961713Sgirish static nxge_status_t 117744961713Sgirish nxge_map_regs(p_nxge_t nxgep) 117844961713Sgirish { 117944961713Sgirish int ddi_status = DDI_SUCCESS; 118044961713Sgirish p_dev_regs_t dev_regs; 118144961713Sgirish char buf[MAXPATHLEN + 1]; 118244961713Sgirish char *devname; 118344961713Sgirish #ifdef NXGE_DEBUG 118444961713Sgirish char *sysname; 118544961713Sgirish #endif 118644961713Sgirish off_t regsize; 118744961713Sgirish nxge_status_t status = NXGE_OK; 118814ea4bb7Ssd #if !defined(_BIG_ENDIAN) 118914ea4bb7Ssd off_t pci_offset; 119014ea4bb7Ssd uint16_t pcie_devctl; 119114ea4bb7Ssd #endif 119244961713Sgirish 1193678453a8Sspeer if (isLDOMguest(nxgep)) { 1194678453a8Sspeer return (nxge_guest_regs_map(nxgep)); 1195678453a8Sspeer } 1196678453a8Sspeer 119744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_map_regs")); 119844961713Sgirish nxgep->dev_regs = NULL; 119944961713Sgirish dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP); 120044961713Sgirish dev_regs->nxge_regh = NULL; 120144961713Sgirish dev_regs->nxge_pciregh = NULL; 120244961713Sgirish dev_regs->nxge_msix_regh = NULL; 120344961713Sgirish dev_regs->nxge_vir_regh = NULL; 120444961713Sgirish dev_regs->nxge_vir2_regh = NULL; 120559ac0c16Sdavemq nxgep->niu_type = NIU_TYPE_NONE; 120644961713Sgirish 120744961713Sgirish devname = ddi_pathname(nxgep->dip, buf); 120844961713Sgirish ASSERT(strlen(devname) > 0); 120944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12104045d941Ssowmini "nxge_map_regs: pathname devname %s", devname)); 121144961713Sgirish 121200161856Syc /* 121300161856Syc * The driver is running on a N2-NIU system if devname is something 121400161856Syc * like "/niu@80/network@0" 121500161856Syc */ 121644961713Sgirish if (strstr(devname, n2_siu_name)) { 121744961713Sgirish /* N2/NIU */ 121844961713Sgirish nxgep->niu_type = N2_NIU; 121944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12204045d941Ssowmini "nxge_map_regs: N2/NIU devname %s", devname)); 12214df55fdeSJanie Lu /* 12224df55fdeSJanie Lu * Get function number: 12234df55fdeSJanie Lu * - N2/NIU: "/niu@80/network@0" and "/niu@80/network@1" 12244df55fdeSJanie Lu */ 122544961713Sgirish nxgep->function_num = 12264045d941Ssowmini (devname[strlen(devname) -1] == '1' ? 1 : 0); 122744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12284045d941Ssowmini "nxge_map_regs: N2/NIU function number %d", 12294045d941Ssowmini nxgep->function_num)); 123044961713Sgirish } else { 123144961713Sgirish int *prop_val; 123244961713Sgirish uint_t prop_len; 123344961713Sgirish uint8_t func_num; 123444961713Sgirish 123544961713Sgirish if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 12364045d941Ssowmini 0, "reg", 12374045d941Ssowmini &prop_val, &prop_len) != DDI_PROP_SUCCESS) { 123844961713Sgirish NXGE_DEBUG_MSG((nxgep, VPD_CTL, 12394045d941Ssowmini "Reg property not found")); 124044961713Sgirish ddi_status = DDI_FAILURE; 124144961713Sgirish goto nxge_map_regs_fail0; 124244961713Sgirish 124344961713Sgirish } else { 124444961713Sgirish func_num = (prop_val[0] >> 8) & 0x7; 124544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12464045d941Ssowmini "Reg property found: fun # %d", 12474045d941Ssowmini func_num)); 124844961713Sgirish nxgep->function_num = func_num; 1249678453a8Sspeer if (isLDOMguest(nxgep)) { 1250678453a8Sspeer nxgep->function_num /= 2; 1251678453a8Sspeer return (NXGE_OK); 1252678453a8Sspeer } 125344961713Sgirish ddi_prop_free(prop_val); 125444961713Sgirish } 125544961713Sgirish } 125644961713Sgirish 125744961713Sgirish switch (nxgep->niu_type) { 125844961713Sgirish default: 125944961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 0, ®size); 126044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12614045d941Ssowmini "nxge_map_regs: pci config size 0x%x", regsize)); 126244961713Sgirish 126344961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 0, 12644045d941Ssowmini (caddr_t *)&(dev_regs->nxge_pciregp), 0, 0, 12654045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_pciregh); 126644961713Sgirish if (ddi_status != DDI_SUCCESS) { 126744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12684045d941Ssowmini "ddi_map_regs, nxge bus config regs failed")); 126944961713Sgirish goto nxge_map_regs_fail0; 127044961713Sgirish } 127144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12724045d941Ssowmini "nxge_map_reg: PCI config addr 0x%0llx " 12734045d941Ssowmini " handle 0x%0llx", dev_regs->nxge_pciregp, 12744045d941Ssowmini dev_regs->nxge_pciregh)); 127544961713Sgirish /* 127644961713Sgirish * IMP IMP 127744961713Sgirish * workaround for bit swapping bug in HW 127844961713Sgirish * which ends up in no-snoop = yes 127944961713Sgirish * resulting, in DMA not synched properly 128044961713Sgirish */ 128144961713Sgirish #if !defined(_BIG_ENDIAN) 128214ea4bb7Ssd /* workarounds for x86 systems */ 128314ea4bb7Ssd pci_offset = 0x80 + PCIE_DEVCTL; 128448056c53SMichael Speer pcie_devctl = pci_config_get16(dev_regs->nxge_pciregh, 128548056c53SMichael Speer pci_offset); 128648056c53SMichael Speer pcie_devctl &= ~PCIE_DEVCTL_ENABLE_NO_SNOOP; 128714ea4bb7Ssd pcie_devctl |= PCIE_DEVCTL_RO_EN; 128814ea4bb7Ssd pci_config_put16(dev_regs->nxge_pciregh, pci_offset, 12894045d941Ssowmini pcie_devctl); 129044961713Sgirish #endif 129114ea4bb7Ssd 129244961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 129344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 12944045d941Ssowmini "nxge_map_regs: pio size 0x%x", regsize)); 129544961713Sgirish /* set up the device mapped register */ 129644961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 12974045d941Ssowmini (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 12984045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 129944961713Sgirish if (ddi_status != DDI_SUCCESS) { 130044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13014045d941Ssowmini "ddi_map_regs for Neptune global reg failed")); 130244961713Sgirish goto nxge_map_regs_fail1; 130344961713Sgirish } 130444961713Sgirish 130544961713Sgirish /* set up the msi/msi-x mapped register */ 130644961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 130744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13084045d941Ssowmini "nxge_map_regs: msix size 0x%x", regsize)); 130944961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 13104045d941Ssowmini (caddr_t *)&(dev_regs->nxge_msix_regp), 0, 0, 13114045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_msix_regh); 131244961713Sgirish if (ddi_status != DDI_SUCCESS) { 131344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13144045d941Ssowmini "ddi_map_regs for msi reg failed")); 131544961713Sgirish goto nxge_map_regs_fail2; 131644961713Sgirish } 131744961713Sgirish 131844961713Sgirish /* set up the vio region mapped register */ 131944961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 132044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13214045d941Ssowmini "nxge_map_regs: vio size 0x%x", regsize)); 132244961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 13234045d941Ssowmini (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 13244045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 132544961713Sgirish 132644961713Sgirish if (ddi_status != DDI_SUCCESS) { 132744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13284045d941Ssowmini "ddi_map_regs for nxge vio reg failed")); 132944961713Sgirish goto nxge_map_regs_fail3; 133044961713Sgirish } 133144961713Sgirish nxgep->dev_regs = dev_regs; 133244961713Sgirish 133344961713Sgirish NPI_PCI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_pciregh); 133444961713Sgirish NPI_PCI_ADD_HANDLE_SET(nxgep, 13354045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_pciregp); 133644961713Sgirish NPI_MSI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_msix_regh); 133744961713Sgirish NPI_MSI_ADD_HANDLE_SET(nxgep, 13384045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_msix_regp); 133944961713Sgirish 134044961713Sgirish NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 134144961713Sgirish NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 134244961713Sgirish 134344961713Sgirish NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 134444961713Sgirish NPI_REG_ADD_HANDLE_SET(nxgep, 13454045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_regp); 134644961713Sgirish 134744961713Sgirish NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 134844961713Sgirish NPI_VREG_ADD_HANDLE_SET(nxgep, 13494045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 135044961713Sgirish 135144961713Sgirish break; 135244961713Sgirish 135344961713Sgirish case N2_NIU: 135444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "ddi_map_regs, NIU")); 135544961713Sgirish /* 135644961713Sgirish * Set up the device mapped register (FWARC 2006/556) 135744961713Sgirish * (changed back to 1: reg starts at 1!) 135844961713Sgirish */ 135944961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 1, ®size); 136044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13614045d941Ssowmini "nxge_map_regs: dev size 0x%x", regsize)); 136244961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 1, 13634045d941Ssowmini (caddr_t *)&(dev_regs->nxge_regp), 0, 0, 13644045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh); 136544961713Sgirish 136644961713Sgirish if (ddi_status != DDI_SUCCESS) { 136744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13684045d941Ssowmini "ddi_map_regs for N2/NIU, global reg failed ")); 136944961713Sgirish goto nxge_map_regs_fail1; 137044961713Sgirish } 137144961713Sgirish 1372678453a8Sspeer /* set up the first vio region mapped register */ 137344961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 2, ®size); 137444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13754045d941Ssowmini "nxge_map_regs: vio (1) size 0x%x", regsize)); 137644961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 2, 13774045d941Ssowmini (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0, 13784045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh); 137944961713Sgirish 138044961713Sgirish if (ddi_status != DDI_SUCCESS) { 138144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13824045d941Ssowmini "ddi_map_regs for nxge vio reg failed")); 138344961713Sgirish goto nxge_map_regs_fail2; 138444961713Sgirish } 1385678453a8Sspeer /* set up the second vio region mapped register */ 138644961713Sgirish (void) ddi_dev_regsize(nxgep->dip, 3, ®size); 138744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 13884045d941Ssowmini "nxge_map_regs: vio (3) size 0x%x", regsize)); 138944961713Sgirish ddi_status = ddi_regs_map_setup(nxgep->dip, 3, 13904045d941Ssowmini (caddr_t *)&(dev_regs->nxge_vir2_regp), 0, 0, 13914045d941Ssowmini &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir2_regh); 139244961713Sgirish 139344961713Sgirish if (ddi_status != DDI_SUCCESS) { 139444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13954045d941Ssowmini "ddi_map_regs for nxge vio2 reg failed")); 139644961713Sgirish goto nxge_map_regs_fail3; 139744961713Sgirish } 139844961713Sgirish nxgep->dev_regs = dev_regs; 139944961713Sgirish 140044961713Sgirish NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 140144961713Sgirish NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp); 140244961713Sgirish 140344961713Sgirish NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh); 140444961713Sgirish NPI_REG_ADD_HANDLE_SET(nxgep, 14054045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_regp); 140644961713Sgirish 140744961713Sgirish NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh); 140844961713Sgirish NPI_VREG_ADD_HANDLE_SET(nxgep, 14094045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_vir_regp); 141044961713Sgirish 141144961713Sgirish NPI_V2REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir2_regh); 141244961713Sgirish NPI_V2REG_ADD_HANDLE_SET(nxgep, 14134045d941Ssowmini (npi_reg_ptr_t)dev_regs->nxge_vir2_regp); 141444961713Sgirish 141544961713Sgirish break; 141644961713Sgirish } 141744961713Sgirish 141844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "nxge_map_reg: hardware addr 0x%0llx " 14194045d941Ssowmini " handle 0x%0llx", dev_regs->nxge_regp, dev_regs->nxge_regh)); 142044961713Sgirish 142144961713Sgirish goto nxge_map_regs_exit; 142244961713Sgirish nxge_map_regs_fail3: 142344961713Sgirish if (dev_regs->nxge_msix_regh) { 142444961713Sgirish ddi_regs_map_free(&dev_regs->nxge_msix_regh); 142544961713Sgirish } 142644961713Sgirish if (dev_regs->nxge_vir_regh) { 142744961713Sgirish ddi_regs_map_free(&dev_regs->nxge_regh); 142844961713Sgirish } 142944961713Sgirish nxge_map_regs_fail2: 143044961713Sgirish if (dev_regs->nxge_regh) { 143144961713Sgirish ddi_regs_map_free(&dev_regs->nxge_regh); 143244961713Sgirish } 143344961713Sgirish nxge_map_regs_fail1: 143444961713Sgirish if (dev_regs->nxge_pciregh) { 143544961713Sgirish ddi_regs_map_free(&dev_regs->nxge_pciregh); 143644961713Sgirish } 143744961713Sgirish nxge_map_regs_fail0: 143844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Freeing register set memory")); 143944961713Sgirish kmem_free(dev_regs, sizeof (dev_regs_t)); 144044961713Sgirish 144144961713Sgirish nxge_map_regs_exit: 144244961713Sgirish if (ddi_status != DDI_SUCCESS) 144344961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 144444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_map_regs")); 144544961713Sgirish return (status); 144644961713Sgirish } 144744961713Sgirish 144844961713Sgirish static void 144944961713Sgirish nxge_unmap_regs(p_nxge_t nxgep) 145044961713Sgirish { 145144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unmap_regs")); 1452678453a8Sspeer 1453678453a8Sspeer if (isLDOMguest(nxgep)) { 1454678453a8Sspeer nxge_guest_regs_map_free(nxgep); 1455678453a8Sspeer return; 1456678453a8Sspeer } 1457678453a8Sspeer 145844961713Sgirish if (nxgep->dev_regs) { 145944961713Sgirish if (nxgep->dev_regs->nxge_pciregh) { 146044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 14614045d941Ssowmini "==> nxge_unmap_regs: bus")); 146244961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_pciregh); 146344961713Sgirish nxgep->dev_regs->nxge_pciregh = NULL; 146444961713Sgirish } 146544961713Sgirish if (nxgep->dev_regs->nxge_regh) { 146644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 14674045d941Ssowmini "==> nxge_unmap_regs: device registers")); 146844961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_regh); 146944961713Sgirish nxgep->dev_regs->nxge_regh = NULL; 147044961713Sgirish } 147144961713Sgirish if (nxgep->dev_regs->nxge_msix_regh) { 147244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 14734045d941Ssowmini "==> nxge_unmap_regs: device interrupts")); 147444961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_msix_regh); 147544961713Sgirish nxgep->dev_regs->nxge_msix_regh = NULL; 147644961713Sgirish } 147744961713Sgirish if (nxgep->dev_regs->nxge_vir_regh) { 147844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 14794045d941Ssowmini "==> nxge_unmap_regs: vio region")); 148044961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_vir_regh); 148144961713Sgirish nxgep->dev_regs->nxge_vir_regh = NULL; 148244961713Sgirish } 148344961713Sgirish if (nxgep->dev_regs->nxge_vir2_regh) { 148444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 14854045d941Ssowmini "==> nxge_unmap_regs: vio2 region")); 148644961713Sgirish ddi_regs_map_free(&nxgep->dev_regs->nxge_vir2_regh); 148744961713Sgirish nxgep->dev_regs->nxge_vir2_regh = NULL; 148844961713Sgirish } 148944961713Sgirish 149044961713Sgirish kmem_free(nxgep->dev_regs, sizeof (dev_regs_t)); 149144961713Sgirish nxgep->dev_regs = NULL; 149244961713Sgirish } 149344961713Sgirish 149444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_unmap_regs")); 149544961713Sgirish } 149644961713Sgirish 149744961713Sgirish static nxge_status_t 149844961713Sgirish nxge_setup_mutexes(p_nxge_t nxgep) 149944961713Sgirish { 150044961713Sgirish int ddi_status = DDI_SUCCESS; 150144961713Sgirish nxge_status_t status = NXGE_OK; 150244961713Sgirish nxge_classify_t *classify_ptr; 150344961713Sgirish int partition; 150444961713Sgirish 150544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_mutexes")); 150644961713Sgirish 150744961713Sgirish /* 150844961713Sgirish * Get the interrupt cookie so the mutexes can be 150958324dfcSspeer * Initialized. 151044961713Sgirish */ 1511678453a8Sspeer if (isLDOMguest(nxgep)) { 1512678453a8Sspeer nxgep->interrupt_cookie = 0; 1513678453a8Sspeer } else { 1514678453a8Sspeer ddi_status = ddi_get_iblock_cookie(nxgep->dip, 0, 1515678453a8Sspeer &nxgep->interrupt_cookie); 1516678453a8Sspeer 1517678453a8Sspeer if (ddi_status != DDI_SUCCESS) { 1518678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1519678453a8Sspeer "<== nxge_setup_mutexes: failed 0x%x", 1520678453a8Sspeer ddi_status)); 1521678453a8Sspeer goto nxge_setup_mutexes_exit; 1522678453a8Sspeer } 152344961713Sgirish } 152444961713Sgirish 152598ecde52Stm cv_init(&nxgep->poll_cv, NULL, CV_DRIVER, NULL); 152698ecde52Stm MUTEX_INIT(&nxgep->poll_lock, NULL, 152798ecde52Stm MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 152898ecde52Stm 152944961713Sgirish /* 153098ecde52Stm * Initialize mutexes for this device. 153144961713Sgirish */ 153244961713Sgirish MUTEX_INIT(nxgep->genlock, NULL, 15334045d941Ssowmini MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 153444961713Sgirish MUTEX_INIT(&nxgep->ouraddr_lock, NULL, 15354045d941Ssowmini MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 153644961713Sgirish MUTEX_INIT(&nxgep->mif_lock, NULL, 15374045d941Ssowmini MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 1538678453a8Sspeer MUTEX_INIT(&nxgep->group_lock, NULL, 1539678453a8Sspeer MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 154044961713Sgirish RW_INIT(&nxgep->filter_lock, NULL, 15414045d941Ssowmini RW_DRIVER, (void *)nxgep->interrupt_cookie); 154244961713Sgirish 154344961713Sgirish classify_ptr = &nxgep->classifier; 154444961713Sgirish /* 154544961713Sgirish * FFLP Mutexes are never used in interrupt context 154644961713Sgirish * as fflp operation can take very long time to 154744961713Sgirish * complete and hence not suitable to invoke from interrupt 154844961713Sgirish * handlers. 154944961713Sgirish */ 155044961713Sgirish MUTEX_INIT(&classify_ptr->tcam_lock, NULL, 155159ac0c16Sdavemq NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 15522e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 155344961713Sgirish MUTEX_INIT(&classify_ptr->fcram_lock, NULL, 155459ac0c16Sdavemq NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 155544961713Sgirish for (partition = 0; partition < MAX_PARTITION; partition++) { 155644961713Sgirish MUTEX_INIT(&classify_ptr->hash_lock[partition], NULL, 155744961713Sgirish NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); 155844961713Sgirish } 155944961713Sgirish } 156044961713Sgirish 156144961713Sgirish nxge_setup_mutexes_exit: 156244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 156359ac0c16Sdavemq "<== nxge_setup_mutexes status = %x", status)); 156444961713Sgirish 156544961713Sgirish if (ddi_status != DDI_SUCCESS) 156644961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 156744961713Sgirish 156844961713Sgirish return (status); 156944961713Sgirish } 157044961713Sgirish 157144961713Sgirish static void 157244961713Sgirish nxge_destroy_mutexes(p_nxge_t nxgep) 157344961713Sgirish { 157444961713Sgirish int partition; 157544961713Sgirish nxge_classify_t *classify_ptr; 157644961713Sgirish 157744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_mutexes")); 157844961713Sgirish RW_DESTROY(&nxgep->filter_lock); 1579678453a8Sspeer MUTEX_DESTROY(&nxgep->group_lock); 158044961713Sgirish MUTEX_DESTROY(&nxgep->mif_lock); 158144961713Sgirish MUTEX_DESTROY(&nxgep->ouraddr_lock); 158244961713Sgirish MUTEX_DESTROY(nxgep->genlock); 158344961713Sgirish 158444961713Sgirish classify_ptr = &nxgep->classifier; 158544961713Sgirish MUTEX_DESTROY(&classify_ptr->tcam_lock); 158644961713Sgirish 158798ecde52Stm /* Destroy all polling resources. */ 158898ecde52Stm MUTEX_DESTROY(&nxgep->poll_lock); 158998ecde52Stm cv_destroy(&nxgep->poll_cv); 159098ecde52Stm 159198ecde52Stm /* free data structures, based on HW type */ 15922e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 159344961713Sgirish MUTEX_DESTROY(&classify_ptr->fcram_lock); 159444961713Sgirish for (partition = 0; partition < MAX_PARTITION; partition++) { 159544961713Sgirish MUTEX_DESTROY(&classify_ptr->hash_lock[partition]); 159644961713Sgirish } 159744961713Sgirish } 159844961713Sgirish 159944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_mutexes")); 160044961713Sgirish } 160144961713Sgirish 160244961713Sgirish nxge_status_t 160344961713Sgirish nxge_init(p_nxge_t nxgep) 160444961713Sgirish { 1605678453a8Sspeer nxge_status_t status = NXGE_OK; 160644961713Sgirish 160744961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_init")); 160844961713Sgirish 160914ea4bb7Ssd if (nxgep->drv_state & STATE_HW_INITIALIZED) { 161014ea4bb7Ssd return (status); 161114ea4bb7Ssd } 161214ea4bb7Ssd 161344961713Sgirish /* 161444961713Sgirish * Allocate system memory for the receive/transmit buffer blocks 161544961713Sgirish * and receive/transmit descriptor rings. 161644961713Sgirish */ 161744961713Sgirish status = nxge_alloc_mem_pool(nxgep); 161844961713Sgirish if (status != NXGE_OK) { 161944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "alloc mem failed\n")); 162044961713Sgirish goto nxge_init_fail1; 162144961713Sgirish } 162244961713Sgirish 1623678453a8Sspeer if (!isLDOMguest(nxgep)) { 1624678453a8Sspeer /* 1625678453a8Sspeer * Initialize and enable the TXC registers. 1626678453a8Sspeer * (Globally enable the Tx controller, 1627678453a8Sspeer * enable the port, configure the dma channel bitmap, 1628678453a8Sspeer * configure the max burst size). 1629678453a8Sspeer */ 1630678453a8Sspeer status = nxge_txc_init(nxgep); 1631678453a8Sspeer if (status != NXGE_OK) { 1632678453a8Sspeer NXGE_ERROR_MSG((nxgep, 1633678453a8Sspeer NXGE_ERR_CTL, "init txc failed\n")); 1634678453a8Sspeer goto nxge_init_fail2; 1635678453a8Sspeer } 163644961713Sgirish } 163744961713Sgirish 163844961713Sgirish /* 163944961713Sgirish * Initialize and enable TXDMA channels. 164044961713Sgirish */ 164144961713Sgirish status = nxge_init_txdma_channels(nxgep); 164244961713Sgirish if (status != NXGE_OK) { 164344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txdma failed\n")); 164444961713Sgirish goto nxge_init_fail3; 164544961713Sgirish } 164644961713Sgirish 164744961713Sgirish /* 164844961713Sgirish * Initialize and enable RXDMA channels. 164944961713Sgirish */ 165044961713Sgirish status = nxge_init_rxdma_channels(nxgep); 165144961713Sgirish if (status != NXGE_OK) { 165244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init rxdma failed\n")); 165344961713Sgirish goto nxge_init_fail4; 165444961713Sgirish } 165544961713Sgirish 1656678453a8Sspeer /* 1657678453a8Sspeer * The guest domain is now done. 1658678453a8Sspeer */ 1659678453a8Sspeer if (isLDOMguest(nxgep)) { 1660678453a8Sspeer nxgep->drv_state |= STATE_HW_INITIALIZED; 1661678453a8Sspeer goto nxge_init_exit; 1662678453a8Sspeer } 1663678453a8Sspeer 166444961713Sgirish /* 166544961713Sgirish * Initialize TCAM and FCRAM (Neptune). 166644961713Sgirish */ 166744961713Sgirish status = nxge_classify_init(nxgep); 166844961713Sgirish if (status != NXGE_OK) { 166944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init classify failed\n")); 167044961713Sgirish goto nxge_init_fail5; 167144961713Sgirish } 167244961713Sgirish 167344961713Sgirish /* 167444961713Sgirish * Initialize ZCP 167544961713Sgirish */ 167644961713Sgirish status = nxge_zcp_init(nxgep); 167744961713Sgirish if (status != NXGE_OK) { 167844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init ZCP failed\n")); 167944961713Sgirish goto nxge_init_fail5; 168044961713Sgirish } 168144961713Sgirish 168244961713Sgirish /* 168344961713Sgirish * Initialize IPP. 168444961713Sgirish */ 168544961713Sgirish status = nxge_ipp_init(nxgep); 168644961713Sgirish if (status != NXGE_OK) { 168744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init IPP failed\n")); 168844961713Sgirish goto nxge_init_fail5; 168944961713Sgirish } 169044961713Sgirish 169144961713Sgirish /* 169244961713Sgirish * Initialize the MAC block. 169344961713Sgirish */ 169444961713Sgirish status = nxge_mac_init(nxgep); 169544961713Sgirish if (status != NXGE_OK) { 169644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init MAC failed\n")); 169744961713Sgirish goto nxge_init_fail5; 169844961713Sgirish } 169944961713Sgirish 170044961713Sgirish /* 1701e759c33aSMichael Speer * Enable the interrrupts for DDI. 170244961713Sgirish */ 1703e759c33aSMichael Speer nxge_intrs_enable(nxgep); 1704e759c33aSMichael Speer 170544961713Sgirish nxgep->drv_state |= STATE_HW_INITIALIZED; 170644961713Sgirish 170744961713Sgirish goto nxge_init_exit; 170844961713Sgirish 170944961713Sgirish nxge_init_fail5: 171044961713Sgirish nxge_uninit_rxdma_channels(nxgep); 171144961713Sgirish nxge_init_fail4: 171244961713Sgirish nxge_uninit_txdma_channels(nxgep); 171344961713Sgirish nxge_init_fail3: 1714678453a8Sspeer if (!isLDOMguest(nxgep)) { 1715678453a8Sspeer (void) nxge_txc_uninit(nxgep); 1716678453a8Sspeer } 171744961713Sgirish nxge_init_fail2: 171844961713Sgirish nxge_free_mem_pool(nxgep); 171944961713Sgirish nxge_init_fail1: 172044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 17214045d941Ssowmini "<== nxge_init status (failed) = 0x%08x", status)); 172244961713Sgirish return (status); 172344961713Sgirish 172444961713Sgirish nxge_init_exit: 172544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_init status = 0x%08x", 17264045d941Ssowmini status)); 172744961713Sgirish return (status); 172844961713Sgirish } 172944961713Sgirish 173044961713Sgirish 173144961713Sgirish timeout_id_t 173244961713Sgirish nxge_start_timer(p_nxge_t nxgep, fptrv_t func, int msec) 173344961713Sgirish { 17344045d941Ssowmini if ((nxgep->suspended == 0) || (nxgep->suspended == DDI_RESUME)) { 173544961713Sgirish return (timeout(func, (caddr_t)nxgep, 17364045d941Ssowmini drv_usectohz(1000 * msec))); 173744961713Sgirish } 173844961713Sgirish return (NULL); 173944961713Sgirish } 174044961713Sgirish 174144961713Sgirish /*ARGSUSED*/ 174244961713Sgirish void 174344961713Sgirish nxge_stop_timer(p_nxge_t nxgep, timeout_id_t timerid) 174444961713Sgirish { 174544961713Sgirish if (timerid) { 174644961713Sgirish (void) untimeout(timerid); 174744961713Sgirish } 174844961713Sgirish } 174944961713Sgirish 175044961713Sgirish void 175144961713Sgirish nxge_uninit(p_nxge_t nxgep) 175244961713Sgirish { 175344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_uninit")); 175444961713Sgirish 175544961713Sgirish if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 175644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 17574045d941Ssowmini "==> nxge_uninit: not initialized")); 175844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 17594045d941Ssowmini "<== nxge_uninit")); 176044961713Sgirish return; 176144961713Sgirish } 176244961713Sgirish 1763e759c33aSMichael Speer if (!isLDOMguest(nxgep)) { 1764e759c33aSMichael Speer /* 1765e759c33aSMichael Speer * Reset the receive MAC side. 1766e759c33aSMichael Speer */ 1767e759c33aSMichael Speer (void) nxge_rx_mac_disable(nxgep); 1768e759c33aSMichael Speer 1769e759c33aSMichael Speer /* 1770e759c33aSMichael Speer * Drain the IPP. 1771e759c33aSMichael Speer */ 1772e759c33aSMichael Speer (void) nxge_ipp_drain(nxgep); 1773e759c33aSMichael Speer } 1774e759c33aSMichael Speer 177544961713Sgirish /* stop timer */ 177644961713Sgirish if (nxgep->nxge_timerid) { 177744961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 177844961713Sgirish nxgep->nxge_timerid = 0; 177944961713Sgirish } 178044961713Sgirish 178144961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 178244961713Sgirish (void) nxge_intr_hw_disable(nxgep); 178344961713Sgirish 178444961713Sgirish 178544961713Sgirish /* Disable and soft reset the IPP */ 1786678453a8Sspeer if (!isLDOMguest(nxgep)) 1787678453a8Sspeer (void) nxge_ipp_disable(nxgep); 178844961713Sgirish 1789a3c5bd6dSspeer /* Free classification resources */ 1790a3c5bd6dSspeer (void) nxge_classify_uninit(nxgep); 1791a3c5bd6dSspeer 179244961713Sgirish /* 179344961713Sgirish * Reset the transmit/receive DMA side. 179444961713Sgirish */ 179544961713Sgirish (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 179644961713Sgirish (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 179744961713Sgirish 179844961713Sgirish nxge_uninit_txdma_channels(nxgep); 179944961713Sgirish nxge_uninit_rxdma_channels(nxgep); 180044961713Sgirish 180144961713Sgirish /* 180244961713Sgirish * Reset the transmit MAC side. 180344961713Sgirish */ 180444961713Sgirish (void) nxge_tx_mac_disable(nxgep); 180544961713Sgirish 180644961713Sgirish nxge_free_mem_pool(nxgep); 180744961713Sgirish 18086f157acbSml /* 18096f157acbSml * Start the timer if the reset flag is not set. 18106f157acbSml * If this reset flag is set, the link monitor 18116f157acbSml * will not be started in order to stop furthur bus 18126f157acbSml * activities coming from this interface. 18136f157acbSml * The driver will start the monitor function 18146f157acbSml * if the interface was initialized again later. 18156f157acbSml */ 18166f157acbSml if (!nxge_peu_reset_enable) { 18176f157acbSml (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 18186f157acbSml } 181944961713Sgirish 182044961713Sgirish nxgep->drv_state &= ~STATE_HW_INITIALIZED; 182144961713Sgirish 182244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_uninit: " 18234045d941Ssowmini "nxge_mblks_pending %d", nxge_mblks_pending)); 182444961713Sgirish } 182544961713Sgirish 182644961713Sgirish void 182744961713Sgirish nxge_get64(p_nxge_t nxgep, p_mblk_t mp) 182844961713Sgirish { 182944961713Sgirish uint64_t reg; 183044961713Sgirish uint64_t regdata; 183144961713Sgirish int i, retry; 183244961713Sgirish 183344961713Sgirish bcopy((char *)mp->b_rptr, (char *)®, sizeof (uint64_t)); 183444961713Sgirish regdata = 0; 183544961713Sgirish retry = 1; 183644961713Sgirish 183744961713Sgirish for (i = 0; i < retry; i++) { 183844961713Sgirish NXGE_REG_RD64(nxgep->npi_handle, reg, ®data); 183944961713Sgirish } 184044961713Sgirish bcopy((char *)®data, (char *)mp->b_rptr, sizeof (uint64_t)); 184144961713Sgirish } 184244961713Sgirish 184344961713Sgirish void 184444961713Sgirish nxge_put64(p_nxge_t nxgep, p_mblk_t mp) 184544961713Sgirish { 184644961713Sgirish uint64_t reg; 184744961713Sgirish uint64_t buf[2]; 184844961713Sgirish 184944961713Sgirish bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t)); 185044961713Sgirish reg = buf[0]; 185144961713Sgirish 185244961713Sgirish NXGE_NPI_PIO_WRITE64(nxgep->npi_handle, reg, buf[1]); 185344961713Sgirish } 185444961713Sgirish 185544961713Sgirish /*ARGSUSED*/ 185644961713Sgirish /*VARARGS*/ 185744961713Sgirish void 185844961713Sgirish nxge_debug_msg(p_nxge_t nxgep, uint64_t level, char *fmt, ...) 185944961713Sgirish { 186044961713Sgirish char msg_buffer[1048]; 186144961713Sgirish char prefix_buffer[32]; 186244961713Sgirish int instance; 186344961713Sgirish uint64_t debug_level; 186444961713Sgirish int cmn_level = CE_CONT; 186544961713Sgirish va_list ap; 186644961713Sgirish 1867678453a8Sspeer if (nxgep && nxgep->nxge_debug_level != nxge_debug_level) { 1868678453a8Sspeer /* In case a developer has changed nxge_debug_level. */ 1869678453a8Sspeer if (nxgep->nxge_debug_level != nxge_debug_level) 1870678453a8Sspeer nxgep->nxge_debug_level = nxge_debug_level; 1871678453a8Sspeer } 1872678453a8Sspeer 187344961713Sgirish debug_level = (nxgep == NULL) ? nxge_debug_level : 18744045d941Ssowmini nxgep->nxge_debug_level; 187544961713Sgirish 187644961713Sgirish if ((level & debug_level) || 18774045d941Ssowmini (level == NXGE_NOTE) || 18784045d941Ssowmini (level == NXGE_ERR_CTL)) { 187944961713Sgirish /* do the msg processing */ 188044961713Sgirish MUTEX_ENTER(&nxgedebuglock); 188144961713Sgirish 188244961713Sgirish if ((level & NXGE_NOTE)) { 188344961713Sgirish cmn_level = CE_NOTE; 188444961713Sgirish } 188544961713Sgirish 188644961713Sgirish if (level & NXGE_ERR_CTL) { 188744961713Sgirish cmn_level = CE_WARN; 188844961713Sgirish } 188944961713Sgirish 189044961713Sgirish va_start(ap, fmt); 189144961713Sgirish (void) vsprintf(msg_buffer, fmt, ap); 189244961713Sgirish va_end(ap); 189344961713Sgirish if (nxgep == NULL) { 189444961713Sgirish instance = -1; 189544961713Sgirish (void) sprintf(prefix_buffer, "%s :", "nxge"); 189644961713Sgirish } else { 189744961713Sgirish instance = nxgep->instance; 189844961713Sgirish (void) sprintf(prefix_buffer, 18994045d941Ssowmini "%s%d :", "nxge", instance); 190044961713Sgirish } 190144961713Sgirish 190244961713Sgirish MUTEX_EXIT(&nxgedebuglock); 190344961713Sgirish cmn_err(cmn_level, "!%s %s\n", 19044045d941Ssowmini prefix_buffer, msg_buffer); 190544961713Sgirish 190644961713Sgirish } 190744961713Sgirish } 190844961713Sgirish 190944961713Sgirish char * 191044961713Sgirish nxge_dump_packet(char *addr, int size) 191144961713Sgirish { 191244961713Sgirish uchar_t *ap = (uchar_t *)addr; 191344961713Sgirish int i; 191444961713Sgirish static char etherbuf[1024]; 191544961713Sgirish char *cp = etherbuf; 191644961713Sgirish char digits[] = "0123456789abcdef"; 191744961713Sgirish 191844961713Sgirish if (!size) 191944961713Sgirish size = 60; 192044961713Sgirish 192144961713Sgirish if (size > MAX_DUMP_SZ) { 192244961713Sgirish /* Dump the leading bytes */ 192344961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 192444961713Sgirish if (*ap > 0x0f) 192544961713Sgirish *cp++ = digits[*ap >> 4]; 192644961713Sgirish *cp++ = digits[*ap++ & 0xf]; 192744961713Sgirish *cp++ = ':'; 192844961713Sgirish } 192944961713Sgirish for (i = 0; i < 20; i++) 193044961713Sgirish *cp++ = '.'; 193144961713Sgirish /* Dump the last MAX_DUMP_SZ/2 bytes */ 193244961713Sgirish ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ/2)); 193344961713Sgirish for (i = 0; i < MAX_DUMP_SZ/2; i++) { 193444961713Sgirish if (*ap > 0x0f) 193544961713Sgirish *cp++ = digits[*ap >> 4]; 193644961713Sgirish *cp++ = digits[*ap++ & 0xf]; 193744961713Sgirish *cp++ = ':'; 193844961713Sgirish } 193944961713Sgirish } else { 194044961713Sgirish for (i = 0; i < size; i++) { 194144961713Sgirish if (*ap > 0x0f) 194244961713Sgirish *cp++ = digits[*ap >> 4]; 194344961713Sgirish *cp++ = digits[*ap++ & 0xf]; 194444961713Sgirish *cp++ = ':'; 194544961713Sgirish } 194644961713Sgirish } 194744961713Sgirish *--cp = 0; 194844961713Sgirish return (etherbuf); 194944961713Sgirish } 195044961713Sgirish 195144961713Sgirish #ifdef NXGE_DEBUG 195244961713Sgirish static void 195344961713Sgirish nxge_test_map_regs(p_nxge_t nxgep) 195444961713Sgirish { 195544961713Sgirish ddi_acc_handle_t cfg_handle; 195644961713Sgirish p_pci_cfg_t cfg_ptr; 195744961713Sgirish ddi_acc_handle_t dev_handle; 195844961713Sgirish char *dev_ptr; 195944961713Sgirish ddi_acc_handle_t pci_config_handle; 196044961713Sgirish uint32_t regval; 196144961713Sgirish int i; 196244961713Sgirish 196344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_test_map_regs")); 196444961713Sgirish 196544961713Sgirish dev_handle = nxgep->dev_regs->nxge_regh; 196644961713Sgirish dev_ptr = (char *)nxgep->dev_regs->nxge_regp; 196744961713Sgirish 19682e59129aSraghus if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 196944961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 197044961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 197144961713Sgirish 197244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 197359ac0c16Sdavemq "Neptune PCI regp cfg_ptr 0x%llx", (char *)cfg_ptr)); 197444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 197559ac0c16Sdavemq "Neptune PCI cfg_ptr vendor id ptr 0x%llx", 197659ac0c16Sdavemq &cfg_ptr->vendorid)); 197744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 197859ac0c16Sdavemq "\tvendorid 0x%x devid 0x%x", 197959ac0c16Sdavemq NXGE_PIO_READ16(cfg_handle, &cfg_ptr->vendorid, 0), 198059ac0c16Sdavemq NXGE_PIO_READ16(cfg_handle, &cfg_ptr->devid, 0))); 198144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 198259ac0c16Sdavemq "PCI BAR: base 0x%x base14 0x%x base 18 0x%x " 198359ac0c16Sdavemq "bar1c 0x%x", 198459ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base, 0), 198559ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base14, 0), 198659ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base18, 0), 198759ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base1c, 0))); 198844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 198959ac0c16Sdavemq "\nNeptune PCI BAR: base20 0x%x base24 0x%x " 199059ac0c16Sdavemq "base 28 0x%x bar2c 0x%x\n", 199159ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base20, 0), 199259ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base24, 0), 199359ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base28, 0), 199459ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base2c, 0))); 199544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 199659ac0c16Sdavemq "\nNeptune PCI BAR: base30 0x%x\n", 199759ac0c16Sdavemq NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base30, 0))); 199844961713Sgirish 199944961713Sgirish cfg_handle = nxgep->dev_regs->nxge_pciregh; 200044961713Sgirish cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp; 200144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 200259ac0c16Sdavemq "first 0x%llx second 0x%llx third 0x%llx " 200359ac0c16Sdavemq "last 0x%llx ", 200459ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 200559ac0c16Sdavemq (uint64_t *)(dev_ptr + 0), 0), 200659ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 200759ac0c16Sdavemq (uint64_t *)(dev_ptr + 8), 0), 200859ac0c16Sdavemq NXGE_PIO_READ64(dev_handle, 200959ac0c16Sdavemq (uint64_t *)(dev_ptr + 16), 0), 201059ac0c16Sdavemq NXGE_PIO_READ64(cfg_handle, 201159ac0c16Sdavemq (uint64_t *)(dev_ptr + 24), 0))); 201244961713Sgirish } 201344961713Sgirish } 201444961713Sgirish 201544961713Sgirish #endif 201644961713Sgirish 201744961713Sgirish static void 201844961713Sgirish nxge_suspend(p_nxge_t nxgep) 201944961713Sgirish { 202044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_suspend")); 202144961713Sgirish 202244961713Sgirish nxge_intrs_disable(nxgep); 202344961713Sgirish nxge_destroy_dev(nxgep); 202444961713Sgirish 202544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_suspend")); 202644961713Sgirish } 202744961713Sgirish 202844961713Sgirish static nxge_status_t 202944961713Sgirish nxge_resume(p_nxge_t nxgep) 203044961713Sgirish { 203144961713Sgirish nxge_status_t status = NXGE_OK; 203244961713Sgirish 203344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_resume")); 203444961713Sgirish 203591c98b31Sjoycey nxgep->suspended = DDI_RESUME; 203691c98b31Sjoycey (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 203791c98b31Sjoycey (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_START); 203891c98b31Sjoycey (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START); 203991c98b31Sjoycey (void) nxge_rx_mac_enable(nxgep); 204091c98b31Sjoycey (void) nxge_tx_mac_enable(nxgep); 204191c98b31Sjoycey nxge_intrs_enable(nxgep); 204244961713Sgirish nxgep->suspended = 0; 204344961713Sgirish 204444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20454045d941Ssowmini "<== nxge_resume status = 0x%x", status)); 204644961713Sgirish return (status); 204744961713Sgirish } 204844961713Sgirish 204944961713Sgirish static nxge_status_t 205044961713Sgirish nxge_setup_dev(p_nxge_t nxgep) 205144961713Sgirish { 205244961713Sgirish nxge_status_t status = NXGE_OK; 205344961713Sgirish 205444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_dev port %d", 205559ac0c16Sdavemq nxgep->mac.portnum)); 205644961713Sgirish 205744961713Sgirish status = nxge_link_init(nxgep); 205814ea4bb7Ssd 205914ea4bb7Ssd if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) { 206014ea4bb7Ssd NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20614045d941Ssowmini "port%d Bad register acc handle", nxgep->mac.portnum)); 206214ea4bb7Ssd status = NXGE_ERROR; 206314ea4bb7Ssd } 206414ea4bb7Ssd 206544961713Sgirish if (status != NXGE_OK) { 206644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20674045d941Ssowmini " nxge_setup_dev status " 20684045d941Ssowmini "(xcvr init 0x%08x)", status)); 206944961713Sgirish goto nxge_setup_dev_exit; 207044961713Sgirish } 207144961713Sgirish 207244961713Sgirish nxge_setup_dev_exit: 207344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 20744045d941Ssowmini "<== nxge_setup_dev port %d status = 0x%08x", 20754045d941Ssowmini nxgep->mac.portnum, status)); 207644961713Sgirish 207744961713Sgirish return (status); 207844961713Sgirish } 207944961713Sgirish 208044961713Sgirish static void 208144961713Sgirish nxge_destroy_dev(p_nxge_t nxgep) 208244961713Sgirish { 208344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_dev")); 208444961713Sgirish 208544961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 208644961713Sgirish 208744961713Sgirish (void) nxge_hw_stop(nxgep); 208844961713Sgirish 208944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_dev")); 209044961713Sgirish } 209144961713Sgirish 209244961713Sgirish static nxge_status_t 209344961713Sgirish nxge_setup_system_dma_pages(p_nxge_t nxgep) 209444961713Sgirish { 209544961713Sgirish int ddi_status = DDI_SUCCESS; 209644961713Sgirish uint_t count; 209744961713Sgirish ddi_dma_cookie_t cookie; 209844961713Sgirish uint_t iommu_pagesize; 209944961713Sgirish nxge_status_t status = NXGE_OK; 210044961713Sgirish 2101678453a8Sspeer NXGE_ERROR_MSG((nxgep, DDI_CTL, "==> nxge_setup_system_dma_pages")); 210244961713Sgirish nxgep->sys_page_sz = ddi_ptob(nxgep->dip, (ulong_t)1); 210344961713Sgirish if (nxgep->niu_type != N2_NIU) { 210444961713Sgirish iommu_pagesize = dvma_pagesize(nxgep->dip); 210544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 21064045d941Ssowmini " nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 21074045d941Ssowmini " default_block_size %d iommu_pagesize %d", 21084045d941Ssowmini nxgep->sys_page_sz, 21094045d941Ssowmini ddi_ptob(nxgep->dip, (ulong_t)1), 21104045d941Ssowmini nxgep->rx_default_block_size, 21114045d941Ssowmini iommu_pagesize)); 211244961713Sgirish 211344961713Sgirish if (iommu_pagesize != 0) { 211444961713Sgirish if (nxgep->sys_page_sz == iommu_pagesize) { 211544961713Sgirish if (iommu_pagesize > 0x4000) 211644961713Sgirish nxgep->sys_page_sz = 0x4000; 211744961713Sgirish } else { 211844961713Sgirish if (nxgep->sys_page_sz > iommu_pagesize) 211944961713Sgirish nxgep->sys_page_sz = iommu_pagesize; 212044961713Sgirish } 212144961713Sgirish } 212244961713Sgirish } 212344961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 212444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 21254045d941Ssowmini "==> nxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 21264045d941Ssowmini "default_block_size %d page mask %d", 21274045d941Ssowmini nxgep->sys_page_sz, 21284045d941Ssowmini ddi_ptob(nxgep->dip, (ulong_t)1), 21294045d941Ssowmini nxgep->rx_default_block_size, 21304045d941Ssowmini nxgep->sys_page_mask)); 213144961713Sgirish 213244961713Sgirish 213344961713Sgirish switch (nxgep->sys_page_sz) { 213444961713Sgirish default: 213544961713Sgirish nxgep->sys_page_sz = 0x1000; 213644961713Sgirish nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1); 213744961713Sgirish nxgep->rx_default_block_size = 0x1000; 213844961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 213944961713Sgirish break; 214044961713Sgirish case 0x1000: 214144961713Sgirish nxgep->rx_default_block_size = 0x1000; 214244961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_4K; 214344961713Sgirish break; 214444961713Sgirish case 0x2000: 214544961713Sgirish nxgep->rx_default_block_size = 0x2000; 214644961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 214744961713Sgirish break; 214844961713Sgirish case 0x4000: 214944961713Sgirish nxgep->rx_default_block_size = 0x4000; 215044961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_16K; 215144961713Sgirish break; 215244961713Sgirish case 0x8000: 215344961713Sgirish nxgep->rx_default_block_size = 0x8000; 215444961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_32K; 215544961713Sgirish break; 215644961713Sgirish } 215744961713Sgirish 215844961713Sgirish #ifndef USE_RX_BIG_BUF 215944961713Sgirish nxge_rx_dma_attr.dma_attr_align = nxgep->sys_page_sz; 216044961713Sgirish #else 216144961713Sgirish nxgep->rx_default_block_size = 0x2000; 216244961713Sgirish nxgep->rx_bksize_code = RBR_BKSIZE_8K; 216344961713Sgirish #endif 216444961713Sgirish /* 216544961713Sgirish * Get the system DMA burst size. 216644961713Sgirish */ 216744961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr, 21684045d941Ssowmini DDI_DMA_DONTWAIT, 0, 21694045d941Ssowmini &nxgep->dmasparehandle); 217044961713Sgirish if (ddi_status != DDI_SUCCESS) { 217144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 21724045d941Ssowmini "ddi_dma_alloc_handle: failed " 21734045d941Ssowmini " status 0x%x", ddi_status)); 217444961713Sgirish goto nxge_get_soft_properties_exit; 217544961713Sgirish } 217644961713Sgirish 217744961713Sgirish ddi_status = ddi_dma_addr_bind_handle(nxgep->dmasparehandle, NULL, 21784045d941Ssowmini (caddr_t)nxgep->dmasparehandle, 21794045d941Ssowmini sizeof (nxgep->dmasparehandle), 21804045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 21814045d941Ssowmini DDI_DMA_DONTWAIT, 0, 21824045d941Ssowmini &cookie, &count); 218344961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 218444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 21854045d941Ssowmini "Binding spare handle to find system" 21864045d941Ssowmini " burstsize failed.")); 218744961713Sgirish ddi_status = DDI_FAILURE; 218844961713Sgirish goto nxge_get_soft_properties_fail1; 218944961713Sgirish } 219044961713Sgirish 219144961713Sgirish nxgep->sys_burst_sz = ddi_dma_burstsizes(nxgep->dmasparehandle); 219244961713Sgirish (void) ddi_dma_unbind_handle(nxgep->dmasparehandle); 219344961713Sgirish 219444961713Sgirish nxge_get_soft_properties_fail1: 219544961713Sgirish ddi_dma_free_handle(&nxgep->dmasparehandle); 219644961713Sgirish 219744961713Sgirish nxge_get_soft_properties_exit: 219844961713Sgirish 219944961713Sgirish if (ddi_status != DDI_SUCCESS) 220044961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 220144961713Sgirish 220244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 22034045d941Ssowmini "<== nxge_setup_system_dma_pages status = 0x%08x", status)); 220444961713Sgirish return (status); 220544961713Sgirish } 220644961713Sgirish 220744961713Sgirish static nxge_status_t 220844961713Sgirish nxge_alloc_mem_pool(p_nxge_t nxgep) 220944961713Sgirish { 221044961713Sgirish nxge_status_t status = NXGE_OK; 221144961713Sgirish 221244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_alloc_mem_pool")); 221344961713Sgirish 221444961713Sgirish status = nxge_alloc_rx_mem_pool(nxgep); 221544961713Sgirish if (status != NXGE_OK) { 221644961713Sgirish return (NXGE_ERROR); 221744961713Sgirish } 221844961713Sgirish 221944961713Sgirish status = nxge_alloc_tx_mem_pool(nxgep); 222044961713Sgirish if (status != NXGE_OK) { 222144961713Sgirish nxge_free_rx_mem_pool(nxgep); 222244961713Sgirish return (NXGE_ERROR); 222344961713Sgirish } 222444961713Sgirish 222544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_alloc_mem_pool")); 222644961713Sgirish return (NXGE_OK); 222744961713Sgirish } 222844961713Sgirish 222944961713Sgirish static void 223044961713Sgirish nxge_free_mem_pool(p_nxge_t nxgep) 223144961713Sgirish { 223244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_mem_pool")); 223344961713Sgirish 223444961713Sgirish nxge_free_rx_mem_pool(nxgep); 223544961713Sgirish nxge_free_tx_mem_pool(nxgep); 223644961713Sgirish 223744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_mem_pool")); 223844961713Sgirish } 223944961713Sgirish 2240678453a8Sspeer nxge_status_t 224144961713Sgirish nxge_alloc_rx_mem_pool(p_nxge_t nxgep) 224244961713Sgirish { 2243678453a8Sspeer uint32_t rdc_max; 224444961713Sgirish p_nxge_dma_pt_cfg_t p_all_cfgp; 224544961713Sgirish p_nxge_hw_pt_cfg_t p_cfgp; 224644961713Sgirish p_nxge_dma_pool_t dma_poolp; 224744961713Sgirish p_nxge_dma_common_t *dma_buf_p; 224844961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 224944961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 225044961713Sgirish uint32_t *num_chunks; /* per dma */ 225144961713Sgirish nxge_status_t status = NXGE_OK; 225244961713Sgirish 225344961713Sgirish uint32_t nxge_port_rbr_size; 225444961713Sgirish uint32_t nxge_port_rbr_spare_size; 225544961713Sgirish uint32_t nxge_port_rcr_size; 2256678453a8Sspeer uint32_t rx_cntl_alloc_size; 225744961713Sgirish 225844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_mem_pool")); 225944961713Sgirish 226044961713Sgirish p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 226144961713Sgirish p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 2262678453a8Sspeer rdc_max = NXGE_MAX_RDCS; 226344961713Sgirish 226444961713Sgirish /* 2265678453a8Sspeer * Allocate memory for the common DMA data structures. 226644961713Sgirish */ 226744961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 22684045d941Ssowmini KM_SLEEP); 226944961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 22704045d941Ssowmini sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP); 227144961713Sgirish 227244961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 22734045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 227444961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 22754045d941Ssowmini sizeof (p_nxge_dma_common_t) * rdc_max, KM_SLEEP); 227644961713Sgirish 227744961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 22784045d941Ssowmini sizeof (uint32_t) * rdc_max, KM_SLEEP); 227944961713Sgirish 228044961713Sgirish /* 2281678453a8Sspeer * Assume that each DMA channel will be configured with 2282678453a8Sspeer * the default block size. 2283678453a8Sspeer * rbr block counts are modulo the batch count (16). 228444961713Sgirish */ 228544961713Sgirish nxge_port_rbr_size = p_all_cfgp->rbr_size; 228644961713Sgirish nxge_port_rcr_size = p_all_cfgp->rcr_size; 228744961713Sgirish 228844961713Sgirish if (!nxge_port_rbr_size) { 228944961713Sgirish nxge_port_rbr_size = NXGE_RBR_RBB_DEFAULT; 229044961713Sgirish } 229144961713Sgirish if (nxge_port_rbr_size % NXGE_RXDMA_POST_BATCH) { 229244961713Sgirish nxge_port_rbr_size = (NXGE_RXDMA_POST_BATCH * 22934045d941Ssowmini (nxge_port_rbr_size / NXGE_RXDMA_POST_BATCH + 1)); 229444961713Sgirish } 229544961713Sgirish 229644961713Sgirish p_all_cfgp->rbr_size = nxge_port_rbr_size; 229744961713Sgirish nxge_port_rbr_spare_size = nxge_rbr_spare_size; 229844961713Sgirish 229944961713Sgirish if (nxge_port_rbr_spare_size % NXGE_RXDMA_POST_BATCH) { 230044961713Sgirish nxge_port_rbr_spare_size = (NXGE_RXDMA_POST_BATCH * 23014045d941Ssowmini (nxge_port_rbr_spare_size / NXGE_RXDMA_POST_BATCH + 1)); 230244961713Sgirish } 230330ac2e7bSml if (nxge_port_rbr_size > RBR_DEFAULT_MAX_BLKS) { 230430ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 230530ac2e7bSml "nxge_alloc_rx_mem_pool: RBR size too high %d, " 230630ac2e7bSml "set to default %d", 230730ac2e7bSml nxge_port_rbr_size, RBR_DEFAULT_MAX_BLKS)); 230830ac2e7bSml nxge_port_rbr_size = RBR_DEFAULT_MAX_BLKS; 230930ac2e7bSml } 231030ac2e7bSml if (nxge_port_rcr_size > RCR_DEFAULT_MAX) { 231130ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 231230ac2e7bSml "nxge_alloc_rx_mem_pool: RCR too high %d, " 231330ac2e7bSml "set to default %d", 231430ac2e7bSml nxge_port_rcr_size, RCR_DEFAULT_MAX)); 231530ac2e7bSml nxge_port_rcr_size = RCR_DEFAULT_MAX; 231630ac2e7bSml } 231744961713Sgirish 231844961713Sgirish /* 231944961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 232044961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 232144961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 232244961713Sgirish * function). 232344961713Sgirish */ 232444961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 232544961713Sgirish if (nxgep->niu_type == N2_NIU) { 232644961713Sgirish nxge_port_rbr_spare_size = 0; 232744961713Sgirish if ((nxge_port_rbr_size > NXGE_NIU_CONTIG_RBR_MAX) || 23284045d941Ssowmini (!ISP2(nxge_port_rbr_size))) { 232944961713Sgirish nxge_port_rbr_size = NXGE_NIU_CONTIG_RBR_MAX; 233044961713Sgirish } 233144961713Sgirish if ((nxge_port_rcr_size > NXGE_NIU_CONTIG_RCR_MAX) || 23324045d941Ssowmini (!ISP2(nxge_port_rcr_size))) { 233344961713Sgirish nxge_port_rcr_size = NXGE_NIU_CONTIG_RCR_MAX; 233444961713Sgirish } 233544961713Sgirish } 233644961713Sgirish #endif 233744961713Sgirish 233844961713Sgirish /* 233944961713Sgirish * Addresses of receive block ring, receive completion ring and the 234044961713Sgirish * mailbox must be all cache-aligned (64 bytes). 234144961713Sgirish */ 234244961713Sgirish rx_cntl_alloc_size = nxge_port_rbr_size + nxge_port_rbr_spare_size; 234344961713Sgirish rx_cntl_alloc_size *= (sizeof (rx_desc_t)); 234444961713Sgirish rx_cntl_alloc_size += (sizeof (rcr_entry_t) * nxge_port_rcr_size); 234544961713Sgirish rx_cntl_alloc_size += sizeof (rxdma_mailbox_t); 234644961713Sgirish 234744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_alloc_rx_mem_pool: " 23484045d941Ssowmini "nxge_port_rbr_size = %d nxge_port_rbr_spare_size = %d " 23494045d941Ssowmini "nxge_port_rcr_size = %d " 23504045d941Ssowmini "rx_cntl_alloc_size = %d", 23514045d941Ssowmini nxge_port_rbr_size, nxge_port_rbr_spare_size, 23524045d941Ssowmini nxge_port_rcr_size, 23534045d941Ssowmini rx_cntl_alloc_size)); 235444961713Sgirish 235544961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 235644961713Sgirish if (nxgep->niu_type == N2_NIU) { 2357678453a8Sspeer uint32_t rx_buf_alloc_size = (nxgep->rx_default_block_size * 2358678453a8Sspeer (nxge_port_rbr_size + nxge_port_rbr_spare_size)); 2359678453a8Sspeer 236044961713Sgirish if (!ISP2(rx_buf_alloc_size)) { 236144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 23624045d941Ssowmini "==> nxge_alloc_rx_mem_pool: " 23634045d941Ssowmini " must be power of 2")); 236444961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 236544961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 236644961713Sgirish } 236744961713Sgirish 236844961713Sgirish if (rx_buf_alloc_size > (1 << 22)) { 236944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 23704045d941Ssowmini "==> nxge_alloc_rx_mem_pool: " 23714045d941Ssowmini " limit size to 4M")); 237244961713Sgirish status |= (NXGE_ERROR | NXGE_DDI_FAILED); 237344961713Sgirish goto nxge_alloc_rx_mem_pool_exit; 237444961713Sgirish } 237544961713Sgirish 237644961713Sgirish if (rx_cntl_alloc_size < 0x2000) { 237744961713Sgirish rx_cntl_alloc_size = 0x2000; 237844961713Sgirish } 237944961713Sgirish } 238044961713Sgirish #endif 238144961713Sgirish nxgep->nxge_port_rbr_size = nxge_port_rbr_size; 238244961713Sgirish nxgep->nxge_port_rcr_size = nxge_port_rcr_size; 2383678453a8Sspeer nxgep->nxge_port_rbr_spare_size = nxge_port_rbr_spare_size; 2384678453a8Sspeer nxgep->nxge_port_rx_cntl_alloc_size = rx_cntl_alloc_size; 238544961713Sgirish 2386678453a8Sspeer dma_poolp->ndmas = p_cfgp->max_rdcs; 238744961713Sgirish dma_poolp->num_chunks = num_chunks; 238844961713Sgirish dma_poolp->buf_allocated = B_TRUE; 238944961713Sgirish nxgep->rx_buf_pool_p = dma_poolp; 239044961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 239144961713Sgirish 2392678453a8Sspeer dma_cntl_poolp->ndmas = p_cfgp->max_rdcs; 239344961713Sgirish dma_cntl_poolp->buf_allocated = B_TRUE; 239444961713Sgirish nxgep->rx_cntl_pool_p = dma_cntl_poolp; 239544961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 239644961713Sgirish 2397678453a8Sspeer /* Allocate the receive rings, too. */ 2398678453a8Sspeer nxgep->rx_rbr_rings = 23994045d941Ssowmini KMEM_ZALLOC(sizeof (rx_rbr_rings_t), KM_SLEEP); 2400678453a8Sspeer nxgep->rx_rbr_rings->rbr_rings = 24014045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_rbr_ring_t) * rdc_max, KM_SLEEP); 2402678453a8Sspeer nxgep->rx_rcr_rings = 24034045d941Ssowmini KMEM_ZALLOC(sizeof (rx_rcr_rings_t), KM_SLEEP); 2404678453a8Sspeer nxgep->rx_rcr_rings->rcr_rings = 24054045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_rcr_ring_t) * rdc_max, KM_SLEEP); 2406678453a8Sspeer nxgep->rx_mbox_areas_p = 24074045d941Ssowmini KMEM_ZALLOC(sizeof (rx_mbox_areas_t), KM_SLEEP); 2408678453a8Sspeer nxgep->rx_mbox_areas_p->rxmbox_areas = 24094045d941Ssowmini KMEM_ZALLOC(sizeof (p_rx_mbox_t) * rdc_max, KM_SLEEP); 2410678453a8Sspeer 2411678453a8Sspeer nxgep->rx_rbr_rings->ndmas = nxgep->rx_rcr_rings->ndmas = 2412678453a8Sspeer p_cfgp->max_rdcs; 241344961713Sgirish 241444961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 24154045d941Ssowmini "<== nxge_alloc_rx_mem_pool:status 0x%08x", status)); 241644961713Sgirish 2417678453a8Sspeer nxge_alloc_rx_mem_pool_exit: 2418678453a8Sspeer return (status); 2419678453a8Sspeer } 2420678453a8Sspeer 2421678453a8Sspeer /* 2422678453a8Sspeer * nxge_alloc_rxb 2423678453a8Sspeer * 2424678453a8Sspeer * Allocate buffers for an RDC. 2425678453a8Sspeer * 2426678453a8Sspeer * Arguments: 2427678453a8Sspeer * nxgep 2428678453a8Sspeer * channel The channel to map into our kernel space. 2429678453a8Sspeer * 2430678453a8Sspeer * Notes: 2431678453a8Sspeer * 2432678453a8Sspeer * NPI function calls: 2433678453a8Sspeer * 2434678453a8Sspeer * NXGE function calls: 2435678453a8Sspeer * 2436678453a8Sspeer * Registers accessed: 2437678453a8Sspeer * 2438678453a8Sspeer * Context: 2439678453a8Sspeer * 2440678453a8Sspeer * Taking apart: 2441678453a8Sspeer * 2442678453a8Sspeer * Open questions: 2443678453a8Sspeer * 2444678453a8Sspeer */ 2445678453a8Sspeer nxge_status_t 2446678453a8Sspeer nxge_alloc_rxb( 2447678453a8Sspeer p_nxge_t nxgep, 2448678453a8Sspeer int channel) 2449678453a8Sspeer { 2450678453a8Sspeer size_t rx_buf_alloc_size; 2451678453a8Sspeer nxge_status_t status = NXGE_OK; 2452678453a8Sspeer 2453678453a8Sspeer nxge_dma_common_t **data; 2454678453a8Sspeer nxge_dma_common_t **control; 2455678453a8Sspeer uint32_t *num_chunks; 2456678453a8Sspeer 2457678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb")); 2458678453a8Sspeer 2459678453a8Sspeer /* 2460678453a8Sspeer * Allocate memory for the receive buffers and descriptor rings. 2461678453a8Sspeer * Replace these allocation functions with the interface functions 2462678453a8Sspeer * provided by the partition manager if/when they are available. 2463678453a8Sspeer */ 2464678453a8Sspeer 2465678453a8Sspeer /* 2466678453a8Sspeer * Allocate memory for the receive buffer blocks. 2467678453a8Sspeer */ 2468678453a8Sspeer rx_buf_alloc_size = (nxgep->rx_default_block_size * 24694045d941Ssowmini (nxgep->nxge_port_rbr_size + nxgep->nxge_port_rbr_spare_size)); 2470678453a8Sspeer 2471678453a8Sspeer data = &nxgep->rx_buf_pool_p->dma_buf_pool_p[channel]; 2472678453a8Sspeer num_chunks = &nxgep->rx_buf_pool_p->num_chunks[channel]; 2473678453a8Sspeer 2474678453a8Sspeer if ((status = nxge_alloc_rx_buf_dma( 2475678453a8Sspeer nxgep, channel, data, rx_buf_alloc_size, 2476678453a8Sspeer nxgep->rx_default_block_size, num_chunks)) != NXGE_OK) { 2477678453a8Sspeer return (status); 247844961713Sgirish } 247944961713Sgirish 2480678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_alloc_rxb(): " 2481678453a8Sspeer "dma %d dma_buf_p %llx &dma_buf_p %llx", channel, *data, data)); 2482678453a8Sspeer 2483678453a8Sspeer /* 2484678453a8Sspeer * Allocate memory for descriptor rings and mailbox. 2485678453a8Sspeer */ 2486678453a8Sspeer control = &nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel]; 2487678453a8Sspeer 2488678453a8Sspeer if ((status = nxge_alloc_rx_cntl_dma( 2489678453a8Sspeer nxgep, channel, control, nxgep->nxge_port_rx_cntl_alloc_size)) 2490678453a8Sspeer != NXGE_OK) { 2491678453a8Sspeer nxge_free_rx_cntl_dma(nxgep, *control); 2492678453a8Sspeer (*data)->buf_alloc_state |= BUF_ALLOCATED_WAIT_FREE; 2493678453a8Sspeer nxge_free_rx_buf_dma(nxgep, *data, *num_chunks); 2494678453a8Sspeer return (status); 2495678453a8Sspeer } 249644961713Sgirish 249744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 2498678453a8Sspeer "<== nxge_alloc_rx_mem_pool:status 0x%08x", status)); 249944961713Sgirish 250044961713Sgirish return (status); 250144961713Sgirish } 250244961713Sgirish 2503678453a8Sspeer void 2504678453a8Sspeer nxge_free_rxb( 2505678453a8Sspeer p_nxge_t nxgep, 2506678453a8Sspeer int channel) 2507678453a8Sspeer { 2508678453a8Sspeer nxge_dma_common_t *data; 2509678453a8Sspeer nxge_dma_common_t *control; 2510678453a8Sspeer uint32_t num_chunks; 2511678453a8Sspeer 2512678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rbb")); 2513678453a8Sspeer 2514678453a8Sspeer data = nxgep->rx_buf_pool_p->dma_buf_pool_p[channel]; 2515678453a8Sspeer num_chunks = nxgep->rx_buf_pool_p->num_chunks[channel]; 2516678453a8Sspeer nxge_free_rx_buf_dma(nxgep, data, num_chunks); 2517678453a8Sspeer 2518678453a8Sspeer nxgep->rx_buf_pool_p->dma_buf_pool_p[channel] = 0; 2519678453a8Sspeer nxgep->rx_buf_pool_p->num_chunks[channel] = 0; 2520678453a8Sspeer 2521678453a8Sspeer control = nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel]; 2522678453a8Sspeer nxge_free_rx_cntl_dma(nxgep, control); 2523678453a8Sspeer 2524678453a8Sspeer nxgep->rx_cntl_pool_p->dma_buf_pool_p[channel] = 0; 2525678453a8Sspeer 2526678453a8Sspeer KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 2527678453a8Sspeer KMEM_FREE(control, sizeof (nxge_dma_common_t)); 2528678453a8Sspeer 2529678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_alloc_rbb")); 2530678453a8Sspeer } 2531678453a8Sspeer 253244961713Sgirish static void 253344961713Sgirish nxge_free_rx_mem_pool(p_nxge_t nxgep) 253444961713Sgirish { 2535678453a8Sspeer int rdc_max = NXGE_MAX_RDCS; 253644961713Sgirish 253744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_mem_pool")); 253844961713Sgirish 2539678453a8Sspeer if (!nxgep->rx_buf_pool_p || !nxgep->rx_buf_pool_p->buf_allocated) { 254044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 25414045d941Ssowmini "<== nxge_free_rx_mem_pool " 25424045d941Ssowmini "(null rx buf pool or buf not allocated")); 254344961713Sgirish return; 254444961713Sgirish } 2545678453a8Sspeer if (!nxgep->rx_cntl_pool_p || !nxgep->rx_cntl_pool_p->buf_allocated) { 254644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 25474045d941Ssowmini "<== nxge_free_rx_mem_pool " 25484045d941Ssowmini "(null rx cntl buf pool or cntl buf not allocated")); 254944961713Sgirish return; 255044961713Sgirish } 255144961713Sgirish 2552678453a8Sspeer KMEM_FREE(nxgep->rx_cntl_pool_p->dma_buf_pool_p, 2553678453a8Sspeer sizeof (p_nxge_dma_common_t) * rdc_max); 2554678453a8Sspeer KMEM_FREE(nxgep->rx_cntl_pool_p, sizeof (nxge_dma_pool_t)); 255544961713Sgirish 2556678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p->num_chunks, 2557678453a8Sspeer sizeof (uint32_t) * rdc_max); 2558678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p->dma_buf_pool_p, 2559678453a8Sspeer sizeof (p_nxge_dma_common_t) * rdc_max); 2560678453a8Sspeer KMEM_FREE(nxgep->rx_buf_pool_p, sizeof (nxge_dma_pool_t)); 256144961713Sgirish 2562678453a8Sspeer nxgep->rx_buf_pool_p = 0; 2563678453a8Sspeer nxgep->rx_cntl_pool_p = 0; 256444961713Sgirish 2565678453a8Sspeer KMEM_FREE(nxgep->rx_rbr_rings->rbr_rings, 2566678453a8Sspeer sizeof (p_rx_rbr_ring_t) * rdc_max); 2567678453a8Sspeer KMEM_FREE(nxgep->rx_rbr_rings, sizeof (rx_rbr_rings_t)); 2568678453a8Sspeer KMEM_FREE(nxgep->rx_rcr_rings->rcr_rings, 2569678453a8Sspeer sizeof (p_rx_rcr_ring_t) * rdc_max); 2570678453a8Sspeer KMEM_FREE(nxgep->rx_rcr_rings, sizeof (rx_rcr_rings_t)); 2571678453a8Sspeer KMEM_FREE(nxgep->rx_mbox_areas_p->rxmbox_areas, 2572678453a8Sspeer sizeof (p_rx_mbox_t) * rdc_max); 2573678453a8Sspeer KMEM_FREE(nxgep->rx_mbox_areas_p, sizeof (rx_mbox_areas_t)); 257444961713Sgirish 2575678453a8Sspeer nxgep->rx_rbr_rings = 0; 2576678453a8Sspeer nxgep->rx_rcr_rings = 0; 2577678453a8Sspeer nxgep->rx_mbox_areas_p = 0; 257844961713Sgirish 257944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_rx_mem_pool")); 258044961713Sgirish } 258144961713Sgirish 258244961713Sgirish 258344961713Sgirish static nxge_status_t 258444961713Sgirish nxge_alloc_rx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 258544961713Sgirish p_nxge_dma_common_t *dmap, 258644961713Sgirish size_t alloc_size, size_t block_size, uint32_t *num_chunks) 258744961713Sgirish { 258844961713Sgirish p_nxge_dma_common_t rx_dmap; 258944961713Sgirish nxge_status_t status = NXGE_OK; 259044961713Sgirish size_t total_alloc_size; 259144961713Sgirish size_t allocated = 0; 259244961713Sgirish int i, size_index, array_size; 2593678453a8Sspeer boolean_t use_kmem_alloc = B_FALSE; 259444961713Sgirish 259544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_buf_dma")); 259644961713Sgirish 259744961713Sgirish rx_dmap = (p_nxge_dma_common_t) 25984045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 25994045d941Ssowmini KM_SLEEP); 260044961713Sgirish 260144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 26024045d941Ssowmini " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ", 26034045d941Ssowmini dma_channel, alloc_size, block_size, dmap)); 260444961713Sgirish 260544961713Sgirish total_alloc_size = alloc_size; 260644961713Sgirish 260744961713Sgirish #if defined(RX_USE_RECLAIM_POST) 260844961713Sgirish total_alloc_size = alloc_size + alloc_size/4; 260944961713Sgirish #endif 261044961713Sgirish 261144961713Sgirish i = 0; 261244961713Sgirish size_index = 0; 261344961713Sgirish array_size = sizeof (alloc_sizes)/sizeof (size_t); 26147b26d9ffSSantwona Behera while ((size_index < array_size) && 26157b26d9ffSSantwona Behera (alloc_sizes[size_index] < alloc_size)) 26164045d941Ssowmini size_index++; 261744961713Sgirish if (size_index >= array_size) { 261844961713Sgirish size_index = array_size - 1; 261944961713Sgirish } 262044961713Sgirish 2621678453a8Sspeer /* For Neptune, use kmem_alloc if the kmem flag is set. */ 2622678453a8Sspeer if (nxgep->niu_type != N2_NIU && nxge_use_kmem_alloc) { 2623678453a8Sspeer use_kmem_alloc = B_TRUE; 2624678453a8Sspeer #if defined(__i386) || defined(__amd64) 2625678453a8Sspeer size_index = 0; 2626678453a8Sspeer #endif 2627678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2628678453a8Sspeer "==> nxge_alloc_rx_buf_dma: " 2629678453a8Sspeer "Neptune use kmem_alloc() - size_index %d", 2630678453a8Sspeer size_index)); 2631678453a8Sspeer } 2632678453a8Sspeer 263344961713Sgirish while ((allocated < total_alloc_size) && 26344045d941Ssowmini (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 263544961713Sgirish rx_dmap[i].dma_chunk_index = i; 263644961713Sgirish rx_dmap[i].block_size = block_size; 263744961713Sgirish rx_dmap[i].alength = alloc_sizes[size_index]; 263844961713Sgirish rx_dmap[i].orig_alength = rx_dmap[i].alength; 263944961713Sgirish rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 264044961713Sgirish rx_dmap[i].dma_channel = dma_channel; 264144961713Sgirish rx_dmap[i].contig_alloc_type = B_FALSE; 2642678453a8Sspeer rx_dmap[i].kmem_alloc_type = B_FALSE; 2643678453a8Sspeer rx_dmap[i].buf_alloc_type = DDI_MEM_ALLOC; 264444961713Sgirish 264544961713Sgirish /* 264644961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 264744961713Sgirish * needs to call Hypervisor api to set up 264844961713Sgirish * logical pages. 264944961713Sgirish */ 265044961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 265144961713Sgirish rx_dmap[i].contig_alloc_type = B_TRUE; 2652678453a8Sspeer rx_dmap[i].buf_alloc_type = CONTIG_MEM_ALLOC; 2653678453a8Sspeer } else if (use_kmem_alloc) { 2654678453a8Sspeer /* For Neptune, use kmem_alloc */ 2655678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2656678453a8Sspeer "==> nxge_alloc_rx_buf_dma: " 2657678453a8Sspeer "Neptune use kmem_alloc()")); 2658678453a8Sspeer rx_dmap[i].kmem_alloc_type = B_TRUE; 2659678453a8Sspeer rx_dmap[i].buf_alloc_type = KMEM_ALLOC; 266044961713Sgirish } 266144961713Sgirish 266244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 26634045d941Ssowmini "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x " 26644045d941Ssowmini "i %d nblocks %d alength %d", 26654045d941Ssowmini dma_channel, i, &rx_dmap[i], block_size, 26664045d941Ssowmini i, rx_dmap[i].nblocks, 26674045d941Ssowmini rx_dmap[i].alength)); 266844961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 26694045d941Ssowmini &nxge_rx_dma_attr, 26704045d941Ssowmini rx_dmap[i].alength, 26714045d941Ssowmini &nxge_dev_buf_dma_acc_attr, 26724045d941Ssowmini DDI_DMA_READ | DDI_DMA_STREAMING, 26734045d941Ssowmini (p_nxge_dma_common_t)(&rx_dmap[i])); 267444961713Sgirish if (status != NXGE_OK) { 267544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2676678453a8Sspeer "nxge_alloc_rx_buf_dma: Alloc Failed: " 2677678453a8Sspeer "dma %d size_index %d size requested %d", 2678678453a8Sspeer dma_channel, 2679678453a8Sspeer size_index, 2680678453a8Sspeer rx_dmap[i].alength)); 268144961713Sgirish size_index--; 268244961713Sgirish } else { 2683678453a8Sspeer rx_dmap[i].buf_alloc_state = BUF_ALLOCATED; 2684678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2685678453a8Sspeer " nxge_alloc_rx_buf_dma DONE alloc mem: " 2686678453a8Sspeer "dma %d dma_buf_p $%p kaddrp $%p alength %d " 2687678453a8Sspeer "buf_alloc_state %d alloc_type %d", 2688678453a8Sspeer dma_channel, 2689678453a8Sspeer &rx_dmap[i], 2690678453a8Sspeer rx_dmap[i].kaddrp, 2691678453a8Sspeer rx_dmap[i].alength, 2692678453a8Sspeer rx_dmap[i].buf_alloc_state, 2693678453a8Sspeer rx_dmap[i].buf_alloc_type)); 2694678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2695678453a8Sspeer " alloc_rx_buf_dma allocated rdc %d " 2696678453a8Sspeer "chunk %d size %x dvma %x bufp %llx kaddrp $%p", 2697678453a8Sspeer dma_channel, i, rx_dmap[i].alength, 2698678453a8Sspeer rx_dmap[i].ioaddr_pp, &rx_dmap[i], 2699678453a8Sspeer rx_dmap[i].kaddrp)); 270044961713Sgirish i++; 270144961713Sgirish allocated += alloc_sizes[size_index]; 270244961713Sgirish } 270344961713Sgirish } 270444961713Sgirish 270544961713Sgirish if (allocated < total_alloc_size) { 270630ac2e7bSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2707678453a8Sspeer "==> nxge_alloc_rx_buf_dma: not enough for channel %d " 270830ac2e7bSml "allocated 0x%x requested 0x%x", 270930ac2e7bSml dma_channel, 271030ac2e7bSml allocated, total_alloc_size)); 271130ac2e7bSml status = NXGE_ERROR; 271244961713Sgirish goto nxge_alloc_rx_mem_fail1; 271344961713Sgirish } 271444961713Sgirish 271530ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 2716678453a8Sspeer "==> nxge_alloc_rx_buf_dma: Allocated for channel %d " 271730ac2e7bSml "allocated 0x%x requested 0x%x", 271830ac2e7bSml dma_channel, 271930ac2e7bSml allocated, total_alloc_size)); 272030ac2e7bSml 272144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 27224045d941Ssowmini " alloc_rx_buf_dma rdc %d allocated %d chunks", 27234045d941Ssowmini dma_channel, i)); 272444961713Sgirish *num_chunks = i; 272544961713Sgirish *dmap = rx_dmap; 272644961713Sgirish 272744961713Sgirish goto nxge_alloc_rx_mem_exit; 272844961713Sgirish 272944961713Sgirish nxge_alloc_rx_mem_fail1: 273044961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 273144961713Sgirish 273244961713Sgirish nxge_alloc_rx_mem_exit: 273344961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 27344045d941Ssowmini "<== nxge_alloc_rx_buf_dma status 0x%08x", status)); 273544961713Sgirish 273644961713Sgirish return (status); 273744961713Sgirish } 273844961713Sgirish 273944961713Sgirish /*ARGSUSED*/ 274044961713Sgirish static void 274144961713Sgirish nxge_free_rx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 274244961713Sgirish uint32_t num_chunks) 274344961713Sgirish { 274444961713Sgirish int i; 274544961713Sgirish 274644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 27474045d941Ssowmini "==> nxge_free_rx_buf_dma: # of chunks %d", num_chunks)); 274844961713Sgirish 2749678453a8Sspeer if (dmap == 0) 2750678453a8Sspeer return; 2751678453a8Sspeer 275244961713Sgirish for (i = 0; i < num_chunks; i++) { 275344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 27544045d941Ssowmini "==> nxge_free_rx_buf_dma: chunk %d dmap 0x%llx", 27554045d941Ssowmini i, dmap)); 2756678453a8Sspeer nxge_dma_free_rx_data_buf(dmap++); 275744961713Sgirish } 275844961713Sgirish 275944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_buf_dma")); 276044961713Sgirish } 276144961713Sgirish 276244961713Sgirish /*ARGSUSED*/ 276344961713Sgirish static nxge_status_t 276444961713Sgirish nxge_alloc_rx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 276544961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 276644961713Sgirish { 276744961713Sgirish p_nxge_dma_common_t rx_dmap; 276844961713Sgirish nxge_status_t status = NXGE_OK; 276944961713Sgirish 277044961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_cntl_dma")); 277144961713Sgirish 277244961713Sgirish rx_dmap = (p_nxge_dma_common_t) 27734045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 277444961713Sgirish 277544961713Sgirish rx_dmap->contig_alloc_type = B_FALSE; 2776678453a8Sspeer rx_dmap->kmem_alloc_type = B_FALSE; 277744961713Sgirish 277844961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 27794045d941Ssowmini &nxge_desc_dma_attr, 27804045d941Ssowmini size, 27814045d941Ssowmini &nxge_dev_desc_dma_acc_attr, 27824045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 27834045d941Ssowmini rx_dmap); 278444961713Sgirish if (status != NXGE_OK) { 278544961713Sgirish goto nxge_alloc_rx_cntl_dma_fail1; 278644961713Sgirish } 278744961713Sgirish 278844961713Sgirish *dmap = rx_dmap; 278944961713Sgirish goto nxge_alloc_rx_cntl_dma_exit; 279044961713Sgirish 279144961713Sgirish nxge_alloc_rx_cntl_dma_fail1: 279244961713Sgirish KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t)); 279344961713Sgirish 279444961713Sgirish nxge_alloc_rx_cntl_dma_exit: 279544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 27964045d941Ssowmini "<== nxge_alloc_rx_cntl_dma status 0x%08x", status)); 279744961713Sgirish 2798678453a8Sspeer return (status); 2799678453a8Sspeer } 2800678453a8Sspeer 2801678453a8Sspeer /*ARGSUSED*/ 2802678453a8Sspeer static void 2803678453a8Sspeer nxge_free_rx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 2804678453a8Sspeer { 2805678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_rx_cntl_dma")); 2806678453a8Sspeer 2807678453a8Sspeer if (dmap == 0) 2808678453a8Sspeer return; 2809678453a8Sspeer 2810678453a8Sspeer nxge_dma_mem_free(dmap); 2811678453a8Sspeer 2812678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_rx_cntl_dma")); 2813678453a8Sspeer } 2814678453a8Sspeer 2815678453a8Sspeer typedef struct { 2816678453a8Sspeer size_t tx_size; 2817678453a8Sspeer size_t cr_size; 2818678453a8Sspeer size_t threshhold; 2819678453a8Sspeer } nxge_tdc_sizes_t; 2820678453a8Sspeer 2821678453a8Sspeer static 2822678453a8Sspeer nxge_status_t 2823678453a8Sspeer nxge_tdc_sizes( 2824678453a8Sspeer nxge_t *nxgep, 2825678453a8Sspeer nxge_tdc_sizes_t *sizes) 2826678453a8Sspeer { 2827678453a8Sspeer uint32_t threshhold; /* The bcopy() threshhold */ 2828678453a8Sspeer size_t tx_size; /* Transmit buffer size */ 2829678453a8Sspeer size_t cr_size; /* Completion ring size */ 2830678453a8Sspeer 2831678453a8Sspeer /* 2832678453a8Sspeer * Assume that each DMA channel will be configured with the 2833678453a8Sspeer * default transmit buffer size for copying transmit data. 2834678453a8Sspeer * (If a packet is bigger than this, it will not be copied.) 2835678453a8Sspeer */ 2836678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 2837678453a8Sspeer threshhold = TX_BCOPY_SIZE; 2838678453a8Sspeer } else { 2839678453a8Sspeer threshhold = nxge_bcopy_thresh; 2840678453a8Sspeer } 2841678453a8Sspeer tx_size = nxge_tx_ring_size * threshhold; 2842678453a8Sspeer 2843678453a8Sspeer cr_size = nxge_tx_ring_size * sizeof (tx_desc_t); 2844678453a8Sspeer cr_size += sizeof (txdma_mailbox_t); 2845678453a8Sspeer 2846678453a8Sspeer #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 2847678453a8Sspeer if (nxgep->niu_type == N2_NIU) { 2848678453a8Sspeer if (!ISP2(tx_size)) { 2849678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 28504045d941Ssowmini "==> nxge_tdc_sizes: Tx size" 28514045d941Ssowmini " must be power of 2")); 2852678453a8Sspeer return (NXGE_ERROR); 2853678453a8Sspeer } 2854678453a8Sspeer 2855678453a8Sspeer if (tx_size > (1 << 22)) { 2856678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 28574045d941Ssowmini "==> nxge_tdc_sizes: Tx size" 28584045d941Ssowmini " limited to 4M")); 2859678453a8Sspeer return (NXGE_ERROR); 2860678453a8Sspeer } 2861678453a8Sspeer 2862678453a8Sspeer if (cr_size < 0x2000) 2863678453a8Sspeer cr_size = 0x2000; 2864678453a8Sspeer } 2865678453a8Sspeer #endif 2866678453a8Sspeer 2867678453a8Sspeer sizes->threshhold = threshhold; 2868678453a8Sspeer sizes->tx_size = tx_size; 2869678453a8Sspeer sizes->cr_size = cr_size; 2870678453a8Sspeer 2871678453a8Sspeer return (NXGE_OK); 2872678453a8Sspeer } 2873678453a8Sspeer /* 2874678453a8Sspeer * nxge_alloc_txb 2875678453a8Sspeer * 2876678453a8Sspeer * Allocate buffers for an TDC. 2877678453a8Sspeer * 2878678453a8Sspeer * Arguments: 2879678453a8Sspeer * nxgep 2880678453a8Sspeer * channel The channel to map into our kernel space. 2881678453a8Sspeer * 2882678453a8Sspeer * Notes: 2883678453a8Sspeer * 2884678453a8Sspeer * NPI function calls: 2885678453a8Sspeer * 2886678453a8Sspeer * NXGE function calls: 2887678453a8Sspeer * 2888678453a8Sspeer * Registers accessed: 2889678453a8Sspeer * 2890678453a8Sspeer * Context: 2891678453a8Sspeer * 2892678453a8Sspeer * Taking apart: 2893678453a8Sspeer * 2894678453a8Sspeer * Open questions: 2895678453a8Sspeer * 2896678453a8Sspeer */ 2897678453a8Sspeer nxge_status_t 2898678453a8Sspeer nxge_alloc_txb( 2899678453a8Sspeer p_nxge_t nxgep, 2900678453a8Sspeer int channel) 2901678453a8Sspeer { 2902678453a8Sspeer nxge_dma_common_t **dma_buf_p; 2903678453a8Sspeer nxge_dma_common_t **dma_cntl_p; 2904678453a8Sspeer uint32_t *num_chunks; 2905678453a8Sspeer nxge_status_t status = NXGE_OK; 2906678453a8Sspeer 2907678453a8Sspeer nxge_tdc_sizes_t sizes; 2908678453a8Sspeer 2909678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tbb")); 2910678453a8Sspeer 2911678453a8Sspeer if (nxge_tdc_sizes(nxgep, &sizes) != NXGE_OK) 2912678453a8Sspeer return (NXGE_ERROR); 2913678453a8Sspeer 2914678453a8Sspeer /* 2915678453a8Sspeer * Allocate memory for transmit buffers and descriptor rings. 2916678453a8Sspeer * Replace these allocation functions with the interface functions 2917678453a8Sspeer * provided by the partition manager Real Soon Now. 2918678453a8Sspeer */ 2919678453a8Sspeer dma_buf_p = &nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2920678453a8Sspeer num_chunks = &nxgep->tx_buf_pool_p->num_chunks[channel]; 2921678453a8Sspeer 2922678453a8Sspeer dma_cntl_p = &nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2923678453a8Sspeer 2924678453a8Sspeer /* 2925678453a8Sspeer * Allocate memory for transmit buffers and descriptor rings. 2926678453a8Sspeer * Replace allocation functions with interface functions provided 2927678453a8Sspeer * by the partition manager when it is available. 2928678453a8Sspeer * 2929678453a8Sspeer * Allocate memory for the transmit buffer pool. 2930678453a8Sspeer */ 2931678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 29324045d941Ssowmini "sizes: tx: %ld, cr:%ld, th:%ld", 29334045d941Ssowmini sizes.tx_size, sizes.cr_size, sizes.threshhold)); 2934678453a8Sspeer 2935678453a8Sspeer *num_chunks = 0; 2936678453a8Sspeer status = nxge_alloc_tx_buf_dma(nxgep, channel, dma_buf_p, 2937678453a8Sspeer sizes.tx_size, sizes.threshhold, num_chunks); 2938678453a8Sspeer if (status != NXGE_OK) { 2939678453a8Sspeer cmn_err(CE_NOTE, "nxge_alloc_tx_buf_dma failed!"); 2940678453a8Sspeer return (status); 2941678453a8Sspeer } 2942678453a8Sspeer 2943678453a8Sspeer /* 2944678453a8Sspeer * Allocate memory for descriptor rings and mailbox. 2945678453a8Sspeer */ 2946678453a8Sspeer status = nxge_alloc_tx_cntl_dma(nxgep, channel, dma_cntl_p, 2947678453a8Sspeer sizes.cr_size); 2948678453a8Sspeer if (status != NXGE_OK) { 2949678453a8Sspeer nxge_free_tx_buf_dma(nxgep, *dma_buf_p, *num_chunks); 2950678453a8Sspeer cmn_err(CE_NOTE, "nxge_alloc_tx_cntl_dma failed!"); 2951678453a8Sspeer return (status); 2952678453a8Sspeer } 2953678453a8Sspeer 2954678453a8Sspeer return (NXGE_OK); 2955678453a8Sspeer } 2956678453a8Sspeer 2957678453a8Sspeer void 2958678453a8Sspeer nxge_free_txb( 2959678453a8Sspeer p_nxge_t nxgep, 2960678453a8Sspeer int channel) 2961678453a8Sspeer { 2962678453a8Sspeer nxge_dma_common_t *data; 2963678453a8Sspeer nxge_dma_common_t *control; 2964678453a8Sspeer uint32_t num_chunks; 2965678453a8Sspeer 2966678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_txb")); 2967678453a8Sspeer 2968678453a8Sspeer data = nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2969678453a8Sspeer num_chunks = nxgep->tx_buf_pool_p->num_chunks[channel]; 2970678453a8Sspeer nxge_free_tx_buf_dma(nxgep, data, num_chunks); 2971678453a8Sspeer 2972678453a8Sspeer nxgep->tx_buf_pool_p->dma_buf_pool_p[channel] = 0; 2973678453a8Sspeer nxgep->tx_buf_pool_p->num_chunks[channel] = 0; 2974678453a8Sspeer 2975678453a8Sspeer control = nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2976678453a8Sspeer nxge_free_tx_cntl_dma(nxgep, control); 297744961713Sgirish 2978678453a8Sspeer nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel] = 0; 297944961713Sgirish 2980678453a8Sspeer KMEM_FREE(data, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 2981678453a8Sspeer KMEM_FREE(control, sizeof (nxge_dma_common_t)); 298244961713Sgirish 2983678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_txb")); 298444961713Sgirish } 298544961713Sgirish 2986678453a8Sspeer /* 2987678453a8Sspeer * nxge_alloc_tx_mem_pool 2988678453a8Sspeer * 2989678453a8Sspeer * This function allocates all of the per-port TDC control data structures. 2990678453a8Sspeer * The per-channel (TDC) data structures are allocated when needed. 2991678453a8Sspeer * 2992678453a8Sspeer * Arguments: 2993678453a8Sspeer * nxgep 2994678453a8Sspeer * 2995678453a8Sspeer * Notes: 2996678453a8Sspeer * 2997678453a8Sspeer * Context: 2998678453a8Sspeer * Any domain 2999678453a8Sspeer */ 3000678453a8Sspeer nxge_status_t 300144961713Sgirish nxge_alloc_tx_mem_pool(p_nxge_t nxgep) 300244961713Sgirish { 3003678453a8Sspeer nxge_hw_pt_cfg_t *p_cfgp; 3004678453a8Sspeer nxge_dma_pool_t *dma_poolp; 3005678453a8Sspeer nxge_dma_common_t **dma_buf_p; 3006678453a8Sspeer nxge_dma_pool_t *dma_cntl_poolp; 3007678453a8Sspeer nxge_dma_common_t **dma_cntl_p; 300844961713Sgirish uint32_t *num_chunks; /* per dma */ 3009678453a8Sspeer int tdc_max; 301044961713Sgirish 301144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool")); 301244961713Sgirish 3013678453a8Sspeer p_cfgp = &nxgep->pt_config.hw_config; 3014678453a8Sspeer tdc_max = NXGE_MAX_TDCS; 301544961713Sgirish 301644961713Sgirish /* 301744961713Sgirish * Allocate memory for each transmit DMA channel. 301844961713Sgirish */ 301944961713Sgirish dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t), 30204045d941Ssowmini KM_SLEEP); 302144961713Sgirish dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 30224045d941Ssowmini sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP); 302344961713Sgirish 302444961713Sgirish dma_cntl_poolp = (p_nxge_dma_pool_t) 30254045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP); 302644961713Sgirish dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC( 30274045d941Ssowmini sizeof (p_nxge_dma_common_t) * tdc_max, KM_SLEEP); 302844961713Sgirish 302930ac2e7bSml if (nxge_tx_ring_size > TDC_DEFAULT_MAX) { 303030ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM_CTL, 303130ac2e7bSml "nxge_alloc_tx_mem_pool: TDC too high %d, " 303230ac2e7bSml "set to default %d", 303330ac2e7bSml nxge_tx_ring_size, TDC_DEFAULT_MAX)); 303430ac2e7bSml nxge_tx_ring_size = TDC_DEFAULT_MAX; 303530ac2e7bSml } 303630ac2e7bSml 303744961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 303844961713Sgirish /* 303944961713Sgirish * N2/NIU has limitation on the descriptor sizes (contiguous 304044961713Sgirish * memory allocation on data buffers to 4M (contig_mem_alloc) 304144961713Sgirish * and little endian for control buffers (must use the ddi/dki mem alloc 304244961713Sgirish * function). The transmit ring is limited to 8K (includes the 304344961713Sgirish * mailbox). 304444961713Sgirish */ 304544961713Sgirish if (nxgep->niu_type == N2_NIU) { 304644961713Sgirish if ((nxge_tx_ring_size > NXGE_NIU_CONTIG_TX_MAX) || 30474045d941Ssowmini (!ISP2(nxge_tx_ring_size))) { 304844961713Sgirish nxge_tx_ring_size = NXGE_NIU_CONTIG_TX_MAX; 304944961713Sgirish } 305044961713Sgirish } 305144961713Sgirish #endif 305244961713Sgirish 305344961713Sgirish nxgep->nxge_port_tx_ring_size = nxge_tx_ring_size; 305444961713Sgirish 305544961713Sgirish num_chunks = (uint32_t *)KMEM_ZALLOC( 30564045d941Ssowmini sizeof (uint32_t) * tdc_max, KM_SLEEP); 305744961713Sgirish 3058678453a8Sspeer dma_poolp->ndmas = p_cfgp->tdc.owned; 305944961713Sgirish dma_poolp->num_chunks = num_chunks; 306044961713Sgirish dma_poolp->dma_buf_pool_p = dma_buf_p; 306144961713Sgirish nxgep->tx_buf_pool_p = dma_poolp; 306244961713Sgirish 3063678453a8Sspeer dma_poolp->buf_allocated = B_TRUE; 3064678453a8Sspeer 3065678453a8Sspeer dma_cntl_poolp->ndmas = p_cfgp->tdc.owned; 306644961713Sgirish dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 306744961713Sgirish nxgep->tx_cntl_pool_p = dma_cntl_poolp; 306844961713Sgirish 3069678453a8Sspeer dma_cntl_poolp->buf_allocated = B_TRUE; 307044961713Sgirish 3071678453a8Sspeer nxgep->tx_rings = 3072678453a8Sspeer KMEM_ZALLOC(sizeof (tx_rings_t), KM_SLEEP); 3073678453a8Sspeer nxgep->tx_rings->rings = 3074678453a8Sspeer KMEM_ZALLOC(sizeof (p_tx_ring_t) * tdc_max, KM_SLEEP); 3075678453a8Sspeer nxgep->tx_mbox_areas_p = 3076678453a8Sspeer KMEM_ZALLOC(sizeof (tx_mbox_areas_t), KM_SLEEP); 3077678453a8Sspeer nxgep->tx_mbox_areas_p->txmbox_areas_p = 3078678453a8Sspeer KMEM_ZALLOC(sizeof (p_tx_mbox_t) * tdc_max, KM_SLEEP); 307944961713Sgirish 3080678453a8Sspeer nxgep->tx_rings->ndmas = p_cfgp->tdc.owned; 308144961713Sgirish 308244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, 30834045d941Ssowmini "==> nxge_alloc_tx_mem_pool: ndmas %d poolp->ndmas %d", 30844045d941Ssowmini tdc_max, dma_poolp->ndmas)); 308544961713Sgirish 3086678453a8Sspeer return (NXGE_OK); 308744961713Sgirish } 308844961713Sgirish 3089678453a8Sspeer nxge_status_t 309044961713Sgirish nxge_alloc_tx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel, 309144961713Sgirish p_nxge_dma_common_t *dmap, size_t alloc_size, 309244961713Sgirish size_t block_size, uint32_t *num_chunks) 309344961713Sgirish { 309444961713Sgirish p_nxge_dma_common_t tx_dmap; 309544961713Sgirish nxge_status_t status = NXGE_OK; 309644961713Sgirish size_t total_alloc_size; 309744961713Sgirish size_t allocated = 0; 309844961713Sgirish int i, size_index, array_size; 309944961713Sgirish 310044961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_buf_dma")); 310144961713Sgirish 310244961713Sgirish tx_dmap = (p_nxge_dma_common_t) 31034045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK, 31044045d941Ssowmini KM_SLEEP); 310544961713Sgirish 310644961713Sgirish total_alloc_size = alloc_size; 310744961713Sgirish i = 0; 310844961713Sgirish size_index = 0; 310944961713Sgirish array_size = sizeof (alloc_sizes) / sizeof (size_t); 31107b26d9ffSSantwona Behera while ((size_index < array_size) && 31117b26d9ffSSantwona Behera (alloc_sizes[size_index] < alloc_size)) 311244961713Sgirish size_index++; 311344961713Sgirish if (size_index >= array_size) { 311444961713Sgirish size_index = array_size - 1; 311544961713Sgirish } 311644961713Sgirish 311744961713Sgirish while ((allocated < total_alloc_size) && 31184045d941Ssowmini (size_index >= 0) && (i < NXGE_DMA_BLOCK)) { 311944961713Sgirish 312044961713Sgirish tx_dmap[i].dma_chunk_index = i; 312144961713Sgirish tx_dmap[i].block_size = block_size; 312244961713Sgirish tx_dmap[i].alength = alloc_sizes[size_index]; 312344961713Sgirish tx_dmap[i].orig_alength = tx_dmap[i].alength; 312444961713Sgirish tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 312544961713Sgirish tx_dmap[i].dma_channel = dma_channel; 312644961713Sgirish tx_dmap[i].contig_alloc_type = B_FALSE; 3127678453a8Sspeer tx_dmap[i].kmem_alloc_type = B_FALSE; 312844961713Sgirish 312944961713Sgirish /* 313044961713Sgirish * N2/NIU: data buffers must be contiguous as the driver 313144961713Sgirish * needs to call Hypervisor api to set up 313244961713Sgirish * logical pages. 313344961713Sgirish */ 313444961713Sgirish if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) { 313544961713Sgirish tx_dmap[i].contig_alloc_type = B_TRUE; 313644961713Sgirish } 313744961713Sgirish 313844961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 31394045d941Ssowmini &nxge_tx_dma_attr, 31404045d941Ssowmini tx_dmap[i].alength, 31414045d941Ssowmini &nxge_dev_buf_dma_acc_attr, 31424045d941Ssowmini DDI_DMA_WRITE | DDI_DMA_STREAMING, 31434045d941Ssowmini (p_nxge_dma_common_t)(&tx_dmap[i])); 314444961713Sgirish if (status != NXGE_OK) { 314544961713Sgirish size_index--; 314644961713Sgirish } else { 314744961713Sgirish i++; 314844961713Sgirish allocated += alloc_sizes[size_index]; 314944961713Sgirish } 315044961713Sgirish } 315144961713Sgirish 315244961713Sgirish if (allocated < total_alloc_size) { 315330ac2e7bSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 315430ac2e7bSml "==> nxge_alloc_tx_buf_dma: not enough channel %d: " 315530ac2e7bSml "allocated 0x%x requested 0x%x", 315630ac2e7bSml dma_channel, 315730ac2e7bSml allocated, total_alloc_size)); 315830ac2e7bSml status = NXGE_ERROR; 315944961713Sgirish goto nxge_alloc_tx_mem_fail1; 316044961713Sgirish } 316144961713Sgirish 316230ac2e7bSml NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 316330ac2e7bSml "==> nxge_alloc_tx_buf_dma: Allocated for channel %d: " 316430ac2e7bSml "allocated 0x%x requested 0x%x", 316530ac2e7bSml dma_channel, 316630ac2e7bSml allocated, total_alloc_size)); 316730ac2e7bSml 316844961713Sgirish *num_chunks = i; 316944961713Sgirish *dmap = tx_dmap; 317044961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 31714045d941Ssowmini "==> nxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d", 31724045d941Ssowmini *dmap, i)); 317344961713Sgirish goto nxge_alloc_tx_mem_exit; 317444961713Sgirish 317544961713Sgirish nxge_alloc_tx_mem_fail1: 317644961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK); 317744961713Sgirish 317844961713Sgirish nxge_alloc_tx_mem_exit: 317944961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 31804045d941Ssowmini "<== nxge_alloc_tx_buf_dma status 0x%08x", status)); 318144961713Sgirish 318244961713Sgirish return (status); 318344961713Sgirish } 318444961713Sgirish 318544961713Sgirish /*ARGSUSED*/ 318644961713Sgirish static void 318744961713Sgirish nxge_free_tx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap, 318844961713Sgirish uint32_t num_chunks) 318944961713Sgirish { 319044961713Sgirish int i; 319144961713Sgirish 319244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_tx_buf_dma")); 319344961713Sgirish 3194678453a8Sspeer if (dmap == 0) 3195678453a8Sspeer return; 3196678453a8Sspeer 319744961713Sgirish for (i = 0; i < num_chunks; i++) { 319844961713Sgirish nxge_dma_mem_free(dmap++); 319944961713Sgirish } 320044961713Sgirish 320144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_tx_buf_dma")); 320244961713Sgirish } 320344961713Sgirish 320444961713Sgirish /*ARGSUSED*/ 3205678453a8Sspeer nxge_status_t 320644961713Sgirish nxge_alloc_tx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel, 320744961713Sgirish p_nxge_dma_common_t *dmap, size_t size) 320844961713Sgirish { 320944961713Sgirish p_nxge_dma_common_t tx_dmap; 321044961713Sgirish nxge_status_t status = NXGE_OK; 321144961713Sgirish 321244961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_cntl_dma")); 321344961713Sgirish tx_dmap = (p_nxge_dma_common_t) 32144045d941Ssowmini KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP); 321544961713Sgirish 321644961713Sgirish tx_dmap->contig_alloc_type = B_FALSE; 3217678453a8Sspeer tx_dmap->kmem_alloc_type = B_FALSE; 321844961713Sgirish 321944961713Sgirish status = nxge_dma_mem_alloc(nxgep, nxge_force_dma, 32204045d941Ssowmini &nxge_desc_dma_attr, 32214045d941Ssowmini size, 32224045d941Ssowmini &nxge_dev_desc_dma_acc_attr, 32234045d941Ssowmini DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 32244045d941Ssowmini tx_dmap); 322544961713Sgirish if (status != NXGE_OK) { 322644961713Sgirish goto nxge_alloc_tx_cntl_dma_fail1; 322744961713Sgirish } 322844961713Sgirish 322944961713Sgirish *dmap = tx_dmap; 323044961713Sgirish goto nxge_alloc_tx_cntl_dma_exit; 323144961713Sgirish 323244961713Sgirish nxge_alloc_tx_cntl_dma_fail1: 323344961713Sgirish KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t)); 323444961713Sgirish 323544961713Sgirish nxge_alloc_tx_cntl_dma_exit: 323644961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 32374045d941Ssowmini "<== nxge_alloc_tx_cntl_dma status 0x%08x", status)); 323844961713Sgirish 323944961713Sgirish return (status); 324044961713Sgirish } 324144961713Sgirish 324244961713Sgirish /*ARGSUSED*/ 324344961713Sgirish static void 324444961713Sgirish nxge_free_tx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap) 324544961713Sgirish { 324644961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_tx_cntl_dma")); 324744961713Sgirish 3248678453a8Sspeer if (dmap == 0) 3249678453a8Sspeer return; 3250678453a8Sspeer 325144961713Sgirish nxge_dma_mem_free(dmap); 325244961713Sgirish 325344961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_tx_cntl_dma")); 325444961713Sgirish } 325544961713Sgirish 3256678453a8Sspeer /* 3257678453a8Sspeer * nxge_free_tx_mem_pool 3258678453a8Sspeer * 3259678453a8Sspeer * This function frees all of the per-port TDC control data structures. 3260678453a8Sspeer * The per-channel (TDC) data structures are freed when the channel 3261678453a8Sspeer * is stopped. 3262678453a8Sspeer * 3263678453a8Sspeer * Arguments: 3264678453a8Sspeer * nxgep 3265678453a8Sspeer * 3266678453a8Sspeer * Notes: 3267678453a8Sspeer * 3268678453a8Sspeer * Context: 3269678453a8Sspeer * Any domain 3270678453a8Sspeer */ 327144961713Sgirish static void 327244961713Sgirish nxge_free_tx_mem_pool(p_nxge_t nxgep) 327344961713Sgirish { 3274678453a8Sspeer int tdc_max = NXGE_MAX_TDCS; 327544961713Sgirish 3276678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_tx_mem_pool")); 327744961713Sgirish 3278678453a8Sspeer if (!nxgep->tx_buf_pool_p || !nxgep->tx_buf_pool_p->buf_allocated) { 3279678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 32804045d941Ssowmini "<== nxge_free_tx_mem_pool " 32814045d941Ssowmini "(null tx buf pool or buf not allocated")); 328244961713Sgirish return; 328344961713Sgirish } 3284678453a8Sspeer if (!nxgep->tx_cntl_pool_p || !nxgep->tx_cntl_pool_p->buf_allocated) { 3285678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 32864045d941Ssowmini "<== nxge_free_tx_mem_pool " 32874045d941Ssowmini "(null tx cntl buf pool or cntl buf not allocated")); 328844961713Sgirish return; 328944961713Sgirish } 329044961713Sgirish 3291678453a8Sspeer /* 1. Free the mailboxes. */ 3292678453a8Sspeer KMEM_FREE(nxgep->tx_mbox_areas_p->txmbox_areas_p, 3293678453a8Sspeer sizeof (p_tx_mbox_t) * tdc_max); 3294678453a8Sspeer KMEM_FREE(nxgep->tx_mbox_areas_p, sizeof (tx_mbox_areas_t)); 329544961713Sgirish 3296678453a8Sspeer nxgep->tx_mbox_areas_p = 0; 329744961713Sgirish 3298678453a8Sspeer /* 2. Free the transmit ring arrays. */ 3299678453a8Sspeer KMEM_FREE(nxgep->tx_rings->rings, 3300678453a8Sspeer sizeof (p_tx_ring_t) * tdc_max); 3301678453a8Sspeer KMEM_FREE(nxgep->tx_rings, sizeof (tx_rings_t)); 330244961713Sgirish 3303678453a8Sspeer nxgep->tx_rings = 0; 330444961713Sgirish 3305678453a8Sspeer /* 3. Free the completion ring data structures. */ 3306678453a8Sspeer KMEM_FREE(nxgep->tx_cntl_pool_p->dma_buf_pool_p, 3307678453a8Sspeer sizeof (p_nxge_dma_common_t) * tdc_max); 3308678453a8Sspeer KMEM_FREE(nxgep->tx_cntl_pool_p, sizeof (nxge_dma_pool_t)); 330944961713Sgirish 3310678453a8Sspeer nxgep->tx_cntl_pool_p = 0; 331144961713Sgirish 3312678453a8Sspeer /* 4. Free the data ring data structures. */ 3313678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p->num_chunks, 3314678453a8Sspeer sizeof (uint32_t) * tdc_max); 3315678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p->dma_buf_pool_p, 3316678453a8Sspeer sizeof (p_nxge_dma_common_t) * tdc_max); 3317678453a8Sspeer KMEM_FREE(nxgep->tx_buf_pool_p, sizeof (nxge_dma_pool_t)); 331844961713Sgirish 3319678453a8Sspeer nxgep->tx_buf_pool_p = 0; 3320678453a8Sspeer 3321678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_tx_mem_pool")); 332244961713Sgirish } 332344961713Sgirish 332444961713Sgirish /*ARGSUSED*/ 332544961713Sgirish static nxge_status_t 332644961713Sgirish nxge_dma_mem_alloc(p_nxge_t nxgep, dma_method_t method, 332744961713Sgirish struct ddi_dma_attr *dma_attrp, 332844961713Sgirish size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags, 332944961713Sgirish p_nxge_dma_common_t dma_p) 333044961713Sgirish { 333144961713Sgirish caddr_t kaddrp; 333244961713Sgirish int ddi_status = DDI_SUCCESS; 333344961713Sgirish boolean_t contig_alloc_type; 3334678453a8Sspeer boolean_t kmem_alloc_type; 333544961713Sgirish 333644961713Sgirish contig_alloc_type = dma_p->contig_alloc_type; 333744961713Sgirish 333844961713Sgirish if (contig_alloc_type && (nxgep->niu_type != N2_NIU)) { 333944961713Sgirish /* 334044961713Sgirish * contig_alloc_type for contiguous memory only allowed 334144961713Sgirish * for N2/NIU. 334244961713Sgirish */ 334344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 33444045d941Ssowmini "nxge_dma_mem_alloc: alloc type not allowed (%d)", 33454045d941Ssowmini dma_p->contig_alloc_type)); 334644961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 334744961713Sgirish } 334844961713Sgirish 334944961713Sgirish dma_p->dma_handle = NULL; 335044961713Sgirish dma_p->acc_handle = NULL; 335144961713Sgirish dma_p->kaddrp = dma_p->last_kaddrp = NULL; 335244961713Sgirish dma_p->first_ioaddr_pp = dma_p->last_ioaddr_pp = NULL; 335344961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, dma_attrp, 33544045d941Ssowmini DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle); 335544961713Sgirish if (ddi_status != DDI_SUCCESS) { 335644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 33574045d941Ssowmini "nxge_dma_mem_alloc:ddi_dma_alloc_handle failed.")); 335844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 335944961713Sgirish } 336044961713Sgirish 3361678453a8Sspeer kmem_alloc_type = dma_p->kmem_alloc_type; 3362678453a8Sspeer 336344961713Sgirish switch (contig_alloc_type) { 336444961713Sgirish case B_FALSE: 3365678453a8Sspeer switch (kmem_alloc_type) { 3366678453a8Sspeer case B_FALSE: 3367678453a8Sspeer ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, 33684045d941Ssowmini length, 33694045d941Ssowmini acc_attr_p, 33704045d941Ssowmini xfer_flags, 33714045d941Ssowmini DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength, 33724045d941Ssowmini &dma_p->acc_handle); 3373678453a8Sspeer if (ddi_status != DDI_SUCCESS) { 3374678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3375678453a8Sspeer "nxge_dma_mem_alloc: " 3376678453a8Sspeer "ddi_dma_mem_alloc failed")); 3377678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3378678453a8Sspeer dma_p->dma_handle = NULL; 3379678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3380678453a8Sspeer } 3381678453a8Sspeer if (dma_p->alength < length) { 3382678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3383678453a8Sspeer "nxge_dma_mem_alloc:di_dma_mem_alloc " 3384678453a8Sspeer "< length.")); 338544961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 3386678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 338744961713Sgirish dma_p->acc_handle = NULL; 3388678453a8Sspeer dma_p->dma_handle = NULL; 3389678453a8Sspeer return (NXGE_ERROR); 339044961713Sgirish } 339144961713Sgirish 3392678453a8Sspeer ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, 3393678453a8Sspeer NULL, 3394678453a8Sspeer kaddrp, dma_p->alength, xfer_flags, 3395678453a8Sspeer DDI_DMA_DONTWAIT, 3396678453a8Sspeer 0, &dma_p->dma_cookie, &dma_p->ncookies); 3397678453a8Sspeer if (ddi_status != DDI_DMA_MAPPED) { 3398678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3399678453a8Sspeer "nxge_dma_mem_alloc: ddi_dma_addr_bind " 3400678453a8Sspeer "failed " 3401678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 3402678453a8Sspeer dma_p->ncookies)); 3403678453a8Sspeer if (dma_p->acc_handle) { 3404678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3405678453a8Sspeer dma_p->acc_handle = NULL; 3406678453a8Sspeer } 3407678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3408678453a8Sspeer dma_p->dma_handle = NULL; 3409678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3410678453a8Sspeer } 3411678453a8Sspeer 3412678453a8Sspeer if (dma_p->ncookies != 1) { 3413678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 3414678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind " 3415678453a8Sspeer "> 1 cookie" 3416678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 3417678453a8Sspeer dma_p->ncookies)); 3418330cd344SMichael Speer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3419678453a8Sspeer if (dma_p->acc_handle) { 3420678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3421678453a8Sspeer dma_p->acc_handle = NULL; 3422678453a8Sspeer } 3423678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3424678453a8Sspeer dma_p->dma_handle = NULL; 3425330cd344SMichael Speer dma_p->acc_handle = NULL; 3426678453a8Sspeer return (NXGE_ERROR); 3427678453a8Sspeer } 3428678453a8Sspeer break; 3429678453a8Sspeer 3430678453a8Sspeer case B_TRUE: 3431678453a8Sspeer kaddrp = KMEM_ALLOC(length, KM_NOSLEEP); 3432678453a8Sspeer if (kaddrp == NULL) { 3433678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3434678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_mem_alloc " 3435678453a8Sspeer "kmem alloc failed")); 3436678453a8Sspeer return (NXGE_ERROR); 3437678453a8Sspeer } 3438678453a8Sspeer 3439678453a8Sspeer dma_p->alength = length; 3440678453a8Sspeer ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, 3441678453a8Sspeer NULL, kaddrp, dma_p->alength, xfer_flags, 3442678453a8Sspeer DDI_DMA_DONTWAIT, 0, 3443678453a8Sspeer &dma_p->dma_cookie, &dma_p->ncookies); 3444678453a8Sspeer if (ddi_status != DDI_DMA_MAPPED) { 3445678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3446678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind: " 3447678453a8Sspeer "(kmem_alloc) failed kaddrp $%p length %d " 3448678453a8Sspeer "(staus 0x%x (%d) ncookies %d.)", 3449678453a8Sspeer kaddrp, length, 3450678453a8Sspeer ddi_status, ddi_status, dma_p->ncookies)); 3451678453a8Sspeer KMEM_FREE(kaddrp, length); 3452678453a8Sspeer dma_p->acc_handle = NULL; 3453678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3454678453a8Sspeer dma_p->dma_handle = NULL; 3455678453a8Sspeer dma_p->kaddrp = NULL; 3456678453a8Sspeer return (NXGE_ERROR | NXGE_DDI_FAILED); 3457678453a8Sspeer } 3458678453a8Sspeer 3459678453a8Sspeer if (dma_p->ncookies != 1) { 3460678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DMA_CTL, 3461678453a8Sspeer "nxge_dma_mem_alloc:ddi_dma_addr_bind " 3462678453a8Sspeer "(kmem_alloc) > 1 cookie" 3463678453a8Sspeer "(staus 0x%x ncookies %d.)", ddi_status, 34644045d941Ssowmini dma_p->ncookies)); 3465678453a8Sspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3466330cd344SMichael Speer KMEM_FREE(kaddrp, length); 3467678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3468678453a8Sspeer dma_p->dma_handle = NULL; 3469330cd344SMichael Speer dma_p->acc_handle = NULL; 3470678453a8Sspeer dma_p->kaddrp = NULL; 3471678453a8Sspeer return (NXGE_ERROR); 347244961713Sgirish } 3473678453a8Sspeer 3474678453a8Sspeer dma_p->kaddrp = kaddrp; 3475678453a8Sspeer 3476678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 34774045d941Ssowmini "nxge_dma_mem_alloc: kmem_alloc dmap $%p " 34784045d941Ssowmini "kaddr $%p alength %d", 34794045d941Ssowmini dma_p, 34804045d941Ssowmini kaddrp, 34814045d941Ssowmini dma_p->alength)); 3482678453a8Sspeer break; 348344961713Sgirish } 348444961713Sgirish break; 348544961713Sgirish 348644961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 348744961713Sgirish case B_TRUE: 348844961713Sgirish kaddrp = (caddr_t)contig_mem_alloc(length); 348944961713Sgirish if (kaddrp == NULL) { 349044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34914045d941Ssowmini "nxge_dma_mem_alloc:contig_mem_alloc failed.")); 349244961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 349344961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 349444961713Sgirish } 349544961713Sgirish 349644961713Sgirish dma_p->alength = length; 349744961713Sgirish ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL, 34984045d941Ssowmini kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0, 34994045d941Ssowmini &dma_p->dma_cookie, &dma_p->ncookies); 350044961713Sgirish if (ddi_status != DDI_DMA_MAPPED) { 350144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 35024045d941Ssowmini "nxge_dma_mem_alloc:di_dma_addr_bind failed " 35034045d941Ssowmini "(status 0x%x ncookies %d.)", ddi_status, 35044045d941Ssowmini dma_p->ncookies)); 350544961713Sgirish 350644961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 35074045d941Ssowmini "==> nxge_dma_mem_alloc: (not mapped)" 35084045d941Ssowmini "length %lu (0x%x) " 35094045d941Ssowmini "free contig kaddrp $%p " 35104045d941Ssowmini "va_to_pa $%p", 35114045d941Ssowmini length, length, 35124045d941Ssowmini kaddrp, 35134045d941Ssowmini va_to_pa(kaddrp))); 351444961713Sgirish 351544961713Sgirish 351644961713Sgirish contig_mem_free((void *)kaddrp, length); 351744961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 351844961713Sgirish 351944961713Sgirish dma_p->dma_handle = NULL; 352044961713Sgirish dma_p->acc_handle = NULL; 352144961713Sgirish dma_p->alength = NULL; 352244961713Sgirish dma_p->kaddrp = NULL; 352344961713Sgirish 352444961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 352544961713Sgirish } 352644961713Sgirish 352744961713Sgirish if (dma_p->ncookies != 1 || 35284045d941Ssowmini (dma_p->dma_cookie.dmac_laddress == NULL)) { 352944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 35304045d941Ssowmini "nxge_dma_mem_alloc:di_dma_addr_bind > 1 " 35314045d941Ssowmini "cookie or " 35324045d941Ssowmini "dmac_laddress is NULL $%p size %d " 35334045d941Ssowmini " (status 0x%x ncookies %d.)", 35344045d941Ssowmini ddi_status, 35354045d941Ssowmini dma_p->dma_cookie.dmac_laddress, 35364045d941Ssowmini dma_p->dma_cookie.dmac_size, 35374045d941Ssowmini dma_p->ncookies)); 353844961713Sgirish 353944961713Sgirish contig_mem_free((void *)kaddrp, length); 354056d930aeSspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 354144961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 354244961713Sgirish 354344961713Sgirish dma_p->alength = 0; 354444961713Sgirish dma_p->dma_handle = NULL; 354544961713Sgirish dma_p->acc_handle = NULL; 354644961713Sgirish dma_p->kaddrp = NULL; 354744961713Sgirish 354844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 354944961713Sgirish } 355044961713Sgirish break; 355144961713Sgirish 355244961713Sgirish #else 355344961713Sgirish case B_TRUE: 355444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 35554045d941Ssowmini "nxge_dma_mem_alloc: invalid alloc type for !sun4v")); 355644961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 355744961713Sgirish #endif 355844961713Sgirish } 355944961713Sgirish 356044961713Sgirish dma_p->kaddrp = kaddrp; 356144961713Sgirish dma_p->last_kaddrp = (unsigned char *)kaddrp + 35624045d941Ssowmini dma_p->alength - RXBUF_64B_ALIGNED; 3563adfcba55Sjoycey #if defined(__i386) 3564adfcba55Sjoycey dma_p->ioaddr_pp = 35654045d941Ssowmini (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress; 3566adfcba55Sjoycey #else 356744961713Sgirish dma_p->ioaddr_pp = (unsigned char *)dma_p->dma_cookie.dmac_laddress; 3568adfcba55Sjoycey #endif 356944961713Sgirish dma_p->last_ioaddr_pp = 3570adfcba55Sjoycey #if defined(__i386) 35714045d941Ssowmini (unsigned char *)(uint32_t)dma_p->dma_cookie.dmac_laddress + 3572adfcba55Sjoycey #else 35734045d941Ssowmini (unsigned char *)dma_p->dma_cookie.dmac_laddress + 3574adfcba55Sjoycey #endif 35754045d941Ssowmini dma_p->alength - RXBUF_64B_ALIGNED; 357644961713Sgirish 357744961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle); 357844961713Sgirish 357944961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 358044961713Sgirish dma_p->orig_ioaddr_pp = 35814045d941Ssowmini (unsigned char *)dma_p->dma_cookie.dmac_laddress; 358244961713Sgirish dma_p->orig_alength = length; 358344961713Sgirish dma_p->orig_kaddrp = kaddrp; 358444961713Sgirish dma_p->orig_vatopa = (uint64_t)va_to_pa(kaddrp); 358544961713Sgirish #endif 358644961713Sgirish 358744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_dma_mem_alloc: " 35884045d941Ssowmini "dma buffer allocated: dma_p $%p " 35894045d941Ssowmini "return dmac_ladress from cookie $%p cookie dmac_size %d " 35904045d941Ssowmini "dma_p->ioaddr_p $%p " 35914045d941Ssowmini "dma_p->orig_ioaddr_p $%p " 35924045d941Ssowmini "orig_vatopa $%p " 35934045d941Ssowmini "alength %d (0x%x) " 35944045d941Ssowmini "kaddrp $%p " 35954045d941Ssowmini "length %d (0x%x)", 35964045d941Ssowmini dma_p, 35974045d941Ssowmini dma_p->dma_cookie.dmac_laddress, dma_p->dma_cookie.dmac_size, 35984045d941Ssowmini dma_p->ioaddr_pp, 35994045d941Ssowmini dma_p->orig_ioaddr_pp, 36004045d941Ssowmini dma_p->orig_vatopa, 36014045d941Ssowmini dma_p->alength, dma_p->alength, 36024045d941Ssowmini kaddrp, 36034045d941Ssowmini length, length)); 360444961713Sgirish 360544961713Sgirish return (NXGE_OK); 360644961713Sgirish } 360744961713Sgirish 360844961713Sgirish static void 360944961713Sgirish nxge_dma_mem_free(p_nxge_dma_common_t dma_p) 361044961713Sgirish { 361144961713Sgirish if (dma_p->dma_handle != NULL) { 361244961713Sgirish if (dma_p->ncookies) { 361344961713Sgirish (void) ddi_dma_unbind_handle(dma_p->dma_handle); 361444961713Sgirish dma_p->ncookies = 0; 361544961713Sgirish } 361644961713Sgirish ddi_dma_free_handle(&dma_p->dma_handle); 361744961713Sgirish dma_p->dma_handle = NULL; 361844961713Sgirish } 361944961713Sgirish 362044961713Sgirish if (dma_p->acc_handle != NULL) { 362144961713Sgirish ddi_dma_mem_free(&dma_p->acc_handle); 362244961713Sgirish dma_p->acc_handle = NULL; 362344961713Sgirish NPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 362444961713Sgirish } 362544961713Sgirish 362644961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 362744961713Sgirish if (dma_p->contig_alloc_type && 36284045d941Ssowmini dma_p->orig_kaddrp && dma_p->orig_alength) { 362944961713Sgirish NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_mem_free: " 36304045d941Ssowmini "kaddrp $%p (orig_kaddrp $%p)" 36314045d941Ssowmini "mem type %d ", 36324045d941Ssowmini "orig_alength %d " 36334045d941Ssowmini "alength 0x%x (%d)", 36344045d941Ssowmini dma_p->kaddrp, 36354045d941Ssowmini dma_p->orig_kaddrp, 36364045d941Ssowmini dma_p->contig_alloc_type, 36374045d941Ssowmini dma_p->orig_alength, 36384045d941Ssowmini dma_p->alength, dma_p->alength)); 363944961713Sgirish 364044961713Sgirish contig_mem_free(dma_p->orig_kaddrp, dma_p->orig_alength); 364144961713Sgirish dma_p->orig_alength = NULL; 364244961713Sgirish dma_p->orig_kaddrp = NULL; 364344961713Sgirish dma_p->contig_alloc_type = B_FALSE; 364444961713Sgirish } 364544961713Sgirish #endif 364644961713Sgirish dma_p->kaddrp = NULL; 364744961713Sgirish dma_p->alength = NULL; 364844961713Sgirish } 364944961713Sgirish 3650678453a8Sspeer static void 3651678453a8Sspeer nxge_dma_free_rx_data_buf(p_nxge_dma_common_t dma_p) 3652678453a8Sspeer { 3653678453a8Sspeer uint64_t kaddr; 3654678453a8Sspeer uint32_t buf_size; 3655678453a8Sspeer 3656678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "==> nxge_dma_free_rx_data_buf")); 3657678453a8Sspeer 3658678453a8Sspeer if (dma_p->dma_handle != NULL) { 3659678453a8Sspeer if (dma_p->ncookies) { 3660678453a8Sspeer (void) ddi_dma_unbind_handle(dma_p->dma_handle); 3661678453a8Sspeer dma_p->ncookies = 0; 3662678453a8Sspeer } 3663678453a8Sspeer ddi_dma_free_handle(&dma_p->dma_handle); 3664678453a8Sspeer dma_p->dma_handle = NULL; 3665678453a8Sspeer } 3666678453a8Sspeer 3667678453a8Sspeer if (dma_p->acc_handle != NULL) { 3668678453a8Sspeer ddi_dma_mem_free(&dma_p->acc_handle); 3669678453a8Sspeer dma_p->acc_handle = NULL; 3670678453a8Sspeer NPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 3671678453a8Sspeer } 3672678453a8Sspeer 3673678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3674678453a8Sspeer "==> nxge_dma_free_rx_data_buf: dmap $%p buf_alloc_state %d", 3675678453a8Sspeer dma_p, 3676678453a8Sspeer dma_p->buf_alloc_state)); 3677678453a8Sspeer 3678678453a8Sspeer if (!(dma_p->buf_alloc_state & BUF_ALLOCATED_WAIT_FREE)) { 3679678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3680678453a8Sspeer "<== nxge_dma_free_rx_data_buf: " 3681678453a8Sspeer "outstanding data buffers")); 3682678453a8Sspeer return; 3683678453a8Sspeer } 3684678453a8Sspeer 3685678453a8Sspeer #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 3686678453a8Sspeer if (dma_p->contig_alloc_type && 36874045d941Ssowmini dma_p->orig_kaddrp && dma_p->orig_alength) { 3688678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_free_rx_data_buf: " 3689678453a8Sspeer "kaddrp $%p (orig_kaddrp $%p)" 3690678453a8Sspeer "mem type %d ", 3691678453a8Sspeer "orig_alength %d " 3692678453a8Sspeer "alength 0x%x (%d)", 3693678453a8Sspeer dma_p->kaddrp, 3694678453a8Sspeer dma_p->orig_kaddrp, 3695678453a8Sspeer dma_p->contig_alloc_type, 3696678453a8Sspeer dma_p->orig_alength, 3697678453a8Sspeer dma_p->alength, dma_p->alength)); 3698678453a8Sspeer 3699678453a8Sspeer kaddr = (uint64_t)dma_p->orig_kaddrp; 3700678453a8Sspeer buf_size = dma_p->orig_alength; 3701678453a8Sspeer nxge_free_buf(CONTIG_MEM_ALLOC, kaddr, buf_size); 3702678453a8Sspeer dma_p->orig_alength = NULL; 3703678453a8Sspeer dma_p->orig_kaddrp = NULL; 3704678453a8Sspeer dma_p->contig_alloc_type = B_FALSE; 3705678453a8Sspeer dma_p->kaddrp = NULL; 3706678453a8Sspeer dma_p->alength = NULL; 3707678453a8Sspeer return; 3708678453a8Sspeer } 3709678453a8Sspeer #endif 3710678453a8Sspeer 3711678453a8Sspeer if (dma_p->kmem_alloc_type) { 3712678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3713678453a8Sspeer "nxge_dma_free_rx_data_buf: free kmem " 37144045d941Ssowmini "kaddrp $%p (orig_kaddrp $%p)" 37154045d941Ssowmini "alloc type %d " 37164045d941Ssowmini "orig_alength %d " 37174045d941Ssowmini "alength 0x%x (%d)", 37184045d941Ssowmini dma_p->kaddrp, 37194045d941Ssowmini dma_p->orig_kaddrp, 37204045d941Ssowmini dma_p->kmem_alloc_type, 37214045d941Ssowmini dma_p->orig_alength, 37224045d941Ssowmini dma_p->alength, dma_p->alength)); 3723678453a8Sspeer #if defined(__i386) 3724678453a8Sspeer kaddr = (uint64_t)(uint32_t)dma_p->kaddrp; 3725678453a8Sspeer #else 3726678453a8Sspeer kaddr = (uint64_t)dma_p->kaddrp; 3727678453a8Sspeer #endif 3728678453a8Sspeer buf_size = dma_p->orig_alength; 3729678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, 3730678453a8Sspeer "nxge_dma_free_rx_data_buf: free dmap $%p " 3731678453a8Sspeer "kaddr $%p buf_size %d", 3732678453a8Sspeer dma_p, 3733678453a8Sspeer kaddr, buf_size)); 3734678453a8Sspeer nxge_free_buf(KMEM_ALLOC, kaddr, buf_size); 3735678453a8Sspeer dma_p->alength = 0; 3736678453a8Sspeer dma_p->orig_alength = 0; 3737678453a8Sspeer dma_p->kaddrp = NULL; 3738678453a8Sspeer dma_p->kmem_alloc_type = B_FALSE; 3739678453a8Sspeer } 3740678453a8Sspeer 3741678453a8Sspeer NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_dma_free_rx_data_buf")); 3742678453a8Sspeer } 3743678453a8Sspeer 374444961713Sgirish /* 374544961713Sgirish * nxge_m_start() -- start transmitting and receiving. 374644961713Sgirish * 374744961713Sgirish * This function is called by the MAC layer when the first 374844961713Sgirish * stream is open to prepare the hardware ready for sending 374944961713Sgirish * and transmitting packets. 375044961713Sgirish */ 375144961713Sgirish static int 375244961713Sgirish nxge_m_start(void *arg) 375344961713Sgirish { 375444961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 375544961713Sgirish 375644961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_start")); 375744961713Sgirish 3758e759c33aSMichael Speer /* 3759e759c33aSMichael Speer * Are we already started? 3760e759c33aSMichael Speer */ 3761e759c33aSMichael Speer if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 3762e759c33aSMichael Speer return (0); 3763e759c33aSMichael Speer } 3764e759c33aSMichael Speer 37656f157acbSml if (nxge_peu_reset_enable && !nxgep->nxge_link_poll_timerid) { 37666f157acbSml (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 37676f157acbSml } 37686f157acbSml 3769e759c33aSMichael Speer /* 3770e759c33aSMichael Speer * Make sure RX MAC is disabled while we initialize. 3771e759c33aSMichael Speer */ 3772e759c33aSMichael Speer if (!isLDOMguest(nxgep)) { 3773e759c33aSMichael Speer (void) nxge_rx_mac_disable(nxgep); 3774e759c33aSMichael Speer } 3775e759c33aSMichael Speer 3776e759c33aSMichael Speer /* 3777e759c33aSMichael Speer * Grab the global lock. 3778e759c33aSMichael Speer */ 377944961713Sgirish MUTEX_ENTER(nxgep->genlock); 3780e759c33aSMichael Speer 3781e759c33aSMichael Speer /* 3782e759c33aSMichael Speer * Initialize the driver and hardware. 3783e759c33aSMichael Speer */ 378414ea4bb7Ssd if (nxge_init(nxgep) != NXGE_OK) { 378544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 37864045d941Ssowmini "<== nxge_m_start: initialization failed")); 378744961713Sgirish MUTEX_EXIT(nxgep->genlock); 378844961713Sgirish return (EIO); 378944961713Sgirish } 379044961713Sgirish 379144961713Sgirish /* 379244961713Sgirish * Start timer to check the system error and tx hangs 379344961713Sgirish */ 3794678453a8Sspeer if (!isLDOMguest(nxgep)) 3795678453a8Sspeer nxgep->nxge_timerid = nxge_start_timer(nxgep, 3796678453a8Sspeer nxge_check_hw_state, NXGE_CHECK_TIMER); 3797e759c33aSMichael Speer #if defined(sun4v) 3798678453a8Sspeer else 3799678453a8Sspeer nxge_hio_start_timer(nxgep); 3800678453a8Sspeer #endif 380144961713Sgirish 3802a3c5bd6dSspeer nxgep->link_notify = B_TRUE; 3803774da109Stc nxgep->link_check_count = 0; 380444961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STARTED; 380544961713Sgirish 3806e759c33aSMichael Speer /* 3807e759c33aSMichael Speer * Let the global lock go, since we are intialized. 3808e759c33aSMichael Speer */ 380944961713Sgirish MUTEX_EXIT(nxgep->genlock); 3810e759c33aSMichael Speer 3811e759c33aSMichael Speer /* 3812e759c33aSMichael Speer * Let the MAC start receiving packets, now that 3813e759c33aSMichael Speer * we are initialized. 3814e759c33aSMichael Speer */ 3815e759c33aSMichael Speer if (!isLDOMguest(nxgep)) { 3816e759c33aSMichael Speer if (nxge_rx_mac_enable(nxgep) != NXGE_OK) { 3817e759c33aSMichael Speer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3818e759c33aSMichael Speer "<== nxge_m_start: enable of RX mac failed")); 3819e759c33aSMichael Speer return (EIO); 3820e759c33aSMichael Speer } 3821e759c33aSMichael Speer 3822e759c33aSMichael Speer /* 3823e759c33aSMichael Speer * Enable hardware interrupts. 3824e759c33aSMichael Speer */ 3825e759c33aSMichael Speer nxge_intr_hw_enable(nxgep); 3826e759c33aSMichael Speer } 3827e759c33aSMichael Speer #if defined(sun4v) 3828e759c33aSMichael Speer else { 3829e759c33aSMichael Speer /* 3830e759c33aSMichael Speer * In guest domain we enable RDCs and their interrupts as 3831e759c33aSMichael Speer * the last step. 3832e759c33aSMichael Speer */ 3833e759c33aSMichael Speer if (nxge_hio_rdc_enable(nxgep) != NXGE_OK) { 3834e759c33aSMichael Speer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3835e759c33aSMichael Speer "<== nxge_m_start: enable of RDCs failed")); 3836e759c33aSMichael Speer return (EIO); 3837e759c33aSMichael Speer } 3838e759c33aSMichael Speer 3839e759c33aSMichael Speer if (nxge_hio_rdc_intr_arm(nxgep, B_TRUE) != NXGE_OK) { 3840e759c33aSMichael Speer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3841e759c33aSMichael Speer "<== nxge_m_start: intrs enable for RDCs failed")); 3842e759c33aSMichael Speer return (EIO); 3843e759c33aSMichael Speer } 3844e759c33aSMichael Speer } 3845e759c33aSMichael Speer #endif 384644961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_start")); 384744961713Sgirish return (0); 384844961713Sgirish } 384944961713Sgirish 3850da14cebeSEric Cheng static boolean_t 3851da14cebeSEric Cheng nxge_check_groups_stopped(p_nxge_t nxgep) 3852da14cebeSEric Cheng { 3853da14cebeSEric Cheng int i; 3854da14cebeSEric Cheng 3855da14cebeSEric Cheng for (i = 0; i < NXGE_MAX_RDC_GROUPS; i++) { 3856da14cebeSEric Cheng if (nxgep->rx_hio_groups[i].started) 3857da14cebeSEric Cheng return (B_FALSE); 3858da14cebeSEric Cheng } 3859da14cebeSEric Cheng 3860da14cebeSEric Cheng return (B_TRUE); 3861da14cebeSEric Cheng } 3862da14cebeSEric Cheng 386344961713Sgirish /* 386444961713Sgirish * nxge_m_stop(): stop transmitting and receiving. 386544961713Sgirish */ 386644961713Sgirish static void 386744961713Sgirish nxge_m_stop(void *arg) 386844961713Sgirish { 386944961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 3870da14cebeSEric Cheng boolean_t groups_stopped; 387144961713Sgirish 387244961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_stop")); 387344961713Sgirish 3874e759c33aSMichael Speer /* 3875e759c33aSMichael Speer * Are the groups stopped? 3876e759c33aSMichael Speer */ 3877da14cebeSEric Cheng groups_stopped = nxge_check_groups_stopped(nxgep); 3878e759c33aSMichael Speer ASSERT(groups_stopped == B_TRUE); 3879da14cebeSEric Cheng if (!groups_stopped) { 3880da14cebeSEric Cheng cmn_err(CE_WARN, "nxge(%d): groups are not stopped!\n", 3881da14cebeSEric Cheng nxgep->instance); 3882da14cebeSEric Cheng return; 3883da14cebeSEric Cheng } 3884da14cebeSEric Cheng 3885e759c33aSMichael Speer if (!isLDOMguest(nxgep)) { 3886e759c33aSMichael Speer /* 3887e759c33aSMichael Speer * Disable the RX mac. 3888e759c33aSMichael Speer */ 3889e759c33aSMichael Speer (void) nxge_rx_mac_disable(nxgep); 3890e759c33aSMichael Speer 3891e759c33aSMichael Speer /* 3892e759c33aSMichael Speer * Wait for the IPP to drain. 3893e759c33aSMichael Speer */ 3894e759c33aSMichael Speer (void) nxge_ipp_drain(nxgep); 3895e759c33aSMichael Speer 3896e759c33aSMichael Speer /* 3897e759c33aSMichael Speer * Disable hardware interrupts. 3898e759c33aSMichael Speer */ 3899e759c33aSMichael Speer nxge_intr_hw_disable(nxgep); 3900e759c33aSMichael Speer } 3901e759c33aSMichael Speer #if defined(sun4v) 3902e759c33aSMichael Speer else { 3903e759c33aSMichael Speer (void) nxge_hio_rdc_intr_arm(nxgep, B_FALSE); 3904e759c33aSMichael Speer } 3905e759c33aSMichael Speer #endif 3906e759c33aSMichael Speer 3907e759c33aSMichael Speer /* 3908e759c33aSMichael Speer * Grab the global lock. 3909e759c33aSMichael Speer */ 3910d7cf53fcSmisaki Miyashita MUTEX_ENTER(nxgep->genlock); 3911d7cf53fcSmisaki Miyashita 3912e759c33aSMichael Speer nxgep->nxge_mac_state = NXGE_MAC_STOPPING; 391344961713Sgirish if (nxgep->nxge_timerid) { 391444961713Sgirish nxge_stop_timer(nxgep, nxgep->nxge_timerid); 391544961713Sgirish nxgep->nxge_timerid = 0; 391644961713Sgirish } 3917a3c5bd6dSspeer 3918e759c33aSMichael Speer /* 3919e759c33aSMichael Speer * Clean up. 3920e759c33aSMichael Speer */ 392144961713Sgirish nxge_uninit(nxgep); 392244961713Sgirish 392344961713Sgirish nxgep->nxge_mac_state = NXGE_MAC_STOPPED; 392444961713Sgirish 3925e759c33aSMichael Speer /* 3926e759c33aSMichael Speer * Let go of the global lock. 3927e759c33aSMichael Speer */ 392844961713Sgirish MUTEX_EXIT(nxgep->genlock); 392944961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_stop")); 393044961713Sgirish } 393144961713Sgirish 393244961713Sgirish static int 393344961713Sgirish nxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 393444961713Sgirish { 393544961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 393644961713Sgirish struct ether_addr addrp; 393744961713Sgirish 393844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 39394045d941Ssowmini "==> nxge_m_multicst: add %d", add)); 394044961713Sgirish 394144961713Sgirish bcopy(mca, (uint8_t *)&addrp, ETHERADDRL); 394244961713Sgirish if (add) { 394344961713Sgirish if (nxge_add_mcast_addr(nxgep, &addrp)) { 394444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 39454045d941Ssowmini "<== nxge_m_multicst: add multicast failed")); 394644961713Sgirish return (EINVAL); 394744961713Sgirish } 394844961713Sgirish } else { 394944961713Sgirish if (nxge_del_mcast_addr(nxgep, &addrp)) { 395044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 39514045d941Ssowmini "<== nxge_m_multicst: del multicast failed")); 395244961713Sgirish return (EINVAL); 395344961713Sgirish } 395444961713Sgirish } 395544961713Sgirish 395644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_multicst")); 395744961713Sgirish 395844961713Sgirish return (0); 395944961713Sgirish } 396044961713Sgirish 396144961713Sgirish static int 396244961713Sgirish nxge_m_promisc(void *arg, boolean_t on) 396344961713Sgirish { 396444961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 396544961713Sgirish 396644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 39674045d941Ssowmini "==> nxge_m_promisc: on %d", on)); 396844961713Sgirish 396944961713Sgirish if (nxge_set_promisc(nxgep, on)) { 397044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 39714045d941Ssowmini "<== nxge_m_promisc: set promisc failed")); 397244961713Sgirish return (EINVAL); 397344961713Sgirish } 397444961713Sgirish 397544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 39764045d941Ssowmini "<== nxge_m_promisc: on %d", on)); 397744961713Sgirish 397844961713Sgirish return (0); 397944961713Sgirish } 398044961713Sgirish 398144961713Sgirish static void 398244961713Sgirish nxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 398344961713Sgirish { 398444961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg; 398556d930aeSspeer struct iocblk *iocp; 398644961713Sgirish boolean_t need_privilege; 398744961713Sgirish int err; 398844961713Sgirish int cmd; 398944961713Sgirish 399044961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl")); 399144961713Sgirish 399244961713Sgirish iocp = (struct iocblk *)mp->b_rptr; 399344961713Sgirish iocp->ioc_error = 0; 399444961713Sgirish need_privilege = B_TRUE; 399544961713Sgirish cmd = iocp->ioc_cmd; 399644961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl: cmd 0x%08x", cmd)); 399744961713Sgirish switch (cmd) { 399844961713Sgirish default: 399944961713Sgirish miocnak(wq, mp, 0, EINVAL); 400044961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl: invalid")); 400144961713Sgirish return; 400244961713Sgirish 400344961713Sgirish case LB_GET_INFO_SIZE: 400444961713Sgirish case LB_GET_INFO: 400544961713Sgirish case LB_GET_MODE: 400644961713Sgirish need_privilege = B_FALSE; 400744961713Sgirish break; 400844961713Sgirish case LB_SET_MODE: 400944961713Sgirish break; 401044961713Sgirish 401144961713Sgirish 401244961713Sgirish case NXGE_GET_MII: 401344961713Sgirish case NXGE_PUT_MII: 401444961713Sgirish case NXGE_GET64: 401544961713Sgirish case NXGE_PUT64: 401644961713Sgirish case NXGE_GET_TX_RING_SZ: 401744961713Sgirish case NXGE_GET_TX_DESC: 401844961713Sgirish case NXGE_TX_SIDE_RESET: 401944961713Sgirish case NXGE_RX_SIDE_RESET: 402044961713Sgirish case NXGE_GLOBAL_RESET: 402144961713Sgirish case NXGE_RESET_MAC: 402244961713Sgirish case NXGE_TX_REGS_DUMP: 402344961713Sgirish case NXGE_RX_REGS_DUMP: 402444961713Sgirish case NXGE_INT_REGS_DUMP: 402544961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 402644961713Sgirish case NXGE_PUT_TCAM: 402744961713Sgirish case NXGE_GET_TCAM: 402844961713Sgirish case NXGE_RTRACE: 402944961713Sgirish case NXGE_RDUMP: 40304df55fdeSJanie Lu case NXGE_RX_CLASS: 40314df55fdeSJanie Lu case NXGE_RX_HASH: 403244961713Sgirish 403344961713Sgirish need_privilege = B_FALSE; 403444961713Sgirish break; 403544961713Sgirish case NXGE_INJECT_ERR: 403644961713Sgirish cmn_err(CE_NOTE, "!nxge_m_ioctl: Inject error\n"); 403744961713Sgirish nxge_err_inject(nxgep, wq, mp); 403844961713Sgirish break; 403944961713Sgirish } 404044961713Sgirish 404144961713Sgirish if (need_privilege) { 404256d930aeSspeer err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 404344961713Sgirish if (err != 0) { 404444961713Sgirish miocnak(wq, mp, 0, err); 404544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 40464045d941Ssowmini "<== nxge_m_ioctl: no priv")); 404744961713Sgirish return; 404844961713Sgirish } 404944961713Sgirish } 405044961713Sgirish 405144961713Sgirish switch (cmd) { 405244961713Sgirish 405344961713Sgirish case LB_GET_MODE: 405444961713Sgirish case LB_SET_MODE: 405544961713Sgirish case LB_GET_INFO_SIZE: 405644961713Sgirish case LB_GET_INFO: 405744961713Sgirish nxge_loopback_ioctl(nxgep, wq, mp, iocp); 405844961713Sgirish break; 405944961713Sgirish 406044961713Sgirish case NXGE_GET_MII: 406144961713Sgirish case NXGE_PUT_MII: 406244961713Sgirish case NXGE_PUT_TCAM: 406344961713Sgirish case NXGE_GET_TCAM: 406444961713Sgirish case NXGE_GET64: 406544961713Sgirish case NXGE_PUT64: 406644961713Sgirish case NXGE_GET_TX_RING_SZ: 406744961713Sgirish case NXGE_GET_TX_DESC: 406844961713Sgirish case NXGE_TX_SIDE_RESET: 406944961713Sgirish case NXGE_RX_SIDE_RESET: 407044961713Sgirish case NXGE_GLOBAL_RESET: 407144961713Sgirish case NXGE_RESET_MAC: 407244961713Sgirish case NXGE_TX_REGS_DUMP: 407344961713Sgirish case NXGE_RX_REGS_DUMP: 407444961713Sgirish case NXGE_INT_REGS_DUMP: 407544961713Sgirish case NXGE_VIR_INT_REGS_DUMP: 407644961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 40774045d941Ssowmini "==> nxge_m_ioctl: cmd 0x%x", cmd)); 407844961713Sgirish nxge_hw_ioctl(nxgep, wq, mp, iocp); 407944961713Sgirish break; 40804df55fdeSJanie Lu case NXGE_RX_CLASS: 40814df55fdeSJanie Lu if (nxge_rxclass_ioctl(nxgep, wq, mp->b_cont) < 0) 40824df55fdeSJanie Lu miocnak(wq, mp, 0, EINVAL); 40834df55fdeSJanie Lu else 40844df55fdeSJanie Lu miocack(wq, mp, sizeof (rx_class_cfg_t), 0); 40854df55fdeSJanie Lu break; 40864df55fdeSJanie Lu case NXGE_RX_HASH: 40874df55fdeSJanie Lu 40884df55fdeSJanie Lu if (nxge_rxhash_ioctl(nxgep, wq, mp->b_cont) < 0) 40894df55fdeSJanie Lu miocnak(wq, mp, 0, EINVAL); 40904df55fdeSJanie Lu else 40914df55fdeSJanie Lu miocack(wq, mp, sizeof (cfg_cmd_t), 0); 40924df55fdeSJanie Lu break; 409344961713Sgirish } 409444961713Sgirish 409544961713Sgirish NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl")); 409644961713Sgirish } 409744961713Sgirish 409844961713Sgirish extern void nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count); 409944961713Sgirish 4100678453a8Sspeer void 4101da14cebeSEric Cheng nxge_mmac_kstat_update(p_nxge_t nxgep, int slot, boolean_t factory) 410258324dfcSspeer { 410358324dfcSspeer p_nxge_mmac_stats_t mmac_stats; 410458324dfcSspeer int i; 410558324dfcSspeer nxge_mmac_t *mmac_info; 410658324dfcSspeer 410758324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 410858324dfcSspeer 410958324dfcSspeer mmac_stats = &nxgep->statsp->mmac_stats; 411058324dfcSspeer mmac_stats->mmac_max_cnt = mmac_info->num_mmac; 411158324dfcSspeer mmac_stats->mmac_avail_cnt = mmac_info->naddrfree; 411258324dfcSspeer 411358324dfcSspeer for (i = 0; i < ETHERADDRL; i++) { 411458324dfcSspeer if (factory) { 411558324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 41164045d941Ssowmini = mmac_info->factory_mac_pool[slot][ 41174045d941Ssowmini (ETHERADDRL-1) - i]; 411858324dfcSspeer } else { 411958324dfcSspeer mmac_stats->mmac_avail_pool[slot-1].ether_addr_octet[i] 41204045d941Ssowmini = mmac_info->mac_pool[slot].addr[ 41214045d941Ssowmini (ETHERADDRL - 1) - i]; 412258324dfcSspeer } 412358324dfcSspeer } 412458324dfcSspeer } 412558324dfcSspeer 412658324dfcSspeer /* 412758324dfcSspeer * nxge_altmac_set() -- Set an alternate MAC address 412858324dfcSspeer */ 4129da14cebeSEric Cheng static int 4130da14cebeSEric Cheng nxge_altmac_set(p_nxge_t nxgep, uint8_t *maddr, int slot, 4131da14cebeSEric Cheng int rdctbl, boolean_t usetbl) 413258324dfcSspeer { 413358324dfcSspeer uint8_t addrn; 413458324dfcSspeer uint8_t portn; 413558324dfcSspeer npi_mac_addr_t altmac; 41367b9fa28bSspeer hostinfo_t mac_rdc; 41377b9fa28bSspeer p_nxge_class_pt_cfg_t clscfgp; 413858324dfcSspeer 4139da14cebeSEric Cheng 414058324dfcSspeer altmac.w2 = ((uint16_t)maddr[0] << 8) | ((uint16_t)maddr[1] & 0x0ff); 414158324dfcSspeer altmac.w1 = ((uint16_t)maddr[2] << 8) | ((uint16_t)maddr[3] & 0x0ff); 414258324dfcSspeer altmac.w0 = ((uint16_t)maddr[4] << 8) | ((uint16_t)maddr[5] & 0x0ff); 414358324dfcSspeer 414458324dfcSspeer portn = nxgep->mac.portnum; 414558324dfcSspeer addrn = (uint8_t)slot - 1; 414658324dfcSspeer 4147da14cebeSEric Cheng if (npi_mac_altaddr_entry(nxgep->npi_handle, OP_SET, 4148da14cebeSEric Cheng nxgep->function_num, addrn, &altmac) != NPI_SUCCESS) 414958324dfcSspeer return (EIO); 41507b9fa28bSspeer 41517b9fa28bSspeer /* 41527b9fa28bSspeer * Set the rdc table number for the host info entry 41537b9fa28bSspeer * for this mac address slot. 41547b9fa28bSspeer */ 41557b9fa28bSspeer clscfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config; 41567b9fa28bSspeer mac_rdc.value = 0; 4157da14cebeSEric Cheng if (usetbl) 4158da14cebeSEric Cheng mac_rdc.bits.w0.rdc_tbl_num = rdctbl; 4159da14cebeSEric Cheng else 4160da14cebeSEric Cheng mac_rdc.bits.w0.rdc_tbl_num = 4161da14cebeSEric Cheng clscfgp->mac_host_info[addrn].rdctbl; 41627b9fa28bSspeer mac_rdc.bits.w0.mac_pref = clscfgp->mac_host_info[addrn].mpr_npr; 41637b9fa28bSspeer 41647b9fa28bSspeer if (npi_mac_hostinfo_entry(nxgep->npi_handle, OP_SET, 41657b9fa28bSspeer nxgep->function_num, addrn, &mac_rdc) != NPI_SUCCESS) { 41667b9fa28bSspeer return (EIO); 41677b9fa28bSspeer } 41687b9fa28bSspeer 416958324dfcSspeer /* 417058324dfcSspeer * Enable comparison with the alternate MAC address. 417158324dfcSspeer * While the first alternate addr is enabled by bit 1 of register 417258324dfcSspeer * BMAC_ALTAD_CMPEN, it is enabled by bit 0 of register 417358324dfcSspeer * XMAC_ADDR_CMPEN, so slot needs to be converted to addrn 417458324dfcSspeer * accordingly before calling npi_mac_altaddr_entry. 417558324dfcSspeer */ 417658324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 417758324dfcSspeer addrn = (uint8_t)slot - 1; 417858324dfcSspeer else 417958324dfcSspeer addrn = (uint8_t)slot; 418058324dfcSspeer 4181da14cebeSEric Cheng if (npi_mac_altaddr_enable(nxgep->npi_handle, 4182da14cebeSEric Cheng nxgep->function_num, addrn) != NPI_SUCCESS) { 418358324dfcSspeer return (EIO); 4184da14cebeSEric Cheng } 4185da14cebeSEric Cheng 418658324dfcSspeer return (0); 418758324dfcSspeer } 418858324dfcSspeer 418958324dfcSspeer /* 4190da14cebeSEric Cheng * nxeg_m_mmac_add_g() - find an unused address slot, set the address 419158324dfcSspeer * value to the one specified, enable the port to start filtering on 419258324dfcSspeer * the new MAC address. Returns 0 on success. 419358324dfcSspeer */ 4194678453a8Sspeer int 4195da14cebeSEric Cheng nxge_m_mmac_add_g(void *arg, const uint8_t *maddr, int rdctbl, 4196da14cebeSEric Cheng boolean_t usetbl) 419758324dfcSspeer { 419858324dfcSspeer p_nxge_t nxgep = arg; 4199da14cebeSEric Cheng int slot; 420058324dfcSspeer nxge_mmac_t *mmac_info; 420158324dfcSspeer int err; 420258324dfcSspeer nxge_status_t status; 420358324dfcSspeer 420458324dfcSspeer mutex_enter(nxgep->genlock); 420558324dfcSspeer 420658324dfcSspeer /* 420758324dfcSspeer * Make sure that nxge is initialized, if _start() has 420858324dfcSspeer * not been called. 420958324dfcSspeer */ 421058324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 421158324dfcSspeer status = nxge_init(nxgep); 421258324dfcSspeer if (status != NXGE_OK) { 421358324dfcSspeer mutex_exit(nxgep->genlock); 421458324dfcSspeer return (ENXIO); 421558324dfcSspeer } 421658324dfcSspeer } 421758324dfcSspeer 421858324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 421958324dfcSspeer if (mmac_info->naddrfree == 0) { 422058324dfcSspeer mutex_exit(nxgep->genlock); 422158324dfcSspeer return (ENOSPC); 422258324dfcSspeer } 4223da14cebeSEric Cheng 422458324dfcSspeer /* 422558324dfcSspeer * Search for the first available slot. Because naddrfree 422658324dfcSspeer * is not zero, we are guaranteed to find one. 422758324dfcSspeer * Each of the first two ports of Neptune has 16 alternate 4228678453a8Sspeer * MAC slots but only the first 7 (of 15) slots have assigned factory 422958324dfcSspeer * MAC addresses. We first search among the slots without bundled 423058324dfcSspeer * factory MACs. If we fail to find one in that range, then we 423158324dfcSspeer * search the slots with bundled factory MACs. A factory MAC 423258324dfcSspeer * will be wasted while the slot is used with a user MAC address. 423358324dfcSspeer * But the slot could be used by factory MAC again after calling 423458324dfcSspeer * nxge_m_mmac_remove and nxge_m_mmac_reserve. 423558324dfcSspeer */ 4236da14cebeSEric Cheng for (slot = 0; slot <= mmac_info->num_mmac; slot++) { 4237da14cebeSEric Cheng if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 4238da14cebeSEric Cheng break; 423958324dfcSspeer } 4240da14cebeSEric Cheng 424158324dfcSspeer ASSERT(slot <= mmac_info->num_mmac); 4242e857d0f3SMichael Speer 4243da14cebeSEric Cheng if ((err = nxge_altmac_set(nxgep, (uint8_t *)maddr, slot, rdctbl, 4244da14cebeSEric Cheng usetbl)) != 0) { 424558324dfcSspeer mutex_exit(nxgep->genlock); 424658324dfcSspeer return (err); 424758324dfcSspeer } 4248e857d0f3SMichael Speer 4249da14cebeSEric Cheng bcopy(maddr, mmac_info->mac_pool[slot].addr, ETHERADDRL); 425058324dfcSspeer mmac_info->mac_pool[slot].flags |= MMAC_SLOT_USED; 425158324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_VENDOR_ADDR; 425258324dfcSspeer mmac_info->naddrfree--; 425358324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 425458324dfcSspeer 425558324dfcSspeer mutex_exit(nxgep->genlock); 425658324dfcSspeer return (0); 425758324dfcSspeer } 425858324dfcSspeer 425958324dfcSspeer /* 426058324dfcSspeer * Remove the specified mac address and update the HW not to filter 426158324dfcSspeer * the mac address anymore. 426258324dfcSspeer */ 4263678453a8Sspeer int 4264da14cebeSEric Cheng nxge_m_mmac_remove(void *arg, int slot) 426558324dfcSspeer { 426658324dfcSspeer p_nxge_t nxgep = arg; 426758324dfcSspeer nxge_mmac_t *mmac_info; 426858324dfcSspeer uint8_t addrn; 426958324dfcSspeer uint8_t portn; 427058324dfcSspeer int err = 0; 427158324dfcSspeer nxge_status_t status; 427258324dfcSspeer 427358324dfcSspeer mutex_enter(nxgep->genlock); 427458324dfcSspeer 427558324dfcSspeer /* 427658324dfcSspeer * Make sure that nxge is initialized, if _start() has 427758324dfcSspeer * not been called. 427858324dfcSspeer */ 427958324dfcSspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 428058324dfcSspeer status = nxge_init(nxgep); 428158324dfcSspeer if (status != NXGE_OK) { 428258324dfcSspeer mutex_exit(nxgep->genlock); 428358324dfcSspeer return (ENXIO); 428458324dfcSspeer } 428558324dfcSspeer } 428658324dfcSspeer 428758324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 428858324dfcSspeer if (slot < 1 || slot > mmac_info->num_mmac) { 428958324dfcSspeer mutex_exit(nxgep->genlock); 429058324dfcSspeer return (EINVAL); 429158324dfcSspeer } 429258324dfcSspeer 429358324dfcSspeer portn = nxgep->mac.portnum; 429458324dfcSspeer if (portn == XMAC_PORT_0 || portn == XMAC_PORT_1) 429558324dfcSspeer addrn = (uint8_t)slot - 1; 429658324dfcSspeer else 429758324dfcSspeer addrn = (uint8_t)slot; 429858324dfcSspeer 429958324dfcSspeer if (mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED) { 430058324dfcSspeer if (npi_mac_altaddr_disable(nxgep->npi_handle, portn, addrn) 43014045d941Ssowmini == NPI_SUCCESS) { 430258324dfcSspeer mmac_info->naddrfree++; 430358324dfcSspeer mmac_info->mac_pool[slot].flags &= ~MMAC_SLOT_USED; 430458324dfcSspeer /* 430558324dfcSspeer * Regardless if the MAC we just stopped filtering 430658324dfcSspeer * is a user addr or a facory addr, we must set 430758324dfcSspeer * the MMAC_VENDOR_ADDR flag if this slot has an 430858324dfcSspeer * associated factory MAC to indicate that a factory 430958324dfcSspeer * MAC is available. 431058324dfcSspeer */ 431158324dfcSspeer if (slot <= mmac_info->num_factory_mmac) { 431258324dfcSspeer mmac_info->mac_pool[slot].flags 43134045d941Ssowmini |= MMAC_VENDOR_ADDR; 431458324dfcSspeer } 431558324dfcSspeer /* 431658324dfcSspeer * Clear mac_pool[slot].addr so that kstat shows 0 431758324dfcSspeer * alternate MAC address if the slot is not used. 431858324dfcSspeer * (But nxge_m_mmac_get returns the factory MAC even 431958324dfcSspeer * when the slot is not used!) 432058324dfcSspeer */ 432158324dfcSspeer bzero(mmac_info->mac_pool[slot].addr, ETHERADDRL); 432258324dfcSspeer nxge_mmac_kstat_update(nxgep, slot, B_FALSE); 432358324dfcSspeer } else { 432458324dfcSspeer err = EIO; 432558324dfcSspeer } 432658324dfcSspeer } else { 432758324dfcSspeer err = EINVAL; 432858324dfcSspeer } 432958324dfcSspeer 433058324dfcSspeer mutex_exit(nxgep->genlock); 433158324dfcSspeer return (err); 433258324dfcSspeer } 433358324dfcSspeer 433458324dfcSspeer /* 4335da14cebeSEric Cheng * The callback to query all the factory addresses. naddr must be the same as 4336da14cebeSEric Cheng * the number of factory addresses (returned by MAC_CAPAB_MULTIFACTADDR), and 4337da14cebeSEric Cheng * mcm_addr is the space allocated for keep all the addresses, whose size is 4338da14cebeSEric Cheng * naddr * MAXMACADDRLEN. 433958324dfcSspeer */ 4340da14cebeSEric Cheng static void 4341da14cebeSEric Cheng nxge_m_getfactaddr(void *arg, uint_t naddr, uint8_t *addr) 434258324dfcSspeer { 4343da14cebeSEric Cheng nxge_t *nxgep = arg; 4344da14cebeSEric Cheng nxge_mmac_t *mmac_info; 4345da14cebeSEric Cheng int i; 434658324dfcSspeer 434758324dfcSspeer mutex_enter(nxgep->genlock); 434858324dfcSspeer 434958324dfcSspeer mmac_info = &nxgep->nxge_mmac_info; 4350da14cebeSEric Cheng ASSERT(naddr == mmac_info->num_factory_mmac); 435158324dfcSspeer 4352da14cebeSEric Cheng for (i = 0; i < naddr; i++) { 4353da14cebeSEric Cheng bcopy(mmac_info->factory_mac_pool[i + 1], 4354da14cebeSEric Cheng addr + i * MAXMACADDRLEN, ETHERADDRL); 435558324dfcSspeer } 435658324dfcSspeer 435758324dfcSspeer mutex_exit(nxgep->genlock); 435858324dfcSspeer } 435958324dfcSspeer 4360da14cebeSEric Cheng 436144961713Sgirish static boolean_t 436244961713Sgirish nxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 436344961713Sgirish { 436458324dfcSspeer nxge_t *nxgep = arg; 436558324dfcSspeer uint32_t *txflags = cap_data; 436644961713Sgirish 436758324dfcSspeer switch (cap) { 436858324dfcSspeer case MAC_CAPAB_HCKSUM: 4369678453a8Sspeer NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4370b4d05839Sml "==> nxge_m_getcapab: checksum %d", nxge_cksum_offload)); 4371b4d05839Sml if (nxge_cksum_offload <= 1) { 4372678453a8Sspeer *txflags = HCKSUM_INET_PARTIAL; 4373678453a8Sspeer } 437444961713Sgirish break; 4375678453a8Sspeer 4376da14cebeSEric Cheng case MAC_CAPAB_MULTIFACTADDR: { 4377da14cebeSEric Cheng mac_capab_multifactaddr_t *mfacp = cap_data; 437844961713Sgirish 437963f531d1SSriharsha Basavapatna if (!isLDOMguest(nxgep)) { 438063f531d1SSriharsha Basavapatna mutex_enter(nxgep->genlock); 438163f531d1SSriharsha Basavapatna mfacp->mcm_naddr = 438263f531d1SSriharsha Basavapatna nxgep->nxge_mmac_info.num_factory_mmac; 438363f531d1SSriharsha Basavapatna mfacp->mcm_getaddr = nxge_m_getfactaddr; 438463f531d1SSriharsha Basavapatna mutex_exit(nxgep->genlock); 438563f531d1SSriharsha Basavapatna } 438658324dfcSspeer break; 4387da14cebeSEric Cheng } 4388678453a8Sspeer 438930ac2e7bSml case MAC_CAPAB_LSO: { 439030ac2e7bSml mac_capab_lso_t *cap_lso = cap_data; 439130ac2e7bSml 43923d16f8e7Sml if (nxgep->soft_lso_enable) { 4393b4d05839Sml if (nxge_cksum_offload <= 1) { 4394b4d05839Sml cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 4395b4d05839Sml if (nxge_lso_max > NXGE_LSO_MAXLEN) { 4396b4d05839Sml nxge_lso_max = NXGE_LSO_MAXLEN; 4397b4d05839Sml } 4398b4d05839Sml cap_lso->lso_basic_tcp_ipv4.lso_max = 4399b4d05839Sml nxge_lso_max; 440030ac2e7bSml } 440130ac2e7bSml break; 440230ac2e7bSml } else { 440330ac2e7bSml return (B_FALSE); 440430ac2e7bSml } 440530ac2e7bSml } 440630ac2e7bSml 4407678453a8Sspeer case MAC_CAPAB_RINGS: { 4408da14cebeSEric Cheng mac_capab_rings_t *cap_rings = cap_data; 4409da14cebeSEric Cheng p_nxge_hw_pt_cfg_t p_cfgp = &nxgep->pt_config.hw_config; 4410678453a8Sspeer 4411da14cebeSEric Cheng mutex_enter(nxgep->genlock); 4412da14cebeSEric Cheng if (cap_rings->mr_type == MAC_RING_TYPE_RX) { 441363f531d1SSriharsha Basavapatna if (isLDOMguest(nxgep)) { 441463f531d1SSriharsha Basavapatna cap_rings->mr_group_type = 441563f531d1SSriharsha Basavapatna MAC_GROUP_TYPE_STATIC; 441663f531d1SSriharsha Basavapatna cap_rings->mr_rnum = 441763f531d1SSriharsha Basavapatna NXGE_HIO_SHARE_MAX_CHANNELS; 441863f531d1SSriharsha Basavapatna cap_rings->mr_rget = nxge_fill_ring; 441963f531d1SSriharsha Basavapatna cap_rings->mr_gnum = 1; 442063f531d1SSriharsha Basavapatna cap_rings->mr_gget = nxge_hio_group_get; 442163f531d1SSriharsha Basavapatna cap_rings->mr_gaddring = NULL; 442263f531d1SSriharsha Basavapatna cap_rings->mr_gremring = NULL; 442363f531d1SSriharsha Basavapatna } else { 442463f531d1SSriharsha Basavapatna /* 442563f531d1SSriharsha Basavapatna * Service Domain. 442663f531d1SSriharsha Basavapatna */ 442763f531d1SSriharsha Basavapatna cap_rings->mr_group_type = 442863f531d1SSriharsha Basavapatna MAC_GROUP_TYPE_DYNAMIC; 442963f531d1SSriharsha Basavapatna cap_rings->mr_rnum = p_cfgp->max_rdcs; 443063f531d1SSriharsha Basavapatna cap_rings->mr_rget = nxge_fill_ring; 443163f531d1SSriharsha Basavapatna cap_rings->mr_gnum = p_cfgp->max_rdc_grpids; 443263f531d1SSriharsha Basavapatna cap_rings->mr_gget = nxge_hio_group_get; 443363f531d1SSriharsha Basavapatna cap_rings->mr_gaddring = nxge_group_add_ring; 443463f531d1SSriharsha Basavapatna cap_rings->mr_gremring = nxge_group_rem_ring; 443563f531d1SSriharsha Basavapatna } 4436da14cebeSEric Cheng 4437da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, RX_CTL, 4438da14cebeSEric Cheng "==> nxge_m_getcapab: rx nrings[%d] ngroups[%d]", 4439da14cebeSEric Cheng p_cfgp->max_rdcs, p_cfgp->max_rdc_grpids)); 4440da14cebeSEric Cheng } else { 444163f531d1SSriharsha Basavapatna /* 444263f531d1SSriharsha Basavapatna * TX Rings. 444363f531d1SSriharsha Basavapatna */ 444463f531d1SSriharsha Basavapatna if (isLDOMguest(nxgep)) { 444563f531d1SSriharsha Basavapatna cap_rings->mr_group_type = 444663f531d1SSriharsha Basavapatna MAC_GROUP_TYPE_STATIC; 444763f531d1SSriharsha Basavapatna cap_rings->mr_rnum = 444863f531d1SSriharsha Basavapatna NXGE_HIO_SHARE_MAX_CHANNELS; 444963f531d1SSriharsha Basavapatna cap_rings->mr_rget = nxge_fill_ring; 445063f531d1SSriharsha Basavapatna cap_rings->mr_gnum = 0; 445163f531d1SSriharsha Basavapatna cap_rings->mr_gget = NULL; 445263f531d1SSriharsha Basavapatna cap_rings->mr_gaddring = NULL; 445363f531d1SSriharsha Basavapatna cap_rings->mr_gremring = NULL; 445463f531d1SSriharsha Basavapatna } else { 445563f531d1SSriharsha Basavapatna /* 445663f531d1SSriharsha Basavapatna * Service Domain. 445763f531d1SSriharsha Basavapatna */ 445863f531d1SSriharsha Basavapatna cap_rings->mr_group_type = 445963f531d1SSriharsha Basavapatna MAC_GROUP_TYPE_DYNAMIC; 446063f531d1SSriharsha Basavapatna cap_rings->mr_rnum = p_cfgp->tdc.count; 446163f531d1SSriharsha Basavapatna cap_rings->mr_rget = nxge_fill_ring; 446263f531d1SSriharsha Basavapatna 446363f531d1SSriharsha Basavapatna /* 446463f531d1SSriharsha Basavapatna * Share capable. 446563f531d1SSriharsha Basavapatna * 446663f531d1SSriharsha Basavapatna * Do not report the default group: hence -1 446763f531d1SSriharsha Basavapatna */ 4468da14cebeSEric Cheng cap_rings->mr_gnum = 4469da14cebeSEric Cheng NXGE_MAX_TDC_GROUPS / nxgep->nports - 1; 447063f531d1SSriharsha Basavapatna cap_rings->mr_gget = nxge_hio_group_get; 447163f531d1SSriharsha Basavapatna cap_rings->mr_gaddring = nxge_group_add_ring; 447263f531d1SSriharsha Basavapatna cap_rings->mr_gremring = nxge_group_rem_ring; 4473678453a8Sspeer } 4474da14cebeSEric Cheng 4475da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, TX_CTL, 4476da14cebeSEric Cheng "==> nxge_m_getcapab: tx rings # of rings %d", 4477da14cebeSEric Cheng p_cfgp->tdc.count)); 4478da14cebeSEric Cheng } 4479da14cebeSEric Cheng mutex_exit(nxgep->genlock); 4480678453a8Sspeer break; 4481678453a8Sspeer } 4482678453a8Sspeer 4483da14cebeSEric Cheng #if defined(sun4v) 4484678453a8Sspeer case MAC_CAPAB_SHARES: { 4485678453a8Sspeer mac_capab_share_t *mshares = (mac_capab_share_t *)cap_data; 4486678453a8Sspeer 4487678453a8Sspeer /* 4488678453a8Sspeer * Only the service domain driver responds to 4489678453a8Sspeer * this capability request. 4490678453a8Sspeer */ 4491da14cebeSEric Cheng mutex_enter(nxgep->genlock); 4492678453a8Sspeer if (isLDOMservice(nxgep)) { 4493678453a8Sspeer mshares->ms_snum = 3; 4494678453a8Sspeer mshares->ms_handle = (void *)nxgep; 4495678453a8Sspeer mshares->ms_salloc = nxge_hio_share_alloc; 4496678453a8Sspeer mshares->ms_sfree = nxge_hio_share_free; 4497da14cebeSEric Cheng mshares->ms_sadd = nxge_hio_share_add_group; 4498da14cebeSEric Cheng mshares->ms_sremove = nxge_hio_share_rem_group; 4499678453a8Sspeer mshares->ms_squery = nxge_hio_share_query; 4500da14cebeSEric Cheng mshares->ms_sbind = nxge_hio_share_bind; 4501da14cebeSEric Cheng mshares->ms_sunbind = nxge_hio_share_unbind; 4502da14cebeSEric Cheng mutex_exit(nxgep->genlock); 4503da14cebeSEric Cheng } else { 4504da14cebeSEric Cheng mutex_exit(nxgep->genlock); 4505678453a8Sspeer return (B_FALSE); 4506da14cebeSEric Cheng } 4507678453a8Sspeer break; 4508678453a8Sspeer } 4509678453a8Sspeer #endif 451044961713Sgirish default: 451144961713Sgirish return (B_FALSE); 451244961713Sgirish } 451344961713Sgirish return (B_TRUE); 451444961713Sgirish } 451544961713Sgirish 45161bd6825cSml static boolean_t 45171bd6825cSml nxge_param_locked(mac_prop_id_t pr_num) 45181bd6825cSml { 45191bd6825cSml /* 45201bd6825cSml * All adv_* parameters are locked (read-only) while 45211bd6825cSml * the device is in any sort of loopback mode ... 45221bd6825cSml */ 45231bd6825cSml switch (pr_num) { 45243fd94f8cSam case MAC_PROP_ADV_1000FDX_CAP: 45253fd94f8cSam case MAC_PROP_EN_1000FDX_CAP: 45263fd94f8cSam case MAC_PROP_ADV_1000HDX_CAP: 45273fd94f8cSam case MAC_PROP_EN_1000HDX_CAP: 45283fd94f8cSam case MAC_PROP_ADV_100FDX_CAP: 45293fd94f8cSam case MAC_PROP_EN_100FDX_CAP: 45303fd94f8cSam case MAC_PROP_ADV_100HDX_CAP: 45313fd94f8cSam case MAC_PROP_EN_100HDX_CAP: 45323fd94f8cSam case MAC_PROP_ADV_10FDX_CAP: 45333fd94f8cSam case MAC_PROP_EN_10FDX_CAP: 45343fd94f8cSam case MAC_PROP_ADV_10HDX_CAP: 45353fd94f8cSam case MAC_PROP_EN_10HDX_CAP: 45363fd94f8cSam case MAC_PROP_AUTONEG: 45373fd94f8cSam case MAC_PROP_FLOWCTRL: 45381bd6825cSml return (B_TRUE); 45391bd6825cSml } 45401bd6825cSml return (B_FALSE); 45411bd6825cSml } 45421bd6825cSml 45431bd6825cSml /* 45441bd6825cSml * callback functions for set/get of properties 45451bd6825cSml */ 45461bd6825cSml static int 45471bd6825cSml nxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 45481bd6825cSml uint_t pr_valsize, const void *pr_val) 45491bd6825cSml { 45501bd6825cSml nxge_t *nxgep = barg; 4551*0dc2366fSVenugopal Iyer p_nxge_param_t param_arr = nxgep->param_arr; 4552*0dc2366fSVenugopal Iyer p_nxge_stats_t statsp = nxgep->statsp; 45531bd6825cSml int err = 0; 45541bd6825cSml 45551bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_setprop")); 4556*0dc2366fSVenugopal Iyer 45571bd6825cSml mutex_enter(nxgep->genlock); 45581bd6825cSml if (statsp->port_stats.lb_mode != nxge_lb_normal && 45591bd6825cSml nxge_param_locked(pr_num)) { 45601bd6825cSml /* 45611bd6825cSml * All adv_* parameters are locked (read-only) 45621bd6825cSml * while the device is in any sort of loopback mode. 45631bd6825cSml */ 45641bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 45651bd6825cSml "==> nxge_m_setprop: loopback mode: read only")); 45661bd6825cSml mutex_exit(nxgep->genlock); 45671bd6825cSml return (EBUSY); 45681bd6825cSml } 45691bd6825cSml 45701bd6825cSml switch (pr_num) { 4571*0dc2366fSVenugopal Iyer case MAC_PROP_EN_1000FDX_CAP: 4572*0dc2366fSVenugopal Iyer nxgep->param_en_1000fdx = 4573*0dc2366fSVenugopal Iyer param_arr[param_anar_1000fdx].value = *(uint8_t *)pr_val; 4574*0dc2366fSVenugopal Iyer goto reprogram; 45751bd6825cSml 4576*0dc2366fSVenugopal Iyer case MAC_PROP_EN_100FDX_CAP: 4577*0dc2366fSVenugopal Iyer nxgep->param_en_100fdx = 4578*0dc2366fSVenugopal Iyer param_arr[param_anar_100fdx].value = *(uint8_t *)pr_val; 4579*0dc2366fSVenugopal Iyer goto reprogram; 45801bd6825cSml 4581*0dc2366fSVenugopal Iyer case MAC_PROP_EN_10FDX_CAP: 4582*0dc2366fSVenugopal Iyer nxgep->param_en_10fdx = 4583*0dc2366fSVenugopal Iyer param_arr[param_anar_10fdx].value = *(uint8_t *)pr_val; 4584*0dc2366fSVenugopal Iyer goto reprogram; 45851bd6825cSml 4586*0dc2366fSVenugopal Iyer case MAC_PROP_AUTONEG: 4587*0dc2366fSVenugopal Iyer param_arr[param_autoneg].value = *(uint8_t *)pr_val; 4588*0dc2366fSVenugopal Iyer goto reprogram; 45891bd6825cSml 4590*0dc2366fSVenugopal Iyer case MAC_PROP_MTU: { 4591*0dc2366fSVenugopal Iyer uint32_t cur_mtu, new_mtu, old_framesize; 45921bd6825cSml 4593*0dc2366fSVenugopal Iyer cur_mtu = nxgep->mac.default_mtu; 4594*0dc2366fSVenugopal Iyer ASSERT(pr_valsize >= sizeof (new_mtu)); 4595*0dc2366fSVenugopal Iyer bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 45961bd6825cSml 4597*0dc2366fSVenugopal Iyer NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4598*0dc2366fSVenugopal Iyer "==> nxge_m_setprop: set MTU: %d is_jumbo %d", 4599*0dc2366fSVenugopal Iyer new_mtu, nxgep->mac.is_jumbo)); 46001bd6825cSml 4601*0dc2366fSVenugopal Iyer if (new_mtu == cur_mtu) { 4602*0dc2366fSVenugopal Iyer err = 0; 4603*0dc2366fSVenugopal Iyer break; 4604*0dc2366fSVenugopal Iyer } 46051bd6825cSml 4606*0dc2366fSVenugopal Iyer if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 4607*0dc2366fSVenugopal Iyer err = EBUSY; 4608*0dc2366fSVenugopal Iyer break; 4609*0dc2366fSVenugopal Iyer } 46101bd6825cSml 4611*0dc2366fSVenugopal Iyer if ((new_mtu < NXGE_DEFAULT_MTU) || 4612*0dc2366fSVenugopal Iyer (new_mtu > NXGE_MAXIMUM_MTU)) { 4613*0dc2366fSVenugopal Iyer err = EINVAL; 4614*0dc2366fSVenugopal Iyer break; 4615*0dc2366fSVenugopal Iyer } 461648056c53SMichael Speer 4617*0dc2366fSVenugopal Iyer old_framesize = (uint32_t)nxgep->mac.maxframesize; 4618*0dc2366fSVenugopal Iyer nxgep->mac.maxframesize = (uint16_t) 4619*0dc2366fSVenugopal Iyer (new_mtu + NXGE_EHEADER_VLAN_CRC); 4620*0dc2366fSVenugopal Iyer if (nxge_mac_set_framesize(nxgep)) { 4621*0dc2366fSVenugopal Iyer nxgep->mac.maxframesize = 4622*0dc2366fSVenugopal Iyer (uint16_t)old_framesize; 4623*0dc2366fSVenugopal Iyer err = EINVAL; 4624*0dc2366fSVenugopal Iyer break; 4625*0dc2366fSVenugopal Iyer } 46261bd6825cSml 4627*0dc2366fSVenugopal Iyer nxgep->mac.default_mtu = new_mtu; 4628*0dc2366fSVenugopal Iyer nxgep->mac.is_jumbo = (new_mtu > NXGE_DEFAULT_MTU); 46291bd6825cSml 4630*0dc2366fSVenugopal Iyer NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4631*0dc2366fSVenugopal Iyer "==> nxge_m_setprop: set MTU: %d maxframe %d", 4632*0dc2366fSVenugopal Iyer new_mtu, nxgep->mac.maxframesize)); 4633*0dc2366fSVenugopal Iyer break; 4634*0dc2366fSVenugopal Iyer } 46351bd6825cSml 4636*0dc2366fSVenugopal Iyer case MAC_PROP_FLOWCTRL: { 4637*0dc2366fSVenugopal Iyer link_flowctrl_t fl; 46381bd6825cSml 4639*0dc2366fSVenugopal Iyer ASSERT(pr_valsize >= sizeof (fl)); 4640*0dc2366fSVenugopal Iyer bcopy(pr_val, &fl, sizeof (fl)); 464148056c53SMichael Speer 4642*0dc2366fSVenugopal Iyer switch (fl) { 4643*0dc2366fSVenugopal Iyer case LINK_FLOWCTRL_NONE: 4644*0dc2366fSVenugopal Iyer param_arr[param_anar_pause].value = 0; 46451bd6825cSml break; 46461bd6825cSml 4647*0dc2366fSVenugopal Iyer case LINK_FLOWCTRL_RX: 4648*0dc2366fSVenugopal Iyer param_arr[param_anar_pause].value = 1; 4649*0dc2366fSVenugopal Iyer break; 46501bd6825cSml 4651*0dc2366fSVenugopal Iyer case LINK_FLOWCTRL_TX: 4652*0dc2366fSVenugopal Iyer case LINK_FLOWCTRL_BI: 4653*0dc2366fSVenugopal Iyer err = EINVAL; 4654*0dc2366fSVenugopal Iyer break; 4655*0dc2366fSVenugopal Iyer default: 4656*0dc2366fSVenugopal Iyer err = EINVAL; 4657*0dc2366fSVenugopal Iyer break; 4658*0dc2366fSVenugopal Iyer } 4659*0dc2366fSVenugopal Iyer reprogram: 4660*0dc2366fSVenugopal Iyer if ((err == 0) && !isLDOMguest(nxgep)) { 4661*0dc2366fSVenugopal Iyer if (!nxge_param_link_update(nxgep)) { 46621bd6825cSml err = EINVAL; 46631bd6825cSml } 4664*0dc2366fSVenugopal Iyer } else { 4665*0dc2366fSVenugopal Iyer err = EINVAL; 4666*0dc2366fSVenugopal Iyer } 4667*0dc2366fSVenugopal Iyer break; 4668*0dc2366fSVenugopal Iyer } 46691bd6825cSml 4670*0dc2366fSVenugopal Iyer case MAC_PROP_PRIVATE: 4671*0dc2366fSVenugopal Iyer NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 4672*0dc2366fSVenugopal Iyer "==> nxge_m_setprop: private property")); 4673*0dc2366fSVenugopal Iyer err = nxge_set_priv_prop(nxgep, pr_name, pr_valsize, pr_val); 4674*0dc2366fSVenugopal Iyer break; 46754045d941Ssowmini 4676*0dc2366fSVenugopal Iyer default: 4677*0dc2366fSVenugopal Iyer err = ENOTSUP; 4678*0dc2366fSVenugopal Iyer break; 46791bd6825cSml } 46801bd6825cSml 46811bd6825cSml mutex_exit(nxgep->genlock); 46821bd6825cSml 46831bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46841bd6825cSml "<== nxge_m_setprop (return %d)", err)); 46851bd6825cSml return (err); 46861bd6825cSml } 46871bd6825cSml 46881bd6825cSml static int 46891bd6825cSml nxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 4690*0dc2366fSVenugopal Iyer uint_t pr_valsize, void *pr_val) 46911bd6825cSml { 46921bd6825cSml nxge_t *nxgep = barg; 46931bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 46941bd6825cSml p_nxge_stats_t statsp = nxgep->statsp; 46951bd6825cSml 46961bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 46971bd6825cSml "==> nxge_m_getprop: pr_num %d", pr_num)); 46984045d941Ssowmini 4699*0dc2366fSVenugopal Iyer switch (pr_num) { 4700*0dc2366fSVenugopal Iyer case MAC_PROP_DUPLEX: 4701*0dc2366fSVenugopal Iyer *(uint8_t *)pr_val = statsp->mac_stats.link_duplex; 4702*0dc2366fSVenugopal Iyer break; 47034045d941Ssowmini 4704*0dc2366fSVenugopal Iyer case MAC_PROP_SPEED: { 4705*0dc2366fSVenugopal Iyer uint64_t val = statsp->mac_stats.link_speed * 1000000ull; 4706afdda45fSVasumathi Sundaram - Sun Microsystems 4707*0dc2366fSVenugopal Iyer ASSERT(pr_valsize >= sizeof (val)); 4708*0dc2366fSVenugopal Iyer bcopy(&val, pr_val, sizeof (val)); 4709*0dc2366fSVenugopal Iyer break; 47104045d941Ssowmini } 47114045d941Ssowmini 4712*0dc2366fSVenugopal Iyer case MAC_PROP_STATUS: { 4713*0dc2366fSVenugopal Iyer link_state_t state = statsp->mac_stats.link_up ? 4714*0dc2366fSVenugopal Iyer LINK_STATE_UP : LINK_STATE_DOWN; 47151bd6825cSml 4716*0dc2366fSVenugopal Iyer ASSERT(pr_valsize >= sizeof (state)); 4717*0dc2366fSVenugopal Iyer bcopy(&state, pr_val, sizeof (state)); 4718*0dc2366fSVenugopal Iyer break; 4719*0dc2366fSVenugopal Iyer } 47201bd6825cSml 4721*0dc2366fSVenugopal Iyer case MAC_PROP_AUTONEG: 4722*0dc2366fSVenugopal Iyer *(uint8_t *)pr_val = param_arr[param_autoneg].value; 4723*0dc2366fSVenugopal Iyer break; 47241bd6825cSml 4725*0dc2366fSVenugopal Iyer case MAC_PROP_FLOWCTRL: { 4726*0dc2366fSVenugopal Iyer link_flowctrl_t fl = param_arr[param_anar_pause].value != 0 ? 4727*0dc2366fSVenugopal Iyer LINK_FLOWCTRL_RX : LINK_FLOWCTRL_NONE; 47281bd6825cSml 4729*0dc2366fSVenugopal Iyer ASSERT(pr_valsize >= sizeof (fl)); 4730*0dc2366fSVenugopal Iyer bcopy(&fl, pr_val, sizeof (fl)); 4731*0dc2366fSVenugopal Iyer break; 4732*0dc2366fSVenugopal Iyer } 47331bd6825cSml 4734*0dc2366fSVenugopal Iyer case MAC_PROP_ADV_1000FDX_CAP: 4735*0dc2366fSVenugopal Iyer *(uint8_t *)pr_val = param_arr[param_anar_1000fdx].value; 4736*0dc2366fSVenugopal Iyer break; 47371bd6825cSml 4738*0dc2366fSVenugopal Iyer case MAC_PROP_EN_1000FDX_CAP: 4739*0dc2366fSVenugopal Iyer *(uint8_t *)pr_val = nxgep->param_en_1000fdx; 4740*0dc2366fSVenugopal Iyer break; 47411bd6825cSml 4742*0dc2366fSVenugopal Iyer case MAC_PROP_ADV_100FDX_CAP: 4743*0dc2366fSVenugopal Iyer *(uint8_t *)pr_val = param_arr[param_anar_100fdx].value; 4744*0dc2366fSVenugopal Iyer break; 47451bd6825cSml 4746*0dc2366fSVenugopal Iyer case MAC_PROP_EN_100FDX_CAP: 4747*0dc2366fSVenugopal Iyer *(uint8_t *)pr_val = nxgep->param_en_100fdx; 4748*0dc2366fSVenugopal Iyer break; 47491bd6825cSml 4750*0dc2366fSVenugopal Iyer case MAC_PROP_ADV_10FDX_CAP: 4751*0dc2366fSVenugopal Iyer *(uint8_t *)pr_val = param_arr[param_anar_10fdx].value; 4752*0dc2366fSVenugopal Iyer break; 47531bd6825cSml 4754*0dc2366fSVenugopal Iyer case MAC_PROP_EN_10FDX_CAP: 4755*0dc2366fSVenugopal Iyer *(uint8_t *)pr_val = nxgep->param_en_10fdx; 4756*0dc2366fSVenugopal Iyer break; 47571bd6825cSml 4758*0dc2366fSVenugopal Iyer case MAC_PROP_PRIVATE: 4759*0dc2366fSVenugopal Iyer return (nxge_get_priv_prop(nxgep, pr_name, pr_valsize, 4760*0dc2366fSVenugopal Iyer pr_val)); 47611bd6825cSml 4762*0dc2366fSVenugopal Iyer default: 4763*0dc2366fSVenugopal Iyer return (ENOTSUP); 4764*0dc2366fSVenugopal Iyer } 47651bd6825cSml 4766*0dc2366fSVenugopal Iyer return (0); 4767*0dc2366fSVenugopal Iyer } 4768f0f2c3a5SGirish Moodalbail 4769*0dc2366fSVenugopal Iyer static void 4770*0dc2366fSVenugopal Iyer nxge_m_propinfo(void *barg, const char *pr_name, mac_prop_id_t pr_num, 4771*0dc2366fSVenugopal Iyer mac_prop_info_handle_t prh) 4772*0dc2366fSVenugopal Iyer { 4773*0dc2366fSVenugopal Iyer nxge_t *nxgep = barg; 4774*0dc2366fSVenugopal Iyer p_nxge_stats_t statsp = nxgep->statsp; 4775*0dc2366fSVenugopal Iyer 4776*0dc2366fSVenugopal Iyer /* 4777*0dc2366fSVenugopal Iyer * By default permissions are read/write unless specified 4778*0dc2366fSVenugopal Iyer * otherwise by the driver. 4779*0dc2366fSVenugopal Iyer */ 4780*0dc2366fSVenugopal Iyer 4781*0dc2366fSVenugopal Iyer switch (pr_num) { 4782*0dc2366fSVenugopal Iyer case MAC_PROP_DUPLEX: 4783*0dc2366fSVenugopal Iyer case MAC_PROP_SPEED: 4784*0dc2366fSVenugopal Iyer case MAC_PROP_STATUS: 4785*0dc2366fSVenugopal Iyer case MAC_PROP_EN_1000HDX_CAP: 4786*0dc2366fSVenugopal Iyer case MAC_PROP_EN_100HDX_CAP: 4787*0dc2366fSVenugopal Iyer case MAC_PROP_EN_10HDX_CAP: 4788*0dc2366fSVenugopal Iyer case MAC_PROP_ADV_1000FDX_CAP: 4789*0dc2366fSVenugopal Iyer case MAC_PROP_ADV_1000HDX_CAP: 4790*0dc2366fSVenugopal Iyer case MAC_PROP_ADV_100FDX_CAP: 4791*0dc2366fSVenugopal Iyer case MAC_PROP_ADV_100HDX_CAP: 4792*0dc2366fSVenugopal Iyer case MAC_PROP_ADV_10FDX_CAP: 4793*0dc2366fSVenugopal Iyer case MAC_PROP_ADV_10HDX_CAP: 4794*0dc2366fSVenugopal Iyer /* 4795*0dc2366fSVenugopal Iyer * Note that read-only properties don't need to 4796*0dc2366fSVenugopal Iyer * provide default values since they cannot be 4797*0dc2366fSVenugopal Iyer * changed by the administrator. 4798*0dc2366fSVenugopal Iyer */ 4799*0dc2366fSVenugopal Iyer mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 4800*0dc2366fSVenugopal Iyer break; 4801*0dc2366fSVenugopal Iyer 4802*0dc2366fSVenugopal Iyer case MAC_PROP_EN_1000FDX_CAP: 4803*0dc2366fSVenugopal Iyer case MAC_PROP_EN_100FDX_CAP: 4804*0dc2366fSVenugopal Iyer case MAC_PROP_EN_10FDX_CAP: 4805*0dc2366fSVenugopal Iyer mac_prop_info_set_default_uint8(prh, 1); 4806*0dc2366fSVenugopal Iyer break; 4807*0dc2366fSVenugopal Iyer 4808*0dc2366fSVenugopal Iyer case MAC_PROP_AUTONEG: 4809*0dc2366fSVenugopal Iyer mac_prop_info_set_default_uint8(prh, 1); 4810*0dc2366fSVenugopal Iyer break; 4811*0dc2366fSVenugopal Iyer 4812*0dc2366fSVenugopal Iyer case MAC_PROP_FLOWCTRL: 4813*0dc2366fSVenugopal Iyer mac_prop_info_set_default_link_flowctrl(prh, LINK_FLOWCTRL_RX); 4814*0dc2366fSVenugopal Iyer break; 4815*0dc2366fSVenugopal Iyer 4816*0dc2366fSVenugopal Iyer case MAC_PROP_MTU: 4817*0dc2366fSVenugopal Iyer mac_prop_info_set_range_uint32(prh, 4818*0dc2366fSVenugopal Iyer NXGE_DEFAULT_MTU, NXGE_MAXIMUM_MTU); 4819*0dc2366fSVenugopal Iyer break; 4820*0dc2366fSVenugopal Iyer 4821*0dc2366fSVenugopal Iyer case MAC_PROP_PRIVATE: 4822*0dc2366fSVenugopal Iyer nxge_priv_propinfo(pr_name, prh); 4823*0dc2366fSVenugopal Iyer break; 4824*0dc2366fSVenugopal Iyer } 4825*0dc2366fSVenugopal Iyer 4826*0dc2366fSVenugopal Iyer mutex_enter(nxgep->genlock); 4827*0dc2366fSVenugopal Iyer if (statsp->port_stats.lb_mode != nxge_lb_normal && 4828*0dc2366fSVenugopal Iyer nxge_param_locked(pr_num)) { 4829*0dc2366fSVenugopal Iyer /* 4830*0dc2366fSVenugopal Iyer * Some properties are locked (read-only) while the 4831*0dc2366fSVenugopal Iyer * device is in any sort of loopback mode. 4832*0dc2366fSVenugopal Iyer */ 4833*0dc2366fSVenugopal Iyer mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 48341bd6825cSml } 4835*0dc2366fSVenugopal Iyer mutex_exit(nxgep->genlock); 4836*0dc2366fSVenugopal Iyer } 48371bd6825cSml 4838*0dc2366fSVenugopal Iyer static void 4839*0dc2366fSVenugopal Iyer nxge_priv_propinfo(const char *pr_name, mac_prop_info_handle_t prh) 4840*0dc2366fSVenugopal Iyer { 4841*0dc2366fSVenugopal Iyer char valstr[64]; 48421bd6825cSml 4843*0dc2366fSVenugopal Iyer bzero(valstr, sizeof (valstr)); 4844*0dc2366fSVenugopal Iyer 4845*0dc2366fSVenugopal Iyer if (strcmp(pr_name, "_function_number") == 0 || 4846*0dc2366fSVenugopal Iyer strcmp(pr_name, "_fw_version") == 0 || 4847*0dc2366fSVenugopal Iyer strcmp(pr_name, "_port_mode") == 0 || 4848*0dc2366fSVenugopal Iyer strcmp(pr_name, "_hot_swap_phy") == 0) { 4849*0dc2366fSVenugopal Iyer mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 4850*0dc2366fSVenugopal Iyer 4851*0dc2366fSVenugopal Iyer } else if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 4852*0dc2366fSVenugopal Iyer (void) snprintf(valstr, sizeof (valstr), 4853*0dc2366fSVenugopal Iyer "%d", RXDMA_RCR_TO_DEFAULT); 4854*0dc2366fSVenugopal Iyer 4855*0dc2366fSVenugopal Iyer } else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 4856*0dc2366fSVenugopal Iyer (void) snprintf(valstr, sizeof (valstr), 4857*0dc2366fSVenugopal Iyer "%d", RXDMA_RCR_PTHRES_DEFAULT); 4858*0dc2366fSVenugopal Iyer 4859*0dc2366fSVenugopal Iyer } else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0 || 4860*0dc2366fSVenugopal Iyer strcmp(pr_name, "_class_opt_ipv4_udp") == 0 || 4861*0dc2366fSVenugopal Iyer strcmp(pr_name, "_class_opt_ipv4_ah") == 0 || 4862*0dc2366fSVenugopal Iyer strcmp(pr_name, "_class_opt_ipv4_sctp") == 0 || 4863*0dc2366fSVenugopal Iyer strcmp(pr_name, "_class_opt_ipv6_tcp") == 0 || 4864*0dc2366fSVenugopal Iyer strcmp(pr_name, "_class_opt_ipv6_udp") == 0 || 4865*0dc2366fSVenugopal Iyer strcmp(pr_name, "_class_opt_ipv6_ah") == 0 || 4866*0dc2366fSVenugopal Iyer strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 4867*0dc2366fSVenugopal Iyer (void) snprintf(valstr, sizeof (valstr), "%x", 4868*0dc2366fSVenugopal Iyer NXGE_CLASS_FLOW_GEN_SERVER); 4869*0dc2366fSVenugopal Iyer 4870*0dc2366fSVenugopal Iyer } else if (strcmp(pr_name, "_soft_lso_enable") == 0) { 4871*0dc2366fSVenugopal Iyer (void) snprintf(valstr, sizeof (valstr), "%d", 0); 4872*0dc2366fSVenugopal Iyer 4873*0dc2366fSVenugopal Iyer } else if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) { 4874*0dc2366fSVenugopal Iyer (void) snprintf(valstr, sizeof (valstr), "%d", 1); 4875*0dc2366fSVenugopal Iyer 4876*0dc2366fSVenugopal Iyer } else if (strcmp(pr_name, "_adv_pause_cap") == 0) { 4877*0dc2366fSVenugopal Iyer (void) snprintf(valstr, sizeof (valstr), "%d", 1); 4878*0dc2366fSVenugopal Iyer } 4879*0dc2366fSVenugopal Iyer 4880*0dc2366fSVenugopal Iyer if (strlen(valstr) > 0) 4881*0dc2366fSVenugopal Iyer mac_prop_info_set_default_str(prh, valstr); 48821bd6825cSml } 48831bd6825cSml 48841bd6825cSml /* ARGSUSED */ 48851bd6825cSml static int 48861bd6825cSml nxge_set_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_valsize, 48871bd6825cSml const void *pr_val) 48881bd6825cSml { 48891bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 48901bd6825cSml int err = 0; 48911bd6825cSml long result; 48921bd6825cSml 48931bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 48941bd6825cSml "==> nxge_set_priv_prop: name %s", pr_name)); 48951bd6825cSml 48961bd6825cSml /* Blanking */ 48971bd6825cSml if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 48981bd6825cSml err = nxge_param_rx_intr_time(nxgep, NULL, NULL, 48991bd6825cSml (char *)pr_val, 49001bd6825cSml (caddr_t)¶m_arr[param_rxdma_intr_time]); 49011bd6825cSml if (err) { 49021bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49031bd6825cSml "<== nxge_set_priv_prop: " 49041bd6825cSml "unable to set (%s)", pr_name)); 49051bd6825cSml err = EINVAL; 49061bd6825cSml } else { 49071bd6825cSml err = 0; 49081bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49091bd6825cSml "<== nxge_set_priv_prop: " 49101bd6825cSml "set (%s)", pr_name)); 49111bd6825cSml } 49121bd6825cSml 49131bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49141bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 49151bd6825cSml pr_name, result)); 49161bd6825cSml 49171bd6825cSml return (err); 49181bd6825cSml } 49191bd6825cSml 49201bd6825cSml if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 49211bd6825cSml err = nxge_param_rx_intr_pkts(nxgep, NULL, NULL, 49221bd6825cSml (char *)pr_val, 49231bd6825cSml (caddr_t)¶m_arr[param_rxdma_intr_pkts]); 49241bd6825cSml if (err) { 49251bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49261bd6825cSml "<== nxge_set_priv_prop: " 49271bd6825cSml "unable to set (%s)", pr_name)); 49281bd6825cSml err = EINVAL; 49291bd6825cSml } else { 49301bd6825cSml err = 0; 49311bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49321bd6825cSml "<== nxge_set_priv_prop: " 49331bd6825cSml "set (%s)", pr_name)); 49341bd6825cSml } 49351bd6825cSml 49361bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49371bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 49381bd6825cSml pr_name, result)); 49391bd6825cSml 49401bd6825cSml return (err); 49411bd6825cSml } 49421bd6825cSml 49431bd6825cSml /* Classification */ 49441bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 49451bd6825cSml if (pr_val == NULL) { 49461bd6825cSml err = EINVAL; 49471bd6825cSml return (err); 49481bd6825cSml } 49491bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49501bd6825cSml 49511bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 49521bd6825cSml NULL, (char *)pr_val, 49531bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 49541bd6825cSml 49551bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49561bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 49571bd6825cSml pr_name, result)); 49581bd6825cSml 49591bd6825cSml return (err); 49601bd6825cSml } 49611bd6825cSml 49621bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 49631bd6825cSml if (pr_val == NULL) { 49641bd6825cSml err = EINVAL; 49651bd6825cSml return (err); 49661bd6825cSml } 49671bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49681bd6825cSml 49691bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 49701bd6825cSml NULL, (char *)pr_val, 49711bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 49721bd6825cSml 49731bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49741bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 49751bd6825cSml pr_name, result)); 49761bd6825cSml 49771bd6825cSml return (err); 49781bd6825cSml } 49791bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 49801bd6825cSml if (pr_val == NULL) { 49811bd6825cSml err = EINVAL; 49821bd6825cSml return (err); 49831bd6825cSml } 49841bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 49851bd6825cSml 49861bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 49871bd6825cSml NULL, (char *)pr_val, 49881bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 49891bd6825cSml 49901bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 49911bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 49921bd6825cSml pr_name, result)); 49931bd6825cSml 49941bd6825cSml return (err); 49951bd6825cSml } 49961bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 49971bd6825cSml if (pr_val == NULL) { 49981bd6825cSml err = EINVAL; 49991bd6825cSml return (err); 50001bd6825cSml } 50011bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50021bd6825cSml 50031bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 50041bd6825cSml NULL, (char *)pr_val, 50051bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 50061bd6825cSml 50071bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50081bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 50091bd6825cSml pr_name, result)); 50101bd6825cSml 50111bd6825cSml return (err); 50121bd6825cSml } 50131bd6825cSml 50141bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 50151bd6825cSml if (pr_val == NULL) { 50161bd6825cSml err = EINVAL; 50171bd6825cSml return (err); 50181bd6825cSml } 50191bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50201bd6825cSml 50211bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 50221bd6825cSml NULL, (char *)pr_val, 50231bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 50241bd6825cSml 50251bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50261bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 50271bd6825cSml pr_name, result)); 50281bd6825cSml 50291bd6825cSml return (err); 50301bd6825cSml } 50311bd6825cSml 50321bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 50331bd6825cSml if (pr_val == NULL) { 50341bd6825cSml err = EINVAL; 50351bd6825cSml return (err); 50361bd6825cSml } 50371bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50381bd6825cSml 50391bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 50401bd6825cSml NULL, (char *)pr_val, 50411bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 50421bd6825cSml 50431bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50441bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 50451bd6825cSml pr_name, result)); 50461bd6825cSml 50471bd6825cSml return (err); 50481bd6825cSml } 50491bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 50501bd6825cSml if (pr_val == NULL) { 50511bd6825cSml err = EINVAL; 50521bd6825cSml return (err); 50531bd6825cSml } 50541bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50551bd6825cSml 50561bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 50571bd6825cSml NULL, (char *)pr_val, 50581bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 50591bd6825cSml 50601bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50611bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 50621bd6825cSml pr_name, result)); 50631bd6825cSml 50641bd6825cSml return (err); 50651bd6825cSml } 50661bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 50671bd6825cSml if (pr_val == NULL) { 50681bd6825cSml err = EINVAL; 50691bd6825cSml return (err); 50701bd6825cSml } 50711bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50721bd6825cSml 50731bd6825cSml err = nxge_param_set_ip_opt(nxgep, NULL, 50741bd6825cSml NULL, (char *)pr_val, 50751bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 50761bd6825cSml 50771bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50781bd6825cSml "<== nxge_set_priv_prop: name %s (value 0x%x)", 50791bd6825cSml pr_name, result)); 50801bd6825cSml 50811bd6825cSml return (err); 50821bd6825cSml } 50831bd6825cSml 50841bd6825cSml if (strcmp(pr_name, "_soft_lso_enable") == 0) { 50851bd6825cSml if (pr_val == NULL) { 50861bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50871bd6825cSml "==> nxge_set_priv_prop: name %s (null)", pr_name)); 50881bd6825cSml err = EINVAL; 50891bd6825cSml return (err); 50901bd6825cSml } 50911bd6825cSml 50921bd6825cSml (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 50931bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 50941bd6825cSml "<== nxge_set_priv_prop: name %s " 50951bd6825cSml "(lso %d pr_val %s value %d)", 50961bd6825cSml pr_name, nxgep->soft_lso_enable, pr_val, result)); 50971bd6825cSml 50981bd6825cSml if (result > 1 || result < 0) { 50991bd6825cSml err = EINVAL; 51001bd6825cSml } else { 51011bd6825cSml if (nxgep->soft_lso_enable == (uint32_t)result) { 51021bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51031bd6825cSml "no change (%d %d)", 51041bd6825cSml nxgep->soft_lso_enable, result)); 51051bd6825cSml return (0); 51061bd6825cSml } 51071bd6825cSml } 51081bd6825cSml 51091bd6825cSml nxgep->soft_lso_enable = (int)result; 51101bd6825cSml 51111bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51121bd6825cSml "<== nxge_set_priv_prop: name %s (value %d)", 51131bd6825cSml pr_name, result)); 51141bd6825cSml 51151bd6825cSml return (err); 51161bd6825cSml } 511700161856Syc /* 511800161856Syc * Commands like "ndd -set /dev/nxge0 adv_10gfdx_cap 1" cause the 511900161856Syc * following code to be executed. 512000161856Syc */ 51214045d941Ssowmini if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) { 51224045d941Ssowmini err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val, 51234045d941Ssowmini (caddr_t)¶m_arr[param_anar_10gfdx]); 51244045d941Ssowmini return (err); 51254045d941Ssowmini } 51264045d941Ssowmini if (strcmp(pr_name, "_adv_pause_cap") == 0) { 51274045d941Ssowmini err = nxge_param_set_mac(nxgep, NULL, NULL, (char *)pr_val, 51284045d941Ssowmini (caddr_t)¶m_arr[param_anar_pause]); 51294045d941Ssowmini return (err); 51304045d941Ssowmini } 51311bd6825cSml 51321bd6825cSml return (EINVAL); 51331bd6825cSml } 51341bd6825cSml 51351bd6825cSml static int 5136*0dc2366fSVenugopal Iyer nxge_get_priv_prop(p_nxge_t nxgep, const char *pr_name, uint_t pr_valsize, 5137*0dc2366fSVenugopal Iyer void *pr_val) 51381bd6825cSml { 51391bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 51401bd6825cSml char valstr[MAXNAMELEN]; 51411bd6825cSml int err = EINVAL; 51421bd6825cSml uint_t strsize; 51431bd6825cSml 51441bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51451bd6825cSml "==> nxge_get_priv_prop: property %s", pr_name)); 51461bd6825cSml 51471bd6825cSml /* function number */ 51481bd6825cSml if (strcmp(pr_name, "_function_number") == 0) { 51494045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 51504045d941Ssowmini nxgep->function_num); 51511bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51521bd6825cSml "==> nxge_get_priv_prop: name %s " 51531bd6825cSml "(value %d valstr %s)", 51541bd6825cSml pr_name, nxgep->function_num, valstr)); 51551bd6825cSml 51561bd6825cSml err = 0; 51571bd6825cSml goto done; 51581bd6825cSml } 51591bd6825cSml 51601bd6825cSml /* Neptune firmware version */ 51611bd6825cSml if (strcmp(pr_name, "_fw_version") == 0) { 51624045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%s", 51634045d941Ssowmini nxgep->vpd_info.ver); 51641bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 51651bd6825cSml "==> nxge_get_priv_prop: name %s " 51661bd6825cSml "(value %d valstr %s)", 51671bd6825cSml pr_name, nxgep->vpd_info.ver, valstr)); 51681bd6825cSml 51691bd6825cSml err = 0; 51701bd6825cSml goto done; 51711bd6825cSml } 51721bd6825cSml 51731bd6825cSml /* port PHY mode */ 51741bd6825cSml if (strcmp(pr_name, "_port_mode") == 0) { 51751bd6825cSml switch (nxgep->mac.portmode) { 51761bd6825cSml case PORT_1G_COPPER: 51774045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G copper %s", 51781bd6825cSml nxgep->hot_swappable_phy ? 51791bd6825cSml "[Hot Swappable]" : ""); 51801bd6825cSml break; 51811bd6825cSml case PORT_1G_FIBER: 51824045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G fiber %s", 51831bd6825cSml nxgep->hot_swappable_phy ? 51841bd6825cSml "[hot swappable]" : ""); 51851bd6825cSml break; 51861bd6825cSml case PORT_10G_COPPER: 51874045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 51884045d941Ssowmini "10G copper %s", 51891bd6825cSml nxgep->hot_swappable_phy ? 51901bd6825cSml "[hot swappable]" : ""); 51911bd6825cSml break; 51921bd6825cSml case PORT_10G_FIBER: 51934045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "10G fiber %s", 51941bd6825cSml nxgep->hot_swappable_phy ? 51951bd6825cSml "[hot swappable]" : ""); 51961bd6825cSml break; 51971bd6825cSml case PORT_10G_SERDES: 51984045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 51994045d941Ssowmini "10G serdes %s", nxgep->hot_swappable_phy ? 52001bd6825cSml "[hot swappable]" : ""); 52011bd6825cSml break; 52021bd6825cSml case PORT_1G_SERDES: 52034045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "1G serdes %s", 52041bd6825cSml nxgep->hot_swappable_phy ? 52051bd6825cSml "[hot swappable]" : ""); 52061bd6825cSml break; 520700161856Syc case PORT_1G_TN1010: 520800161856Syc (void) snprintf(valstr, sizeof (valstr), 520900161856Syc "1G TN1010 copper %s", nxgep->hot_swappable_phy ? 521000161856Syc "[hot swappable]" : ""); 521100161856Syc break; 521200161856Syc case PORT_10G_TN1010: 521300161856Syc (void) snprintf(valstr, sizeof (valstr), 521400161856Syc "10G TN1010 copper %s", nxgep->hot_swappable_phy ? 521500161856Syc "[hot swappable]" : ""); 521600161856Syc break; 52171bd6825cSml case PORT_1G_RGMII_FIBER: 52184045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 52194045d941Ssowmini "1G rgmii fiber %s", nxgep->hot_swappable_phy ? 52201bd6825cSml "[hot swappable]" : ""); 52211bd6825cSml break; 52221bd6825cSml case PORT_HSP_MODE: 52234045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 5224c2d37b8bSml "phy not present[hot swappable]"); 52251bd6825cSml break; 52261bd6825cSml default: 52274045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "unknown %s", 52281bd6825cSml nxgep->hot_swappable_phy ? 52291bd6825cSml "[hot swappable]" : ""); 52301bd6825cSml break; 52311bd6825cSml } 52321bd6825cSml 52331bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52341bd6825cSml "==> nxge_get_priv_prop: name %s (value %s)", 52351bd6825cSml pr_name, valstr)); 52361bd6825cSml 52371bd6825cSml err = 0; 52381bd6825cSml goto done; 52391bd6825cSml } 52401bd6825cSml 52411bd6825cSml /* Hot swappable PHY */ 52421bd6825cSml if (strcmp(pr_name, "_hot_swap_phy") == 0) { 52434045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%s", 52441bd6825cSml nxgep->hot_swappable_phy ? 52451bd6825cSml "yes" : "no"); 52461bd6825cSml 52471bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52481bd6825cSml "==> nxge_get_priv_prop: name %s " 52491bd6825cSml "(value %d valstr %s)", 52501bd6825cSml pr_name, nxgep->hot_swappable_phy, valstr)); 52511bd6825cSml 52521bd6825cSml err = 0; 52531bd6825cSml goto done; 52541bd6825cSml } 52551bd6825cSml 52561bd6825cSml 52571bd6825cSml /* Receive Interrupt Blanking Parameters */ 52581bd6825cSml if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 52594045d941Ssowmini err = 0; 52604045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 52614045d941Ssowmini nxgep->intr_timeout); 52621bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52631bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 52641bd6825cSml pr_name, 52651bd6825cSml (uint32_t)nxgep->intr_timeout)); 52661bd6825cSml goto done; 52671bd6825cSml } 52681bd6825cSml 52691bd6825cSml if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 52704045d941Ssowmini err = 0; 52714045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 52724045d941Ssowmini nxgep->intr_threshold); 52731bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52741bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 52751bd6825cSml pr_name, (uint32_t)nxgep->intr_threshold)); 52761bd6825cSml 52771bd6825cSml goto done; 52781bd6825cSml } 52791bd6825cSml 52801bd6825cSml /* Classification and Load Distribution Configuration */ 52811bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 52821bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 52831bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 52841bd6825cSml 52854045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52861bd6825cSml (int)param_arr[param_class_opt_ipv4_tcp].value); 52871bd6825cSml 52881bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 52891bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 52901bd6825cSml goto done; 52911bd6825cSml } 52921bd6825cSml 52931bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 52941bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 52951bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 52961bd6825cSml 52974045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 52981bd6825cSml (int)param_arr[param_class_opt_ipv4_udp].value); 52991bd6825cSml 53001bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53011bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 53021bd6825cSml goto done; 53031bd6825cSml } 53041bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 53051bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 53061bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 53071bd6825cSml 53084045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53091bd6825cSml (int)param_arr[param_class_opt_ipv4_ah].value); 53101bd6825cSml 53111bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53121bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 53131bd6825cSml goto done; 53141bd6825cSml } 53151bd6825cSml 53161bd6825cSml if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 53171bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 53181bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 53191bd6825cSml 53204045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53211bd6825cSml (int)param_arr[param_class_opt_ipv4_sctp].value); 53221bd6825cSml 53231bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53241bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 53251bd6825cSml goto done; 53261bd6825cSml } 53271bd6825cSml 53281bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 53291bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 53301bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 53311bd6825cSml 53324045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53331bd6825cSml (int)param_arr[param_class_opt_ipv6_tcp].value); 53341bd6825cSml 53351bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53361bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 53371bd6825cSml goto done; 53381bd6825cSml } 53391bd6825cSml 53401bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 53411bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 53421bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 53431bd6825cSml 53444045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53451bd6825cSml (int)param_arr[param_class_opt_ipv6_udp].value); 53461bd6825cSml 53471bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53481bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 53491bd6825cSml goto done; 53501bd6825cSml } 53511bd6825cSml 53521bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 53531bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 53541bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 53551bd6825cSml 53564045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53571bd6825cSml (int)param_arr[param_class_opt_ipv6_ah].value); 53581bd6825cSml 53591bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53601bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 53611bd6825cSml goto done; 53621bd6825cSml } 53631bd6825cSml 53641bd6825cSml if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 53651bd6825cSml err = nxge_dld_get_ip_opt(nxgep, 53661bd6825cSml (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 53671bd6825cSml 53684045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%x", 53691bd6825cSml (int)param_arr[param_class_opt_ipv6_sctp].value); 53701bd6825cSml 53711bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53721bd6825cSml "==> nxge_get_priv_prop: %s", valstr)); 53731bd6825cSml goto done; 53741bd6825cSml } 53751bd6825cSml 53761bd6825cSml /* Software LSO */ 53771bd6825cSml if (strcmp(pr_name, "_soft_lso_enable") == 0) { 53784045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), 53794045d941Ssowmini "%d", nxgep->soft_lso_enable); 53801bd6825cSml err = 0; 53811bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 53821bd6825cSml "==> nxge_get_priv_prop: name %s (value %d)", 53831bd6825cSml pr_name, nxgep->soft_lso_enable)); 53841bd6825cSml 53851bd6825cSml goto done; 53861bd6825cSml } 53874045d941Ssowmini if (strcmp(pr_name, "_adv_10gfdx_cap") == 0) { 53884045d941Ssowmini err = 0; 5389*0dc2366fSVenugopal Iyer if (nxgep->param_arr[param_anar_10gfdx].value != 0) { 53904045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 1); 53914045d941Ssowmini goto done; 53924045d941Ssowmini } else { 53934045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 53944045d941Ssowmini goto done; 53954045d941Ssowmini } 53964045d941Ssowmini } 53974045d941Ssowmini if (strcmp(pr_name, "_adv_pause_cap") == 0) { 53984045d941Ssowmini err = 0; 5399*0dc2366fSVenugopal Iyer if (nxgep->param_arr[param_anar_pause].value != 0) { 54004045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 1); 54014045d941Ssowmini goto done; 54024045d941Ssowmini } else { 54034045d941Ssowmini (void) snprintf(valstr, sizeof (valstr), "%d", 0); 54044045d941Ssowmini goto done; 54054045d941Ssowmini } 54064045d941Ssowmini } 54071bd6825cSml 54081bd6825cSml done: 54091bd6825cSml if (err == 0) { 54101bd6825cSml strsize = (uint_t)strlen(valstr); 54111bd6825cSml if (pr_valsize < strsize) { 54121bd6825cSml err = ENOBUFS; 54131bd6825cSml } else { 54141bd6825cSml (void) strlcpy(pr_val, valstr, pr_valsize); 54151bd6825cSml } 54161bd6825cSml } 54171bd6825cSml 54181bd6825cSml NXGE_DEBUG_MSG((nxgep, NXGE_CTL, 54191bd6825cSml "<== nxge_get_priv_prop: return %d", err)); 54201bd6825cSml return (err); 54211bd6825cSml } 54221bd6825cSml 542344961713Sgirish /* 542444961713Sgirish * Module loading and removing entry points. 542544961713Sgirish */ 542644961713Sgirish 54276f157acbSml DDI_DEFINE_STREAM_OPS(nxge_dev_ops, nulldev, nulldev, nxge_attach, nxge_detach, 542819397407SSherry Moore nodev, NULL, D_MP, NULL, nxge_quiesce); 542944961713Sgirish 54302e59129aSraghus #define NXGE_DESC_VER "Sun NIU 10Gb Ethernet" 543144961713Sgirish 543244961713Sgirish /* 543344961713Sgirish * Module linkage information for the kernel. 543444961713Sgirish */ 543544961713Sgirish static struct modldrv nxge_modldrv = { 543644961713Sgirish &mod_driverops, 543744961713Sgirish NXGE_DESC_VER, 543844961713Sgirish &nxge_dev_ops 543944961713Sgirish }; 544044961713Sgirish 544144961713Sgirish static struct modlinkage modlinkage = { 544244961713Sgirish MODREV_1, (void *) &nxge_modldrv, NULL 544344961713Sgirish }; 544444961713Sgirish 544544961713Sgirish int 544644961713Sgirish _init(void) 544744961713Sgirish { 544844961713Sgirish int status; 544944961713Sgirish 54503b2d9860SMichael Speer MUTEX_INIT(&nxgedebuglock, NULL, MUTEX_DRIVER, NULL); 54513b2d9860SMichael Speer 545244961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init")); 54533b2d9860SMichael Speer 545444961713Sgirish mac_init_ops(&nxge_dev_ops, "nxge"); 54553b2d9860SMichael Speer 545644961713Sgirish status = ddi_soft_state_init(&nxge_list, sizeof (nxge_t), 0); 545744961713Sgirish if (status != 0) { 545844961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, 54594045d941Ssowmini "failed to init device soft state")); 546044961713Sgirish goto _init_exit; 546144961713Sgirish } 54623b2d9860SMichael Speer 546344961713Sgirish status = mod_install(&modlinkage); 546444961713Sgirish if (status != 0) { 546544961713Sgirish ddi_soft_state_fini(&nxge_list); 546644961713Sgirish NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, "Mod install failed")); 546744961713Sgirish goto _init_exit; 546844961713Sgirish } 546944961713Sgirish 547044961713Sgirish MUTEX_INIT(&nxge_common_lock, NULL, MUTEX_DRIVER, NULL); 547144961713Sgirish 54723b2d9860SMichael Speer NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _init status = 0x%X", status)); 54733b2d9860SMichael Speer return (status); 547444961713Sgirish 54753b2d9860SMichael Speer _init_exit: 54763b2d9860SMichael Speer NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _init status = 0x%X", status)); 54773b2d9860SMichael Speer MUTEX_DESTROY(&nxgedebuglock); 547844961713Sgirish return (status); 547944961713Sgirish } 548044961713Sgirish 548144961713Sgirish int 548244961713Sgirish _fini(void) 548344961713Sgirish { 548444961713Sgirish int status; 548544961713Sgirish 548644961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini")); 548744961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove")); 5488a3c5bd6dSspeer 5489a3c5bd6dSspeer if (nxge_mblks_pending) 5490a3c5bd6dSspeer return (EBUSY); 5491a3c5bd6dSspeer 549244961713Sgirish status = mod_remove(&modlinkage); 549344961713Sgirish if (status != DDI_SUCCESS) { 549444961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, 54954045d941Ssowmini "Module removal failed 0x%08x", 54964045d941Ssowmini status)); 549744961713Sgirish goto _fini_exit; 549844961713Sgirish } 549944961713Sgirish 550044961713Sgirish mac_fini_ops(&nxge_dev_ops); 550144961713Sgirish 550244961713Sgirish ddi_soft_state_fini(&nxge_list); 550344961713Sgirish 55043b2d9860SMichael Speer NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _fini status = 0x%08x", status)); 55053b2d9860SMichael Speer 550644961713Sgirish MUTEX_DESTROY(&nxge_common_lock); 55073b2d9860SMichael Speer MUTEX_DESTROY(&nxgedebuglock); 55083b2d9860SMichael Speer return (status); 550944961713Sgirish 55103b2d9860SMichael Speer _fini_exit: 55113b2d9860SMichael Speer NXGE_DEBUG_MSG((NULL, MOD_CTL, "<== _fini status = 0x%08x", status)); 551244961713Sgirish return (status); 551344961713Sgirish } 551444961713Sgirish 551544961713Sgirish int 551644961713Sgirish _info(struct modinfo *modinfop) 551744961713Sgirish { 551844961713Sgirish int status; 551944961713Sgirish 552044961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info")); 552144961713Sgirish status = mod_info(&modlinkage, modinfop); 552244961713Sgirish NXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status)); 552344961713Sgirish 552444961713Sgirish return (status); 552544961713Sgirish } 552644961713Sgirish 5527da14cebeSEric Cheng /*ARGSUSED*/ 5528da14cebeSEric Cheng static int 5529da14cebeSEric Cheng nxge_tx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num) 5530da14cebeSEric Cheng { 5531da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5532da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5533da14cebeSEric Cheng uint32_t channel; 5534da14cebeSEric Cheng p_tx_ring_t ring; 5535da14cebeSEric Cheng 5536da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.tdc.start + rhp->index; 5537da14cebeSEric Cheng ring = nxgep->tx_rings->rings[channel]; 5538da14cebeSEric Cheng 5539da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 5540*0dc2366fSVenugopal Iyer ASSERT(ring->tx_ring_handle == NULL); 5541da14cebeSEric Cheng ring->tx_ring_handle = rhp->ring_handle; 5542da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5543da14cebeSEric Cheng 5544da14cebeSEric Cheng return (0); 5545da14cebeSEric Cheng } 5546da14cebeSEric Cheng 5547da14cebeSEric Cheng static void 5548da14cebeSEric Cheng nxge_tx_ring_stop(mac_ring_driver_t rdriver) 5549da14cebeSEric Cheng { 5550da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5551da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5552da14cebeSEric Cheng uint32_t channel; 5553da14cebeSEric Cheng p_tx_ring_t ring; 5554da14cebeSEric Cheng 5555da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.tdc.start + rhp->index; 5556da14cebeSEric Cheng ring = nxgep->tx_rings->rings[channel]; 5557da14cebeSEric Cheng 5558da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 5559*0dc2366fSVenugopal Iyer ASSERT(ring->tx_ring_handle != NULL); 5560da14cebeSEric Cheng ring->tx_ring_handle = (mac_ring_handle_t)NULL; 5561da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5562da14cebeSEric Cheng } 5563da14cebeSEric Cheng 5564*0dc2366fSVenugopal Iyer int 5565da14cebeSEric Cheng nxge_rx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num) 5566da14cebeSEric Cheng { 5567da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5568da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5569da14cebeSEric Cheng uint32_t channel; 5570da14cebeSEric Cheng p_rx_rcr_ring_t ring; 5571da14cebeSEric Cheng int i; 5572da14cebeSEric Cheng 5573da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.start_rdc + rhp->index; 5574da14cebeSEric Cheng ring = nxgep->rx_rcr_rings->rcr_rings[channel]; 5575da14cebeSEric Cheng 5576da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 5577da14cebeSEric Cheng 5578*0dc2366fSVenugopal Iyer if (ring->started) { 5579*0dc2366fSVenugopal Iyer ASSERT(ring->started == B_FALSE); 5580da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5581da14cebeSEric Cheng return (0); 5582da14cebeSEric Cheng } 5583da14cebeSEric Cheng 5584da14cebeSEric Cheng /* set rcr_ring */ 5585da14cebeSEric Cheng for (i = 0; i < nxgep->ldgvp->maxldvs; i++) { 5586*0dc2366fSVenugopal Iyer if ((nxgep->ldgvp->ldvp[i].is_rxdma) && 5587da14cebeSEric Cheng (nxgep->ldgvp->ldvp[i].channel == channel)) { 5588da14cebeSEric Cheng ring->ldvp = &nxgep->ldgvp->ldvp[i]; 5589da14cebeSEric Cheng ring->ldgp = nxgep->ldgvp->ldvp[i].ldgp; 5590da14cebeSEric Cheng } 5591da14cebeSEric Cheng } 5592da14cebeSEric Cheng 5593da14cebeSEric Cheng ring->rcr_mac_handle = rhp->ring_handle; 5594da14cebeSEric Cheng ring->rcr_gen_num = mr_gen_num; 5595*0dc2366fSVenugopal Iyer ring->started = B_TRUE; 5596*0dc2366fSVenugopal Iyer rhp->ring_gen_num = mr_gen_num; 5597da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5598da14cebeSEric Cheng 5599da14cebeSEric Cheng return (0); 5600da14cebeSEric Cheng } 5601da14cebeSEric Cheng 5602da14cebeSEric Cheng static void 5603da14cebeSEric Cheng nxge_rx_ring_stop(mac_ring_driver_t rdriver) 5604da14cebeSEric Cheng { 5605da14cebeSEric Cheng p_nxge_ring_handle_t rhp = (p_nxge_ring_handle_t)rdriver; 5606da14cebeSEric Cheng p_nxge_t nxgep = rhp->nxgep; 5607da14cebeSEric Cheng uint32_t channel; 5608da14cebeSEric Cheng p_rx_rcr_ring_t ring; 5609da14cebeSEric Cheng 5610da14cebeSEric Cheng channel = nxgep->pt_config.hw_config.start_rdc + rhp->index; 5611da14cebeSEric Cheng ring = nxgep->rx_rcr_rings->rcr_rings[channel]; 5612da14cebeSEric Cheng 5613da14cebeSEric Cheng MUTEX_ENTER(&ring->lock); 5614*0dc2366fSVenugopal Iyer ASSERT(ring->started == B_TRUE); 5615da14cebeSEric Cheng ring->rcr_mac_handle = NULL; 5616*0dc2366fSVenugopal Iyer ring->ldvp = NULL; 5617*0dc2366fSVenugopal Iyer ring->ldgp = NULL; 5618*0dc2366fSVenugopal Iyer ring->started = B_FALSE; 5619da14cebeSEric Cheng MUTEX_EXIT(&ring->lock); 5620da14cebeSEric Cheng } 5621da14cebeSEric Cheng 5622*0dc2366fSVenugopal Iyer static int 5623*0dc2366fSVenugopal Iyer nxge_ring_get_htable_idx(p_nxge_t nxgep, mac_ring_type_t type, uint32_t channel) 5624*0dc2366fSVenugopal Iyer { 5625*0dc2366fSVenugopal Iyer int i; 5626*0dc2366fSVenugopal Iyer 5627*0dc2366fSVenugopal Iyer #if defined(sun4v) 5628*0dc2366fSVenugopal Iyer if (isLDOMguest(nxgep)) { 5629*0dc2366fSVenugopal Iyer return (nxge_hio_get_dc_htable_idx(nxgep, 5630*0dc2366fSVenugopal Iyer (type == MAC_RING_TYPE_TX) ? VP_BOUND_TX : VP_BOUND_RX, 5631*0dc2366fSVenugopal Iyer channel)); 5632*0dc2366fSVenugopal Iyer } 5633*0dc2366fSVenugopal Iyer #endif 5634*0dc2366fSVenugopal Iyer 5635*0dc2366fSVenugopal Iyer ASSERT(nxgep->ldgvp != NULL); 5636*0dc2366fSVenugopal Iyer 5637*0dc2366fSVenugopal Iyer switch (type) { 5638*0dc2366fSVenugopal Iyer case MAC_RING_TYPE_TX: 5639*0dc2366fSVenugopal Iyer for (i = 0; i < nxgep->ldgvp->maxldvs; i++) { 5640*0dc2366fSVenugopal Iyer if ((nxgep->ldgvp->ldvp[i].is_txdma) && 5641*0dc2366fSVenugopal Iyer (nxgep->ldgvp->ldvp[i].channel == channel)) { 5642*0dc2366fSVenugopal Iyer return ((int) 5643*0dc2366fSVenugopal Iyer nxgep->ldgvp->ldvp[i].ldgp->htable_idx); 5644*0dc2366fSVenugopal Iyer } 5645*0dc2366fSVenugopal Iyer } 5646*0dc2366fSVenugopal Iyer break; 5647*0dc2366fSVenugopal Iyer 5648*0dc2366fSVenugopal Iyer case MAC_RING_TYPE_RX: 5649*0dc2366fSVenugopal Iyer for (i = 0; i < nxgep->ldgvp->maxldvs; i++) { 5650*0dc2366fSVenugopal Iyer if ((nxgep->ldgvp->ldvp[i].is_rxdma) && 5651*0dc2366fSVenugopal Iyer (nxgep->ldgvp->ldvp[i].channel == channel)) { 5652*0dc2366fSVenugopal Iyer return ((int) 5653*0dc2366fSVenugopal Iyer nxgep->ldgvp->ldvp[i].ldgp->htable_idx); 5654*0dc2366fSVenugopal Iyer } 5655*0dc2366fSVenugopal Iyer } 5656*0dc2366fSVenugopal Iyer } 5657*0dc2366fSVenugopal Iyer 5658*0dc2366fSVenugopal Iyer return (-1); 5659*0dc2366fSVenugopal Iyer } 5660*0dc2366fSVenugopal Iyer 5661da14cebeSEric Cheng /* 5662da14cebeSEric Cheng * Callback funtion for MAC layer to register all rings. 5663da14cebeSEric Cheng */ 5664da14cebeSEric Cheng static void 5665da14cebeSEric Cheng nxge_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index, 5666da14cebeSEric Cheng const int index, mac_ring_info_t *infop, mac_ring_handle_t rh) 5667da14cebeSEric Cheng { 5668da14cebeSEric Cheng p_nxge_t nxgep = (p_nxge_t)arg; 5669da14cebeSEric Cheng p_nxge_hw_pt_cfg_t p_cfgp = &nxgep->pt_config.hw_config; 5670*0dc2366fSVenugopal Iyer p_nxge_intr_t intrp; 5671*0dc2366fSVenugopal Iyer uint32_t channel; 5672*0dc2366fSVenugopal Iyer int htable_idx; 5673*0dc2366fSVenugopal Iyer p_nxge_ring_handle_t rhandlep; 5674*0dc2366fSVenugopal Iyer 5675*0dc2366fSVenugopal Iyer ASSERT(nxgep != NULL); 5676*0dc2366fSVenugopal Iyer ASSERT(p_cfgp != NULL); 5677*0dc2366fSVenugopal Iyer ASSERT(infop != NULL); 5678da14cebeSEric Cheng 5679*0dc2366fSVenugopal Iyer NXGE_DEBUG_MSG((nxgep, DDI_CTL, 5680da14cebeSEric Cheng "==> nxge_fill_ring 0x%x index %d", rtype, index)); 5681da14cebeSEric Cheng 5682*0dc2366fSVenugopal Iyer 5683da14cebeSEric Cheng switch (rtype) { 5684da14cebeSEric Cheng case MAC_RING_TYPE_TX: { 5685*0dc2366fSVenugopal Iyer mac_intr_t *mintr = &infop->mri_intr; 5686da14cebeSEric Cheng 5687da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, TX_CTL, 5688da14cebeSEric Cheng "==> nxge_fill_ring (TX) 0x%x index %d ntdcs %d", 5689da14cebeSEric Cheng rtype, index, p_cfgp->tdc.count)); 5690da14cebeSEric Cheng 5691da14cebeSEric Cheng ASSERT((index >= 0) && (index < p_cfgp->tdc.count)); 5692da14cebeSEric Cheng rhandlep = &nxgep->tx_ring_handles[index]; 5693da14cebeSEric Cheng rhandlep->nxgep = nxgep; 5694da14cebeSEric Cheng rhandlep->index = index; 5695da14cebeSEric Cheng rhandlep->ring_handle = rh; 5696da14cebeSEric Cheng 5697*0dc2366fSVenugopal Iyer channel = nxgep->pt_config.hw_config.tdc.start + index; 5698*0dc2366fSVenugopal Iyer rhandlep->channel = channel; 5699*0dc2366fSVenugopal Iyer intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 5700*0dc2366fSVenugopal Iyer htable_idx = nxge_ring_get_htable_idx(nxgep, rtype, 5701*0dc2366fSVenugopal Iyer channel); 5702*0dc2366fSVenugopal Iyer if (htable_idx >= 0) 5703*0dc2366fSVenugopal Iyer mintr->mi_ddi_handle = intrp->htable[htable_idx]; 5704*0dc2366fSVenugopal Iyer else 5705*0dc2366fSVenugopal Iyer mintr->mi_ddi_handle = NULL; 5706*0dc2366fSVenugopal Iyer 5707da14cebeSEric Cheng infop->mri_driver = (mac_ring_driver_t)rhandlep; 5708da14cebeSEric Cheng infop->mri_start = nxge_tx_ring_start; 5709da14cebeSEric Cheng infop->mri_stop = nxge_tx_ring_stop; 5710da14cebeSEric Cheng infop->mri_tx = nxge_tx_ring_send; 5711*0dc2366fSVenugopal Iyer infop->mri_stat = nxge_tx_ring_stat; 5712*0dc2366fSVenugopal Iyer infop->mri_flags = MAC_RING_TX_SERIALIZE; 5713da14cebeSEric Cheng break; 5714da14cebeSEric Cheng } 5715*0dc2366fSVenugopal Iyer 5716da14cebeSEric Cheng case MAC_RING_TYPE_RX: { 5717da14cebeSEric Cheng mac_intr_t nxge_mac_intr; 5718*0dc2366fSVenugopal Iyer int nxge_rindex; 5719*0dc2366fSVenugopal Iyer p_nxge_intr_t intrp; 5720*0dc2366fSVenugopal Iyer 5721*0dc2366fSVenugopal Iyer intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 5722da14cebeSEric Cheng 5723da14cebeSEric Cheng NXGE_DEBUG_MSG((nxgep, RX_CTL, 5724da14cebeSEric Cheng "==> nxge_fill_ring (RX) 0x%x index %d nrdcs %d", 5725da14cebeSEric Cheng rtype, index, p_cfgp->max_rdcs)); 5726da14cebeSEric Cheng 5727da14cebeSEric Cheng /* 5728da14cebeSEric Cheng * 'index' is the ring index within the group. 5729da14cebeSEric Cheng * Find the ring index in the nxge instance. 5730da14cebeSEric Cheng */ 5731da14cebeSEric Cheng nxge_rindex = nxge_get_rxring_index(nxgep, rg_index, index); 5732*0dc2366fSVenugopal Iyer channel = nxgep->pt_config.hw_config.start_rdc + index; 5733*0dc2366fSVenugopal Iyer intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 5734da14cebeSEric Cheng 5735da14cebeSEric Cheng ASSERT((nxge_rindex >= 0) && (nxge_rindex < p_cfgp->max_rdcs)); 5736da14cebeSEric Cheng rhandlep = &nxgep->rx_ring_handles[nxge_rindex]; 5737da14cebeSEric Cheng rhandlep->nxgep = nxgep; 5738da14cebeSEric Cheng rhandlep->index = nxge_rindex; 5739da14cebeSEric Cheng rhandlep->ring_handle = rh; 5740*0dc2366fSVenugopal Iyer rhandlep->channel = channel; 5741da14cebeSEric Cheng 5742da14cebeSEric Cheng /* 5743da14cebeSEric Cheng * Entrypoint to enable interrupt (disable poll) and 5744da14cebeSEric Cheng * disable interrupt (enable poll). 5745da14cebeSEric Cheng */ 5746*0dc2366fSVenugopal Iyer bzero(&nxge_mac_intr, sizeof (nxge_mac_intr)); 5747da14cebeSEric Cheng nxge_mac_intr.mi_handle = (mac_intr_handle_t)rhandlep; 5748da14cebeSEric Cheng nxge_mac_intr.mi_enable = (mac_intr_enable_t)nxge_disable_poll; 5749da14cebeSEric Cheng nxge_mac_intr.mi_disable = (mac_intr_disable_t)nxge_enable_poll; 5750*0dc2366fSVenugopal Iyer 5751*0dc2366fSVenugopal Iyer htable_idx = nxge_ring_get_htable_idx(nxgep, rtype, 5752*0dc2366fSVenugopal Iyer channel); 5753*0dc2366fSVenugopal Iyer if (htable_idx >= 0) 5754*0dc2366fSVenugopal Iyer nxge_mac_intr.mi_ddi_handle = intrp->htable[htable_idx]; 5755*0dc2366fSVenugopal Iyer else 5756*0dc2366fSVenugopal Iyer nxge_mac_intr.mi_ddi_handle = NULL; 5757*0dc2366fSVenugopal Iyer 5758da14cebeSEric Cheng infop->mri_driver = (mac_ring_driver_t)rhandlep; 5759da14cebeSEric Cheng infop->mri_start = nxge_rx_ring_start; 5760da14cebeSEric Cheng infop->mri_stop = nxge_rx_ring_stop; 5761*0dc2366fSVenugopal Iyer infop->mri_intr = nxge_mac_intr; 5762da14cebeSEric Cheng infop->mri_poll = nxge_rx_poll; 5763*0dc2366fSVenugopal Iyer infop->mri_stat = nxge_rx_ring_stat; 5764*0dc2366fSVenugopal Iyer infop->mri_flags = MAC_RING_RX_ENQUEUE; 5765da14cebeSEric Cheng break; 5766da14cebeSEric Cheng } 5767*0dc2366fSVenugopal Iyer 5768da14cebeSEric Cheng default: 5769da14cebeSEric Cheng break; 5770da14cebeSEric Cheng } 5771da14cebeSEric Cheng 5772*0dc2366fSVenugopal Iyer NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_fill_ring 0x%x", rtype)); 5773da14cebeSEric Cheng } 5774da14cebeSEric Cheng 5775da14cebeSEric Cheng static void 5776da14cebeSEric Cheng nxge_group_add_ring(mac_group_driver_t gh, mac_ring_driver_t rh, 5777da14cebeSEric Cheng mac_ring_type_t type) 5778da14cebeSEric Cheng { 5779da14cebeSEric Cheng nxge_ring_group_t *rgroup = (nxge_ring_group_t *)gh; 5780da14cebeSEric Cheng nxge_ring_handle_t *rhandle = (nxge_ring_handle_t *)rh; 5781da14cebeSEric Cheng nxge_t *nxge; 5782da14cebeSEric Cheng nxge_grp_t *grp; 5783da14cebeSEric Cheng nxge_rdc_grp_t *rdc_grp; 5784da14cebeSEric Cheng uint16_t channel; /* device-wise ring id */ 5785da14cebeSEric Cheng int dev_gindex; 5786da14cebeSEric Cheng int rv; 5787da14cebeSEric Cheng 5788da14cebeSEric Cheng nxge = rgroup->nxgep; 5789da14cebeSEric Cheng 5790da14cebeSEric Cheng switch (type) { 5791da14cebeSEric Cheng case MAC_RING_TYPE_TX: 5792da14cebeSEric Cheng /* 5793da14cebeSEric Cheng * nxge_grp_dc_add takes a channel number which is a 5794da14cebeSEric Cheng * "devise" ring ID. 5795da14cebeSEric Cheng */ 5796da14cebeSEric Cheng channel = nxge->pt_config.hw_config.tdc.start + rhandle->index; 5797da14cebeSEric Cheng 5798da14cebeSEric Cheng /* 5799da14cebeSEric Cheng * Remove the ring from the default group 5800da14cebeSEric Cheng */ 5801da14cebeSEric Cheng if (rgroup->gindex != 0) { 5802da14cebeSEric Cheng (void) nxge_grp_dc_remove(nxge, VP_BOUND_TX, channel); 5803da14cebeSEric Cheng } 5804da14cebeSEric Cheng 5805da14cebeSEric Cheng /* 5806da14cebeSEric Cheng * nxge->tx_set.group[] is an array of groups indexed by 5807da14cebeSEric Cheng * a "port" group ID. 5808da14cebeSEric Cheng */ 5809da14cebeSEric Cheng grp = nxge->tx_set.group[rgroup->gindex]; 5810da14cebeSEric Cheng rv = nxge_grp_dc_add(nxge, grp, VP_BOUND_TX, channel); 5811da14cebeSEric Cheng if (rv != 0) { 5812da14cebeSEric Cheng NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 5813da14cebeSEric Cheng "nxge_group_add_ring: nxge_grp_dc_add failed")); 5814da14cebeSEric Cheng } 5815da14cebeSEric Cheng break; 5816da14cebeSEric Cheng 5817da14cebeSEric Cheng case MAC_RING_TYPE_RX: 5818da14cebeSEric Cheng /* 5819da14cebeSEric Cheng * nxge->rx_set.group[] is an array of groups indexed by 5820da14cebeSEric Cheng * a "port" group ID. 5821da14cebeSEric Cheng */ 5822da14cebeSEric Cheng grp = nxge->rx_set.group[rgroup->gindex]; 5823da14cebeSEric Cheng 5824da14cebeSEric Cheng dev_gindex = nxge->pt_config.hw_config.def_mac_rxdma_grpid + 5825da14cebeSEric Cheng rgroup->gindex; 5826da14cebeSEric Cheng rdc_grp = &nxge->pt_config.rdc_grps[dev_gindex]; 5827da14cebeSEric Cheng 5828da14cebeSEric Cheng /* 5829da14cebeSEric Cheng * nxge_grp_dc_add takes a channel number which is a 5830da14cebeSEric Cheng * "devise" ring ID. 5831da14cebeSEric Cheng */ 5832da14cebeSEric Cheng channel = nxge->pt_config.hw_config.start_rdc + rhandle->index; 5833da14cebeSEric Cheng rv = nxge_grp_dc_add(nxge, grp, VP_BOUND_RX, channel); 5834da14cebeSEric Cheng if (rv != 0) { 5835da14cebeSEric Cheng NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 5836da14cebeSEric Cheng "nxge_group_add_ring: nxge_grp_dc_add failed")); 5837da14cebeSEric Cheng } 5838da14cebeSEric Cheng 5839da14cebeSEric Cheng rdc_grp->map |= (1 << channel); 5840da14cebeSEric Cheng rdc_grp->max_rdcs++; 5841da14cebeSEric Cheng 58424ba491f5SMichael Speer (void) nxge_init_fzc_rdc_tbl(nxge, rdc_grp, rgroup->rdctbl); 5843da14cebeSEric Cheng break; 5844da14cebeSEric Cheng } 5845da14cebeSEric Cheng } 5846da14cebeSEric Cheng 5847da14cebeSEric Cheng static void 5848da14cebeSEric Cheng nxge_group_rem_ring(mac_group_driver_t gh, mac_ring_driver_t rh, 5849da14cebeSEric Cheng mac_ring_type_t type) 5850da14cebeSEric Cheng { 5851da14cebeSEric Cheng nxge_ring_group_t *rgroup = (nxge_ring_group_t *)gh; 5852da14cebeSEric Cheng nxge_ring_handle_t *rhandle = (nxge_ring_handle_t *)rh; 5853da14cebeSEric Cheng nxge_t *nxge; 5854da14cebeSEric Cheng uint16_t channel; /* device-wise ring id */ 5855da14cebeSEric Cheng nxge_rdc_grp_t *rdc_grp; 5856da14cebeSEric Cheng int dev_gindex; 5857da14cebeSEric Cheng 5858da14cebeSEric Cheng nxge = rgroup->nxgep; 5859da14cebeSEric Cheng 5860da14cebeSEric Cheng switch (type) { 5861da14cebeSEric Cheng case MAC_RING_TYPE_TX: 5862da14cebeSEric Cheng dev_gindex = nxge->pt_config.hw_config.def_mac_txdma_grpid + 5863da14cebeSEric Cheng rgroup->gindex; 5864da14cebeSEric Cheng channel = nxge->pt_config.hw_config.tdc.start + rhandle->index; 5865da14cebeSEric Cheng nxge_grp_dc_remove(nxge, VP_BOUND_TX, channel); 5866da14cebeSEric Cheng 5867da14cebeSEric Cheng /* 5868da14cebeSEric Cheng * Add the ring back to the default group 5869da14cebeSEric Cheng */ 5870da14cebeSEric Cheng if (rgroup->gindex != 0) { 5871da14cebeSEric Cheng nxge_grp_t *grp; 5872da14cebeSEric Cheng grp = nxge->tx_set.group[0]; 5873da14cebeSEric Cheng (void) nxge_grp_dc_add(nxge, grp, VP_BOUND_TX, channel); 5874da14cebeSEric Cheng } 5875da14cebeSEric Cheng break; 5876da14cebeSEric Cheng 5877da14cebeSEric Cheng case MAC_RING_TYPE_RX: 5878da14cebeSEric Cheng dev_gindex = nxge->pt_config.hw_config.def_mac_rxdma_grpid + 5879da14cebeSEric Cheng rgroup->gindex; 5880da14cebeSEric Cheng rdc_grp = &nxge->pt_config.rdc_grps[dev_gindex]; 5881da14cebeSEric Cheng channel = rdc_grp->start_rdc + rhandle->index; 5882da14cebeSEric Cheng nxge_grp_dc_remove(nxge, VP_BOUND_RX, channel); 5883da14cebeSEric Cheng 5884da14cebeSEric Cheng rdc_grp->map &= ~(1 << channel); 5885da14cebeSEric Cheng rdc_grp->max_rdcs--; 5886da14cebeSEric Cheng 58874ba491f5SMichael Speer (void) nxge_init_fzc_rdc_tbl(nxge, rdc_grp, rgroup->rdctbl); 5888da14cebeSEric Cheng break; 5889da14cebeSEric Cheng } 5890da14cebeSEric Cheng } 5891da14cebeSEric Cheng 5892da14cebeSEric Cheng 589344961713Sgirish /*ARGSUSED*/ 589444961713Sgirish static nxge_status_t 589544961713Sgirish nxge_add_intrs(p_nxge_t nxgep) 589644961713Sgirish { 589744961713Sgirish 589844961713Sgirish int intr_types; 589944961713Sgirish int type = 0; 590044961713Sgirish int ddi_status = DDI_SUCCESS; 590144961713Sgirish nxge_status_t status = NXGE_OK; 590244961713Sgirish 590344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs")); 590444961713Sgirish 590544961713Sgirish nxgep->nxge_intr_type.intr_registered = B_FALSE; 590644961713Sgirish nxgep->nxge_intr_type.intr_enabled = B_FALSE; 590744961713Sgirish nxgep->nxge_intr_type.msi_intx_cnt = 0; 590844961713Sgirish nxgep->nxge_intr_type.intr_added = 0; 590944961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_FALSE; 591044961713Sgirish nxgep->nxge_intr_type.intr_type = 0; 591144961713Sgirish 591244961713Sgirish if (nxgep->niu_type == N2_NIU) { 591344961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 591444961713Sgirish } else if (nxge_msi_enable) { 591544961713Sgirish nxgep->nxge_intr_type.niu_msi_enable = B_TRUE; 591644961713Sgirish } 591744961713Sgirish 591844961713Sgirish /* Get the supported interrupt types */ 591944961713Sgirish if ((ddi_status = ddi_intr_get_supported_types(nxgep->dip, &intr_types)) 59204045d941Ssowmini != DDI_SUCCESS) { 592144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_intrs: " 59224045d941Ssowmini "ddi_intr_get_supported_types failed: status 0x%08x", 59234045d941Ssowmini ddi_status)); 592444961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 592544961713Sgirish } 592644961713Sgirish nxgep->nxge_intr_type.intr_types = intr_types; 592744961713Sgirish 592844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 59294045d941Ssowmini "ddi_intr_get_supported_types: 0x%08x", intr_types)); 593044961713Sgirish 593144961713Sgirish /* 593244961713Sgirish * Solaris MSIX is not supported yet. use MSI for now. 593344961713Sgirish * nxge_msi_enable (1): 593444961713Sgirish * 1 - MSI 2 - MSI-X others - FIXED 593544961713Sgirish */ 593644961713Sgirish switch (nxge_msi_enable) { 593744961713Sgirish default: 593844961713Sgirish type = DDI_INTR_TYPE_FIXED; 593944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 59404045d941Ssowmini "use fixed (intx emulation) type %08x", 59414045d941Ssowmini type)); 594244961713Sgirish break; 594344961713Sgirish 594444961713Sgirish case 2: 594544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 59464045d941Ssowmini "ddi_intr_get_supported_types: 0x%08x", intr_types)); 594744961713Sgirish if (intr_types & DDI_INTR_TYPE_MSIX) { 594844961713Sgirish type = DDI_INTR_TYPE_MSIX; 594944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 59504045d941Ssowmini "ddi_intr_get_supported_types: MSIX 0x%08x", 59514045d941Ssowmini type)); 595244961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSI) { 595344961713Sgirish type = DDI_INTR_TYPE_MSI; 595444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 59554045d941Ssowmini "ddi_intr_get_supported_types: MSI 0x%08x", 59564045d941Ssowmini type)); 595744961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 595844961713Sgirish type = DDI_INTR_TYPE_FIXED; 595944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 59604045d941Ssowmini "ddi_intr_get_supported_types: MSXED0x%08x", 59614045d941Ssowmini type)); 596244961713Sgirish } 596344961713Sgirish break; 596444961713Sgirish 596544961713Sgirish case 1: 596644961713Sgirish if (intr_types & DDI_INTR_TYPE_MSI) { 596744961713Sgirish type = DDI_INTR_TYPE_MSI; 596844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: " 59694045d941Ssowmini "ddi_intr_get_supported_types: MSI 0x%08x", 59704045d941Ssowmini type)); 597144961713Sgirish } else if (intr_types & DDI_INTR_TYPE_MSIX) { 597244961713Sgirish type = DDI_INTR_TYPE_MSIX; 597344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 59744045d941Ssowmini "ddi_intr_get_supported_types: MSIX 0x%08x", 59754045d941Ssowmini type)); 597644961713Sgirish } else if (intr_types & DDI_INTR_TYPE_FIXED) { 597744961713Sgirish type = DDI_INTR_TYPE_FIXED; 597844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 59794045d941Ssowmini "ddi_intr_get_supported_types: MSXED0x%08x", 59804045d941Ssowmini type)); 598144961713Sgirish } 598244961713Sgirish } 598344961713Sgirish 598444961713Sgirish nxgep->nxge_intr_type.intr_type = type; 598544961713Sgirish if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI || 59864045d941Ssowmini type == DDI_INTR_TYPE_FIXED) && 59874045d941Ssowmini nxgep->nxge_intr_type.niu_msi_enable) { 598844961713Sgirish if ((status = nxge_add_intrs_adv(nxgep)) != DDI_SUCCESS) { 598944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59904045d941Ssowmini " nxge_add_intrs: " 59914045d941Ssowmini " nxge_add_intrs_adv failed: status 0x%08x", 59924045d941Ssowmini status)); 599344961713Sgirish return (status); 599444961713Sgirish } else { 599544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: " 59964045d941Ssowmini "interrupts registered : type %d", type)); 599744961713Sgirish nxgep->nxge_intr_type.intr_registered = B_TRUE; 599844961713Sgirish 599944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 60004045d941Ssowmini "\nAdded advanced nxge add_intr_adv " 60014045d941Ssowmini "intr type 0x%x\n", type)); 600244961713Sgirish 600344961713Sgirish return (status); 600444961713Sgirish } 600544961713Sgirish } 600644961713Sgirish 600744961713Sgirish if (!nxgep->nxge_intr_type.intr_registered) { 600844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_add_intrs: " 60094045d941Ssowmini "failed to register interrupts")); 601044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 601144961713Sgirish } 601244961713Sgirish 601344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_add_intrs")); 601444961713Sgirish return (status); 601544961713Sgirish } 601644961713Sgirish 601744961713Sgirish static nxge_status_t 601844961713Sgirish nxge_add_intrs_adv(p_nxge_t nxgep) 601944961713Sgirish { 602044961713Sgirish int intr_type; 602144961713Sgirish p_nxge_intr_t intrp; 602244961713Sgirish 602344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv")); 602444961713Sgirish 602544961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 602644961713Sgirish intr_type = intrp->intr_type; 602744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv: type 0x%x", 60284045d941Ssowmini intr_type)); 602944961713Sgirish 603044961713Sgirish switch (intr_type) { 603144961713Sgirish case DDI_INTR_TYPE_MSI: /* 0x2 */ 603244961713Sgirish case DDI_INTR_TYPE_MSIX: /* 0x4 */ 603344961713Sgirish return (nxge_add_intrs_adv_type(nxgep, intr_type)); 603444961713Sgirish 603544961713Sgirish case DDI_INTR_TYPE_FIXED: /* 0x1 */ 603644961713Sgirish return (nxge_add_intrs_adv_type_fix(nxgep, intr_type)); 603744961713Sgirish 603844961713Sgirish default: 603944961713Sgirish return (NXGE_ERROR); 604044961713Sgirish } 604144961713Sgirish } 604244961713Sgirish 604344961713Sgirish 604444961713Sgirish /*ARGSUSED*/ 604544961713Sgirish static nxge_status_t 604644961713Sgirish nxge_add_intrs_adv_type(p_nxge_t nxgep, uint32_t int_type) 604744961713Sgirish { 604844961713Sgirish dev_info_t *dip = nxgep->dip; 604944961713Sgirish p_nxge_ldg_t ldgp; 605044961713Sgirish p_nxge_intr_t intrp; 605144961713Sgirish uint_t *inthandler; 605244961713Sgirish void *arg1, *arg2; 605344961713Sgirish int behavior; 6054ec090658Sml int nintrs, navail, nrequest; 605544961713Sgirish int nactual, nrequired; 605644961713Sgirish int inum = 0; 605744961713Sgirish int x, y; 605844961713Sgirish int ddi_status = DDI_SUCCESS; 605944961713Sgirish nxge_status_t status = NXGE_OK; 606044961713Sgirish 606144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type")); 606244961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 606344961713Sgirish intrp->start_inum = 0; 606444961713Sgirish 606544961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 606644961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 606744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60684045d941Ssowmini "ddi_intr_get_nintrs() failed, status: 0x%x%, " 60694045d941Ssowmini "nintrs: %d", ddi_status, nintrs)); 607044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 607144961713Sgirish } 607244961713Sgirish 607344961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 607444961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 607544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60764045d941Ssowmini "ddi_intr_get_navail() failed, status: 0x%x%, " 60774045d941Ssowmini "nintrs: %d", ddi_status, navail)); 607844961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 607944961713Sgirish } 608044961713Sgirish 608144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 60824045d941Ssowmini "ddi_intr_get_navail() returned: nintrs %d, navail %d", 60834045d941Ssowmini nintrs, navail)); 608444961713Sgirish 6085ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override */ 6086ec090658Sml if (int_type == DDI_INTR_TYPE_MSIX) { 6087ec090658Sml nrequest = nxge_create_msi_property(nxgep); 6088ec090658Sml if (nrequest < navail) { 6089ec090658Sml navail = nrequest; 6090ec090658Sml NXGE_DEBUG_MSG((nxgep, INT_CTL, 6091ec090658Sml "nxge_add_intrs_adv_type: nintrs %d " 6092ec090658Sml "navail %d (nrequest %d)", 6093ec090658Sml nintrs, navail, nrequest)); 6094ec090658Sml } 6095ec090658Sml } 6096ec090658Sml 609744961713Sgirish if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) { 609844961713Sgirish /* MSI must be power of 2 */ 609944961713Sgirish if ((navail & 16) == 16) { 610044961713Sgirish navail = 16; 610144961713Sgirish } else if ((navail & 8) == 8) { 610244961713Sgirish navail = 8; 610344961713Sgirish } else if ((navail & 4) == 4) { 610444961713Sgirish navail = 4; 610544961713Sgirish } else if ((navail & 2) == 2) { 610644961713Sgirish navail = 2; 610744961713Sgirish } else { 610844961713Sgirish navail = 1; 610944961713Sgirish } 611044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 61114045d941Ssowmini "ddi_intr_get_navail(): (msi power of 2) nintrs %d, " 61124045d941Ssowmini "navail %d", nintrs, navail)); 611344961713Sgirish } 611444961713Sgirish 611544961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 61164045d941Ssowmini DDI_INTR_ALLOC_NORMAL); 611744961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 611844961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 611944961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 61204045d941Ssowmini navail, &nactual, behavior); 612144961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 612244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61234045d941Ssowmini " ddi_intr_alloc() failed: %d", 61244045d941Ssowmini ddi_status)); 612544961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 612644961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 612744961713Sgirish } 612844961713Sgirish 612944961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 61304045d941Ssowmini (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 613144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61324045d941Ssowmini " ddi_intr_get_pri() failed: %d", 61334045d941Ssowmini ddi_status)); 613444961713Sgirish /* Free already allocated interrupts */ 613544961713Sgirish for (y = 0; y < nactual; y++) { 613644961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 613744961713Sgirish } 613844961713Sgirish 613944961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 614044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 614144961713Sgirish } 614244961713Sgirish 614344961713Sgirish nrequired = 0; 614444961713Sgirish switch (nxgep->niu_type) { 614544961713Sgirish default: 614644961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 614744961713Sgirish break; 614844961713Sgirish 614944961713Sgirish case N2_NIU: 615044961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 615144961713Sgirish break; 615244961713Sgirish } 615344961713Sgirish 615444961713Sgirish if (status != NXGE_OK) { 615544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61564045d941Ssowmini "nxge_add_intrs_adv_typ:nxge_ldgv_init " 61574045d941Ssowmini "failed: 0x%x", status)); 615844961713Sgirish /* Free already allocated interrupts */ 615944961713Sgirish for (y = 0; y < nactual; y++) { 616044961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 616144961713Sgirish } 616244961713Sgirish 616344961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 616444961713Sgirish return (status); 616544961713Sgirish } 616644961713Sgirish 616744961713Sgirish ldgp = nxgep->ldgvp->ldgp; 616844961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 616944961713Sgirish ldgp->vector = (uint8_t)x; 617044961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 617144961713Sgirish arg1 = ldgp->ldvp; 617244961713Sgirish arg2 = nxgep; 617344961713Sgirish if (ldgp->nldvs == 1) { 617444961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 617544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 61764045d941Ssowmini "nxge_add_intrs_adv_type: " 61774045d941Ssowmini "arg1 0x%x arg2 0x%x: " 61784045d941Ssowmini "1-1 int handler (entry %d intdata 0x%x)\n", 61794045d941Ssowmini arg1, arg2, 61804045d941Ssowmini x, ldgp->intdata)); 618144961713Sgirish } else if (ldgp->nldvs > 1) { 618244961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 618344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 61844045d941Ssowmini "nxge_add_intrs_adv_type: " 61854045d941Ssowmini "arg1 0x%x arg2 0x%x: " 61864045d941Ssowmini "nldevs %d int handler " 61874045d941Ssowmini "(entry %d intdata 0x%x)\n", 61884045d941Ssowmini arg1, arg2, 61894045d941Ssowmini ldgp->nldvs, x, ldgp->intdata)); 619044961713Sgirish } 619144961713Sgirish 619244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 61934045d941Ssowmini "==> nxge_add_intrs_adv_type: ddi_add_intr(inum) #%d " 61944045d941Ssowmini "htable 0x%llx", x, intrp->htable[x])); 619544961713Sgirish 619644961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 61974045d941Ssowmini (ddi_intr_handler_t *)inthandler, arg1, arg2)) 61984045d941Ssowmini != DDI_SUCCESS) { 619944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 62004045d941Ssowmini "==> nxge_add_intrs_adv_type: failed #%d " 62014045d941Ssowmini "status 0x%x", x, ddi_status)); 620244961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 620344961713Sgirish (void) ddi_intr_remove_handler( 62044045d941Ssowmini intrp->htable[y]); 620544961713Sgirish } 620644961713Sgirish /* Free already allocated intr */ 620744961713Sgirish for (y = 0; y < nactual; y++) { 620844961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 620944961713Sgirish } 621044961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 621144961713Sgirish 621244961713Sgirish (void) nxge_ldgv_uninit(nxgep); 621344961713Sgirish 621444961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 621544961713Sgirish } 6216*0dc2366fSVenugopal Iyer 6217*0dc2366fSVenugopal Iyer ldgp->htable_idx = x; 621844961713Sgirish intrp->intr_added++; 621944961713Sgirish } 622044961713Sgirish 622144961713Sgirish intrp->msi_intx_cnt = nactual; 622244961713Sgirish 622344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 62244045d941Ssowmini "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d", 62254045d941Ssowmini navail, nactual, 62264045d941Ssowmini intrp->msi_intx_cnt, 62274045d941Ssowmini intrp->intr_added)); 622844961713Sgirish 622944961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 623044961713Sgirish 623144961713Sgirish (void) nxge_intr_ldgv_init(nxgep); 623244961713Sgirish 623344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type")); 623444961713Sgirish 623544961713Sgirish return (status); 623644961713Sgirish } 623744961713Sgirish 623844961713Sgirish /*ARGSUSED*/ 623944961713Sgirish static nxge_status_t 624044961713Sgirish nxge_add_intrs_adv_type_fix(p_nxge_t nxgep, uint32_t int_type) 624144961713Sgirish { 624244961713Sgirish dev_info_t *dip = nxgep->dip; 624344961713Sgirish p_nxge_ldg_t ldgp; 624444961713Sgirish p_nxge_intr_t intrp; 624544961713Sgirish uint_t *inthandler; 624644961713Sgirish void *arg1, *arg2; 624744961713Sgirish int behavior; 624844961713Sgirish int nintrs, navail; 624944961713Sgirish int nactual, nrequired; 625044961713Sgirish int inum = 0; 625144961713Sgirish int x, y; 625244961713Sgirish int ddi_status = DDI_SUCCESS; 625344961713Sgirish nxge_status_t status = NXGE_OK; 625444961713Sgirish 625544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type_fix")); 625644961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 625744961713Sgirish intrp->start_inum = 0; 625844961713Sgirish 625944961713Sgirish ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 626044961713Sgirish if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 626144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 62624045d941Ssowmini "ddi_intr_get_nintrs() failed, status: 0x%x%, " 62634045d941Ssowmini "nintrs: %d", status, nintrs)); 626444961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 626544961713Sgirish } 626644961713Sgirish 626744961713Sgirish ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 626844961713Sgirish if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 626944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 62704045d941Ssowmini "ddi_intr_get_navail() failed, status: 0x%x%, " 62714045d941Ssowmini "nintrs: %d", ddi_status, navail)); 627244961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 627344961713Sgirish } 627444961713Sgirish 627544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 62764045d941Ssowmini "ddi_intr_get_navail() returned: nintrs %d, naavail %d", 62774045d941Ssowmini nintrs, navail)); 627844961713Sgirish 627944961713Sgirish behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 62804045d941Ssowmini DDI_INTR_ALLOC_NORMAL); 628144961713Sgirish intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 628244961713Sgirish intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 628344961713Sgirish ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 62844045d941Ssowmini navail, &nactual, behavior); 628544961713Sgirish if (ddi_status != DDI_SUCCESS || nactual == 0) { 628644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 62874045d941Ssowmini " ddi_intr_alloc() failed: %d", 62884045d941Ssowmini ddi_status)); 628944961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 629044961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 629144961713Sgirish } 629244961713Sgirish 629344961713Sgirish if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 62944045d941Ssowmini (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 629544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 62964045d941Ssowmini " ddi_intr_get_pri() failed: %d", 62974045d941Ssowmini ddi_status)); 629844961713Sgirish /* Free already allocated interrupts */ 629944961713Sgirish for (y = 0; y < nactual; y++) { 630044961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 630144961713Sgirish } 630244961713Sgirish 630344961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 630444961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 630544961713Sgirish } 630644961713Sgirish 630744961713Sgirish nrequired = 0; 630844961713Sgirish switch (nxgep->niu_type) { 630944961713Sgirish default: 631044961713Sgirish status = nxge_ldgv_init(nxgep, &nactual, &nrequired); 631144961713Sgirish break; 631244961713Sgirish 631344961713Sgirish case N2_NIU: 631444961713Sgirish status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired); 631544961713Sgirish break; 631644961713Sgirish } 631744961713Sgirish 631844961713Sgirish if (status != NXGE_OK) { 631944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 63204045d941Ssowmini "nxge_add_intrs_adv_type_fix:nxge_ldgv_init " 63214045d941Ssowmini "failed: 0x%x", status)); 632244961713Sgirish /* Free already allocated interrupts */ 632344961713Sgirish for (y = 0; y < nactual; y++) { 632444961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 632544961713Sgirish } 632644961713Sgirish 632744961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 632844961713Sgirish return (status); 632944961713Sgirish } 633044961713Sgirish 633144961713Sgirish ldgp = nxgep->ldgvp->ldgp; 633244961713Sgirish for (x = 0; x < nrequired; x++, ldgp++) { 633344961713Sgirish ldgp->vector = (uint8_t)x; 633444961713Sgirish if (nxgep->niu_type != N2_NIU) { 633544961713Sgirish ldgp->intdata = SID_DATA(ldgp->func, x); 633644961713Sgirish } 633744961713Sgirish 633844961713Sgirish arg1 = ldgp->ldvp; 633944961713Sgirish arg2 = nxgep; 634044961713Sgirish if (ldgp->nldvs == 1) { 634144961713Sgirish inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 634244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 63434045d941Ssowmini "nxge_add_intrs_adv_type_fix: " 63444045d941Ssowmini "1-1 int handler(%d) ldg %d ldv %d " 63454045d941Ssowmini "arg1 $%p arg2 $%p\n", 63464045d941Ssowmini x, ldgp->ldg, ldgp->ldvp->ldv, 63474045d941Ssowmini arg1, arg2)); 634844961713Sgirish } else if (ldgp->nldvs > 1) { 634944961713Sgirish inthandler = (uint_t *)ldgp->sys_intr_handler; 635044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 63514045d941Ssowmini "nxge_add_intrs_adv_type_fix: " 63524045d941Ssowmini "shared ldv %d int handler(%d) ldv %d ldg %d" 63534045d941Ssowmini "arg1 0x%016llx arg2 0x%016llx\n", 63544045d941Ssowmini x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv, 63554045d941Ssowmini arg1, arg2)); 635644961713Sgirish } 635744961713Sgirish 635844961713Sgirish if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 63594045d941Ssowmini (ddi_intr_handler_t *)inthandler, arg1, arg2)) 63604045d941Ssowmini != DDI_SUCCESS) { 636144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 63624045d941Ssowmini "==> nxge_add_intrs_adv_type_fix: failed #%d " 63634045d941Ssowmini "status 0x%x", x, ddi_status)); 636444961713Sgirish for (y = 0; y < intrp->intr_added; y++) { 636544961713Sgirish (void) ddi_intr_remove_handler( 63664045d941Ssowmini intrp->htable[y]); 636744961713Sgirish } 636844961713Sgirish for (y = 0; y < nactual; y++) { 636944961713Sgirish (void) ddi_intr_free(intrp->htable[y]); 637044961713Sgirish } 637144961713Sgirish /* Free already allocated intr */ 637244961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 637344961713Sgirish 637444961713Sgirish (void) nxge_ldgv_uninit(nxgep); 637544961713Sgirish 637644961713Sgirish return (NXGE_ERROR | NXGE_DDI_FAILED); 637744961713Sgirish } 6378*0dc2366fSVenugopal Iyer 6379*0dc2366fSVenugopal Iyer ldgp->htable_idx = x; 638044961713Sgirish intrp->intr_added++; 638144961713Sgirish } 638244961713Sgirish 638344961713Sgirish intrp->msi_intx_cnt = nactual; 638444961713Sgirish 638544961713Sgirish (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 638644961713Sgirish 638744961713Sgirish status = nxge_intr_ldgv_init(nxgep); 638844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type_fix")); 638944961713Sgirish 639044961713Sgirish return (status); 639144961713Sgirish } 639244961713Sgirish 639344961713Sgirish static void 639444961713Sgirish nxge_remove_intrs(p_nxge_t nxgep) 639544961713Sgirish { 639644961713Sgirish int i, inum; 639744961713Sgirish p_nxge_intr_t intrp; 639844961713Sgirish 639944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs")); 640044961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 640144961713Sgirish if (!intrp->intr_registered) { 640244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 64034045d941Ssowmini "<== nxge_remove_intrs: interrupts not registered")); 640444961713Sgirish return; 640544961713Sgirish } 640644961713Sgirish 640744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs:advanced")); 640844961713Sgirish 640944961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 641044961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 64114045d941Ssowmini intrp->intr_added); 641244961713Sgirish } else { 641344961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 641444961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 641544961713Sgirish } 641644961713Sgirish } 641744961713Sgirish 641844961713Sgirish for (inum = 0; inum < intrp->intr_added; inum++) { 641944961713Sgirish if (intrp->htable[inum]) { 642044961713Sgirish (void) ddi_intr_remove_handler(intrp->htable[inum]); 642144961713Sgirish } 642244961713Sgirish } 642344961713Sgirish 642444961713Sgirish for (inum = 0; inum < intrp->msi_intx_cnt; inum++) { 642544961713Sgirish if (intrp->htable[inum]) { 642644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, 64274045d941Ssowmini "nxge_remove_intrs: ddi_intr_free inum %d " 64284045d941Ssowmini "msi_intx_cnt %d intr_added %d", 64294045d941Ssowmini inum, 64304045d941Ssowmini intrp->msi_intx_cnt, 64314045d941Ssowmini intrp->intr_added)); 643244961713Sgirish 643344961713Sgirish (void) ddi_intr_free(intrp->htable[inum]); 643444961713Sgirish } 643544961713Sgirish } 643644961713Sgirish 643744961713Sgirish kmem_free(intrp->htable, intrp->intr_size); 643844961713Sgirish intrp->intr_registered = B_FALSE; 643944961713Sgirish intrp->intr_enabled = B_FALSE; 644044961713Sgirish intrp->msi_intx_cnt = 0; 644144961713Sgirish intrp->intr_added = 0; 644244961713Sgirish 6443a3c5bd6dSspeer (void) nxge_ldgv_uninit(nxgep); 6444a3c5bd6dSspeer 6445ec090658Sml (void) ddi_prop_remove(DDI_DEV_T_NONE, nxgep->dip, 6446ec090658Sml "#msix-request"); 6447ec090658Sml 644844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_intrs")); 644944961713Sgirish } 645044961713Sgirish 645144961713Sgirish /*ARGSUSED*/ 645244961713Sgirish static void 645344961713Sgirish nxge_intrs_enable(p_nxge_t nxgep) 645444961713Sgirish { 645544961713Sgirish p_nxge_intr_t intrp; 645644961713Sgirish int i; 645744961713Sgirish int status; 645844961713Sgirish 645944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable")); 646044961713Sgirish 646144961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 646244961713Sgirish 646344961713Sgirish if (!intrp->intr_registered) { 646444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_intrs_enable: " 64654045d941Ssowmini "interrupts are not registered")); 646644961713Sgirish return; 646744961713Sgirish } 646844961713Sgirish 646944961713Sgirish if (intrp->intr_enabled) { 647044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 64714045d941Ssowmini "<== nxge_intrs_enable: already enabled")); 647244961713Sgirish return; 647344961713Sgirish } 647444961713Sgirish 647544961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 647644961713Sgirish status = ddi_intr_block_enable(intrp->htable, 64774045d941Ssowmini intrp->intr_added); 647844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 64794045d941Ssowmini "block enable - status 0x%x total inums #%d\n", 64804045d941Ssowmini status, intrp->intr_added)); 648144961713Sgirish } else { 648244961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 648344961713Sgirish status = ddi_intr_enable(intrp->htable[i]); 648444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable " 64854045d941Ssowmini "ddi_intr_enable:enable - status 0x%x " 64864045d941Ssowmini "total inums %d enable inum #%d\n", 64874045d941Ssowmini status, intrp->intr_added, i)); 648844961713Sgirish if (status == DDI_SUCCESS) { 648944961713Sgirish intrp->intr_enabled = B_TRUE; 649044961713Sgirish } 649144961713Sgirish } 649244961713Sgirish } 649344961713Sgirish 649444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_enable")); 649544961713Sgirish } 649644961713Sgirish 649744961713Sgirish /*ARGSUSED*/ 649844961713Sgirish static void 649944961713Sgirish nxge_intrs_disable(p_nxge_t nxgep) 650044961713Sgirish { 650144961713Sgirish p_nxge_intr_t intrp; 650244961713Sgirish int i; 650344961713Sgirish 650444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_disable")); 650544961713Sgirish 650644961713Sgirish intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type; 650744961713Sgirish 650844961713Sgirish if (!intrp->intr_registered) { 650944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable: " 65104045d941Ssowmini "interrupts are not registered")); 651144961713Sgirish return; 651244961713Sgirish } 651344961713Sgirish 651444961713Sgirish if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 651544961713Sgirish (void) ddi_intr_block_disable(intrp->htable, 65164045d941Ssowmini intrp->intr_added); 651744961713Sgirish } else { 651844961713Sgirish for (i = 0; i < intrp->intr_added; i++) { 651944961713Sgirish (void) ddi_intr_disable(intrp->htable[i]); 652044961713Sgirish } 652144961713Sgirish } 652244961713Sgirish 652344961713Sgirish intrp->intr_enabled = B_FALSE; 652444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable")); 652544961713Sgirish } 652644961713Sgirish 652763f531d1SSriharsha Basavapatna nxge_status_t 652844961713Sgirish nxge_mac_register(p_nxge_t nxgep) 652944961713Sgirish { 653044961713Sgirish mac_register_t *macp; 653144961713Sgirish int status; 653244961713Sgirish 653344961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_mac_register")); 653444961713Sgirish 653544961713Sgirish if ((macp = mac_alloc(MAC_VERSION)) == NULL) 653644961713Sgirish return (NXGE_ERROR); 653744961713Sgirish 653844961713Sgirish macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 653944961713Sgirish macp->m_driver = nxgep; 654044961713Sgirish macp->m_dip = nxgep->dip; 654163f531d1SSriharsha Basavapatna if (!isLDOMguest(nxgep)) { 654263f531d1SSriharsha Basavapatna macp->m_src_addr = nxgep->ouraddr.ether_addr_octet; 654363f531d1SSriharsha Basavapatna } else { 654463f531d1SSriharsha Basavapatna macp->m_src_addr = KMEM_ZALLOC(MAXMACADDRLEN, KM_SLEEP); 654563f531d1SSriharsha Basavapatna macp->m_dst_addr = KMEM_ZALLOC(MAXMACADDRLEN, KM_SLEEP); 654663f531d1SSriharsha Basavapatna (void) memset(macp->m_src_addr, 0xff, sizeof (MAXMACADDRLEN)); 654763f531d1SSriharsha Basavapatna } 654844961713Sgirish macp->m_callbacks = &nxge_m_callbacks; 654944961713Sgirish macp->m_min_sdu = 0; 65501bd6825cSml nxgep->mac.default_mtu = nxgep->mac.maxframesize - 65511bd6825cSml NXGE_EHEADER_VLAN_CRC; 65521bd6825cSml macp->m_max_sdu = nxgep->mac.default_mtu; 6553d62bc4baSyz macp->m_margin = VLAN_TAGSZ; 65544045d941Ssowmini macp->m_priv_props = nxge_priv_props; 6555*0dc2366fSVenugopal Iyer if (isLDOMguest(nxgep)) 6556*0dc2366fSVenugopal Iyer macp->m_v12n = MAC_VIRT_LEVEL1; 6557*0dc2366fSVenugopal Iyer else 6558*0dc2366fSVenugopal Iyer macp->m_v12n = MAC_VIRT_HIO | MAC_VIRT_LEVEL1; 655944961713Sgirish 65601bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 65611bd6825cSml "==> nxge_mac_register: instance %d " 65621bd6825cSml "max_sdu %d margin %d maxframe %d (header %d)", 65631bd6825cSml nxgep->instance, 65641bd6825cSml macp->m_max_sdu, macp->m_margin, 65651bd6825cSml nxgep->mac.maxframesize, 65661bd6825cSml NXGE_EHEADER_VLAN_CRC)); 65671bd6825cSml 656844961713Sgirish status = mac_register(macp, &nxgep->mach); 656963f531d1SSriharsha Basavapatna if (isLDOMguest(nxgep)) { 657063f531d1SSriharsha Basavapatna KMEM_FREE(macp->m_src_addr, MAXMACADDRLEN); 657163f531d1SSriharsha Basavapatna KMEM_FREE(macp->m_dst_addr, MAXMACADDRLEN); 657263f531d1SSriharsha Basavapatna } 657344961713Sgirish mac_free(macp); 657444961713Sgirish 657544961713Sgirish if (status != 0) { 657644961713Sgirish cmn_err(CE_WARN, 65774045d941Ssowmini "!nxge_mac_register failed (status %d instance %d)", 65784045d941Ssowmini status, nxgep->instance); 657944961713Sgirish return (NXGE_ERROR); 658044961713Sgirish } 658144961713Sgirish 658244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_mac_register success " 65834045d941Ssowmini "(instance %d)", nxgep->instance)); 658444961713Sgirish 658544961713Sgirish return (NXGE_OK); 658644961713Sgirish } 658744961713Sgirish 658844961713Sgirish void 658944961713Sgirish nxge_err_inject(p_nxge_t nxgep, queue_t *wq, mblk_t *mp) 659044961713Sgirish { 659144961713Sgirish ssize_t size; 659244961713Sgirish mblk_t *nmp; 659344961713Sgirish uint8_t blk_id; 659444961713Sgirish uint8_t chan; 659544961713Sgirish uint32_t err_id; 659644961713Sgirish err_inject_t *eip; 659744961713Sgirish 659844961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_err_inject")); 659944961713Sgirish 660044961713Sgirish size = 1024; 660144961713Sgirish nmp = mp->b_cont; 660244961713Sgirish eip = (err_inject_t *)nmp->b_rptr; 660344961713Sgirish blk_id = eip->blk_id; 660444961713Sgirish err_id = eip->err_id; 660544961713Sgirish chan = eip->chan; 660644961713Sgirish cmn_err(CE_NOTE, "!blk_id = 0x%x\n", blk_id); 660744961713Sgirish cmn_err(CE_NOTE, "!err_id = 0x%x\n", err_id); 660844961713Sgirish cmn_err(CE_NOTE, "!chan = 0x%x\n", chan); 660944961713Sgirish switch (blk_id) { 661044961713Sgirish case MAC_BLK_ID: 661144961713Sgirish break; 661244961713Sgirish case TXMAC_BLK_ID: 661344961713Sgirish break; 661444961713Sgirish case RXMAC_BLK_ID: 661544961713Sgirish break; 661644961713Sgirish case MIF_BLK_ID: 661744961713Sgirish break; 661844961713Sgirish case IPP_BLK_ID: 661944961713Sgirish nxge_ipp_inject_err(nxgep, err_id); 662044961713Sgirish break; 662144961713Sgirish case TXC_BLK_ID: 662244961713Sgirish nxge_txc_inject_err(nxgep, err_id); 662344961713Sgirish break; 662444961713Sgirish case TXDMA_BLK_ID: 662544961713Sgirish nxge_txdma_inject_err(nxgep, err_id, chan); 662644961713Sgirish break; 662744961713Sgirish case RXDMA_BLK_ID: 662844961713Sgirish nxge_rxdma_inject_err(nxgep, err_id, chan); 662944961713Sgirish break; 663044961713Sgirish case ZCP_BLK_ID: 663144961713Sgirish nxge_zcp_inject_err(nxgep, err_id); 663244961713Sgirish break; 663344961713Sgirish case ESPC_BLK_ID: 663444961713Sgirish break; 663544961713Sgirish case FFLP_BLK_ID: 663644961713Sgirish break; 663744961713Sgirish case PHY_BLK_ID: 663844961713Sgirish break; 663944961713Sgirish case ETHER_SERDES_BLK_ID: 664044961713Sgirish break; 664144961713Sgirish case PCIE_SERDES_BLK_ID: 664244961713Sgirish break; 664344961713Sgirish case VIR_BLK_ID: 664444961713Sgirish break; 664544961713Sgirish } 664644961713Sgirish 664744961713Sgirish nmp->b_wptr = nmp->b_rptr + size; 664844961713Sgirish NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_err_inject")); 664944961713Sgirish 665044961713Sgirish miocack(wq, mp, (int)size, 0); 665144961713Sgirish } 665244961713Sgirish 665344961713Sgirish static int 665444961713Sgirish nxge_init_common_dev(p_nxge_t nxgep) 665544961713Sgirish { 665644961713Sgirish p_nxge_hw_list_t hw_p; 665744961713Sgirish dev_info_t *p_dip; 665844961713Sgirish 6659ef523517SMichael Speer ASSERT(nxgep != NULL); 6660ef523517SMichael Speer 666144961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_init_common_device")); 666244961713Sgirish 666344961713Sgirish p_dip = nxgep->p_dip; 666444961713Sgirish MUTEX_ENTER(&nxge_common_lock); 666544961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66664045d941Ssowmini "==> nxge_init_common_dev:func # %d", 66674045d941Ssowmini nxgep->function_num)); 666844961713Sgirish /* 666944961713Sgirish * Loop through existing per neptune hardware list. 667044961713Sgirish */ 667144961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 667244961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66734045d941Ssowmini "==> nxge_init_common_device:func # %d " 66744045d941Ssowmini "hw_p $%p parent dip $%p", 66754045d941Ssowmini nxgep->function_num, 66764045d941Ssowmini hw_p, 66774045d941Ssowmini p_dip)); 667844961713Sgirish if (hw_p->parent_devp == p_dip) { 667944961713Sgirish nxgep->nxge_hw_p = hw_p; 668044961713Sgirish hw_p->ndevs++; 668144961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 668244961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 66834045d941Ssowmini "==> nxge_init_common_device:func # %d " 66844045d941Ssowmini "hw_p $%p parent dip $%p " 66854045d941Ssowmini "ndevs %d (found)", 66864045d941Ssowmini nxgep->function_num, 66874045d941Ssowmini hw_p, 66884045d941Ssowmini p_dip, 66894045d941Ssowmini hw_p->ndevs)); 669044961713Sgirish break; 669144961713Sgirish } 669244961713Sgirish } 669344961713Sgirish 669444961713Sgirish if (hw_p == NULL) { 669523b952a3SSantwona Behera 669623b952a3SSantwona Behera char **prop_val; 669723b952a3SSantwona Behera uint_t prop_len; 669823b952a3SSantwona Behera int i; 669923b952a3SSantwona Behera 670044961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 67014045d941Ssowmini "==> nxge_init_common_device:func # %d " 67024045d941Ssowmini "parent dip $%p (new)", 67034045d941Ssowmini nxgep->function_num, 67044045d941Ssowmini p_dip)); 670544961713Sgirish hw_p = kmem_zalloc(sizeof (nxge_hw_list_t), KM_SLEEP); 670644961713Sgirish hw_p->parent_devp = p_dip; 670744961713Sgirish hw_p->magic = NXGE_NEPTUNE_MAGIC; 670844961713Sgirish nxgep->nxge_hw_p = hw_p; 670944961713Sgirish hw_p->ndevs++; 671044961713Sgirish hw_p->nxge_p[nxgep->function_num] = nxgep; 671144961713Sgirish hw_p->next = nxge_hw_list; 671259ac0c16Sdavemq if (nxgep->niu_type == N2_NIU) { 671359ac0c16Sdavemq hw_p->niu_type = N2_NIU; 671459ac0c16Sdavemq hw_p->platform_type = P_NEPTUNE_NIU; 67154df55fdeSJanie Lu hw_p->tcam_size = TCAM_NIU_TCAM_MAX_ENTRY; 671659ac0c16Sdavemq } else { 671759ac0c16Sdavemq hw_p->niu_type = NIU_TYPE_NONE; 67182e59129aSraghus hw_p->platform_type = P_NEPTUNE_NONE; 67194df55fdeSJanie Lu hw_p->tcam_size = TCAM_NXGE_TCAM_MAX_ENTRY; 672059ac0c16Sdavemq } 672144961713Sgirish 67224df55fdeSJanie Lu hw_p->tcam = KMEM_ZALLOC(sizeof (tcam_flow_spec_t) * 67234df55fdeSJanie Lu hw_p->tcam_size, KM_SLEEP); 67244df55fdeSJanie Lu 672544961713Sgirish MUTEX_INIT(&hw_p->nxge_cfg_lock, NULL, MUTEX_DRIVER, NULL); 672644961713Sgirish MUTEX_INIT(&hw_p->nxge_tcam_lock, NULL, MUTEX_DRIVER, NULL); 672744961713Sgirish MUTEX_INIT(&hw_p->nxge_vlan_lock, NULL, MUTEX_DRIVER, NULL); 672844961713Sgirish MUTEX_INIT(&hw_p->nxge_mdio_lock, NULL, MUTEX_DRIVER, NULL); 672944961713Sgirish 673044961713Sgirish nxge_hw_list = hw_p; 673159ac0c16Sdavemq 673223b952a3SSantwona Behera if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, nxgep->dip, 0, 673323b952a3SSantwona Behera "compatible", &prop_val, &prop_len) == DDI_PROP_SUCCESS) { 673423b952a3SSantwona Behera for (i = 0; i < prop_len; i++) { 673523b952a3SSantwona Behera if ((strcmp((caddr_t)prop_val[i], 673623b952a3SSantwona Behera NXGE_ROCK_COMPATIBLE) == 0)) { 673723b952a3SSantwona Behera hw_p->platform_type = P_NEPTUNE_ROCK; 673823b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MOD_CTL, 673923b952a3SSantwona Behera "ROCK hw_p->platform_type %d", 674023b952a3SSantwona Behera hw_p->platform_type)); 674123b952a3SSantwona Behera break; 674223b952a3SSantwona Behera } 674323b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MOD_CTL, 674423b952a3SSantwona Behera "nxge_init_common_dev: read compatible" 674523b952a3SSantwona Behera " property[%d] val[%s]", 674623b952a3SSantwona Behera i, (caddr_t)prop_val[i])); 674723b952a3SSantwona Behera } 674823b952a3SSantwona Behera } 674923b952a3SSantwona Behera 675023b952a3SSantwona Behera ddi_prop_free(prop_val); 675123b952a3SSantwona Behera 675259ac0c16Sdavemq (void) nxge_scan_ports_phy(nxgep, nxge_hw_list); 675344961713Sgirish } 675444961713Sgirish 675544961713Sgirish MUTEX_EXIT(&nxge_common_lock); 675659ac0c16Sdavemq 67572e59129aSraghus nxgep->platform_type = hw_p->platform_type; 675823b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MOD_CTL, "nxgep->platform_type %d", 675923b952a3SSantwona Behera nxgep->platform_type)); 676059ac0c16Sdavemq if (nxgep->niu_type != N2_NIU) { 676159ac0c16Sdavemq nxgep->niu_type = hw_p->niu_type; 676259ac0c16Sdavemq } 676359ac0c16Sdavemq 676444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 67654045d941Ssowmini "==> nxge_init_common_device (nxge_hw_list) $%p", 67664045d941Ssowmini nxge_hw_list)); 676744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<== nxge_init_common_device")); 676844961713Sgirish 676944961713Sgirish return (NXGE_OK); 677044961713Sgirish } 677144961713Sgirish 677244961713Sgirish static void 677344961713Sgirish nxge_uninit_common_dev(p_nxge_t nxgep) 677444961713Sgirish { 677544961713Sgirish p_nxge_hw_list_t hw_p, h_hw_p; 67760b0beae0Sspeer p_nxge_dma_pt_cfg_t p_dma_cfgp; 67770b0beae0Sspeer p_nxge_hw_pt_cfg_t p_cfgp; 677844961713Sgirish dev_info_t *p_dip; 677944961713Sgirish 6780ef523517SMichael Speer ASSERT(nxgep != NULL); 6781ef523517SMichael Speer 678244961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_uninit_common_device")); 678344961713Sgirish if (nxgep->nxge_hw_p == NULL) { 678444961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 67854045d941Ssowmini "<== nxge_uninit_common_device (no common)")); 678644961713Sgirish return; 678744961713Sgirish } 678844961713Sgirish 678944961713Sgirish MUTEX_ENTER(&nxge_common_lock); 679044961713Sgirish h_hw_p = nxge_hw_list; 679144961713Sgirish for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) { 679244961713Sgirish p_dip = hw_p->parent_devp; 679344961713Sgirish if (nxgep->nxge_hw_p == hw_p && 67944045d941Ssowmini p_dip == nxgep->p_dip && 67954045d941Ssowmini nxgep->nxge_hw_p->magic == NXGE_NEPTUNE_MAGIC && 67964045d941Ssowmini hw_p->magic == NXGE_NEPTUNE_MAGIC) { 679744961713Sgirish 679844961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 67994045d941Ssowmini "==> nxge_uninit_common_device:func # %d " 68004045d941Ssowmini "hw_p $%p parent dip $%p " 68014045d941Ssowmini "ndevs %d (found)", 68024045d941Ssowmini nxgep->function_num, 68034045d941Ssowmini hw_p, 68044045d941Ssowmini p_dip, 68054045d941Ssowmini hw_p->ndevs)); 680644961713Sgirish 68070b0beae0Sspeer /* 68080b0beae0Sspeer * Release the RDC table, a shared resoruce 68090b0beae0Sspeer * of the nxge hardware. The RDC table was 68100b0beae0Sspeer * assigned to this instance of nxge in 68110b0beae0Sspeer * nxge_use_cfg_dma_config(). 68120b0beae0Sspeer */ 68139d5b8bc5SMichael Speer if (!isLDOMguest(nxgep)) { 68149d5b8bc5SMichael Speer p_dma_cfgp = 68159d5b8bc5SMichael Speer (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 68169d5b8bc5SMichael Speer p_cfgp = 68179d5b8bc5SMichael Speer (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; 68189d5b8bc5SMichael Speer (void) nxge_fzc_rdc_tbl_unbind(nxgep, 68199d5b8bc5SMichael Speer p_cfgp->def_mac_rxdma_grpid); 6820651ce697SMichael Speer 6821651ce697SMichael Speer /* Cleanup any outstanding groups. */ 6822651ce697SMichael Speer nxge_grp_cleanup(nxgep); 68239d5b8bc5SMichael Speer } 68240b0beae0Sspeer 682544961713Sgirish if (hw_p->ndevs) { 682644961713Sgirish hw_p->ndevs--; 682744961713Sgirish } 682844961713Sgirish hw_p->nxge_p[nxgep->function_num] = NULL; 682944961713Sgirish if (!hw_p->ndevs) { 68304df55fdeSJanie Lu KMEM_FREE(hw_p->tcam, 68314df55fdeSJanie Lu sizeof (tcam_flow_spec_t) * 68324df55fdeSJanie Lu hw_p->tcam_size); 683344961713Sgirish MUTEX_DESTROY(&hw_p->nxge_vlan_lock); 683444961713Sgirish MUTEX_DESTROY(&hw_p->nxge_tcam_lock); 683544961713Sgirish MUTEX_DESTROY(&hw_p->nxge_cfg_lock); 683644961713Sgirish MUTEX_DESTROY(&hw_p->nxge_mdio_lock); 683744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 68384045d941Ssowmini "==> nxge_uninit_common_device: " 68394045d941Ssowmini "func # %d " 68404045d941Ssowmini "hw_p $%p parent dip $%p " 68414045d941Ssowmini "ndevs %d (last)", 68424045d941Ssowmini nxgep->function_num, 68434045d941Ssowmini hw_p, 68444045d941Ssowmini p_dip, 68454045d941Ssowmini hw_p->ndevs)); 684644961713Sgirish 6847678453a8Sspeer nxge_hio_uninit(nxgep); 6848678453a8Sspeer 684944961713Sgirish if (hw_p == nxge_hw_list) { 685044961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 68514045d941Ssowmini "==> nxge_uninit_common_device:" 68524045d941Ssowmini "remove head func # %d " 68534045d941Ssowmini "hw_p $%p parent dip $%p " 68544045d941Ssowmini "ndevs %d (head)", 68554045d941Ssowmini nxgep->function_num, 68564045d941Ssowmini hw_p, 68574045d941Ssowmini p_dip, 68584045d941Ssowmini hw_p->ndevs)); 685944961713Sgirish nxge_hw_list = hw_p->next; 686044961713Sgirish } else { 686144961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 68624045d941Ssowmini "==> nxge_uninit_common_device:" 68634045d941Ssowmini "remove middle func # %d " 68644045d941Ssowmini "hw_p $%p parent dip $%p " 68654045d941Ssowmini "ndevs %d (middle)", 68664045d941Ssowmini nxgep->function_num, 68674045d941Ssowmini hw_p, 68684045d941Ssowmini p_dip, 68694045d941Ssowmini hw_p->ndevs)); 687044961713Sgirish h_hw_p->next = hw_p->next; 687144961713Sgirish } 687244961713Sgirish 6873678453a8Sspeer nxgep->nxge_hw_p = NULL; 687444961713Sgirish KMEM_FREE(hw_p, sizeof (nxge_hw_list_t)); 687544961713Sgirish } 687644961713Sgirish break; 687744961713Sgirish } else { 687844961713Sgirish h_hw_p = hw_p; 687944961713Sgirish } 688044961713Sgirish } 688144961713Sgirish 688244961713Sgirish MUTEX_EXIT(&nxge_common_lock); 688344961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, 68844045d941Ssowmini "==> nxge_uninit_common_device (nxge_hw_list) $%p", 68854045d941Ssowmini nxge_hw_list)); 688644961713Sgirish 688744961713Sgirish NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<= nxge_uninit_common_device")); 688844961713Sgirish } 688959ac0c16Sdavemq 689059ac0c16Sdavemq /* 68912e59129aSraghus * Determines the number of ports from the niu_type or the platform type. 689259ac0c16Sdavemq * Returns the number of ports, or returns zero on failure. 689359ac0c16Sdavemq */ 689459ac0c16Sdavemq 689559ac0c16Sdavemq int 68962e59129aSraghus nxge_get_nports(p_nxge_t nxgep) 689759ac0c16Sdavemq { 689859ac0c16Sdavemq int nports = 0; 689959ac0c16Sdavemq 69002e59129aSraghus switch (nxgep->niu_type) { 690159ac0c16Sdavemq case N2_NIU: 690259ac0c16Sdavemq case NEPTUNE_2_10GF: 690359ac0c16Sdavemq nports = 2; 690459ac0c16Sdavemq break; 690559ac0c16Sdavemq case NEPTUNE_4_1GC: 690659ac0c16Sdavemq case NEPTUNE_2_10GF_2_1GC: 690759ac0c16Sdavemq case NEPTUNE_1_10GF_3_1GC: 690859ac0c16Sdavemq case NEPTUNE_1_1GC_1_10GF_2_1GC: 690959a835ddSjoycey case NEPTUNE_2_10GF_2_1GRF: 691059ac0c16Sdavemq nports = 4; 691159ac0c16Sdavemq break; 691259ac0c16Sdavemq default: 69132e59129aSraghus switch (nxgep->platform_type) { 69142e59129aSraghus case P_NEPTUNE_NIU: 69152e59129aSraghus case P_NEPTUNE_ATLAS_2PORT: 69162e59129aSraghus nports = 2; 69172e59129aSraghus break; 69182e59129aSraghus case P_NEPTUNE_ATLAS_4PORT: 69192e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 69202e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 692123b952a3SSantwona Behera case P_NEPTUNE_ROCK: 6922d81011f0Ssbehera case P_NEPTUNE_ALONSO: 69232e59129aSraghus nports = 4; 69242e59129aSraghus break; 69252e59129aSraghus default: 69262e59129aSraghus break; 69272e59129aSraghus } 692859ac0c16Sdavemq break; 692959ac0c16Sdavemq } 693059ac0c16Sdavemq 693159ac0c16Sdavemq return (nports); 693259ac0c16Sdavemq } 6933ec090658Sml 6934ec090658Sml /* 6935ec090658Sml * The following two functions are to support 6936ec090658Sml * PSARC/2007/453 MSI-X interrupt limit override. 6937ec090658Sml */ 6938ec090658Sml static int 6939ec090658Sml nxge_create_msi_property(p_nxge_t nxgep) 6940ec090658Sml { 6941ec090658Sml int nmsi; 6942ec090658Sml extern int ncpus; 6943ec090658Sml 6944ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==>nxge_create_msi_property")); 6945ec090658Sml 6946ec090658Sml switch (nxgep->mac.portmode) { 6947ec090658Sml case PORT_10G_COPPER: 6948ec090658Sml case PORT_10G_FIBER: 694900161856Syc case PORT_10G_TN1010: 6950ec090658Sml (void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip, 6951ec090658Sml DDI_PROP_CANSLEEP, "#msix-request", NULL, 0); 6952ec090658Sml /* 6953ec090658Sml * The maximum MSI-X requested will be 8. 6954ef755e7aStc * If the # of CPUs is less than 8, we will request 6955ef755e7aStc * # MSI-X based on the # of CPUs (default). 6956ec090658Sml */ 6957ef755e7aStc NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6958ef755e7aStc "==>nxge_create_msi_property (10G): nxge_msix_10g_intrs %d", 6959ef755e7aStc nxge_msix_10g_intrs)); 6960ef755e7aStc if ((nxge_msix_10g_intrs == 0) || 6961ef755e7aStc (nxge_msix_10g_intrs > NXGE_MSIX_MAX_ALLOWED)) { 6962ec090658Sml nmsi = NXGE_MSIX_REQUEST_10G; 6963ef755e7aStc NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6964ef755e7aStc "==>nxge_create_msi_property (10G): reset to 8")); 6965ec090658Sml } else { 6966ef755e7aStc nmsi = nxge_msix_10g_intrs; 6967ef755e7aStc } 6968ef755e7aStc 6969ef755e7aStc /* 6970ef755e7aStc * If # of interrupts requested is 8 (default), 6971ef755e7aStc * the checking of the number of cpus will be 6972ef755e7aStc * be maintained. 6973ef755e7aStc */ 6974ef755e7aStc if ((nmsi == NXGE_MSIX_REQUEST_10G) && 6975ef755e7aStc (ncpus < nmsi)) { 6976ef755e7aStc NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6977ef755e7aStc "==>nxge_create_msi_property (10G): reset to 8")); 6978ec090658Sml nmsi = ncpus; 6979ec090658Sml } 6980ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6981ec090658Sml "==>nxge_create_msi_property(10G): exists 0x%x (nmsi %d)", 6982ec090658Sml ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 6983ec090658Sml DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 6984ec090658Sml break; 6985ec090658Sml 6986ec090658Sml default: 6987ef755e7aStc (void) ddi_prop_create(DDI_DEV_T_NONE, nxgep->dip, 6988ef755e7aStc DDI_PROP_CANSLEEP, "#msix-request", NULL, 0); 6989ef755e7aStc NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6990ef755e7aStc "==>nxge_create_msi_property (1G): nxge_msix_1g_intrs %d", 6991ef755e7aStc nxge_msix_1g_intrs)); 6992ef755e7aStc if ((nxge_msix_1g_intrs == 0) || 6993ef755e7aStc (nxge_msix_1g_intrs > NXGE_MSIX_MAX_ALLOWED)) { 6994ef755e7aStc nmsi = NXGE_MSIX_REQUEST_1G; 6995ef755e7aStc NXGE_DEBUG_MSG((nxgep, MOD_CTL, 6996ef755e7aStc "==>nxge_create_msi_property (1G): reset to 2")); 6997ef755e7aStc } else { 6998ef755e7aStc nmsi = nxge_msix_1g_intrs; 6999ef755e7aStc } 7000ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, 7001ec090658Sml "==>nxge_create_msi_property(1G): exists 0x%x (nmsi %d)", 7002ec090658Sml ddi_prop_exists(DDI_DEV_T_NONE, nxgep->dip, 7003ec090658Sml DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 7004ec090658Sml break; 7005ec090658Sml } 7006ec090658Sml 7007ec090658Sml NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<==nxge_create_msi_property")); 7008ec090658Sml return (nmsi); 7009ec090658Sml } 70104045d941Ssowmini 70116f157acbSml /* 70126f157acbSml * The following is a software around for the Neptune hardware's 70136f157acbSml * interrupt bugs; The Neptune hardware may generate spurious interrupts when 70146f157acbSml * an interrupr handler is removed. 70156f157acbSml */ 70166f157acbSml #define NXGE_PCI_PORT_LOGIC_OFFSET 0x98 70176f157acbSml #define NXGE_PIM_RESET (1ULL << 29) 70186f157acbSml #define NXGE_GLU_RESET (1ULL << 30) 70196f157acbSml #define NXGE_NIU_RESET (1ULL << 31) 70206f157acbSml #define NXGE_PCI_RESET_ALL (NXGE_PIM_RESET | \ 70216f157acbSml NXGE_GLU_RESET | \ 70226f157acbSml NXGE_NIU_RESET) 70236f157acbSml 70246f157acbSml #define NXGE_WAIT_QUITE_TIME 200000 70256f157acbSml #define NXGE_WAIT_QUITE_RETRY 40 70266f157acbSml #define NXGE_PCI_RESET_WAIT 1000000 /* one second */ 70276f157acbSml 70286f157acbSml static void 70296f157acbSml nxge_niu_peu_reset(p_nxge_t nxgep) 70306f157acbSml { 70316f157acbSml uint32_t rvalue; 70326f157acbSml p_nxge_hw_list_t hw_p; 70336f157acbSml p_nxge_t fnxgep; 70346f157acbSml int i, j; 70356f157acbSml 70366f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_niu_peu_reset")); 70376f157acbSml if ((hw_p = nxgep->nxge_hw_p) == NULL) { 70386f157acbSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 70396f157acbSml "==> nxge_niu_peu_reset: NULL hardware pointer")); 70406f157acbSml return; 70416f157acbSml } 70426f157acbSml 70436f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 70446f157acbSml "==> nxge_niu_peu_reset: flags 0x%x link timer id %d timer id %d", 70456f157acbSml hw_p->flags, nxgep->nxge_link_poll_timerid, 70466f157acbSml nxgep->nxge_timerid)); 70476f157acbSml 70486f157acbSml MUTEX_ENTER(&hw_p->nxge_cfg_lock); 70496f157acbSml /* 70506f157acbSml * Make sure other instances from the same hardware 70516f157acbSml * stop sending PIO and in quiescent state. 70526f157acbSml */ 70536f157acbSml for (i = 0; i < NXGE_MAX_PORTS; i++) { 70546f157acbSml fnxgep = hw_p->nxge_p[i]; 70556f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 70566f157acbSml "==> nxge_niu_peu_reset: checking entry %d " 70576f157acbSml "nxgep $%p", i, fnxgep)); 70586f157acbSml #ifdef NXGE_DEBUG 70596f157acbSml if (fnxgep) { 70606f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 70616f157acbSml "==> nxge_niu_peu_reset: entry %d (function %d) " 70626f157acbSml "link timer id %d hw timer id %d", 70636f157acbSml i, fnxgep->function_num, 70646f157acbSml fnxgep->nxge_link_poll_timerid, 70656f157acbSml fnxgep->nxge_timerid)); 70666f157acbSml } 70676f157acbSml #endif 70686f157acbSml if (fnxgep && fnxgep != nxgep && 70696f157acbSml (fnxgep->nxge_timerid || fnxgep->nxge_link_poll_timerid)) { 70706f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 70716f157acbSml "==> nxge_niu_peu_reset: checking $%p " 70726f157acbSml "(function %d) timer ids", 70736f157acbSml fnxgep, fnxgep->function_num)); 70746f157acbSml for (j = 0; j < NXGE_WAIT_QUITE_RETRY; j++) { 70756f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 70766f157acbSml "==> nxge_niu_peu_reset: waiting")); 70776f157acbSml NXGE_DELAY(NXGE_WAIT_QUITE_TIME); 70786f157acbSml if (!fnxgep->nxge_timerid && 70796f157acbSml !fnxgep->nxge_link_poll_timerid) { 70806f157acbSml break; 70816f157acbSml } 70826f157acbSml } 70836f157acbSml NXGE_DELAY(NXGE_WAIT_QUITE_TIME); 70846f157acbSml if (fnxgep->nxge_timerid || 70856f157acbSml fnxgep->nxge_link_poll_timerid) { 70866f157acbSml MUTEX_EXIT(&hw_p->nxge_cfg_lock); 70876f157acbSml NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 70886f157acbSml "<== nxge_niu_peu_reset: cannot reset " 70896f157acbSml "hardware (devices are still in use)")); 70906f157acbSml return; 70916f157acbSml } 70926f157acbSml } 70936f157acbSml } 70946f157acbSml 70956f157acbSml if ((hw_p->flags & COMMON_RESET_NIU_PCI) != COMMON_RESET_NIU_PCI) { 70966f157acbSml hw_p->flags |= COMMON_RESET_NIU_PCI; 70976f157acbSml rvalue = pci_config_get32(nxgep->dev_regs->nxge_pciregh, 70986f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET); 70996f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 71006f157acbSml "nxge_niu_peu_reset: read offset 0x%x (%d) " 71016f157acbSml "(data 0x%x)", 71026f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, 71036f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, 71046f157acbSml rvalue)); 71056f157acbSml 71066f157acbSml rvalue |= NXGE_PCI_RESET_ALL; 71076f157acbSml pci_config_put32(nxgep->dev_regs->nxge_pciregh, 71086f157acbSml NXGE_PCI_PORT_LOGIC_OFFSET, rvalue); 71096f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 71106f157acbSml "nxge_niu_peu_reset: RESETTING NIU: write NIU reset 0x%x", 71116f157acbSml rvalue)); 71126f157acbSml 71136f157acbSml NXGE_DELAY(NXGE_PCI_RESET_WAIT); 71146f157acbSml } 71156f157acbSml 71166f157acbSml MUTEX_EXIT(&hw_p->nxge_cfg_lock); 71176f157acbSml NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_niu_peu_reset")); 71186f157acbSml } 7119d6d3405fSml 7120d6d3405fSml static void 7121d6d3405fSml nxge_set_pci_replay_timeout(p_nxge_t nxgep) 7122d6d3405fSml { 7123da14cebeSEric Cheng p_dev_regs_t dev_regs; 7124d6d3405fSml uint32_t value; 7125d6d3405fSml 7126d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_set_pci_replay_timeout")); 7127d6d3405fSml 7128d6d3405fSml if (!nxge_set_replay_timer) { 7129d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7130d6d3405fSml "==> nxge_set_pci_replay_timeout: will not change " 7131d6d3405fSml "the timeout")); 7132d6d3405fSml return; 7133d6d3405fSml } 7134d6d3405fSml 7135d6d3405fSml dev_regs = nxgep->dev_regs; 7136d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7137d6d3405fSml "==> nxge_set_pci_replay_timeout: dev_regs 0x%p pcireg 0x%p", 7138d6d3405fSml dev_regs, dev_regs->nxge_pciregh)); 7139d6d3405fSml 7140d6d3405fSml if (dev_regs == NULL || (dev_regs->nxge_pciregh == NULL)) { 7141f720bc57Syc NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7142d6d3405fSml "==> nxge_set_pci_replay_timeout: NULL dev_regs $%p or " 7143d6d3405fSml "no PCI handle", 7144d6d3405fSml dev_regs)); 7145d6d3405fSml return; 7146d6d3405fSml } 7147d6d3405fSml value = (pci_config_get32(dev_regs->nxge_pciregh, 7148d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET) | 7149d6d3405fSml (nxge_replay_timeout << PCI_REPLAY_TIMEOUT_SHIFT)); 7150d6d3405fSml 7151d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7152d6d3405fSml "nxge_set_pci_replay_timeout: replay timeout value before set 0x%x " 7153d6d3405fSml "(timeout value to set 0x%x at offset 0x%x) value 0x%x", 7154d6d3405fSml pci_config_get32(dev_regs->nxge_pciregh, 7155d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET), nxge_replay_timeout, 7156d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET, value)); 7157d6d3405fSml 7158d6d3405fSml pci_config_put32(dev_regs->nxge_pciregh, PCI_REPLAY_TIMEOUT_CFG_OFFSET, 7159d6d3405fSml value); 7160d6d3405fSml 7161d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, 7162d6d3405fSml "nxge_set_pci_replay_timeout: replay timeout value after set 0x%x", 7163d6d3405fSml pci_config_get32(dev_regs->nxge_pciregh, 7164d6d3405fSml PCI_REPLAY_TIMEOUT_CFG_OFFSET))); 7165d6d3405fSml 7166d6d3405fSml NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_set_pci_replay_timeout")); 7167d6d3405fSml } 716819397407SSherry Moore 716919397407SSherry Moore /* 717019397407SSherry Moore * quiesce(9E) entry point. 717119397407SSherry Moore * 717219397407SSherry Moore * This function is called when the system is single-threaded at high 717319397407SSherry Moore * PIL with preemption disabled. Therefore, this function must not be 717419397407SSherry Moore * blocked. 717519397407SSherry Moore * 717619397407SSherry Moore * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 717719397407SSherry Moore * DDI_FAILURE indicates an error condition and should almost never happen. 717819397407SSherry Moore */ 717919397407SSherry Moore static int 718019397407SSherry Moore nxge_quiesce(dev_info_t *dip) 718119397407SSherry Moore { 718219397407SSherry Moore int instance = ddi_get_instance(dip); 718319397407SSherry Moore p_nxge_t nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); 718419397407SSherry Moore 718519397407SSherry Moore if (nxgep == NULL) 718619397407SSherry Moore return (DDI_FAILURE); 718719397407SSherry Moore 718819397407SSherry Moore /* Turn off debugging */ 718919397407SSherry Moore nxge_debug_level = NO_DEBUG; 719019397407SSherry Moore nxgep->nxge_debug_level = NO_DEBUG; 719119397407SSherry Moore npi_debug_level = NO_DEBUG; 719219397407SSherry Moore 719319397407SSherry Moore /* 719419397407SSherry Moore * Stop link monitor only when linkchkmod is interrupt based 719519397407SSherry Moore */ 719619397407SSherry Moore if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 719719397407SSherry Moore (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 719819397407SSherry Moore } 719919397407SSherry Moore 720019397407SSherry Moore (void) nxge_intr_hw_disable(nxgep); 720119397407SSherry Moore 720219397407SSherry Moore /* 720319397407SSherry Moore * Reset the receive MAC side. 720419397407SSherry Moore */ 720519397407SSherry Moore (void) nxge_rx_mac_disable(nxgep); 720619397407SSherry Moore 720719397407SSherry Moore /* Disable and soft reset the IPP */ 720819397407SSherry Moore if (!isLDOMguest(nxgep)) 720919397407SSherry Moore (void) nxge_ipp_disable(nxgep); 721019397407SSherry Moore 721119397407SSherry Moore /* 721219397407SSherry Moore * Reset the transmit/receive DMA side. 721319397407SSherry Moore */ 721419397407SSherry Moore (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 721519397407SSherry Moore (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 721619397407SSherry Moore 721719397407SSherry Moore /* 721819397407SSherry Moore * Reset the transmit MAC side. 721919397407SSherry Moore */ 722019397407SSherry Moore (void) nxge_tx_mac_disable(nxgep); 722119397407SSherry Moore 722219397407SSherry Moore return (DDI_SUCCESS); 722319397407SSherry Moore } 7224